X

Geertjan's Blog

  • November 10, 2008

LookupListener & Children.Keys

Geertjan Wielenga
Product Manager
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.


Join the discussion

Comments ( 8 )
  • Jesse Glick Monday, November 10, 2008

    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).


  • Geertjan Wielenga Monday, November 10, 2008

    Thanks!!


  • Geertjan Wielenga Monday, November 10, 2008

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

    }

    }

    }


  • Geertjan Wielenga Monday, November 10, 2008

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

    }


  • Ludo Monday, November 10, 2008
  • Jesse Glick Monday, November 10, 2008

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


  • Jesse Glick Monday, November 10, 2008

    "need no list field" that is.


  • miky Tuesday, February 3, 2009

    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


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha