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.

 

Comments:

I think you want addNotify calling resultChanged(null), and resultChanged should call setKeys rather than addNotify. Then you also need no list field.

BTW better style:

result = Utilities.actionsGlobalContext().lookupResult(User.class);
// ...
for (User user : result.allInstances()) {...}

and Lookups.fixed() can be replaced by Lookup.EMPTY (or just not specified at all).

Posted by Jesse Glick on November 10, 2008 at 05:24 AM PST #

Thanks!!

Posted by Geertjan Wielenga on November 10, 2008 at 05:27 AM PST #

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 PropNode(key)};
}

private class PropNode extends AbstractNode {

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

}

Posted by Geertjan Wielenga on November 10, 2008 at 05:52 AM PST #

Above you can see I still have a List, hard to avoid that:

@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);
}

Posted by Geertjan Wielenga on November 10, 2008 at 05:54 AM PST #

Still searching for Demi Moore?

http://blogs.sun.com/geertjan/entry/find_demi_moore_in_netbeans

Ludo

Posted by Ludo on November 10, 2008 at 05:57 AM PST #

I said you would need to list field. You still need a list variable.

Posted by Jesse Glick on November 10, 2008 at 06:06 AM PST #

"need no list field" that is.

Posted by Jesse Glick on November 10, 2008 at 06:07 AM PST #

Hi,

I'm new in Netbean RCP programming, and i have a little question.

In my netbeans platform application, there is a toolbar button to open a popup using dialogDescriptor.
This popup allow user to authenticate themself. This popup is a Jpanel wich contains 2 jTextBox and 1 jButton. I set an Ation Listener wich execute the authentication, and build an application list owned y the user.

Next i have a TopCoponent using explorer API to show in a tree the user available applications.

i Use a class like "UserChildren extends Children.Keys<String> implements LookupListener"
to build my tree.

BUT ---

I dont know how i can share my application list from my Action to my topComponent. There is no way to use associateLookup(Lookups.Singleton(myApplicationList)) from my action like i did in a topcomponent, to register my collection in the global lookup, and then process the resultChanged of my children.key to build the tree.

Can you please give me soée advise

Thx

Mickael

Can y

Posted by miky on February 03, 2009 at 01:20 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
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
« April 2014
SunMonTueWedThuFriSat
  
12
13
14
23
24
25
26
27
28
29
30
   
       
Today