Friday, August 14, 2009

Palette, ItemNode <-> DataNode

Following the (always) excellent blogs from Geertjan, I decided to leverage the Palette for some of my selections. See Palette Filter, Listen to Palette, Palette API and 6.0 Part 1, Part 2 and Part 3.

Now, I decided to have my palette instantiate its Items via a Node tree, so that those also could be represented at the same time via the Explorer Tree view. I created Nodes via the FileSystem as described in the "Rich Client Programming" book but initialize the PaletteController with the root Node instead of the root of the FileSytem representing the tree.

All happy. Now, of course I would like the user to be able to Edit the different Palette Items and followed Extend the Palette blog creating MyPalette and a CustomItermAction alla

public Action[] getCustomItemActions(Lookup lookup) {
Node itemNode = (Node)lookup.lookup( Node.class );
if( null != itemNode ) {
return new Action[] { new CustomizeItemAction( itemNode ) };
}
return null;
}

So far so good. The problem started when I tried to get hand on the underlying DataNode representing this Palette Item. In the implementation of my CustomizeItemAction I tried (naively) to cast the itemNode to a DataNode with the very unforgiving error

ClassCastException: Cannot cast org.netbeans.modules.palette.ItemNode to ... DataNode.

What the heck ? Could not even find any JavaDoc for org.netbeans.modules.palette.ItemNode. Well Google is your friend and after locating the source of ItemNode, I found that ItemNode is a FilterNode and hence of course I could not get hand on my DataNode, and the getOriginalNode() method in ItemNode was package protected - hmpf.

Solution: Lookup !

Lookup was very friendly. After adding the code

Collection c = item.lookupAll(Object.class); Iterator i = c.iterator(); while(i.hasNext()) { Object o = i.next(); System.out.println("o "+o); }

to check what is in the Lookup at the time of selection, I could see that the Lookup send to the Action did contain the instance of my DataObject represented by this Node. (Thank you !) Still, - trying to change the code from


public Action[] getCustomItemActions(Lookup lookup) {
Node itemNode = (Node)lookup.lookup( Node.class );
if( null != itemNode ) {
return new Action[] { new CustomizeItemAction( itemNode ) };
}
return null;
}


To

public Action[] getCustomItemActions(Lookup lookup) {
MyDataObject myDataObject = (MyDataObject)lookup.lookup( MyDataObject );
if( null != myDataObject ) {
return new Action[] { new CustomizeItemAction( myDataObject ) };
}
return null;
}

Did give me an annoying error in the Java Editor
inconvertable types
found: org.openide.util.Lookup.lookup
required: com.demo.MyDataObject

?!?! All looked normal - just replaced "Node" with "MyDataObject" ! After some strong coffee - the trivial solution was that my module having the action defined did not include the Datasystems API - and the reason it is triggering it is because the MyDataObject extends MultiDataObject living in the Datasystems API

So - finally, after some confusing hours I have a ItemAction which has hand on the DataObject representing the PaletteItem and can thereby get hand on the underlying FileObject and do whatever is needed.

... by the way .. it turned out to be a good idea to send down the PaletteController together with the Action to allow the code in the Action implementation to perform a refresh() on the Palette.

No comments:

Post a Comment