Sean,
I'm sorry but I feel somewhat like talking to stones at the moment :-( I'm repeating myself over and over again but you just seem to ignore my argument that TreeNode is nothing more than a helper interface to support the Swing JTree component. Please have a look at the sources if you don't beleave me but JTree is operating on a TreeModel instance and TreeModel operates on any kind of objects not just TreeNode instances. JTree is not relying on the node objects implementing any specific interface, nowhere! The same is true for the current tree component. In my opinion TreeModel is the more flexible, lightweight and resource-saving approach and so far I did not get an idea what your argument is against TreeModel and for TreeNode. Your decision to force the user to implement TreeNode for all of his node objects is no improvement but a step backwards from my POV.
Sean Schofield wrote:
Exactly that's my argument: the TreeNodeBase instance is the extra object you force me to create!!! When implementing TreeModel there is no need for this extra object, I'm able to use just the 3rd party data objects, naked and unwrapped as I get the from the external library. I don't have to wrap them with DefaultMutableTreeNode or any other object.o) TreeNode instead of TreeModel
My argument here is that TreeModel in the way it is used by the current
tree component and in the way it is used by the Swing JTree is more
generic and lightweight than your approach using TreeNode. If you have a
look at the JTree sources you'll see that despite there are constructors
taking a TreeNode as their argument, internally JTree is operating on a
TreeModel. The TreeNode interface and DefaultTreeModel are just helpers
to make it easier for the user to create a TreeModel instance. You will
not find any reference to TreeNode in the JTree sources besides the
constructors which just take the node to build a DefaultTreeModel
instance used as the model.
If you look at the javadoc for the Swing TreeNode interface it states "Defines the requirements for an object that can be used as a tree node in a JTree." That's all I am using TreeNode for as well. You can't just add arbitrary data to the tree you need some kind of interface to guarantee certain functionality. Swing uses it and both of our trees use it.
The differences between our two TreeNode interfaces is very slight. Lets focus on that and not worry about what Swing is doing. What
Swing is doing is similar and serves as an example of how one might do
things but I think its a mistake for us to dwell on it too much at
this point.
And according the 3rd party library: I have a java library based on a
library of C functions which provides access to some kind of
hierarchical data I have to present in a tree. At the moment I have an
implementation of TreeModel (as used by the current tree component)
which uses named 3rd party lib to provide the tree with the data to
display. The implementation of TreeModel is straightforward as it's just
an adapter to the external API and uses/returns the objects it gets from
there. So far, so simple. Now consider your programming model where I
have to provide the tree with objects implementing the TreeNode
interface. As I have no access to the sources of named 3rd party library
I have to wrap the objects I get from the library with another object
implementing TreeNode to fulfill the contract. This makes the
implementation a little bit more complex and increases memory
consumption as I definitely would have to deal with two objects per node.
OK. You are adapting your third party data to TreeModel. This is where the *slight* code change comes into play. You need to change your adapter and adapt to a new interface.
Here is the difference as I see it. The new component has one
interface the user needs to worry about: TreeNode. The current one
has two: TreeNode and TreeModel. The tree.jsp example shows the
mapping of data to DefaultMutableTreeNode. In tree2.jsp the data is
put into TreeNodeBase. Please explain to me how this is substantially
different? Your third party data is not going to implement TreeNode. You must be putting it in DefaultMutableTreeNode or something
equivalent. So you put it in TreeNodeBase instead. You don't
need any extra objects in the new tree.
Now if TreeNodeBase is not doing it for you, then we can talk aboutAgain you seem to ignore my argument. I'm not talking about expanded/collapsed state but about SELECTED nodes. Take the tree example in the examples webapp. When you click the text of the root node it will get bold as the root node is the selected node now. Go on and expand some of the children and click the text of one of the child nodes: again the text will get bold to mark the selected node. At any time it is possible to ask the current tree for the path to the node currently selected. In tree2 the component itself does not care about that so I have to implement that feature on my own. It can be done using some specific command links and actions but I think to keep track of a selected node is a feature so common to tree components that is should be implemented there.
other implementations of TreeNode that could provide what you want. But I can't really see how you can say that the new approach requires
substantial code changes let alone more memory.
The current tree control (in tree.jsp) does one extra step that the
new tree control does not require. You need to create a
DefaultTreeModel using the DefaultMutableTreeNodes you just created. The new control does not require the user to do this. It does
something similar but behind the scenes. So if anything the new tree
component is simpler to configure your tree data.
o) node selection
The current tree keeps track of selected nodes as does Swing JTree and
there are events emitted when selection changes as there is a
possibility to register listeners interested in this kind of events. If
I did not miss something there is no such functionality in tree2. In
fact I do not have a proposal at the moment on how to implement it, but
that's an important feature from my POV and we should not tell the user
to find a way on his own on how to deal with that.
Tree2 is definitely keeping track of which nodes are open and closed. How else could it show the correct expand/collapse every time you
clicked a new node? Its just not doing it in the same way as the
current tree control.
As for the other aspect of this argument, you are correct that there is no special event for node selection. I studied what the current tree is doing in this regard and considered it to be unecessary. I am happy to debate that conclusion with you and I am willing to reconsider if you can demonstrate that its necessary.
Recall the two major usecases are client-side and server-side toggle. In client-side toggle the user may open and close numerous nodes
before ever submitting anything back to the server. In this case its
impossible to generate events every time a node opens and closes
because the expanding and collapsing is handled by the client. Also,
if you click a link in your tree that would navigate you to another
page, you don't even really care anymore.
The important thing is to know which nodes are open and which are closed. Whether or not a node was "selected" only really matters in that it helps us answer this question. (We're talking branch nodes, not leaf nodes here.) Do you agree with me on that point?
I've basically come up with a mechanism to maintain the
expand/collapse state without adding a new event. The actual clicking
on a leaf node can be handled by ActionEvent. So I've cut down on the
amount of code and relied on standard JSF functionality that the user
will be more familiar with.
Actually that's what I'm doing I suppose: to talk about features that are missing for tree2. But you have to be open for the fact that there are other scenarios and applications than the one you have in mind. I understand that your effort is driven by the requirements of the project you are currently working on. The current tree component has it's origin in a similar effort. To get a general-purpose tree component we have to address the issues I brought on the table. Otherwise we end up with two tree implementations which have something in common but miss some feature the other implementation has and vice versa. This can not be the goal if you ask me.
o) node rendering rules
In fact I had the first point in mind here: if the node objects do not
have to implement TreeNode then there is no way to use getType() to
decide which facet to use to render a node.
I can see this concern but I think we have a way around it. getType() is about the only new method to TreeNode interface that I am adding so lets explore what new requirements this would put on our legacy users. getType() is just to provide additional information to the renderer so you can customize rendering of the nodes based on the type of the node.
We *definitely* require this method. This gives you additional flexability to customize the look of your tree that you cannot do now. If you do not want to take advantage of this extra functionality then you can just pick an arbitrary string (say "default") and set this to be the type of all of your TreeNodes. You would do this as you adapt your data to TreeNode. No big deal really.
I would really like to reach closure on this soon. I think the new tree is quite powerful and useful and I have an immediate need for it in my current project at work. Also other users are reporting to me that they are using it in their own projects. It will be easier for all involved if we can stop using tree2 package refs in our code and start using tree.
I haven't really heard an objection that we cannot handle through the
existing code. If there is a use case for tree selection event then
we can look at adding that back in. But right now the new tree has a
lot of new functionaltiy with about 50% of the code base. I don't
think we should stop moving forward because its implemented
differently behind the scenes. In fact, the changes behind the scenes
are what result in less code to maintain.
Lets focus on what features are missing (I don't think there are any)
and what changes to the user's code are required (I think they are
small.)
Oliver
Oliver
sean
-- Oliver Rossmueller Software Engineer and IT-Consultant Hamburg, Germany http://www.rossmueller.com
