NetBeans: How to create a context aware action with an icon for the context menu

Here a small sample how to create a context aware action with icons for a NetBeans Platform RCP application or even the NB IDE. You may wonder and questions like “Why the heck he is doing this” or “Why he won’t use the standard action wizard?” may pop up.

Assigning icons to actions is easy. BUT the icons do will not be displayed in the context menu (by default). It is possible but not best practice in NB RCP. Keep in mind that icons in menus are not supported for MacOS. So use it wisely.

The important points are:

  • extend from AbstractAction to get access to putValue (you loose the standard context aware features, so you have to implement them yourself via keeping a proxy to the global lookup and enabling the action depending on the content of the lookup)
  • implement Presenter.Popup and return a JMenuItem instance for the current action (see [1], [2])
  • set the icon via putValue(javax.swing.Action.SMALL_ICON, ...)
package de.markiewb.netbeans.sample.contextmenu;

import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import static javax.swing.Action.SMALL_ICON;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import org.netbeans.api.annotations.common.StaticResource;
import org.netbeans.api.project.Project;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.NbBundle.Messages;
import org.openide.util.Utilities;
import org.openide.util.actions.Presenter;

@ActionID(
        category = "Build",
        id = "de.markiewb.netbeans.sample.contextmenu.HelloIconAction")
@ActionReferences({
    @ActionReference(path = "Menu/File", position = 0),
    @ActionReference(path = "Loaders/Languages/Actions", position = 0),
    @ActionReference(path="Projects/Actions")
})
@ActionRegistration(
        displayName = "#CTL_HelloIconAction")

@Messages("CTL_HelloIconAction=Hello Icon Action")
public final class HelloIconAction extends AbstractAction implements Presenter.Popup {

    @StaticResource
    private static final String ICON = "de/markiewb/netbeans/sample/contextmenu/sample.gif";
    private static final long serialVersionUID = 1L;
    private final Lookup context;

    public HelloIconAction() {
        context = Utilities.actionsGlobalContext();
        putValue(SMALL_ICON, ImageUtilities.loadImageIcon(ICON, false));
        putValue(NAME, Bundle.CTL_HelloIconAction());
    }

    @Override
    public boolean isEnabled() {
        return null != context.lookup(Project.class);
    }

    @Override
    public void actionPerformed(ActionEvent ev) {
        JOptionPane.showMessageDialog(null, "Hello colorful project.\n" + context.lookup(Project.class).toString());
    }

    @Override
    public JMenuItem getPopupPresenter() {
        return new JMenuItem(this);
    }
}

[1] http://wiki.netbeans.org/DevFaqChangeMenuItemToolbarAppearanceForAction
[2] http://forums.netbeans.org/topic40762.html
[3] http://wiki.netbeans.org/DevFaqAddIconToContextMenu

 

The result:
Shows the result

See sample code at https://github.com/markiewb/nb-api-samples/tree/master/ContextMenuWithIcon

Advertisements