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)};


Very interesting, thanks so much! I'd been trying unsuccessfully to change the text with putValue(Action.NAME, displayText). Where did you derive the menuText and popupText keys? I can't find a reference to them in the JDK docs. Are these keys that the NetBeans platform has adopted?

Posted by Michael Bishop on March 03, 2013 at 12:17 PM PST #

They're NetBeans Platform keys:

Posted by Geertjan on March 03, 2013 at 12:22 PM PST #

Hi Geertjan,

Seeing this part of the code:

personNodeResult = Utilities.actionsGlobalContext().lookupResult(PersonNode.class);
WeakListeners.create(LookupListener.class, this, personNodeResult));
resultChanged(new LookupEvent(personNodeResult));

makes me think about an interesting topic about the WeakListeners class provided by Netbeans. You could explain the purpose of the lines above to newbies and if this it the "state of the art" way to work with lookups or not (or when to use WeakListeners and when not).



Posted by Jean-Marc Borer on March 04, 2013 at 01:02 AM PST #

By the way, I remember from some docuement that you are supposed to invoke allInstance() method on the lookup (or someting like this), to somehow start listening to changes events. Is this still true?

Posted by Jean-Marc Borer on March 04, 2013 at 01:04 AM PST #

Lots of info about WeakListeners in the javadoc:

About your second question, no that's not needed anymore.

Posted by Geertjan on March 04, 2013 at 12:01 PM PST #

Hi Geertjan,

I'm trying to make an Multiview XML Editor with ability to use Palette drag and drop function. The problem is the Top Component's lookup should be associate with a PaletteSupport and it seems impossible to get add thing to other TopComponent's lookup on the fly.

Is there anyway around this? Thank a lot.

Posted by Atomix on July 19, 2013 at 12:16 AM PDT #

Hi Atomix,

I typed "multview palette geertjan" into Google and found this:

Hope it helps,


Posted by Geertjan on July 20, 2013 at 04:36 AM PDT #

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.


« June 2016