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;

@ActionID(
        category = "PersonActions",
        id = "org.person.viewer.PersonOpenAction")
@ActionRegistration(
        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);
        personNodeResult.addLookupListener(
                WeakListeners.create(LookupListener.class, this, personNodeResult));
        resultChanged(new LookupEvent(personNodeResult));
    }

    @Override
    public void actionPerformed(ActionEvent ev) {
        context.open();
    }

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

    @Override
    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):

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

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
« March 2013 »
SunMonTueWedThuFriSat
     
10
11
12
13
14
15
18
23
24
27
28
      
Today