You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by tv...@apache.org on 2009/10/05 17:59:56 UTC

svn commit: r821885 - in /incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk: TreeView.java content/TreeViewNodeEditor.java content/TreeViewNodeRenderer.java skin/terra/TerraTreeViewSkin.java

Author: tvolkert
Date: Mon Oct  5 15:59:55 2009
New Revision: 821885

URL: http://svn.apache.org/viewvc?rev=821885&view=rev
Log:
PIVOT-305 :: Added path to TreeView.NodeRenderer interface

Modified:
    incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TreeView.java
    incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeViewNodeEditor.java
    incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeViewNodeRenderer.java
    incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/terra/TerraTreeViewSkin.java

Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TreeView.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TreeView.java?rev=821885&r1=821884&r2=821885&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TreeView.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/TreeView.java Mon Oct  5 15:59:55 2009
@@ -89,9 +89,37 @@
      * Tree view node renderer interface.
      */
     public interface NodeRenderer extends Renderer {
-        public void render(Object node, TreeView treeView, boolean expanded,
-            boolean selected, NodeCheckState checkState, boolean highlighted,
-            boolean disabled);
+        /**
+         * Prepares the renderer for layout or paint.
+         *
+         * @param node
+         * The node value to render, or <tt>null</tt> if called to calculate
+         * preferred height for skins that assume a fixed renderer height.
+         *
+         * @param path
+         * The path to the node being rendered, or <tt>null</tt> if
+         * <tt>node</tt> is <tt>null</tt>.
+         *
+         * @param treeView
+         * The tree view that contains the node.
+         *
+         * @param expanded
+         * <tt>true</tt> if the node is expanded; <tt>false</tt> otherwise.
+         *
+         * @param selected
+         * <tt>true</tt> if the node is selected; <tt>false</tt> otherwise.
+         *
+         * @param checkState
+         * The node's {@linkplain NodeCheckState check state}.
+         *
+         * @param highlighted
+         * <tt>true</tt> if the node is highlighted; <tt>false</tt> otherwise.
+         *
+         * @param disabled
+         * <tt>true</tt> if the node is disabled; <tt>false</tt> otherwise.
+         */
+        public void render(Object node, Path path, TreeView treeView, boolean expanded,
+            boolean selected, NodeCheckState checkState, boolean highlighted, boolean disabled);
     }
 
     /**

Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeViewNodeEditor.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeViewNodeEditor.java?rev=821885&r1=821884&r2=821885&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeViewNodeEditor.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeViewNodeEditor.java Mon Oct  5 15:59:55 2009
@@ -255,7 +255,7 @@
 
         // Render the node data
         TreeViewNodeRenderer nodeRenderer = (TreeViewNodeRenderer)treeView.getNodeRenderer();
-        nodeRenderer.render(nodeData, treeView, false, false,
+        nodeRenderer.render(nodeData, path, treeView, false, false,
             TreeView.NodeCheckState.UNCHECKED, false, false);
         nodeRenderer.setSize(nodeBounds.width, nodeBounds.height);
 

Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeViewNodeRenderer.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeViewNodeRenderer.java?rev=821885&r1=821884&r2=821885&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeViewNodeRenderer.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/content/TreeViewNodeRenderer.java Mon Oct  5 15:59:55 2009
@@ -19,6 +19,7 @@
 import java.awt.Color;
 import java.awt.Font;
 
+import org.apache.pivot.collections.Sequence.Tree.Path;
 import org.apache.pivot.wtk.Bounds;
 import org.apache.pivot.wtk.BoxPane;
 import org.apache.pivot.wtk.HorizontalAlignment;
@@ -28,7 +29,6 @@
 import org.apache.pivot.wtk.VerticalAlignment;
 import org.apache.pivot.wtk.media.Image;
 
-
 /**
  * Default tree node renderer, which knows how to render instances of
  * {@link TreeNode} and {@link Image}. Anything else will be rendered as a
@@ -65,7 +65,7 @@
     }
 
     @Override
-    public void render(Object node, TreeView treeView, boolean expanded,
+    public void render(Object node, Path path, TreeView treeView, boolean expanded,
         boolean selected, TreeView.NodeCheckState checkState,
         boolean highlighted, boolean disabled) {
         if (node != null) {

Modified: incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/terra/TerraTreeViewSkin.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/terra/TerraTreeViewSkin.java?rev=821885&r1=821884&r2=821885&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/terra/TerraTreeViewSkin.java (original)
+++ incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/terra/TerraTreeViewSkin.java Mon Oct  5 15:59:55 2009
@@ -23,6 +23,8 @@
 import java.awt.RenderingHints;
 import java.awt.Transparency;
 import java.awt.geom.GeneralPath;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
 
 import org.apache.pivot.collections.ArrayList;
 import org.apache.pivot.collections.List;
@@ -46,7 +48,6 @@
 import org.apache.pivot.wtk.TreeViewSelectionListener;
 import org.apache.pivot.wtk.skin.ComponentSkin;
 
-
 /**
  * Tree view skin.
  */
