Synchronizing an Editor Window with a Viewer Window

Now that we're able to open a TopComponent per Node, let's... synchronize back to the viewer window from the editor window.

Below you can see that right now there's a TopComponent open for each of the Nodes. However, wouldn't it be nice if selecting one of the open TopComponents would cause the related Node to automatically be selected? In other words, below I have clicked on the "professor" window, which automatically results in the "professor" node in the viewer window being highlighted:

How to achieve this? Via a very elegant NetBeans Platform mechanism.

  1. Create a "Synchronizable" Capability. Here it is, in the domain module:
    package org.person.domain.capabilities;
    import org.person.domain.Person;
    public interface Synchronizable {
        Person getPerson();
  2. Add an Implementation of the Capability to the Node Lookup. You can see that the Synchronizable capability has been added to the Lookup of the Node, in the Node constructor, as shown in the highlighted bit below:
    private PersonNode(final Person person, InstanceContent ic) throws IntrospectionException {
        super(person, Children.LEAF, new AbstractLookup(ic));
        ic.add(new Openable() {
            public void open() {
                TopComponent tc = findTopComponent(person);
                if (tc == null) {
                    tc = new PersonEditorTopComponent(person);
        ic.add(new Synchronizable() {
            public Person getPerson() {
                return person;

    Note: There's no 'naked' Person object in the Node Lookup, only a Person object wrapped in a capability. This way, you have more control over the Object; since various other parts of the application may (and currently are already) be listening/responding to Person objects, using a capability gives you a fresh access point to the Object.

  3. Retrieve the Capability from the Lookup in the Viewer. In the Viewer window, implement LookupListener, listen for the current Person object, and set the Node that has the same Person object in the Synchronizable in its Lookup to be the selected Node in the ExplorerManager:
    public void resultChanged(LookupEvent le) {
        Collection<? extends Person> p = personResult.allInstances();
        if (p.size() == 1) {
            Person currentPerson = p.iterator().next();
            for (Node node : em.getRootContext().getChildren().getNodes()) {
                if (node.getLookup().lookup(Synchronizable.class).getPerson() == currentPerson) {
                    try {
                        em.setSelectedNodes(new Node[]{node});
                    } catch (PropertyVetoException ex) {

And these are the three files created/changed during the above instructions:

Source code of the current state of the sample above:


When we were initially investigating using Nodes for our internal app, we looked at BeanNode. Unfortunately, one can't replace the object in BeanNode after instantiation.

Having a wrapper class such as the aforementioned Synchronizable/capability is a great workaround for BeanNode. One can add events (e.g. PropertyChangeSupport) to that wrapper class.

Posted by Derek Witt on March 08, 2013 at 01:03 PM PST #

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.


« July 2016