Presenter.Toolbar & Presenter.Menu (Part 2)

A big weakness in the previous blog entry was that I specified a particular folder in the layer ("Actions/MyActions") as being the one of interest. Now... let's handle things differently. We'd like to build up a list of JMenuItems and JPopupMenu's for display when the menu item or toolbar button are clicked. Rather than forcing everyone to register their actions in the same folder in the layer.xml, let's simply tell them they need to add an attribute to their action registration. Then we'll find that attribute and add the action accordingly.

Concretely, we have a menu item and toolbar button that should display all actions that relate to tasks. So, whenever an external module developer registers such an action, they should include an attribute that we tell them to use especially for this purpose. I.e.:

<folder name="Actions">
    <folder name="Edit">
        <file name="com-netbeansrcp-taskeditor-NewTaskAction.instance">
            <attr name="task-related" boolvalue="true"/>
            <attr name="delegate" newvalue="com.netbeansrcp.taskeditor.NewTaskAction"/>
            <attr name="displayName" bundlevalue="com.netbeansrcp.taskeditor.Bundle#CTL_NewTaskAction"/>
            <attr name="iconBase" stringvalue="com/netbeansrcp/taskeditor/Add.png"/>
            <attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
            <attr name="noIconInMenu" boolvalue="false"/>

OK. Now the actions that relate to tasks are marked as such.

Now this is the action that builds up a list of task-related actions and makes them available as JMenuItems from a menu item and JPopupMenus from a toolbar button:

public final class AddAction implements ActionListener, Presenter.Toolbar, Presenter.Menu {

    private ArrayList<Action> foundActions = new ArrayList();
    private String ICON_PATH = "org/netbeansrcp/taskactions/Add.png";

    public AddAction() {
    //Go through all actions and find the ones that have our attribute
    //and then add them to our "foundActions" array list:
    public void findTaskRelatedActions() {
        FileObject actionsFolder = FileUtil.getConfigFile("Actions");
        FileObject[] actionsCategories = actionsFolder.getChildren();
        for (FileObject oneActionsCategory : actionsCategories) {
            FileObject[] actions = oneActionsCategory.getChildren();
            for (FileObject fo : actions) {
                Boolean isTaskRelated = (Boolean) fo.getAttribute("task-related");
                if (isTaskRelated != null && isTaskRelated) {
                    DataObject dob;
                    try {
                        dob = DataObject.find(fo);
                        InstanceCookie ck = dob.getLookup().lookup(InstanceCookie.class);
                        try {
                            foundActions.add((Action) ck.instanceCreate());
                        } catch (IOException ex) {
                        } catch (ClassNotFoundException ex) {
                    } catch (DataObjectNotFoundException ex) {

    public void actionPerformed(ActionEvent e) {
        //Nothing needs to happen here.

    public JMenuItem getMenuPresenter() {
        JMenu menu = new JMenu(NbBundle.getMessage(AddAction.class, "CTL_AddAction"));
        menu.setIcon(ImageUtilities.loadImageIcon(ICON_PATH, true));
        //Iterate through the found actions:
        for (Action action : foundActions) {
            //Create a new JMenuItem for each found action:
            JMenuItem item = new JMenuItem(action);
            //Add the new JMenuItem to the JMenu:
        return menu;

    public Component getToolbarPresenter() {
        return new MyToolbarPresenter();

    private class MyToolbarPresenter extends JButton {

        private JPopupMenu popup;

        MyToolbarPresenter() {
            this.setText(NbBundle.getMessage(AddAction.class, "CTL_AddAction"));
            this.setIcon(ImageUtilities.loadImageIcon(ICON_PATH, true));
            this.popup = new JPopupMenu();
            //Iterate through all the found actions:
            for (Action action : foundActions) {
                //Add the current found action from the layer to the popup:
                //Show the button when the popup is clicked:
                this.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent arg0) {
                                MyToolbarPresenter.this, 0,

The above action is registered in the layer, as shown in the previous blog entry. Now all the task-related actions are identified and made available as JMenuItems and JPopupMenus from a menu item and a toolbar button.


I am having a hard time applying this approach where I want to merge into existing sub-menus. That is each instance of the action belongs to a unique and already existing menu item that it should be a sub-menu of.

If I create a JMenu and add menu items to it, the menu has duplicate entries for the upper level menu instead of merged sub-menus.

Posted by guest on February 17, 2012 at 11:38 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed

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.


« February 2015