@@ -68,6 +69,107 @@
     }
 
     /**
+     * Iterates through the visible nodes. For callers who wish to know the
+     * path of each visible node, using this iterator will be much more
+     * efficient than manually iterating over the visible nodes and calling
+     * <tt>getPath()</tt> on each node.
+     */
+    protected final class VisibleNodeIterator implements Iterator<NodeInfo> {
+        private int index;
+        private int end;
+
+        private Path path = null;
+        private NodeInfo previous = null;
+
+        public VisibleNodeIterator() {
+            this(0, visibleNodes.getLength() - 1);
+        }
+
+        /**
+         * Creates a new visible node iterator that will iterate over a portion
+         * of the visible nodes list (useful during painting).
+         *
+         * @param start
+         * The start index, inclusive
+         *
+         * @param end
+         * The end index, inclusive
+         */
+        public VisibleNodeIterator(int start, int end) {
+            if (start < 0
+                || end >= visibleNodes.getLength()
+                || start > end) {
+                throw new IndexOutOfBoundsException();
+            }
+
+            this.index = start;
+            this.end = end;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public boolean hasNext() {
+            return (index <= end);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public NodeInfo next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+
+            NodeInfo next = visibleNodes.get(index++);
+
+            if (path == null) {
+                // First iteration
+                path = next.getPath();
+            } else if (next.parent == previous) {
+                // Child of previous visible node
+                path.add(0);
+            } else {
+                int n = path.getLength();
+                while (next.parent != previous.parent) {
+                    path.remove(--n, 1);
+                    previous = previous.parent;
+                }
+
+                int tail = path.get(n - 1);
+                path.update(n - 1, tail + 1);
+            }
+
+            previous = next;
+
+            return next;
+        }
+
+        /**
+         * This operation is not supported by this iterator.
+         *
+         * @throws UnsupportedOperationException
+         */
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        /**
+         * Gets the path of the node last returned by a call to {@link #next()}.
+         *
+         * @return
+         * The path to the node, or <tt>null</tt> if <tt>next()</tt> has not
+         * yet been called.
+         */
+        public Path getPath() {
+            return path;
+        }
+    }
+
+    /**
      * An internal data structure that keeps track of skin-related metadata
      * for a tree node. The justification for the existence of this class lies
      * in the <tt>visibleNodes</tt> data structure, which is a flat list of
@@ -83,15 +185,15 @@
      */
     protected static class NodeInfo {
         // Core metadata
-        protected final TreeView treeView;
-        protected final BranchInfo parent;
-        protected final Object data;
-        protected final int depth;
+        final TreeView treeView;
+        final BranchInfo parent;
+        final Object data;
+        final int depth;
 
         // Cached fields. Note that this is maintained as a bitmask in favor of
         // separate properties because it allows us to easily clear any cached
         // field for all nodes in one common method. See #clearField(byte)
-        protected byte fields = 0;
+        byte fields = 0;
 
         public static final byte HIGHLIGHTED_MASK = 1 << 0;
         public static final byte SELECTED_MASK = 1 << 1;
@@ -104,7 +206,7 @@
             | CHECK_STATE_MIXED_MASK;
 
         @SuppressWarnings("unchecked")
-        public NodeInfo(TreeView treeView, BranchInfo parent, Object data) {
+        private NodeInfo(TreeView treeView, BranchInfo parent, Object data) {
             this.treeView = treeView;
             this.parent = parent;
             this.data = data;
@@ -128,7 +230,7 @@
         }
 
         @SuppressWarnings("unchecked")
-        public static NodeInfo createNew(TreeView treeView, BranchInfo parent, Object data) {
+        private static NodeInfo newInstance(TreeView treeView, BranchInfo parent, Object data) {
             NodeInfo nodeInfo = null;
 
             if (data instanceof List<?>) {
@@ -249,13 +351,13 @@
      * An internal data structure that keeps track of skin-related metadata
      * for a tree branch.
      */
-    protected static class BranchInfo extends NodeInfo {
+    protected static final class BranchInfo extends NodeInfo {
         // Core skin metadata
-        protected List<NodeInfo> children = null;
+        private List<NodeInfo> children = null;
 
         public static final byte EXPANDED_MASK = 1 << 6;
 
-        public BranchInfo(TreeView treeView, BranchInfo parent, List<Object> data) {
+        private BranchInfo(TreeView treeView, BranchInfo parent, List<Object> data) {
             super(treeView, parent, data);
         }
 
@@ -277,7 +379,7 @@
 
                 for (int i = 0; i < count; i++) {
                     Object nodeData = data.get(i);
-                    NodeInfo childNodeInfo = NodeInfo.createNew(treeView, this, nodeData);
+                    NodeInfo childNodeInfo = NodeInfo.newInstance(treeView, this, nodeData);
                     children.add(childNodeInfo);
                 }
             }
@@ -382,13 +484,14 @@
 
         int preferredWidth = 0;
 
-        for (int i = 0, n = visibleNodes.getLength(); i < n; i++) {
-            NodeInfo nodeInfo = visibleNodes.get(i);
+        VisibleNodeIterator visibleNodeIterator = new VisibleNodeIterator();
+        while (visibleNodeIterator.hasNext()) {
+            NodeInfo nodeInfo = visibleNodeIterator.next();
 
             int nodeWidth = (nodeInfo.depth - 1) * (indent + spacing);
 
-            nodeRenderer.render(nodeInfo.data, treeView, false, false,
-                TreeView.NodeCheckState.UNCHECKED, false, false);
+            nodeRenderer.render(nodeInfo.data, visibleNodeIterator.getPath(), treeView,
+                false, false, TreeView.NodeCheckState.UNCHECKED, false, false);
             nodeWidth += nodeRenderer.getPreferredWidth(-1);
 
             preferredWidth = Math.max(preferredWidth, nodeWidth);
@@ -455,8 +558,9 @@
 
         int nodeY = nodeStart * (nodeHeight + VERTICAL_SPACING);
 
-        for (int i = nodeStart; i <= nodeEnd; i++) {
-            NodeInfo nodeInfo = visibleNodes.get(i);
+        VisibleNodeIterator visibleNodeIterator = new VisibleNodeIterator(nodeStart, nodeEnd);
+        while (visibleNodeIterator.hasNext()) {
+            NodeInfo nodeInfo = visibleNodeIterator.next();
 
             boolean expanded = false;
             boolean highlighted = nodeInfo.isHighlighted();
@@ -568,8 +672,8 @@
             // Paint the node data
             Graphics2D rendererGraphics = (Graphics2D)graphics.create(nodeX, nodeY,
                 nodeWidth, nodeHeight);
-            nodeRenderer.render(nodeInfo.data, treeView, expanded, selected,
-                checkState, highlighted, disabled);
+            nodeRenderer.render(nodeInfo.data, visibleNodeIterator.getPath(), treeView,
+                expanded, selected, checkState, highlighted, disabled);
             nodeRenderer.setSize(nodeWidth, nodeHeight);
             nodeRenderer.paint(rendererGraphics);
             rendererGraphics.dispose();
@@ -1034,7 +1138,7 @@
     protected int getNodeHeight() {
         TreeView treeView = (TreeView)getComponent();
         TreeView.NodeRenderer nodeRenderer = treeView.getNodeRenderer();
-        nodeRenderer.render(null, treeView, false, false,
+        nodeRenderer.render(null, null, treeView, false, false,
             TreeView.NodeCheckState.UNCHECKED, false, false);
 
         int nodeHeight = nodeRenderer.getPreferredHeight(-1);
@@ -1049,7 +1153,7 @@
      * Gets the metadata associated with the node found at the specified
      * y-coordinate, or <tt>null</tt> if there is no node at that location.
      */
-    protected NodeInfo getNodeInfoAt(int y) {
+    protected final NodeInfo getNodeInfoAt(int y) {
         NodeInfo nodeInfo = null;
 
         int nodeHeight = getNodeHeight();
@@ -1068,7 +1172,7 @@
      * The path must be valid. The empty path is supported and represents the
      * root node info.
      */
-    protected NodeInfo getNodeInfoAt(Path path) {
+    protected final NodeInfo getNodeInfoAt(Path path) {
         assert(path != null) : "Path is null";
 
         NodeInfo result = null;
@@ -1100,7 +1204,7 @@
      * Gets the bounding box defined by the specified node, or <tt>null</tt>
      * if the node is not currently visible.
      */
-    protected Bounds getNodeBounds(NodeInfo nodeInfo) {
+    protected final Bounds getNodeBounds(NodeInfo nodeInfo) {
         Bounds bounds = null;
 
         int index = visibleNodes.indexOf(nodeInfo);
@@ -1892,7 +1996,7 @@
 
         // Update our internal branch info
         if (branchInfo.children != null) {
-            NodeInfo nodeInfo = NodeInfo.createNew(treeView, branchInfo, branchData.get(index));
+            NodeInfo nodeInfo = NodeInfo.newInstance(treeView, branchInfo, branchData.get(index));
             branchInfo.children.insert(nodeInfo, index);
         }
 
@@ -1931,7 +2035,7 @@
             removeVisibleNodes(branchInfo, index, 1);
 
             // Update our internal branch info
-            nodeInfo = NodeInfo.createNew(treeView, branchInfo, nodeData);
+            nodeInfo = NodeInfo.newInstance(treeView, branchInfo, nodeData);
             branchInfo.children.update(index, nodeInfo);
 
             // Add the new node to the visible nodes list