You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by eh...@apache.org on 2007/04/13 00:59:06 UTC
svn commit: r528277 [1/5] - in /incubator/wicket/branches/wicket-1.x/jdk-1.4:
wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tree/
wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tree/res/
wicket-exten...
Author: ehillenius
Date: Thu Apr 12 15:59:03 2007
New Revision: 528277
URL: http://svn.apache.org/viewvc?view=rev&rev=528277
Log:
switch trees, part one
Added:
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/AbstractTree.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/SelectedPathReplacementModel.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree$DefaultNodePanel.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/TreeState.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/blank.gif (with props)
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/minus.gif (with props)
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/package.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/plus.gif (with props)
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/tree.css
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/AbstractTreePage.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/BorderedPage.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/MyTree.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/PageBorder.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/PageBorder.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePage.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePage.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageExpectedResult_1-1.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageExpectedResult_1.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageNoHtmlHead.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageNoHtmlHead.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageNoHtmlHeadExpectedResult_1-1.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageNoHtmlHeadExpectedResult_1.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageNoWicketHeadTag.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageNoWicketHeadTag.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageNoWicketHeadTagExpectedResult_1-1.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageNoWicketHeadTagExpectedResult_1.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageWithBorder.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageWithBorder.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageWithBorderExpectedResult_1-1.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreePageWithBorderExpectedResult_1.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/TreeTest.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/folder.gif (with props)
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/folderopen.gif (with props)
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/test/java/org/apache/wicket/markup/html/tree/node.gif (with props)
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/AbstractTree.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/DefaultAbstractTree.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/DefaultTreeState.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/ITreeState.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/ITreeStateListener.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/Tree.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/Tree.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/package.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/res/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/res/dotted-line.png (with props)
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/res/folder-closed.gif (with props)
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/res/folder-open.gif (with props)
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/res/item.gif (with props)
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/res/tree-images.png (with props)
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/res/tree-table.css
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/res/tree.css
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/res/tree.js
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/AbstractColumn.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/AbstractRenderableColumn.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/AbstractTreeColumn.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/ColumnLocation.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/IColumn.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/IRenderable.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/MiddleColumnsView.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/PropertyRenderableColumn.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/PropertyTreeColumn.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/SideColumnsView.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/TreeTable$TreeFragment.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/TreeTable.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/TreeTable.java
Removed:
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tree/AbstractTree.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tree/DefaultAbstractTree.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tree/DefaultTreeState.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tree/ITreeState.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tree/ITreeStateListener.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tree/Tree.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tree/Tree.java
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tree/package.html
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tree/res/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/tree/table/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/main/java/org/apache/wicket/markup/html/tree/
incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket/src/test/java/org/apache/wicket/markup/html/tree/
Added: incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/AbstractTree.java
URL: http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/AbstractTree.java?view=auto&rev=528277
==============================================================================
--- incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/AbstractTree.java (added)
+++ incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/AbstractTree.java Thu Apr 12 15:59:03 2007
@@ -0,0 +1,398 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.markup.html.tree;
+
+import java.util.Enumeration;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeSelectionModel;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeSelectionModel;
+
+import org.apache.wicket.markup.html.panel.Panel;
+
+
+/**
+ * Base component for trees. The trees from this package work with the Swing
+ * tree models and {@link javax.swing.tree.DefaultMutableTreeNode}s. Hence,
+ * users can re-use their Swing tree models.
+ *
+ * @author Eelco Hillenius
+ */
+public abstract class AbstractTree extends Panel
+{
+ /** AbstractTree state for this component. */
+ private TreeState treeState;
+
+ /**
+ * Construct using the given model as the tree model to use. A new tree
+ * state will be constructed by calling newTreeState.
+ *
+ * @param id
+ * The id of this component
+ * @param model
+ * the underlying tree model
+ */
+ public AbstractTree(final String id, final TreeModel model)
+ {
+ super(id);
+ this.treeState = newTreeState(model);
+ }
+
+ /**
+ * Construct using the given tree state that holds the model to be used as
+ * the tree model.
+ *
+ * @param id
+ * The id of this component
+ * @param treeState
+ * treeState that holds the underlying tree model
+ */
+ public AbstractTree(final String id, final TreeState treeState)
+ {
+ super(id);
+ this.treeState = treeState;
+ }
+
+ /**
+ * Ensures that the node identified by the specified path is collapsed and
+ * viewable.
+ *
+ * @param path
+ * the <code>TreePath</code> identifying a node
+ */
+ public void collapsePath(TreePath path)
+ {
+ setExpandedState(path, false);
+ }
+
+ /**
+ * Collapses all the siblings of a given node.
+ *
+ * @param node
+ * The node of which to collapse the siblings.
+ */
+ public void collapseSiblings(final DefaultMutableTreeNode node)
+ {
+ // Collapse all previous siblings
+ DefaultMutableTreeNode previousNode = node.getPreviousSibling();
+ while (null != previousNode)
+ {
+ final TreePath siblingSelection = new TreePath(previousNode.getPath());
+ setExpandedState(siblingSelection, false); // inverse
+ previousNode = previousNode.getPreviousSibling();
+ }
+ // Collapse all following siblings
+ DefaultMutableTreeNode nextNode = node.getNextSibling();
+ while (null != nextNode)
+ {
+ final TreePath siblingSelection = new TreePath(nextNode.getPath());
+ setExpandedState(siblingSelection, false); // inverse
+ // ToDo: Check if previousNode can be null? If so, needs trapping - Gwyn
+ nextNode = previousNode.getNextSibling();
+ }
+ }
+
+ /**
+ * Expand or collapse all nodes.
+ *
+ * @param expand
+ * If true, expand all nodes in the tree. Else collapse all nodes
+ * in the tree.
+ */
+ public void expandAll(boolean expand)
+ {
+ TreeNode root = (TreeNode)getTreeState().getModel().getRoot();
+ expandAll(new TreePath(root), expand);
+ }
+
+ /**
+ * Ensures that the node identified by the specified path is expanded and
+ * viewable. If the last item in the path is a leaf, this will have no
+ * effect.
+ *
+ * @param path
+ * the <code>TreePath</code> identifying a node
+ */
+ public void expandPath(TreePath path)
+ {
+ // Only expand if not leaf!
+ TreeModel model = getTreeState().getModel();
+
+ if (path != null && model != null && !model.isLeaf(path.getLastPathComponent()))
+ {
+ setExpandedState(path, true);
+ }
+ }
+
+ /**
+ * Gets the current tree state.
+ *
+ * @return the tree current tree state
+ */
+ public final TreeState getTreeState()
+ {
+ return treeState;
+ }
+
+ /**
+ * Convenience method that determines whether the path of the given tree
+ * node is expanded in this tree's state.
+ *
+ * @param node
+ * the tree node
+ * @return whether the path of the given tree node is expanded
+ */
+ public final boolean isExpanded(DefaultMutableTreeNode node)
+ {
+ return isExpanded(new TreePath(node.getPath()));
+ }
+
+ /**
+ * Convenience method that determines whether the given path is expanded in
+ * this tree's state.
+ *
+ * @param path
+ * the tree path
+ * @return whether the given path is expanded
+ */
+ public final boolean isExpanded(TreePath path)
+ {
+ return treeState.isExpanded(path);
+ }
+
+ /**
+ * Gets whether the tree root node should be displayed.
+ *
+ * @return whether the tree root node should be displayed
+ */
+ public final boolean isRootVisible()
+ {
+ return treeState.isRootVisible();
+ }
+
+ /**
+ * Returns true if the value identified by path is currently viewable, which
+ * means it is either the root or all of its parents are expanded.
+ * Otherwise, this method returns false.
+ *
+ * @param path
+ * The path
+ *
+ * @return true if the node is viewable, otherwise false
+ */
+ public final boolean isVisible(TreePath path)
+ {
+ if (path != null)
+ {
+ TreePath parentPath = path.getParentPath();
+
+ if (parentPath != null)
+ return isExpanded(parentPath);
+ // Root.
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Creates a new tree state by creating a new {@link TreeState}object,
+ * which is then set as the current tree state, creating a new
+ * {@link TreeSelectionModel}and then calling setTreeModel with this
+ *
+ * @param model
+ * the model that the new tree state applies to
+ * @return the tree state
+ */
+ public TreeState newTreeState(final TreeModel model)
+ {
+ return newTreeState(model, true);
+ }
+
+ /**
+ * Sets the new expanded state, based on the given node
+ *
+ * @param node
+ * the tree node model
+ */
+ public void setExpandedState(final DefaultMutableTreeNode node)
+ {
+ final TreePath selection = new TreePath(node.getPath());
+ setExpandedState(selection, (!treeState.isExpanded(selection))); // inverse
+
+ // If set to SINGLE_TREE_SELECTION, collapse all sibling nodes
+ final int selectionType = getTreeState().getSelectionModel().getSelectionMode();
+ if (TreeSelectionModel.SINGLE_TREE_SELECTION == selectionType)
+ {
+ collapseSiblings(node);
+ }
+ }
+
+ /**
+ * Sets the expanded property in the stree state for selection.
+ *
+ * @param selection
+ * the selection to set the expanded property for
+ * @param expanded
+ * true if the selection is expanded, false otherwise
+ */
+ public void setExpandedState(final TreePath selection, final boolean expanded)
+ {
+ treeState.setExpandedState(selection, expanded);
+ }
+
+ /**
+ * Sets whether the tree root node should be displayed.
+ *
+ * @param rootVisible
+ * whether the tree node should be displayed
+ */
+ public void setRootVisible(final boolean rootVisible)
+ {
+ treeState.setRootVisible(rootVisible);
+ }
+
+ /**
+ * Sets the new expanded state (to true), based on the given user node and
+ * set the tree path to the currently selected.
+ *
+ * @param node
+ * the tree node model
+ */
+ public void setSelected(final DefaultMutableTreeNode node)
+ {
+ final TreePath selection = new TreePath(node.getPath());
+ treeState.setSelectedPath(selection);
+ setExpandedState(selection, true);
+ }
+
+ /**
+ * Sets the current tree model.
+ *
+ * @param treeModel
+ * the tree model to set as the current one
+ */
+ public void setTreeModel(final TreeModel treeModel)
+ {
+ this.treeState = newTreeState(treeModel);
+ }
+
+ /**
+ * Sets the current tree state to the given tree state.
+ *
+ * @param treeState
+ * the tree state to set as the current one
+ */
+ public void setTreeState(final TreeState treeState)
+ {
+ this.treeState = treeState;
+ }
+
+ /**
+ * Gives the current tree model as a string.
+ *
+ * @return the current tree model as a string
+ */
+ public String toString()
+ {
+ StringBuffer b = new StringBuffer("-- TREE MODEL --\n");
+ TreeState state = getTreeState();
+ TreeModel treeModel = null;
+ if (state != null)
+ {
+ treeModel = state.getModel();
+ }
+ if (treeModel != null)
+ {
+ StringBuffer tabs = new StringBuffer();
+ DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)treeModel.getRoot();
+ Enumeration e = rootNode.preorderEnumeration();
+ while (e.hasMoreElements())
+ {
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode)e.nextElement();
+ tabs.delete(0, tabs.length());
+ tabs.append("|");
+ for (int i = 0; i < node.getLevel(); i++)
+ {
+ tabs.append("-");
+ }
+ b.append(tabs).append(node).append("\n");
+ }
+ }
+ else
+ {
+ b.append("<EMPTY>");
+ }
+ return b.toString();
+ }
+
+ /**
+ * Creates a new tree state by creating a new {@link TreeState}object,
+ * which is then set as the current tree state, creating a new
+ * {@link TreeSelectionModel}and then calling setTreeModel with this
+ *
+ * @param treeModel
+ * the model that the new tree state applies to
+ * @param rootVisible
+ * whether the tree node should be displayed
+ * @return the tree state
+ */
+ protected final TreeState newTreeState(final TreeModel treeModel, final boolean rootVisible)
+ {
+ final TreeState treeState = new TreeState();
+ final TreeSelectionModel treeSelectionModel = new DefaultTreeSelectionModel();
+ treeSelectionModel.setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
+ treeState.setModel(treeModel);
+ treeState.setSelectionModel(treeSelectionModel);
+ treeState.setRootVisible(rootVisible);
+ treeModel.addTreeModelListener(treeState);
+ return treeState;
+ }
+
+ /**
+ * Expand recursively.
+ *
+ * @param parent
+ * The current parent node
+ * @param expand
+ * Whether to expand or to collapse
+ */
+ private final void expandAll(TreePath parent, boolean expand)
+ {
+ TreeNode node = (TreeNode)parent.getLastPathComponent();
+ if (node.getChildCount() >= 0)
+ {
+ for (Enumeration e = node.children(); e.hasMoreElements();)
+ {
+ TreeNode n = (TreeNode)e.nextElement();
+ TreePath path = parent.pathByAddingChild(n);
+ expandAll(path, expand);
+ }
+ }
+
+ if (expand)
+ {
+ expandPath(parent);
+ }
+ else
+ {
+ collapsePath(parent);
+ }
+ }
+}
Added: incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/SelectedPathReplacementModel.java
URL: http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/SelectedPathReplacementModel.java?view=auto&rev=528277
==============================================================================
--- incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/SelectedPathReplacementModel.java (added)
+++ incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/SelectedPathReplacementModel.java Thu Apr 12 15:59:03 2007
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.markup.html.tree;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreePath;
+
+import org.apache.wicket.model.AbstractReadOnlyModel;
+
+
+/**
+ * Replacement model that looks up whether the current row is the active one.
+ *
+ * @author Eelco Hillenius
+ */
+public final class SelectedPathReplacementModel extends AbstractReadOnlyModel
+{
+ private static final long serialVersionUID = 1L;
+
+ /** the tree node. */
+ private final DefaultMutableTreeNode node;
+
+ /** The tree. */
+ private final Tree tree;
+
+ /**
+ * Construct.
+ *
+ * @param tree
+ * The tree
+ *
+ * @param node
+ * The tree node
+ */
+ public SelectedPathReplacementModel(Tree tree, DefaultMutableTreeNode node)
+ {
+ this.node = node;
+ this.tree = tree;
+ }
+
+ /**
+ * @see org.apache.wicket.model.IModel#getObject()
+ */
+ public Object getObject()
+ {
+ TreePath path = new TreePath(node.getPath());
+ TreePath selectedPath = tree.getTreeState().getSelectedPath();
+ if (selectedPath != null)
+ {
+ boolean equals = tree.equals(path, selectedPath);
+
+ if (equals)
+ {
+ return "treerow-selected";
+ }
+ }
+ return "treerow";
+ }
+}
\ No newline at end of file
Added: incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree$DefaultNodePanel.html
URL: http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree%24DefaultNodePanel.html?view=auto&rev=528277
==============================================================================
--- incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree$DefaultNodePanel.html (added)
+++ incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree$DefaultNodePanel.html Thu Apr 12 15:59:03 2007
@@ -0,0 +1,23 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<wicket:panel>
+<a href="#" wicket:id="junctionLink" class="wicket-indent-tree-junctionlink"
+ ><img wicket:id="junctionImage" class="wicket-indent-tree-junctionimage"/></a>
+<a href="#" wicket:id="nodeLink" class="wicket-indent-tree-nodelink"
+ ><img wicket:id="nodeImage" class="wicket-indent-tree-nodeimage"/><span
+ wicket:id="label" class="wicket-indent-tree-nodelabel">label</span></a>
+</wicket:panel>
Added: incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree.html
URL: http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree.html?view=auto&rev=528277
==============================================================================
--- incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree.html (added)
+++ incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree.html Thu Apr 12 15:59:03 2007
@@ -0,0 +1,24 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<wicket:panel>
+<span class="wicket-indent-tree">
+<span wicket:id="tree" class="wicket-indent-tree-row">
+ <span wicket:id="spacers" class="wicket-indent-tree-spacer"></span>
+ <span wicket:id="node" class="wicket-indent-tree-node"></span>
+ </span>
+</span>
+</wicket:panel>
Added: incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree.java
URL: http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree.java?view=auto&rev=528277
==============================================================================
--- incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree.java (added)
+++ incubator/wicket/branches/wicket-1.x/jdk-1.4/wicket-extensions/src/main/java/org/apache/wicket/markup/html/tree/Tree.java Thu Apr 12 15:59:03 2007
@@ -0,0 +1,756 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.markup.html.tree;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+
+import org.apache.wicket.AttributeModifier;
+import org.apache.wicket.Component;
+import org.apache.wicket.ResourceReference;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.behavior.HeaderContributor;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.image.Image;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.list.Loop;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.markup.html.resources.CompressedResourceReference;
+import org.apache.wicket.model.IModel;
+
+
+/**
+ * An tree that renders as a flat (not-nested) list, using spacers for
+ * indentation and nodes at the end of one row.
+ * <p>
+ * The visible tree rows are put in one flat list. For each row, a list is
+ * constructed with fillers, that can be used to create indentation. After the
+ * fillers, the actual node content is put.
+ * </p>
+ * <p>
+ * </p>
+ *
+ * @author Eelco Hillenius
+ */
+public class Tree extends AbstractTree implements TreeModelListener
+{
+ /**
+ * The default node panel. If you provide your own panel by overriding
+ * Tree.newNodePanel, but only want to override the markup, not the
+ * components that are added, you <i>may</i> extend this class. If you want
+ * to use other components than the default, provide a panel or fragment
+ * instead (and that's probably what you want as the look and feel of what
+ * this panel renders may be adjusted by overriding
+ * {@link Tree#createJunctionLink(DefaultMutableTreeNode)} and
+ * {@link Tree#createNodeLink(DefaultMutableTreeNode)}.
+ */
+ public static class DefaultNodePanel extends Panel
+ {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Construct.
+ *
+ * @param panelId
+ * The component id
+ * @param tree
+ * The containing tree component
+ * @param node
+ * The tree node for this panel
+ */
+ public DefaultNodePanel(String panelId, Tree tree, DefaultMutableTreeNode node)
+ {
+ super(panelId);
+ // create a link for expanding and collapsing the node
+ Link expandCollapsLink = tree.createJunctionLink(node);
+ add(expandCollapsLink);
+ // create a link for selecting a node
+ Link selectLink = tree.createNodeLink(node);
+ add(selectLink);
+ }
+ }
+
+ /**
+ * Renders spacer items.
+ */
+ private static final class SpacerList extends Loop
+ {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Construct.
+ *
+ * @param id
+ * component id
+ * @param size
+ * size of loop
+ */
+ public SpacerList(String id, int size)
+ {
+ super(id, size);
+ }
+
+ /**
+ * @see org.apache.wicket.markup.html.list.Loop#populateItem(LoopItem)
+ */
+ protected void populateItem(final Loop.LoopItem loopItem)
+ {
+ // nothing needed; we just render the tags and use CSS to indent
+ }
+ }
+
+ /**
+ * List view for tree paths.
+ */
+ private final class TreePathsListView extends ListView
+ {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Construct.
+ *
+ * @param name
+ * name of the component
+ */
+ public TreePathsListView(String name)
+ {
+ super(name, treePathsModel);
+ }
+
+ /**
+ * @see org.apache.wicket.markup.html.list.ListView#getReuseItems()
+ */
+ public boolean getReuseItems()
+ {
+ return Tree.this.getOptimizeItemRemoval();
+ }
+
+ /**
+ * @see org.apache.wicket.markup.html.list.ListView#newItem(int)
+ */
+ protected ListItem newItem(final int index)
+ {
+ IModel listItemModel = getListItemModel(getModel(), index);
+
+ // create a list item that is smart enough to determine whether
+ // it should be displayed or not
+ return new ListItem(index, listItemModel)
+ {
+ private static final long serialVersionUID = 1L;
+
+ public boolean isVisible()
+ {
+ TreeState treeState = getTreeState();
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode)getModelObject();
+ final TreePath path = new TreePath(node.getPath());
+ final int row = treeState.getRowForPath(path);
+
+ // if the row is -1, it is not visible, otherwise it is
+ return (row != -1);
+ }
+ };
+ }
+
+ /**
+ * @see org.apache.wicket.markup.html.list.ListView#populateItem(org.apache.wicket.markup.html.list.ListItem)
+ */
+ protected void populateItem(ListItem listItem)
+ {
+ // get the model object which is a tree node
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode)listItem.getModelObject();
+
+ // add spacers
+ int level = node.getLevel();
+ listItem.add(new SpacerList("spacers", level));
+
+ // add node panel
+ Component nodePanel = newNodePanel("node", node);
+ if (nodePanel == null)
+ {
+ throw new WicketRuntimeException("node panel must be not-null");
+ }
+ if (!"node".equals(nodePanel.getId()))
+ {
+ throw new WicketRuntimeException("panel must have id 'node' assigned");
+ }
+
+ listItem.add(nodePanel);
+
+ // add attr modifier for highlighting the selection
+ listItem.add(new AttributeModifier("class", true, new SelectedPathReplacementModel(
+ Tree.this, node)));
+ }
+ }
+
+ /**
+ * Model for the paths of the tree.
+ */
+ private final class TreePathsModel implements IModel
+ {
+ private static final long serialVersionUID = 1L;
+
+ /** whether this model is dirty. */
+ boolean dirty = true;
+
+ /** tree paths. */
+ private List paths = new ArrayList();
+
+ private transient boolean attached = false;
+
+ /**
+ * Inserts the given node in the path list with the given index.
+ *
+ * @param index
+ * the index where the node should be inserted in
+ * @param node
+ * node to insert
+ */
+ void add(int index, DefaultMutableTreeNode node)
+ {
+ paths.add(index, node);
+ }
+
+ /**
+ * Gives the index of the given node withing this tree.
+ *
+ * @param node
+ * node to look for
+ * @return the index of the given node withing this tree
+ */
+ int indexOf(DefaultMutableTreeNode node)
+ {
+ return paths.indexOf(node);
+ }
+
+ /**
+ * Removes the given node from the path list.
+ *
+ * @param node
+ * the node to remove
+ */
+ void remove(DefaultMutableTreeNode node)
+ {
+ paths.remove(node);
+ }
+
+
+ public Object getObject()
+ {
+ if (dirty && !attached)
+ {
+ paths.clear();
+ TreeModel model = getTreeState().getModel();
+ DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)model.getRoot();
+ Enumeration e = rootNode.preorderEnumeration();
+ while (e.hasMoreElements())
+ {
+ DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)e.nextElement();
+ // TreePath path = new TreePath(treeNode.getPath());
+ paths.add(treeNode);
+ }
+ dirty = false;
+ }
+ attached = true;
+ return paths;
+ }
+
+ public void setObject(Object object)
+ {
+ throw new UnsupportedOperationException("This is a read-only model");
+ }
+
+ public void detach()
+ {
+ attached = false;
+ }
+ }
+
+ /** Name of the junction image component; value = 'junctionImage'. */
+ public static final String JUNCTION_IMAGE_NAME = "junctionImage";
+
+ /** Name of the node image component; value = 'nodeImage'. */
+ public static final String NODE_IMAGE_NAME = "nodeImage";
+
+ /** Blank image. */
+ private static final ResourceReference BLANK = new ResourceReference(Tree.class, "blank.gif");
+
+ /**
+ * Reference to the css file.
+ */
+ private static final ResourceReference CSS = new CompressedResourceReference(Tree.class,
+ "tree.css");
+
+ /** Minus sign image. */
+ private static final ResourceReference MINUS = new ResourceReference(Tree.class, "minus.gif");
+
+ /** Plus sign image. */
+ private static final ResourceReference PLUS = new ResourceReference(Tree.class, "plus.gif");
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * If true, re-rendering the tree is more efficient if the tree model
+ * doesn't get changed. However, if this is true, you need to push changes
+ * to this tree. This can easility be done by registering this tree as the
+ * listener for tree model events (TreeModelListener), but you should <b>be
+ * carefull</b> not to create a memory leak by doing this (e.g. when you
+ * store the tree model in your session, the tree you registered cannot be
+ * GC-ed). TRUE by default.
+ */
+ private boolean reuseItems = true;
+
+ /** List view for tree paths. */
+ private TreePathsListView treePathsListView;
+
+ /** Model for the paths of the tree. */
+ private TreePathsModel treePathsModel;
+
+ /**
+ * Constructor.
+ *
+ * @param id
+ * The id of this container
+ * @param model
+ * the underlying tree model
+ */
+ public Tree(final String id, final TreeModel model)
+ {
+ super(id, model);
+ this.treePathsModel = new TreePathsModel();
+ add(treePathsListView = createTreePathsListView());
+
+ ResourceReference css = getCss();
+ add(HeaderContributor.forCss(css.getScope(), css.getName()));
+ }
+
+ /**
+ * Construct using the given tree state that holds the model to be used as
+ * the tree model.
+ *
+ * @param id
+ * The id of this container
+ * @param treeState
+ * treeState that holds the underlying tree model
+ */
+ public Tree(String id, TreeState treeState)
+ {
+ super(id, treeState);
+ this.treePathsModel = new TreePathsModel();
+ add(treePathsListView = createTreePathsListView());
+
+ ResourceReference css = getCss();
+ add(HeaderContributor.forCss(css.getScope(), css.getName()));
+ }
+
+ /**
+ * Gets whether item removal should be optimized. If true, re-rendering the
+ * tree is more efficient if the tree model doesn't get changed. However, if
+ * this is true, you need to push changes to this tree. This can easility be
+ * done by registering this tree as the listener for tree model events
+ * (TreeModelListener), but you should <b>be carefull</b> not to create a
+ * memory leak by doing this (e.g. when you store the tree model in your
+ * session, the tree you registered cannot be GC-ed). TRUE by default.
+ *
+ * @return whether item removal should be optimized
+ * @deprecated Will be replaced by {@link #getReuseItems()}
+ */
+ // TODO Post 1.2: Remove
+ public boolean getOptimizeItemRemoval()
+ {
+ return getReuseItems();
+ }
+
+ /**
+ * Gets whether items should be reused. If true, re-rendering the tree is
+ * more efficient if the tree model doesn't get changed. However, if this is
+ * true, you need to push changes to this tree. This can easility be done by
+ * registering this tree as the listener for tree model events
+ * (TreeModelListener), but you should <b>be carefull</b> not to create a
+ * memory leak by doing this (e.g. when you store the tree model in your
+ * session, the tree you registered cannot be GC-ed). TRUE by default.
+ *
+ * @return whether items should be reused
+ */
+ public boolean getReuseItems()
+ {
+ return reuseItems;
+ }
+
+ /**
+ * Sets whether items should be reused. If true, re-rendering the tree is
+ * more efficient if the tree model doesn't get changed. However, if this is
+ * true, you need to push changes to this tree. This can easility be done by
+ * registering this tree as the listener for tree model events
+ * (TreeModelListener), but you should <b>be carefull</b> not to create a
+ * memory leak by doing this (e.g. when you store the tree model in your
+ * session, the tree you registered cannot be GC-ed). TRUE by default.
+ *
+ * @param optimizeItemRemoval
+ * whether the child items should be reused
+ * @deprecated Will be replaced by {@link #setReuseItems(boolean)}
+ */
+ // TODO Post 1.2: Remove
+ public void setOptimizeItemRemoval(boolean optimizeItemRemoval)
+ {
+ setReuseItems(optimizeItemRemoval);
+ }
+
+ /**
+ * Sets whether item removal should be optimized. If true, re-rendering the
+ * tree is more efficient if the tree model doesn't get changed. However, if
+ * this is true, you need to push changes to this tree. This can easility be
+ * done by registering this tree as the listener for tree model events
+ * (TreeModelListener), but you should <b>be carefull</b> not to create a
+ * memory leak by doing this (e.g. when you store the tree model in your
+ * session, the tree you registered cannot be GC-ed). TRUE by default.
+ *
+ * @param reuseItems
+ * whether the child items should be reused
+ * @return This
+ */
+ public Tree setReuseItems(boolean reuseItems)
+ {
+ this.reuseItems = reuseItems;
+ return this;
+ }
+
+ /**
+ * Sets the current tree model.
+ *
+ * @param treeModel
+ * the tree model to set as the current one
+ */
+ public void setTreeModel(final TreeModel treeModel)
+ {
+ super.setTreeModel(treeModel);
+ this.treePathsModel = new TreePathsModel();
+ treePathsListView = createTreePathsListView();
+ replace(treePathsListView);
+ }
+
+ /**
+ * Sets the current tree state to the given tree state.
+ *
+ * @param treeState
+ * the tree state to set as the current one
+ */
+ public void setTreeState(final TreeState treeState)
+ {
+ super.setTreeState(treeState);
+ this.treePathsModel = new TreePathsModel();
+ treePathsListView = createTreePathsListView();
+ replace(treePathsListView);
+ }
+
+ /**
+ * @see javax.swing.event.TreeModelListener#treeNodesChanged(javax.swing.event.TreeModelEvent)
+ */
+ public void treeNodesChanged(TreeModelEvent e)
+ {
+ // nothing to do here
+ }
+
+ /**
+ * @see javax.swing.event.TreeModelListener#treeNodesInserted(javax.swing.event.TreeModelEvent)
+ */
+ public void treeNodesInserted(TreeModelEvent e)
+ {
+ modelChanging();
+ Object[] newNodes = e.getChildren();
+ int len = newNodes.length;
+ for (int i = 0; i < len; i++)
+ {
+ DefaultMutableTreeNode newNode = (DefaultMutableTreeNode)newNodes[i];
+ DefaultMutableTreeNode previousNode = newNode.getPreviousSibling();
+ int insertRow;
+ if (previousNode == null)
+ {
+ previousNode = (DefaultMutableTreeNode)newNode.getParent();
+ }
+ if (previousNode != null)
+ {
+ insertRow = treePathsModel.indexOf(previousNode) + 1;
+ if (insertRow == -1)
+ {
+ throw new IllegalStateException("node " + previousNode
+ + " not found in backing list");
+ }
+ }
+ else
+ {
+ insertRow = 0;
+ }
+ treePathsModel.add(insertRow, newNode);
+ }
+ modelChanged();
+ }
+
+ /**
+ * @see javax.swing.event.TreeModelListener#treeNodesRemoved(javax.swing.event.TreeModelEvent)
+ */
+ public void treeNodesRemoved(TreeModelEvent e)
+ {
+ modelChanging();
+ Object[] deletedNodes = e.getChildren();
+ int len = deletedNodes.length;
+ for (int i = 0; i < len; i++)
+ {
+ DefaultMutableTreeNode deletedNode = (DefaultMutableTreeNode)deletedNodes[i];
+ treePathsModel.remove(deletedNode);
+ }
+ modelChanged();
+ }
+
+ /**
+ * @see javax.swing.event.TreeModelListener#treeStructureChanged(javax.swing.event.TreeModelEvent)
+ */
+ public void treeStructureChanged(TreeModelEvent e)
+ {
+ treePathsModel.dirty = true;
+ modelChanged();
+ }
+
+ /**
+ * Creates a junction link.
+ *
+ * @param node
+ * the node
+ * @return link for expanding/ collapsing the tree
+ */
+ protected Link createJunctionLink(final DefaultMutableTreeNode node)
+ {
+ final Link junctionLink = new Link("junctionLink")
+ {
+ private static final long serialVersionUID = 1L;
+
+ public void onClick()
+ {
+ junctionLinkClicked(node);
+ }
+ };
+ junctionLink.add(getJunctionImage(node));
+ return junctionLink;
+ }
+
+ /**
+ * Creates a node link.
+ *
+ * @param node
+ * the model of the node
+ * @return link for selection
+ */
+ protected Link createNodeLink(final DefaultMutableTreeNode node)
+ {
+ final Link nodeLink = new Link("nodeLink")
+ {
+ private static final long serialVersionUID = 1L;
+
+ public void onClick()
+ {
+ nodeLinkClicked(node);
+ }
+ };
+ nodeLink.add(getNodeImage(node));
+ nodeLink.add(new Label("label", getNodeLabel(node)));
+ return nodeLink;
+ }
+
+ /**
+ * Creates the tree paths list view.
+ *
+ * @return the tree paths list view
+ */
+ protected final TreePathsListView createTreePathsListView()
+ {
+ final TreePathsListView treePaths = new TreePathsListView("tree");
+ return treePaths;
+ }
+
+ /**
+ * Returns whether the path and the selected path are equal. This method is
+ * used by the {@link AttributeModifier}that is used for setting the CSS
+ * class for the selected row.
+ *
+ * @param path
+ * the path
+ * @param selectedPath
+ * the selected path
+ * @return true if the path and the selected are equal, false otherwise
+ */
+ protected boolean equals(final TreePath path, final TreePath selectedPath)
+ {
+ Object pathNode = path.getLastPathComponent();
+ Object selectedPathNode = selectedPath.getLastPathComponent();
+ return (pathNode != null && selectedPathNode != null && pathNode.equals(selectedPathNode));
+ }
+
+ /**
+ * Gets the stylesheet.
+ *
+ * @return the stylesheet
+ */
+ protected ResourceReference getCss()
+ {
+ return CSS;
+ }
+
+ /**
+ * Get image for a junction; used by method createExpandCollapseLink. If you
+ * use the packaged panel (Tree.html), you must name the component using
+ * JUNCTION_IMAGE_NAME.
+ *
+ * @param node
+ * the tree node
+ * @return the image for the junction
+ */
+ protected Image getJunctionImage(final DefaultMutableTreeNode node)
+ {
+ if (!node.isLeaf())
+ {
+ // we want the image to be dynamically, yet resolving to a static
+ // image.
+ return new Image(JUNCTION_IMAGE_NAME)
+ {
+ private static final long serialVersionUID = 1L;
+
+ protected ResourceReference getImageResourceReference()
+ {
+ if (isExpanded(node))
+ {
+ return MINUS;
+ }
+ else
+ {
+ return PLUS;
+ }
+ }
+ };
+ }
+ else
+ {
+ return new Image(JUNCTION_IMAGE_NAME, BLANK);
+ }
+ }
+
+ /**
+ * Get image for a node; used by method createNodeLink. If you use the
+ * packaged panel (Tree.html), you must name the component using
+ * NODE_IMAGE_NAME.
+ *
+ * @param node
+ * the tree node
+ * @return the image for the node
+ */
+ protected Image getNodeImage(final DefaultMutableTreeNode node)
+ {
+ return new Image(NODE_IMAGE_NAME, BLANK);
+ }
+
+ /**
+ * Gets the label of the node that is used for the node link. Defaults to
+ * treeNodeModel.getUserObject().toString(); override to provide a custom
+ * label
+ *
+ * @param node
+ * the tree node
+ * @return the label of the node that is used for the node link
+ */
+ protected String getNodeLabel(final DefaultMutableTreeNode node)
+ {
+ return String.valueOf(node.getUserObject());
+ }
+
+ /**
+ * @see org.apache.wicket.Component#onAttach()
+ */
+ protected void onAttach()
+ {
+ super.onAttach();
+ // if we don't optimize, rebuild the paths on every request
+ if (!getOptimizeItemRemoval())
+ {
+ treePathsModel.dirty = true;
+ }
+ }
+
+ /**
+ * Handler that is called when a junction link is clicked; this
+ * implementation sets the expanded state to one that corresponds with the
+ * node selection.
+ *
+ * @param node
+ * the tree node
+ */
+ protected void junctionLinkClicked(final DefaultMutableTreeNode node)
+ {
+ setExpandedState(node);
+ }
+
+ /**
+ * Create a new panel for a tree node. This method can be overriden to
+ * provide a custom panel. This way, you can effectively nest anything you
+ * want in the tree, like input fields, images, etc.
+ * <p>
+ * <strong> you must use the provide panelId as the id of your custom panel
+ * </strong><br>
+ * for example, do:
+ *
+ * <pre>
+ * return new MyNodePanel(panelId, node);
+ * </pre>
+ *
+ * </p>
+ * <p>
+ * You can choose to either let your own panel extend from DefaultNodePanel
+ * when you just want to provide different markup but want to reuse the
+ * default components on this panel, or extend from NodePanel directly, and
+ * provide any component structure you like.
+ * </p>
+ *
+ * @param panelId
+ * the id that the panel MUST use
+ * @param node
+ * the tree node for the panel
+ * @return a new Panel
+ */
+ protected Component newNodePanel(String panelId, DefaultMutableTreeNode node)
+ {
+ return new DefaultNodePanel(panelId, this, node);
+ }
+
+ /**
+ * Handler that is called when a node link is clicked; this implementation
+ * sets the expanded state just as a click on a junction would do. Override
+ * this for custom behavior.
+ *
+ * @param node
+ * the tree node model
+ */
+ protected void nodeLinkClicked(final DefaultMutableTreeNode node)
+ {
+ setSelected(node);
+ }
+}