[RSS]

Transforming CallableSystemAction Into CookieAction

Contributed By Varun Nischal

This is based on the existing tutorial. That tutorial, lets you get started with the NetBeans Plugin-Development, by creating an Always Enabled (see CallableSystemAction), without using any Wizard and that too smoothly.

Pre-requisites


If you don’t have prior experience with NetBeans Platform, read that tutorial. That's a must! Now, after you have done that, you might like to explore a bit more. So, you should give the following a read as well(if you want you can skip it for a while and read it along with my tutorial),
This overview will quickly familiarize you with how NetBeans plug-in modules interact with the NetBeans infrastructure and with each other.

Now, you're ready for transformation. So, lets get started then!

What's CookieAction?


"An action dependent on the cookies of the selected nodes", as defined in the Javadocs! Exactly, so when you have done following transformation, you would see the action, but would be enabled, only when the node is selected, which supports particular Cookies. You will understand more, as you read further.

Getting Started


Here, we are going to transform an Action from one type to another, i.e. from CallableSystemAction TO CookieAction, sounds cool! Though, never tried! Well, here I am sharing with you another tips and tricks to make it possible, without using New File Type Wizard. We will make use of SayCheez.java, which was made in the reference tutorial.

Solution


So, to start with, remove the CallableSystemAction and let the class SayCheez inherit from CookieAction, like this;
public final class SayCheez extends CookieAction {

Now, don’t remove the already existing implementations of abstract methods of CallableSystemAction,


    @Override
    public void performAction() {
        //throw new UnsupportedOperationException("Not supported yet.");
        String msg = "I'm plugged in!";
        NotifyDescriptor d = new NotifyDescriptor.Message(msg, 
                NotifyDescriptor.INFORMATION_MESSAGE);
        DialogDisplayer.getDefault().notify(d);  
    }

    @Override
    public String getName() {
        //throw new UnsupportedOperationException("Not supported yet.");
        return NbBundle.getMessage(SayCheez.class, "CTL_SayCheez");
    }

    @Override
    public HelpCtx getHelpCtx() {
        //throw new UnsupportedOperationException("Not supported yet.");
        return HelpCtx.DEFAULT_HELP;
    }

    @Override      
    protected String iconResource() {  
        //Replace org/nvarun/tat with your path/to/icon  
        //see attachments to download icon24.png  
        return "org/nvarun/tat/icon24.png";  
    }      

    // Newly Added	
    @Override
    protected void initialize() {
        super.initialize();
        // see org.openide.util.actions.SystemAction.iconResource() Javadoc for more details
        putValue("noIconInMenu", Boolean.TRUE);
    }    
	
    // Newly Added	
    @Override
    protected boolean asynchronous() {
        return false;
    }
}

Now, just add the following 2 methods TO let the class SayCheez implement all the abstract methods defined by CookieAction.


@Override
protected Class<?>[] cookieClasses() {
return new Class[]{{$Interface}.class};
}

protected int mode() {
return CookieAction.{$mode};
}

Please note, that {$Interface} needs to be replaced by appropriate interface, i.e. it could be either of the following Cookie class(es), which are basically interfaces/abstract class(es);

1. Project
2. OpenCookie
3. EditCookie
4. EditorCookie
5. DataObject (Abstract Class, NOT an Interface)

I will be using EditorCookie for this transformation. Also, {$mode} needs to be replaced with either MODE_EXACTLY_ONE[1] or MODE_ALL[2].

1. User Selects One Node
2. User May Select Multiple Nodes

I will be using MODE_EXACTLY_ONE for this transformation.

MODE_EXACTLY_ONE
Action will be enabled if there is exactly one selected node and it supports the given cookies.
MODE_ALL
Action will be enabled if there are one or more selected nodes and all of them support the given cookies.

In our case, its EditorCookie! Now, alter the performAction method like this,


@Override
protected void performAction(Node[] activatedNodes) {
{$Interface} ref = activatedNodes[0].getLookup().lookup({$Interface}.class);
// TODO use {$Interface}
}

Here, ref is basically the reference to either the interface/class being made, which is being assigned a subclass reference, it could be of great use. Now, add your code for DialogDisplayer used in reference tutorial, in place of TODO comment.

        String msg = "I'm plugged in!";
        NotifyDescriptor d = new NotifyDescriptor.Message(msg, 
                NotifyDescriptor.INFORMATION_MESSAGE);
        DialogDisplayer.getDefault().notify(d); 

See, it was too easy! Anyways, the changes in XML Layer, which shall be done with respect to the change in the Action type, some of them are as follows and rest will be the mentioned in the next part of this series.

