Tuesday Dec 02, 2008

Creating a NetBeans Platform Toolbar in 6.5

Creating a new toolbar for NetBeans IDE is now easy in 6.5. Just use the New Action wizard, which gives you an "ActionListener", and then replace the "ActionListener" implementation with a "Presenter.Toolbar", as shown here:
package org.demo.toolbar;

import java.awt.Component;
import org.openide.util.actions.Presenter;

public final class SomeAction implements Presenter.Toolbar {

    //Here's where you put your panel into the toolbar area:
    @Override
    public Component getToolbarPresenter() {
        return new DemoJPanel();
    }

}

Finally, delete the "instanceCreate" attribute that the New Action wizard created in the layer.xml. Then install and you're done.

Update. See this tutorial for the complete example, the above is partial and incomplete.

From ActionListener to CallableSystemAction

In 6.5, when you create an "Always Enabled" action, the "New Action" wizard gives you this Java code:
package org.demo.module;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public final class SomeAction implements ActionListener {

    public void actionPerformed(ActionEvent e) {
        // TODO implement action body
    }
}

Very nice... because you're using plain old Java code. The ActionListener is one of the JDK's classes, unlike the Action classes that the NetBeans Platform provides. In previous releases, you would get a CallableSystemAction instead, which is one of those NetBeans Platform classes.

To make it possible for the NetBeans Platform to hook the above class into the NetBeans action system, the following entries are added to the layer.xml file, by the same "New Action" wizard that created the above Java class:



<filesystem>
    <folder name="Actions">
        <folder name="Build">
            <file name="org-demo-module-SomeAction.instance">
                <attr name="SystemFileSystem.localizingBundle" stringvalue="org.demo.module.Bundle"/>
                <attr name="delegate" newvalue="org.demo.module.SomeAction"/>
                <attr name="displayName" bundlevalue="org.demo.module.Bundle#CTL_SomeAction"/>
                <attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
                <attr name="noIconInMenu" boolvalue="false"/>
            </file>
        </folder>
    </folder>
    <folder name="Menu">
        <folder name="File">
            <file name="org-demo-module-SomeAction.shadow">
                <attr name="originalFile" stringvalue="Actions/Build/org-demo-module-SomeAction.instance"/>
                <attr name="position" intvalue="0"/>
            </file>
        </folder>
    </folder>
</filesystem>

Take careful note of the section that is in bold above! There you can see how the ActionListener implementation is hooked into the NetBeans action system. For example, the "instanceCreate" attribute causes a NetBeans Platform action to be created for your ActionListener! So, even though you're using plain old Java, the entries above (generated automatically by the wizard) cause the ActionListener to be treated as a NetBeans Platform class.

However... the NetBeans Platform classes are much more powerful than the ActionListener class. For example, if you use the CallableSystemAction class, you can (in bad pseudo code, any way) do something like this:

@Override
public void setEnabled(boolean enabled) {
    if (hell freezes over){
        enable this menu item
    } else {
        not
    }
}

In other words, the NetBeans Platform action classes provide built-in support for enabling/disabling themselves. Therefore, you're quite likely to want to 'upgrade' your ActionListener to a CallableSystemAction. So, what must one do to transform one's ActionListener into a CallableSystemAction? First, change the class signature so that you're extending "CallableSystemAction", instead of implementing "ActionListener". The Utilities API, which provides the "CallableSystemAction" class, is already set as one of the module's dependencies when you complete the "New Action" wizard, so there are no additional dependencies you need to set. You'll find you need to do something with a bunch of methods that come from the CallableSystemAction class and/or its ancestors.

Next... you need to tweak the layer.xml file so that the bits in bold above are removed. You'll be left with this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
<filesystem>
    <folder name="Actions">
        <folder name="Build">
            <file name="org-demo-module-SomeAction.instance"/>
        </folder>
    </folder>
    <folder name="Menu">
        <folder name="File">
            <file name="org-demo-module-SomeAction.shadow">
                <attr name="originalFile" stringvalue="Actions/Build/org-demo-module-SomeAction.instance"/>
                <attr name="position" intvalue="0"/>
            </file>
        </folder>
    </folder>
</filesystem>

Or, if you have the display name in the localizing bundle, you might have this instead:

    <folder name="Actions">
        <folder name="Build">
            <file name="org-demo-module-SomeAction.instance">
                <attr name="SystemFileSystem.localizingBundle" stringvalue="org.demo.module.Bundle"/>
                <attr name="displayName" bundlevalue="org.demo.module.Bundle#CTL_SomeAction"/>
            </file>
        </folder>
    </folder>

And now install your module. Your ActionListener is now a CallableSystemAction.

About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« December 2008 »
SunMonTueWedThuFriSat
 
3
7
12
16
17
18
19
21
22
25
26
27
28
29
30
   
       
Today