Geertjan's Blog

  • June 21, 2012

Showing an Action on a TopComponent Node

Geertjan Wielenga
Product Manager

Let's say you want to extend the tools in NetBeans IDE, specifically for TopComponents. When the user right-clicks in the Projects window (or Files window or Favorites window) on a Java class that extends TopComponent, a menu item should be available for branding the TopComponent. What "branding" entails is, at this stage, a secondary question. The primary question, from an implementation point of view, is "how do I create an action that is only shown when the user right-clicks on a TopComponent?"

Here's the solution, in NetBeans IDE 7.2 (the "lazy" attribute, here set to false, is new in 7.2):

import com.sun.source.tree.ClassTree;
import com.sun.source.util.TreePathScanner;
import java.awt.event.ActionEvent;
import java.io.IOException;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JOptionPane;
import org.netbeans.api.java.source.CompilationController;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.JavaSource.Phase;
import org.netbeans.api.java.source.Task;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration;
import org.openide.awt.DynamicMenuContent;
import org.openide.loaders.DataObject;
import org.openide.util.ContextAwareAction;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle.Messages;
import org.openide.util.Utilities;
    category = "Tools",
id = "org.tc.customizer.BrandTopComponentAction")
    displayName = "#CTL_BrandTopComponentAction",
    lazy = false)
    @ActionReference(path = "Loaders/text/x-java/Actions", position = 150)
public final class BrandTopComponentAction extends AbstractAction implements ContextAwareAction {
    private final DataObject dobj;
    public BrandTopComponentAction() {
    public BrandTopComponentAction(Lookup context) {
        this.dobj = context.lookup(DataObject.class);
        //Enable the menu item only if we're dealing with a TopComponent
        JavaSource javaSource = JavaSource.forFileObject(dobj.getPrimaryFile());
        try {
            javaSource.runUserActionTask(new ScanForTopComponentTask(this), true);
        } catch (IOException ex) {
        //Hide the menu item if it isn't enabled:
        putValue(DynamicMenuContent.HIDE_WHEN_DISABLED, true);
    public void actionPerformed(ActionEvent ev) {
        JOptionPane.showMessageDialog(null, "Hurray, I am a TopComponent!");
        //Now add your code for showing a dialog,
        //where the dialog will display UI for branding the TopComponent somehow
        //and retrieve those branding values
        //and then change the TopComponent class accordingly.
    public Action createContextAwareInstance(Lookup actionContext) {
        return new BrandTopComponentAction(actionContext);
    private static class ScanForTopComponentTask implements Task<CompilationController> {
        private final BrandTopComponentAction action;
        private ScanForTopComponentTask(BrandTopComponentAction action) {
            this.action = action;
        public void run(CompilationController compilationController) throws Exception {
            new MemberVisitor(compilationController, action).scan(
                    compilationController.getCompilationUnit(), null);
    private static class MemberVisitor extends TreePathScanner<Void, Void> {
        private CompilationInfo info;
        private final AbstractAction action;
        public MemberVisitor(CompilationInfo info, AbstractAction action) {
            this.info = info;
            this.action = action;
        public Void visitClass(ClassTree t, Void v) {
            Element el = info.getTrees().getElement(getCurrentPath());
            if (el != null) {
                TypeElement te = (TypeElement) el;
                if (te.getSuperclass().toString().equals("org.openide.windows.TopComponent")){
                } else {
            return null;

The code above is the result of combining various tutorials found on the NetBeans Platform Learning Trail.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.