Changing a Node from its Popup Menu

I learnt some interesting things with Børre Dalhaug today. Look at the screenshot below:

When a submenu is selected, the display name of the Node is automatically updated to the text in the selected submenu:

I couldn't figure out how to use the new Actions.* factories for the above scenario. Instead, it's done like this:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import net.dalhaug.borre.context691.domainobjects.IDrummer;
import org.openide.nodes.Node;
import org.openide.util.HelpCtx;
import org.openide.util.ImageUtilities;
import org.openide.util.actions.CookieAction;
import org.openide.util.actions.Presenter;

public final class ChangeDrumAction extends CookieAction 
    implements Presenter.Popup, ActionListener {

    private static final String PROP_KEY = "";
    private IDrummer context = null;

    @Override
    public JMenuItem getPopupPresenter() {
        JMenu changeDrumKitMenu = new JMenu("Change " + context.getDrumKit());
        changeDrumKitMenu.setIcon(ImageUtilities.loadImageIcon("net/dalhaug/icons/Arrow.png", false));
        for (String string : context.getAvailableDrumsets()) {
            JMenuItem subMenu = new JMenuItem(string);
            //Create a client property on the JMenuItem:
            subMenu.putClientProperty(PROP_KEY, string);
            subMenu.addActionListener(this);
            changeDrumKitMenu.add(subMenu);
        }
        return changeDrumKitMenu;
    }
 
    //The Action that will be invoked on the submenus:
    @Override
    public void actionPerformed(ActionEvent ev) {
        if (ev.getSource() instanceof JMenuItem) {
            JMenuItem item = (JMenuItem) ev.getSource();
            //Retrieve from the client property on the JMenuItem:
            String drumKit = (String) item.getClientProperty(PROP_KEY);
            context.setDrumKit(drumKit);
        } 
    }

    @Override
    protected boolean enable(Node[] nodes) {
        if (nodes[0].getLookup().lookup(IDrummer.class)!=null){
            context = nodes[0].getLookup().lookup(IDrummer.class);
            return true;
        }
        return false;
    }
 
    @Override
    protected int mode() {
        return CookieAction.MODE_EXACTLY_ONE;
    }

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

    //Not used:
    @Override
    public String getName() {return null;}
 
    //Not used:
    @Override protected void performAction(Node[] nodes) {}

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

}

The above is registered as follows:

<folder name="Actions">
    <folder name="OSC">
        <file name="net-dalhaug-ChangeDrumAction.instance"/>
    </folder>
</folder>

And here's the Node:

public class DrummerNode extends AbstractNode implements PropertyChangeListener {

    private final IDrummer drummer;

    public DrummerNode(IDrummer drummer) {
        super(Children.LEAF, Lookups.singleton(drummer));
        this.drummer = drummer;
        drummer.addPropertyChangeListener(this);
        setName(drummer.getName() + " plays " + drummer.getDrumKit());
    }

    @Override
    public Image getIcon(int type) {
        return ImageUtilities.loadImage("net/dalhaug/borre/context691/Drum24.png");
    }

    @Override
    public Action[] getActions(boolean context) {
        List<? extends Action> oscActions = Utilities.actionsForPath("Actions/OSC");
        return oscActions.toArray(new Action[oscActions.size()]);
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals(Drummer.PROP_DRUMKIT)) {
            setDisplayName(drummer.getName() + " plays " + drummer.getDrumKit());
        }
    }
 
}
Comments:

You cannot use Actions.* factories for this since it is inherently nonlazy, but you should be able to use @ActionRegistration on it anyway. (By implementing Presenter.Popup you magically indicate that you do not want to use a factory.)

Posted by Jesse Glick on November 08, 2011 at 10:51 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
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
« April 2014
SunMonTueWedThuFriSat
  
12
13
14
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today