Sunday Mar 03, 2013

Creating a Customized OpenAction

The question of the day comes from Michael Bishop who, in a follow up to yesterday's blog entry, doesn't simply want the display text of the OpenAction to be "Open". He wants it to show something about the context, e.g., "Open Joe", where Joe is the name of the underlying object.

The key to solving this problem is described in Dynamically Changing the Display Names of Menus and Popups.

And so here's the code, i.e., remove the NetBeans Platform OpenAction and create your own instead:

import java.awt.event.ActionEvent;
import java.util.Collection;
import javax.swing.AbstractAction;
import org.netbeans.api.actions.Openable;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.Utilities;
import org.openide.util.WeakListeners;

        category = "PersonActions",
        id = "org.person.viewer.PersonOpenAction")
        lazy = false,
        displayName = "NOT-USED")
@ActionReference(path = "Menu/File", position = 1300)
public final class PersonOpenAction extends AbstractAction implements LookupListener {

    private Lookup.Result<PersonNode> personNodeResult;
    private Openable context;

    public PersonOpenAction() {
        super("Open Person");
        personNodeResult = Utilities.actionsGlobalContext().lookupResult(PersonNode.class);
                WeakListeners.create(LookupListener.class, this, personNodeResult));
        resultChanged(new LookupEvent(personNodeResult));

    public void actionPerformed(ActionEvent ev) {;

    public void resultChanged(LookupEvent le) {
        Collection<? extends PersonNode> p = personNodeResult.allInstances();
        if (p.size() == 1) {
            PersonNode currentPersonNode = p.iterator().next();
            context = currentPersonNode.getLookup().lookup(Openable.class);
            String displayText = "Open Person: " + currentPersonNode.getDisplayName();
            putValue("popupText", displayText);
            putValue("menuText", displayText);

    public boolean isEnabled() {
        return context!=null ? true : false;


Above, the assumption is that there's an Openable in the Node Lookup. If you're using OpenCookie or something different instead, change the code above accordingly. Secondly, above the display name of the Node is used to set the display text of the popup and menu. Of course, instead of that, you could look in the Lookup of the Node for your Object, e.g., Person, and then get some value from that Object.

Display the Action above on the Node as follows (and it is automatically available in the menu bar thanks to the @ActionReference annotation above):

public Action[] getActions(boolean context) {
    List<? extends Action> personActions = Utilities.actionsForPath("Actions/PersonActions");
    return personActions.toArray(new Action[personActions.size()]);
//        return new Action[]{SystemAction.get(OpenAction.class)};


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.


« March 2013 »