Once you realize that... the toolbar is a TopComponent, everything should be clear(er):
All the sample code for the above can be found here: http://kenai.com/projects/lookup-in-toolbar
Here are the highlights:
package org.demo.sample;
public class Person {
String name;
String city;
String country;
public String getCity() {return city;}
public void setCity(String city) {this.city = city;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public String getCountry() {return country;}
public void setCountry(String country) {this.country = country;}
}
public class EntryActionListener implements ActionListener, Presenter.Toolbar {
@Override
public void actionPerformed(ActionEvent e) {
//Nothing needs to happen here.
}
@Override
public Component getToolbarPresenter() {
return EntryTopComponent.findInstance();
}
}
...and then register it in the layer:
<folder name="Actions">
<folder name="File">
<file name="org-demo-sample-EntryActionListener.instance">
<attr name="delegate" newvalue="org.demo.sample.EntryActionListener"/>
</file>
</folder>
</folder>
<folder name="Toolbars">
<folder name="Person">
<file name="org-demo-sample-EntryActionListener.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-demo-sample-EntryActionListener.instance"/>
</file>
</folder>
</folder>
public class PersonChildFactory extends ChildFactory<Person> implements LookupListener {
private Result<Person> result;
private List<Person> persons;
public PersonChildFactory() {//Listen for Person objects in the EntryTopComponent's lookup:
result = WindowManager.getDefault().findTopComponent("EntryTopComponent").getLookup().lookupResult(Person.class);
result.addLookupListener(this);//Call once to 'resultChanged' to activate the listener:
resultChanged(new LookupEvent(result));
}//When there is a new Person object in the lookup of the EntryTopComponent,
//add that Person object to our list of Person objects,
//and then call 'refresh' to recreate the keys:
@Override
public void resultChanged(LookupEvent arg0) {
persons = new ArrayList();
Collection<? extends Person> coll = result.allInstances();
for (Person person : coll) {
persons.add(person);
}
refresh(true);
}//When the keys are created, iterate through the list of Person objects,
//creating a new person object for each instance,
//and then add each one to the list,
//which will trigger the 'createNodeForKey':
@Override
protected boolean createKeys(List<Person> list) {
if (!persons.isEmpty()) {
for (int i = 0; i < persons.size(); i++) {
Person person = new Person();
person.setName(persons.get(i).getName());
person.setCity(persons.get(i).getCity());
person.setCountry(persons.get(i).getCountry());
list.add(person);
}
} else {
Person person = new Person();
person.setName("<empty>");
person.setCity("<empty>");
person.setCountry("<empty>");
list.add(person);
}
return true;
}//Whenever a new Person object is added to the list above,
//create a new node:
@Override
protected Node createNodeForKey(Person person) {
return new PersonNode(person);
}//Use the values from the current Person object to define the node:
public class PersonNode extends AbstractNode {
private final Person person;
public PersonNode(Person person) {
super(Children.LEAF);
this.person = person;
setDisplayName(person.getName());
setShortDescription(person.getCity());
setIconBaseWithExtension("/org/demo/sample/resources/tv.gif");
}
@Override
public Action[] getActions(boolean context) {
return new Action[]{new ShowCountryAction(person)};
}//Double-clicking on the node will invoke this:
@Override
public Action getPreferredAction() {
return new ShowCountryAction(person);
}
public class ShowCountryAction extends AbstractAction {
private final Person person;
public ShowCountryAction(Person person) {
this.person = person;
putValue(Action.NAME,"Show Country");
}
@Override
public void actionPerformed(ActionEvent e) {
StatusDisplayer.getDefault().setStatusText(person.getCountry());
}
}
}
}
You're done. The question to ask is, of course, whether it makes sense to have a toolbar like this. Nevertheless, if needed, you can now see how to implement it.
Question:
How does "WindowManager.getDefault().findTopComponent("EntryTopComponent")" work?
Do you need to define the key "EntryTopComponent" somewhere (didn't find it in you code) or does it use some reflexion to discover the component based on its class?
"EntryTopComponent" is an ID generated in the TopComponent by the New Window Component wizard. (Since I didn't code it myself, I didn't mention it, because it was generated in the step where this TopComponent was generated.) It identifies the TopComponent to the WindowManager and is used by the WindowManager to find the TopComponent so that we can listen to its lookup.
Can I send you my questions to your Yahoo email account?
You can send your questions to dev@openide.netbeans.org where developers with far more knowledge than me are found.