Question

I have a TopComponent that shows in properties mode. There are two ways to open this.

  1. via Window/ Top component open action
  2. open a file and the top component is opened automatically.

I am configuring the first action using annotations like so.

@ActionID(category = "Window", id = "org.netbeans.modules.plantumlnb.PUMLTopComponent")
@ActionReference(path = "Menu/Window" /*, position = 333 */)
@TopComponent.OpenActionRegistration( displayName = "#CTL_PUMLAction",
    preferredID = "PUMLTopComponent")

I am manually creating a new TopComponent and calling open on it to enable the second action.

    SwingUtilities.invokeLater(new Runnable(){
        @Override
        public void run() {
            PUMLTopComponent pumltc = new PUMLTopComponent();                
            pumltc.open();
            pumltc.setNewContent(obj);
        }
    });

When the user opens a file an instance of PUMLTopComponent is opened by the second code snippet. But if the user now goes and clicks on Window/open action a second window is opened.

How can I register the manually instantiated TopComponent instance with netbeans so that when user clicks on Window/open action netbeans uses the above mentioned instance rather than creating a new one ?

Was it helpful?

Solution

If you need just one instance of your TopComponent throughout the whole application, you can simply make it a singleton and then get the instance using a static method anywhere in your code.

PUMLTopComponent.java:

private static PUMLTopComponent instance;

public PUMLTopComponent() {
    initComponents();
    // your stuff
    instance = this;
}

public static PUMLTopComponent getInstance() {
    return instance;
}

Then in your action:

SwingUtilities.invokeLater(new Runnable(){
    @Override
    public void run() {
        PUMLTopComponent pumltc = PUMLTopComponent.getInstance();                
        pumltc.open();
        pumltc.requestActive(); //you might also need to call this
        pumltc.setNewContent(obj);
    }
});

This is how I personally do it and so far works great.

OTHER TIPS

The problem was the annotation on the TopComponent.

@ActionID(category = "Window", id = "org.netbeans.modules.plantumlnb.PUMLTopComponent")
@ActionReference(path = "Menu/Window" /*, position = 333 */)

I removed these annotations. I assume the annotation was instantiating a new TopComponent everytime and there was no way for me to tell the annotation to call the getInstance method instead of instantiating it everytime.

Then I implemented a custom action and then wired the action to call open on the topcomponent as shown below. This is what seems to have fixed the problem.

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.netbeans.modules.plantumlnb;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration;
import org.openide.util.NbBundle.Messages;

@ActionID(
        category = "Window",
        id = "org.netbeans.modules.plantumlnb.PUMLViewAction")
@ActionRegistration(
        iconBase = "org/netbeans/modules/plantumlnb/icon.png",
        displayName = "#CTL_PUMLViewAction")
@ActionReferences({
    @ActionReference(path = "Menu/Window/Other", position = 1050),
    @ActionReference(path = "Shortcuts", name = "DS-P"),
    @ActionReference(path = "Shortcuts", name = "DS-U")
})
@Messages("CTL_PUMLViewAction=Plant UML")
public final class PUMLViewAction implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        PUMLTopComponent pumlTopComponent = PUMLTopComponent.getInstance();
        pumlTopComponent.open();
    }
}

EDIT

Netbeans added support for singleton TopComponents in the first patch of Netbeans 7.3.

Support to Singleton TopComponents - @FactoryMethod

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top