Monday Nov 10, 2008

LookupListener & Children.Keys

My first LookupListener on Children.Keys enables the two window components you see below to be decoupled from each other:

Whenever the Enter key is pressed in the editor component, a new instance of the API object is added to my InstanceContent, exactly as described in the first part of Tim's 'Selection Management' series. This component, the provider of the API object, is exposed via the META-INF/services folder.

Whenever the Children.Keys class (which is in a separate module) detects that a new API object is available in the global lookup, a new item is added to the list that is used to create the nodes in the hierarchy. Here's the Children.Keys with LookupListener:

public class UserChildren extends Children.Keys implements LookupListener {

    private Lookup.Result result = null;
    private ArrayList list = new ArrayList();

    public UserChildren() {
        Lookup.Template tpl = new Lookup.Template(User.class);
        result = Utilities.actionsGlobalContext().lookup(tpl);
        result.addLookupListener(this);
    }

    @Override
    public void resultChanged(LookupEvent lookupEvent) {
        Lookup.Result r = (Lookup.Result) lookupEvent.getSource();
        Collection c = r.allInstances();
        for (int i = 0; i < c.size(); i++) {
            User user = (User) c.iterator().next();
            list.add(new String(user.getName()));
        }
        //Call this to let the nodes be recreated
        //when the result changes:
        addNotify();
    }

    @Override
    protected void addNotify() {
        setKeys(list);
    }

    @Override
    protected Node[] createNodes(String key) {
        return new Node[]{new UserNode(key)};
    }

    private class UserNode extends AbstractNode {
        private UserNode(String key) {
            super(Children.LEAF, Lookups.fixed());
            setDisplayName(key);
        }
    }

}

In other words, the viewer component is populated on the fly, based on the name typed into the editor component. And if the editor component is replaced by a different editor component, the viewer component will be unaffected: so long as it receives implementations of the API object, it will function correctly regardless of the editor's implementation.

 

PS: After some code cleaning (see the comments below) the code above is now as follows:

public class UserChildren extends Children.Keys<String> implements LookupListener {

    private Lookup.Result result = null;

    public UserChildren() {
        result = Utilities.actionsGlobalContext().lookupResult(User.class);
        result.addLookupListener(this);
    }

    @Override
    public void resultChanged(LookupEvent lookupEvent) {
        ArrayList list = new ArrayList();
        Collection<User> c = result.allInstances();
        for (User user : c) {
            list.add(new String(user.getName()));
        }
        setKeys(list);
    }

    @Override
    protected void addNotify() {
        resultChanged(null);
    }

    @Override
    protected Node[] createNodes(String key) {
        return new Node[]{new UserNode(key)};
    }

    private class UserNode extends AbstractNode {

        private UserNode(String key) {
            super(Children.LEAF);
            setDisplayName(key);
        }

    }

}

In other news. DZone has a new Refcard... a cheat sheet for MySQL! Take a look. It's free.

 

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
« November 2008 »
SunMonTueWedThuFriSat
      
4
7
15
16
17
20
22
23
25
27
29
30
      
Today