Jens Hofschröer, who has one of the very best NetBeans Platform blogs (if you more or less understand German), and who wrote, sometime ago, the initial version of the Import Statement Organizer, as well as being the main developer of a great gear design & manufacturing tool on the NetBeans Platform in Aachen, commented on my recent blog entry "Viewing the NetBeans Central Registry", where the root Node of the Central Registry is shown in a BeanTreeView, with the words:
"I wrapped that Node in a FilterNode to provide the 'position' attribute and the 'file extension'. All Children are wrapped too. Then I used an OutlineView to show these two properties. Great tool to find wrong layer entries."
I asked him for the code he describes above and he sent it to me. He discussed it here in his blog, while all the code involved can be read below.
The result is as follows, where you can see that the OutlineView shows information that my simple implementation (via a BeanTreeView) kept hidden:
And so here is the definition of the Node.
class LayerPropertiesNode extends FilterNode {
public LayerPropertiesNode(Node node) {
super(node, isFolder(node) ?
Children.create(new LayerPropertiesFactory(node), true) :
Children.LEAF);
}
private static boolean isFolder(Node node) {
return null != node.getLookup().lookup(DataFolder.class);
}
@Override
public String getDisplayName() {
return getLookup().lookup(FileObject.class).getName();
}
@Override
public Image getIcon(int type) {
FileObject fo = getLookup().lookup(FileObject.class);
try {
DataObject data = DataObject.find(fo);
return data.getNodeDelegate().getIcon(type);
} catch (DataObjectNotFoundException ex) {
Exceptions.printStackTrace(ex);
}
return super.getIcon(type);
}
@Override
public Image getOpenedIcon(int type) {
return getIcon(type);
}
@Override
public PropertySet[] getPropertySets() {
Set set = Sheet.createPropertiesSet();
set.put(new PropertySupport.ReadOnly<Integer>(
"position", Integer.class, "Position", null) {
@Override
public Integer getValue() throws IllegalAccessException,
InvocationTargetException {
FileObject fileEntry = getLookup().lookup(FileObject.class);
Integer posValue = (Integer) fileEntry.getAttribute("position");
return posValue != null ? posValue : Integer.valueOf(0);
}
});
set.put(new PropertySupport.ReadOnly<String>(
"ext", String.class, "Extension", null) {
@Override
public String getValue() throws IllegalAccessException,
InvocationTargetException {
FileObject fileEntry = getLookup().lookup(FileObject.class);
return fileEntry.getExt();
}
});
PropertySet[] original = super.getPropertySets();
PropertySet[] withLayer = new PropertySet[original.length + 1];
System.arraycopy(original, 0, withLayer, 0, original.length);
withLayer[withLayer.length - 1] = set;
return withLayer;
}
private static class LayerPropertiesFactory extends ChildFactory<FileObject> {
private final Node context;
public LayerPropertiesFactory(Node context) {
this.context = context;
}
@Override
protected boolean createKeys(List<FileObject> list) {
FileObject folder =
context.getLookup().lookup(FileObject.class);
FileObject[] children = folder.getChildren();
List<FileObject> ordered =
FileUtil.getOrder(Arrays.asList(children), false);
list.addAll(ordered);
return true;
}
@Override
protected Node createNodeForKey(FileObject key) {
AbstractNode node = new AbstractNode(org.openide.nodes.Children.LEAF,
key.isFolder()
? Lookups.fixed(key, DataFolder.findFolder(key))
: Lookups.singleton(key));
return new LayerPropertiesNode(node);
}
}
}
Then here is the definition of the Action, which pops up a JPanel, displaying an OutlineView:
@ActionID(category = "Tools",
id = "de.nigjo.nb.layerview.LayerViewAction")
@ActionRegistration(displayName = "#CTL_LayerViewAction")
@ActionReferences({
@ActionReference(path = "Menu/Tools", position = 1450, separatorBefore = 1425)
})
@Messages("CTL_LayerViewAction=Display XML Layer")
public final class LayerViewAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
try {
Node node = DataObject.find(FileUtil.getConfigRoot()).getNodeDelegate();
node = new LayerPropertiesNode(node);
node = new FilterNode(node) {
@Override
public Component getCustomizer() {
LayerView view = new LayerView();
view.getExplorerManager().setRootContext(this);
return view;
}
@Override
public boolean hasCustomizer() {
return true;
}
};
NodeOperation.getDefault().customize(node);
} catch (DataObjectNotFoundException ex) {
Exceptions.printStackTrace(ex);
}
}
private static class LayerView extends JPanel implements ExplorerManager.Provider {
private final ExplorerManager em;
public LayerView() {
super(new BorderLayout());
em = new ExplorerManager();
OutlineView view = new OutlineView("entry");
view.addPropertyColumn("position", "Position");
view.addPropertyColumn("ext", "Extension");
add(view);
}
@Override
public ExplorerManager getExplorerManager() {
return em;
}
}
}