Tricks for Menu Item, Toolbar Button, Shortcut Keys

Trick #1

As you had made a Global Menu Item and Toolbar Button with CallableSystemAction, so no changes required, for transformation.

Trick #2

If you had made use of Shortcut Keys earlier, then you have to remove them, as CookieAction doesn’t support Shortcut Keys! Well, I don’t know why. So, remove following code from our XML Layer, if present in refernce tutorial OR in your plug-in module XML Layer;

    <folder name="Shortcuts">
        <file name="O-F3.shadow">
            <attr name="originalFile" stringvalue="Actions/Tools/org-nvarun-tat-SayCheez.instance"/>
        </file>
    </folder>

  • Replace "org-nvarun-tat" with your package name, in which SayCheez resides.

Ready to Install/Reload

  • Not yet, firstly, recall if you saw some red underlines present in the code, Add relevant Module Dependencies...(see tutorial) to get rid of them, so finally your code looks like this;

Transformed Source Code


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

//package {$your-package};

import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.cookies.EditorCookie;
import org.openide.nodes.Node;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CookieAction;

/**
 *
 * @author Varun Nischal (nvarun@NetBeans.org)
 */
public class SayCheez extends CookieAction {

    @Override
    protected void performAction(Node[] activatedNodes) {        
        EditorCookie ref = activatedNodes[0].getLookup().lookup(EditorCookie.class);
        
        String msg = "I'm plugged in!";
	NotifyDescriptor d = new NotifyDescriptor.Message(msg, 
                NotifyDescriptor.INFORMATION_MESSAGE);
	DialogDisplayer.getDefault().notify(d); 
    }

    @Override
    public String getName() {
        return NbBundle.getMessage(SayCheez.class, "CTL_SayCheez");
    }

   @Override
    protected void initialize() {
        super.initialize();
        // see org.openide.util.actions.SystemAction.iconResource() Javadoc for more details
        putValue("noIconInMenu", Boolean.TRUE);
    }    

    @Override      
    protected String iconResource() {  
        //Replace org/nvarun/tat with your path/to/icon  
        //see attachments to download icon24.png  
        return "org/nvarun/tat/icon24.png";  
    }      

    public HelpCtx getHelpCtx() {
        return HelpCtx.DEFAULT_HELP;
    }

    @Override
    protected boolean asynchronous() {
        return false;
    }

    @Override
    protected int mode() {
        return CookieAction.MODE_EXACTLY_ONE;
    }

    @Override
    protected Class<?>[] cookieClasses() {
        return new Class[]{EditorCookie.class};
    }

}

Module's XML Layer

  • By the way, we missed one thing, what to do with the XML Layer. Don't worry, just see the following tips about your existing layer.xml, formed in reference tutorial. This is how it looks;
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
<filesystem>
    <folder name="Actions">
        <folder name="Tools">        
            <file name="org-nvarun-tat-SayCheez.instance"/>
        </folder>
    </folder>
  • Here, more tags are added, when you make this action, File Type OR Editor Context-sensitive;
 <!--Code To Be Added-->
  • Add relevant code, and you could also be ready for making it context-sensitive, however for time being, leave it as it is. I will tell you later how to add the code.
    <folder name="Menu">
        <folder name="Tools">
            <file name="org-nvarun-tat-SayCheez.shadow">
                <attr name="originalFile" stringvalue="Actions/Tools/org-nvarun-tat-SayCheez.instance"/>
                <attr name="position" intvalue="150"/>
            </file>
            <file name="org-nvarun-tat-separatorAfter.instance">
                <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
                <attr name="position" intvalue="175"/>
            </file>
            <file name="org-nvarun-tat-separatorBefore.instance">
                <attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
                <attr name="position" intvalue="125"/>
            </file>
        </folder>
    </folder>
    <folder name="Toolbars">
        <folder name="Build">
            <file name="org-nvarun-tat-SayCheez.shadow">
                <attr name="originalFile" stringvalue="Actions/Tools/org-nvarun-tat-SayCheez.instance"/>
                <attr name="position" intvalue="325"/>
            </file>
        </folder>
    </folder>
</filesystem>

  • Replace "org-nvarun-tat" with your package name, in which SayCheez resides.

Installing and Using the Plug-in Module


Refer to the reference tutorial, on how to Install and use your plug-in module. If you liked it, feel free to give feedback, because this tutorial can only get better, if you actively participate in community.

Version Compatability


Works with NetBeans 6.0, 6.1 as said above. Try this out on your version, and make sure to notify us if anything goes wrong!

Thanks for following, enjoy and have fun!

Attachments

icon24.png Info on icon24.png 1908 bytes