You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Igor Drobiazko <ig...@gmail.com> on 2011/06/16 22:05:45 UTC
Fwd: svn commit: r1135351 - in /tapestry/tapestry5/trunk/tapestry-core/src:
main/java/org/apache/tapestry5/corelib/components/ main/java/org/apache/tapestry5/internal/services/javascript/
main/java/org/apache/tapestry5/tree/ main/resources/org/apache
Unfortunately this commit made Tapestry to depend on Java 1.6. Class
java.util.Deque
is available starting from Java 1.6.
---------- Forwarded message ----------
From: <hl...@apache.org>
Date: Tue, Jun 14, 2011 at 2:40 AM
Subject: svn commit: r1135351 - in
/tapestry/tapestry5/trunk/tapestry-core/src:
main/java/org/apache/tapestry5/corelib/components/
main/java/org/apache/tapestry5/internal/services/javascript/
main/java/org/apache/tapestry5/tree/ main/resources/org/apache/tapest...
To: commits@tapestry.apache.org
Author: hlship
Date: Tue Jun 14 00:40:55 2011
New Revision: 1135351
URL: http://svn.apache.org/viewvc?rev=1135351&view=rev
Log:
Copy TapX Tree component into tapestry-core
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeExpansionModel.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeExpansionModel.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModel.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModelAdapter.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeNode.java
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Tree.tml
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branch.png
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branchend.png
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-sprites.png
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-vpipe.png
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.css
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.js
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FileSystemTreeModel.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeDemo.java
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeDemo.tml
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/CoreJavaScriptStack.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,294 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.corelib.components;
+
+import java.util.List;
+
+import org.apache.tapestry5.BindingConstants;
+import org.apache.tapestry5.Block;
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.Link;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.annotations.Environmental;
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.dom.Element;
+import org.apache.tapestry5.func.F;
+import org.apache.tapestry5.func.Flow;
+import org.apache.tapestry5.func.Worker;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.json.JSONObject;
+import org.apache.tapestry5.runtime.RenderCommand;
+import org.apache.tapestry5.runtime.RenderQueue;
+import org.apache.tapestry5.services.javascript.JavaScriptSupport;
+import org.apache.tapestry5.tree.DefaultTreeExpansionModel;
+import org.apache.tapestry5.tree.TreeExpansionModel;
+import org.apache.tapestry5.tree.TreeModel;
+import org.apache.tapestry5.tree.TreeNode;
+
+/**
+ * A component used to render a recursive tree structure, with
expandable/collapsable nodes. The data that is displayed
+ * by the component is provided as a {@link TreeModel}. A secondary model,
the {@link TreeExpansionModel}, is used
+ * to track which nodes have been expanded. The Tree component uses special
tricks to support recursive rendering
+ * of the Tree as necessary.
+ *
+ * @since 5.3.0
+ */
+@SuppressWarnings(
+{ "rawtypes", "unchecked", "unused" })
+public class Tree
+{
+ /**
+ * The model that drives the tree, determining top level nodes and
making revealing the overall structure of the
+ * tree.
+ */
+ @Parameter(required = true, autoconnect = true)
+ private TreeModel model;
+
+ /**
+ * Allows the container to specify additional CSS class names for the
outer DIV element. The outer DIV
+ * always has the class name "t-tree-container"; the additional class
names are typically used to apply
+ * a specific size and width to the component.
+ */
+ @Parameter(name = "class", defaultPrefix = BindingConstants.LITERAL)
+ private String className;
+
+ /**
+ * Optional parameter used to inform the container about what TreeNode
is currently rendering; this
+ * is primarily used when the label parameter is bound.
+ */
+ @Property
+ @Parameter
+ private TreeNode node;
+
+ /**
+ * Used to control the Tree's expansion model. By default, a persistent
field inside the Tree
+ * component stores a {@link DefaultTreeExpansionModel}. This parameter
may be bound when more
+ * control over the implementation of the expansion model, or how it is
stored, is
+ * required.
+ */
+ @Parameter(allowNull = false, value = "defaultTreeExpansionModel")
+ private TreeExpansionModel expansionModel;
+
+ /**
+ * Optional parameter used to inform the container about the value of
the currently rendering TreeNode; this
+ * is often preferable to the TreeNode, and like the node parameter, is
primarily used when the label parameter
+ * it bound.
+ */
+ @Parameter
+ private Object value;
+
+ /**
+ * A renderable (usually a {@link Block}) that can render the label for
a tree node.
+ * This will be invoked after the {@link #value} parameter has been
updated.
+ */
+ @Property
+ @Parameter(value = "block:defaultRenderTreeNodeLabel")
+ private RenderCommand label;
+
+ @Environmental
+ private JavaScriptSupport jss;
+
+ @Inject
+ private ComponentResources resources;
+
+ @Persist
+ private TreeExpansionModel defaultTreeExpansionModel;
+
+ private static RenderCommand RENDER_CLOSE_TAG = new RenderCommand()
+ {
+ public void render(MarkupWriter writer, RenderQueue queue)
+ {
+ writer.end();
+ };
+ };
+
+ private static RenderCommand RENDER_LABEL_SPAN = new RenderCommand()
+ {
+ public void render(MarkupWriter writer, RenderQueue queue)
+ {
+ writer.element("span", "class", "t-tree-label");
+ };
+ };
+
+ /**
+ * Renders a single node (which may be the last within its containing
node).
+ * This is a mix of immediate rendering, and queuing up various Blocks
and Render commands
+ * to do the rest. May recursively render child nodes of the active
node.
+ *
+ * @param node
+ * to render
+ * @param isLast
+ * if true, add "t-last" attribute to the LI element
+ * @return command to render the node
+ */
+ private RenderCommand toRenderCommand(final TreeNode node, final
boolean isLast)
+ {
+ return new RenderCommand()
+ {
+ public void render(MarkupWriter writer, RenderQueue queue)
+ {
+ // Inform the component's container about what value is
being rendered
+ // (this may be necessary to generate the correct label for
the node).
+ Tree.this.node = node;
+
+ value = node.getValue();
+
+ writer.element("li");
+
+ if (isLast)
+ writer.attributes("class", "t-last");
+
+ Element e = writer.element("span", "class", "t-tree-icon");
+
+ if (node.isLeaf())
+ e.addClassName("t-leaf-node");
+ else if (!node.getHasChildren())
+ e.addClassName("t-empty-node");
+
+ boolean hasChildren = !node.isLeaf() &&
node.getHasChildren();
+ boolean expanded = hasChildren &&
expansionModel.isExpanded(node);
+
+ if (hasChildren)
+ {
+ String clientId = jss.allocateClientId(resources);
+
+ e.attribute("id", clientId);
+
+ Link expandChildren =
resources.createEventLink("expandChildren", node.getId());
+ Link markExpanded =
resources.createEventLink("markExpanded", node.getId());
+ Link markCollapsed =
resources.createEventLink("markCollapsed", node.getId());
+
+ JSONObject spec = new JSONObject("clientId", clientId,
+
+ "expandChildrenURL", expandChildren.toString(),
+
+ "markExpandedURL", markExpanded.toString(),
+
+ "markCollapsedURL", markCollapsed.toString());
+
+ if (expanded)
+ spec.put("expanded", true);
+
+ jss.addInitializerCall("treeNode", spec);
+ }
+
+ writer.end(); // span.tx-tree-icon
+
+ // From here on in, we're pushing things onto the queue.
Remember that
+ // execution order is reversed from order commands are
pushed.
+
+ queue.push(RENDER_CLOSE_TAG); // li
+
+ if (expanded)
+ {
+ queue.push(new RenderNodes(node.getChildren()));
+ }
+
+ queue.push(RENDER_CLOSE_TAG);
+ queue.push(label);
+ queue.push(RENDER_LABEL_SPAN);
+
+ }
+ };
+ }
+
+ /** Renders an <ul> element and renders each node recusively
inside the element. */
+ private class RenderNodes implements RenderCommand
+ {
+ private final Flow<TreeNode> nodes;
+
+ public RenderNodes(List<TreeNode> nodes)
+ {
+ assert !nodes.isEmpty();
+
+ this.nodes = F.flow(nodes).reverse();
+ }
+
+ public void render(MarkupWriter writer, final RenderQueue queue)
+ {
+ writer.element("ul");
+ queue.push(RENDER_CLOSE_TAG);
+
+ queue.push(toRenderCommand(nodes.first(), true));
+
+ nodes.rest().each(new Worker<TreeNode>()
+ {
+ public void work(TreeNode element)
+ {
+ queue.push(toRenderCommand(element, false));
+ }
+ });
+ }
+ }
+
+ public String getContainerClass()
+ {
+ return className == null ? "t-tree-container" : "t-tree-container "
+ className;
+ }
+
+ Object onExpandChildren(String nodeId)
+ {
+ TreeNode container = model.getById(nodeId);
+
+ expansionModel.markExpanded(container);
+
+ return new RenderNodes(container.getChildren());
+ }
+
+ Object onMarkExpanded(String nodeId)
+ {
+ expansionModel.markExpanded(model.getById(nodeId));
+
+ return new JSONObject();
+ }
+
+ Object onMarkCollapsed(String nodeId)
+ {
+ expansionModel.markCollapsed(model.getById(nodeId));
+
+ return new JSONObject();
+ }
+
+ public TreeExpansionModel getDefaultTreeExpansionModel()
+ {
+ if (defaultTreeExpansionModel == null)
+ defaultTreeExpansionModel = new DefaultTreeExpansionModel();
+
+ return defaultTreeExpansionModel;
+ }
+
+ /**
+ * Returns the actual {@link TreeExpansionModel} in use for this Tree
component,
+ * as per the expansionModel parameter. This is often, but not always,
the same
+ * as {@link #getDefaultTreeExpansionModel()}.
+ */
+ public TreeExpansionModel getExpansionModel()
+ {
+ return expansionModel;
+ }
+
+ public Object getRenderRootNodes()
+ {
+ return new RenderNodes(model.getRootNodes());
+ }
+
+ /** Clears the tree's {@link TreeExpansionModel}. */
+ public void clearExpansions()
+ {
+ expansionModel.clear();
+ }
+}
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/CoreJavaScriptStack.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/CoreJavaScriptStack.java?rev=1135351&r1=1135350&r2=1135351&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/CoreJavaScriptStack.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/CoreJavaScriptStack.java
Tue Jun 14 00:40:55 2011
@@ -69,17 +69,20 @@ public class CoreJavaScriptStack impleme
ROOT + "/t5-core.js",
ROOT + "/t5-arrays.js",
-
+
ROOT + "/t5-init.js",
-
+
ROOT + "/t5-pubsub.js",
- ROOT + "/tapestry.js" };
+ ROOT + "/tapestry.js",
+
+ ROOT + "/tree.js" };
// Because of changes to the logic of how stylesheets get incorporated,
the default stylesheet
// was removed, the logic for it is now in
TapestryModule.contributeMarkupRenderer().
- private static final String[] CORE_STYLESHEET = new String[0];
+ private static final String[] CORE_STYLESHEET = new String[]
+ { ROOT + "/tree.css" };
public CoreJavaScriptStack(@Symbol(SymbolConstants.PRODUCTION_MODE)
boolean productionMode,
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeExpansionModel.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeExpansionModel.java?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeExpansionModel.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeExpansionModel.java
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,64 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.tree;
+
+import java.util.Set;
+
+import org.apache.tapestry5.BaseOptimizedSessionPersistedObject;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+
+/**
+ * Manages a Set of String {@link TreeNode} ids.
+ *
+ * @param <T>
+ * @since 5.3.0
+ * @see TreeModel
+ */
+public class DefaultTreeExpansionModel<T> extends
BaseOptimizedSessionPersistedObject implements TreeExpansionModel<T>
+{
+ private final Set<String> expandedIds = CollectionFactory.newSet();
+
+ public boolean isExpanded(TreeNode<T> node)
+ {
+ assert node != null;
+
+ return expandedIds.contains(node.getId());
+ }
+
+ public void markExpanded(TreeNode<T> node)
+ {
+ assert node != null;
+
+ if (expandedIds.add(node.getId()))
+ markDirty();
+ }
+
+ public void markCollapsed(TreeNode<T> node)
+ {
+ assert node != null;
+
+ if (expandedIds.remove(node.getId()))
+ markDirty();
+ }
+
+ public void clear()
+ {
+ if (!expandedIds.isEmpty())
+ {
+ expandedIds.clear();
+ markDirty();
+ }
+ }
+}
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,189 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.tree;
+
+import java.util.Collections;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry5.ValueEncoder;
+import org.apache.tapestry5.func.F;
+import org.apache.tapestry5.func.Mapper;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+
+/**
+ * A default implementation of TreeModel that starts with a {@link
ValueEncoder} (for the element to string conversion),
+ * a {@link TreeModelAdapter}, and a list of root nodes.
+ * <p>
+ * This implementation is <em>not</em> thread safe.
+ *
+ * @param <T>
+ * @since 5.3.0
+ */
+public class DefaultTreeModel<T> implements TreeModel<T>
+{
+ private final ValueEncoder<T> encoder;
+
+ private final TreeModelAdapter<T> adapter;
+
+ private final List<TreeNode<T>> roots;
+
+ private final Map<String, TreeNode<T>> cache =
CollectionFactory.newMap();
+
+ private final Mapper<T, TreeNode<T>> toTreeNode = new Mapper<T,
TreeNode<T>>()
+ {
+ public TreeNode<T> map(T value)
+ {
+ return new DefaultTreeNode(value);
+ };
+ };
+
+ private class DefaultTreeNode implements TreeNode<T>
+ {
+ private final T value;
+
+ private List<TreeNode<T>> children;
+
+ DefaultTreeNode(T value)
+ {
+ this.value = value;
+ }
+
+ public String getId()
+ {
+ return encoder.toClient(value);
+ }
+
+ public T getValue()
+ {
+ return value;
+ }
+
+ public boolean isLeaf()
+ {
+ return adapter.isLeaf(value);
+ }
+
+ public boolean getHasChildren()
+ {
+ return adapter.hasChildren(value);
+ }
+
+ public List<TreeNode<T>> getChildren()
+ {
+ if (children == null)
+ children =
F.flow(adapter.getChildren(value)).map(toTreeNode).toList();
+
+ return children;
+ }
+
+ public String getLabel()
+ {
+ return adapter.getLabel(value);
+ }
+
+ }
+
+ /**
+ * Creates a new model starting from a single root element.
+ *
+ * @param encoder
+ * @param adapter
+ * @param root
+ */
+ public DefaultTreeModel(ValueEncoder<T> encoder, TreeModelAdapter<T>
adapter, T root)
+ {
+ this(encoder, adapter, Collections.singletonList(root));
+ }
+
+ /**
+ * Standard constructor.
+ *
+ * @param encoder
+ * used to convert values to strings and vice-versa
+ * @param adapter
+ * adapts elements to the tree
+ * @param roots
+ * defines the root nodes of the model
+ */
+ public DefaultTreeModel(ValueEncoder<T> encoder, TreeModelAdapter<T>
adapter, List<T> roots)
+ {
+ assert encoder != null;
+ assert adapter != null;
+ assert roots != null;
+ assert !roots.isEmpty();
+
+ this.encoder = encoder;
+ this.adapter = adapter;
+ this.roots = F.flow(roots).map(toTreeNode).toList();
+ }
+
+ public List<TreeNode<T>> getRootNodes()
+ {
+ return roots;
+ }
+
+ public TreeNode<T> getById(String id)
+ {
+ assert id != null;
+
+ TreeNode<T> result = findById(id);
+
+ if (result == null)
+ throw new IllegalArgumentException(String.format("Could not
locate TreeNode '%s'.", id));
+
+ return result;
+ }
+
+ private TreeNode<T> findById(String id)
+ {
+ TreeNode<T> result = cache.get(id);
+
+ if (result != null)
+ return result;
+
+ Deque<TreeNode<T>> queue = new LinkedList<TreeNode<T>>(roots);
+
+ while (!queue.isEmpty())
+ {
+ TreeNode<T> node = queue.removeFirst();
+
+ String nodeId = node.getId();
+
+ cache.put(nodeId, node);
+
+ if (nodeId.equals(id))
+ return node;
+
+ if (!node.isLeaf() && node.getHasChildren())
+ {
+ for (TreeNode<T> child : node.getChildren())
+ {
+ queue.addFirst(child);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public TreeNode<T> find(T element)
+ {
+ return findById(encoder.toClient(element));
+ }
+
+}
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeExpansionModel.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeExpansionModel.java?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeExpansionModel.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeExpansionModel.java
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,47 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.tree;
+
+import org.apache.tapestry5.corelib.components.Tree;
+
+/**
+ * Tracks which nodes of a {@link TreeModel} are currently expanded. The
{@linkplain DefaultTreeExpansionModel default
+ * implementation} simply stores a set of {@linkplain TreeNode#getId()
unique node
+ * ids} to identify expanded nodes. The expansion model is updated whenever
folders are expanded or
+ * collapsed on the client side.
+ *
+ * @since 5.3.0
+ * @see Tree
+ */
+public interface TreeExpansionModel<T>
+{
+ /**
+ * Returns true if the node has been previously {@linkplain
#markExpanded(TreeNode) expanded}.
+ *
+ * @param node
+ * node to check for expansion
+ * @return
+ */
+ boolean isExpanded(TreeNode<T> node);
+
+ /** Marks the node as expanded. */
+ void markExpanded(TreeNode<T> node);
+
+ /** Marks the node as collapsed (not expanded). */
+ void markCollapsed(TreeNode<T> node);
+
+ /** Marks all nodes as collapsed. */
+ void clear();
+}
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModel.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModel.java?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModel.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModel.java
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,59 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.tree;
+
+import java.util.List;
+
+import javax.swing.tree.TreeSelectionModel;
+
+import org.apache.tapestry5.ValueEncoder;
+import org.apache.tapestry5.corelib.components.Tree;
+
+/**
+ * A model for tree-oriented data used by the {@link Tree} component. The
default implemention, {@link DefaultTreeModel}
+ * uses a {@link ValueEncoder} and a {@link TreeModelAdapter} to supply the
+ * underlying information.
+ *
+ * @param <T>
+ * type of data in the tree
+ * @since 5.3.0
+ * @see TreeSelectionModel
+ */
+public interface TreeModel<T>
+{
+ /**
+ * Returns the node or nodes that are the top level of the tree.
+ */
+ List<TreeNode<T>> getRootNodes();
+
+ /**
+ * Locates a node in the tree by its unique id.
+ *
+ * @throws IllegalArgumentException
+ * if no such node exists
+ * @see TreeNode#getId()
+ */
+ TreeNode<T> getById(String id);
+
+ /**
+ * Recursively searches from the root nodes to find the tree node that
matches
+ * the provided element.
+ *
+ * @param element
+ * to search for
+ * @return matching node, or null if not found
+ */
+ TreeNode<T> find(T element);
+}
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModelAdapter.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModelAdapter.java?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModelAdapter.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModelAdapter.java
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,53 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.tree;
+
+import java.util.List;
+
+/**
+ * Used with {@link DefaultTreeModel} to define how to extract labels and
child nodes from a value.
+ *
+ * @since 5.3.0
+ */
+public interface TreeModelAdapter<T>
+{
+ /**
+ * Determines if the value is a leaf or a (potential) container of
children.
+ *
+ * @see TreeNode#isLeaf()
+ */
+ boolean isLeaf(T value);
+
+ /**
+ * Returns true if the value has children (only invoked for non-leaf
values).
+ *
+ * @see TreeNode#getHasChildren()
+ */
+ boolean hasChildren(T value);
+
+ /**
+ * Returns the children, in the order they should be presented to the
client.
+ *
+ * @see TreeNode#getChildren()
+ */
+ List<T> getChildren(T value);
+
+ /**
+ * Returns a text label for the value, which may be presented to the
client.
+ *
+ * @see TreeNode#getLabel()
+ */
+ String getLabel(T value);
+}
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeNode.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeNode.java?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeNode.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeNode.java
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,72 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.tree;
+
+import java.util.List;
+
+/**
+ * A node within a {@link TreeModel}. In a {@link DefaultTreeModel}, most
of the node's information
+ * comes via the {@link TreeModelAdapter}.
+ *
+ * @param <T>
+ * type of node
+ * @since 5.3.0
+ */
+public interface TreeNode<T>
+{
+ /**
+ * Returns a string Id for the node that uniquely identifies it.
+ *
+ * @return unique string identifying the node
+ * @see TreeModel#getById(String)
+ */
+ String getId();
+
+ /** Returns the value represented by this node. */
+ T getValue();
+
+ /**
+ * If true, then this node is a leaf node, which never has children
(i.e., a file). If false, the node
+ * may have children (i.e., a folder).
+ *
+ * @return true for leaf nodes, false for folder nodes
+ * @see TreeModelAdapter#isLeaf(Object)
+ */
+ boolean isLeaf();
+
+ /**
+ * Returns true if this non-leaf node has child nodes. This will not be
invoked for leaf nodes.
+ *
+ * @see TreeModelAdapter#hasChildren(Object)
+ */
+ boolean getHasChildren();
+
+ /**
+ * Returns the actual children of this non-leaf node, as additional
nodes.
+ *
+ * @see TreeModelAdapter#getChildren(Object)
+ */
+ List<TreeNode<T>> getChildren();
+
+ // TODO: Some way to influence the rendered output (i.e., to display
different icons based on
+ // file type).
+
+ /**
+ * Returns a textual label for the node. Not all UIs will make use of
the label, but default UIs will.
+ *
+ * @see TreeModelAdapter#getLabel(Object)
+ */
+ public String getLabel();
+}
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Tree.tml
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Tree.tml?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Tree.tml
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Tree.tml
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,11 @@
+<t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
xmlns:p="tapestry:parameter">
+
+ <div class="${containerClass}">
+ <t:delegate to="renderRootNodes"/>
+ </div>
+
+ <t:block id="defaultRenderTreeNodeLabel">
+ ${node.label}
+ </t:block>
+
+</t:container>
\ No newline at end of file
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branch.png
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branch.png?rev=1135351&view=auto
==============================================================================
Files
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branch.png
(added) and
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branch.png
Tue Jun 14 00:40:55 2011 differ
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branchend.png
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branchend.png?rev=1135351&view=auto
==============================================================================
Files
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branchend.png
(added) and
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branchend.png
Tue Jun 14 00:40:55 2011 differ
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-sprites.png
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-sprites.png?rev=1135351&view=auto
==============================================================================
Files
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-sprites.png
(added) and
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-sprites.png
Tue Jun 14 00:40:55 2011 differ
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-vpipe.png
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-vpipe.png?rev=1135351&view=auto
==============================================================================
Files
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-vpipe.png
(added) and
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-vpipe.png
Tue Jun 14 00:40:55 2011 differ
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.css
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.css?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.css
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.css
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,84 @@
+
+DIV.t-tree-container
+{
+ padding: 0;
+ margin: 0;
+}
+
+DIV.t-tree-container UL
+{
+ list-style-type: none;
+ background-image: url(tree-vpipe.png);
+ background-repeat: repeat-y;
+ margin: 0 0 0 12px;
+ padding: 0;
+}
+
+DIV.t-tree-container UL UL
+{
+ /* Line up the nested list's vertical bar under the element's folder
icon. */
+ margin: 0 0 0 24px;
+}
+
+
+DIV.t-tree-container LI {
+ margin: 0;
+ padding: 0 0 0 16px;
+ background-image: url(tree-branch.png);
+ background-repeat: no-repeat;
+ line-height: 1.5;
+}
+
+DIV.t-tree-container LI.t-last
+{
+ background-color: white;
+ background-image: url(tree-branchend.png);
+}
+
+/* Assume its a collapsed, but expandable, tree node. Later CSS rules
overwrite this. */
+
+SPAN.t-tree-icon {
+ display: inline-block;
+ width: 32px;
+ height: 16px;
+ cursor: pointer;
+ background-image: url(tree-sprites.png);
+ background-position: 0px 0px;
+}
+
+SPAN.t-tree-icon.t-leaf-node {
+ cursor: default;
+ background-position: -32px -16px;
+}
+
+SPAN.t-tree-icon.t-empty-node {
+ cursor: default;
+ background-position: -32px 0px !important;
+}
+
+SPAN.t-tree-expanded {
+ background-position: 0px -16px;
+}
+
+SPAN.t-ajax-wait {
+ width: 16px;
+ height: 16px;
+ display: inline-block;
+ background-image: url(ajax-loader.gif);
+}
+
+SPAN.t-tree-icon.t-expand {
+ width: 16px;
+ height: 16px;
+ background-image: url(expand.png);
+ display: inline-block;
+ cursor: pointer;
+}
+
+SPAN.t-tree-icon.t-collapse {
+ width: 16px;
+ height: 16px;
+ background-image: url(collapse.png);
+ display: inline-block;
+ cursor: pointer;
+}
Added:
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.js
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.js?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.js
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.js
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,138 @@
+T5.extend(T5, {
+ Tree : {
+
+ /**
+ * Approximate time per pixel for the hide and reveal
animations. The
+ * idea is to have small (few children) and large (many
childen)
+ * animations operate at the same visible rate, even though
they will
+ * take different amounts of time.
+ */
+ ANIMATION_RATE : .005,
+
+ /**
+ * Maximum animation time, in seconds. This is necessary for
very large
+ * animations, otherwise its looks visually odd to see the
child tree
+ * nodes whip down the screen.
+ */
+ MAX_ANIMATION_DURATION : .5,
+
+ /** Type of Scriptaculous effect to hide/show child nodes.
*/
+ TOGGLE_TYPE : 'blind',
+
+ /**
+ * Name of Scriptaculous effects queue to ensure that
animations do not
+ * overwrite each other.
+ */
+ QUEUE_NAME : 't-tree-updates'
+ }
+});
+
+T5.extendInitializer(function() {
+
+ var cfg = T5.Tree;
+
+ function doAnimate(element) {
+ var sublist = $(element).up('li').down("ul");
+
+ var dim = sublist.getDimensions();
+
+ var duration = Math.min(dim.height * cfg.ANIMATION_RATE,
+ cfg.MAX_ANIMATION_DURATION)
+
+ new Effect.toggle(sublist, cfg.TOGGLE_TYPE, {
+ duration : duration,
+ queue : {
+ position : 'end',
+ scope : cfg.QUEUE_NAME
+ }
+ });
+ }
+
+ function animateRevealChildren(element) {
+ $(element).addClassName("t-tree-expanded");
+
+ doAnimate(element);
+ }
+
+ function animateHideChildren(element) {
+ $(element).removeClassName("t-tree-expanded");
+
+ doAnimate(element);
+ }
+
+ function initializer(spec) {
+ var loaded = spec.expanded;
+ var expanded = spec.expanded;
+ if (expanded) {
+ $(spec.clientId).addClassName("t-tree-expanded")
+ }
+ var loading = false;
+
+ function successHandler(reply) {
+ // Remove the Ajax load indicator
+ $(spec.clientId).update("");
+ $(spec.clientId).removeClassName("t-empty-node");
+
+ var response = reply.responseJSON;
+
+ Tapestry.loadScriptsInReply(response, function() {
+ var element = $(spec.clientId).up("li");
+ var label =
element.down("span.t-tree-label");
+
+ label.insert({
+ after : response.content
+ });
+
+ // Hide the new sublist so that we can
animate revealing it.
+ element.down("ul").hide();
+
+ animateRevealChildren(spec.clientId);
+
+ loading = false;
+ loaded = true;
+ expanded = true;
+ });
+
+ }
+
+ function doLoad() {
+ if (loading)
+ return;
+
+ loading = true;
+
+ $(spec.clientId).addClassName("t-empty-node");
+ $(spec.clientId).update("<span
class='t-ajax-wait'/>");
+
+ Tapestry.ajaxRequest(spec.expandChildrenURL,
successHandler);
+ }
+
+ $(spec.clientId).observe("click", function(event) {
+ event.stop();
+
+ if (!loaded) {
+
+ doLoad();
+
+ return;
+ }
+
+ // Children have been loaded, just a matter of
toggling
+ // between showing or hiding the children.
+
+ var f = expanded ? animateHideChildren :
animateRevealChildren;
+
+ f.call(null, spec.clientId);
+
+ var url = expanded ? spec.markCollapsedURL :
spec.markExpandedURL;
+
+ Tapestry.ajaxRequest(url, {});
+
+ expanded = !expanded;
+ });
+ }
+
+ return {
+ treeNode : initializer
+ };
+});
Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FileSystemTreeModel.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FileSystemTreeModel.java?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FileSystemTreeModel.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FileSystemTreeModel.java
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,75 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.integration.app1;
+
+import java.io.File;
+import java.util.List;
+
+import org.apache.tapestry5.ValueEncoder;
+import org.apache.tapestry5.func.F;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry5.tree.DefaultTreeModel;
+import org.apache.tapestry5.tree.TreeModelAdapter;
+
+public class FileSystemTreeModel extends DefaultTreeModel<File>
+{
+ private static final ValueEncoder<File> ENCODER = new
ValueEncoder<File>()
+ {
+
+ public String toClient(File value)
+ {
+ return value.getPath();
+ }
+
+ public File toValue(String clientValue)
+ {
+ return new File(clientValue);
+ }
+ };
+
+ private static final TreeModelAdapter<File> ADAPTER = new
TreeModelAdapter<File>()
+ {
+
+ public boolean isLeaf(File value)
+ {
+ return value.isFile();
+ }
+
+ public boolean hasChildren(File value)
+ {
+ return value.list().length > 0;
+ }
+
+ public List<File> getChildren(File value)
+ {
+ return CollectionFactory.newList(value.listFiles());
+ }
+
+ public String getLabel(File value)
+ {
+ return value.getName();
+ }
+ };
+
+ public FileSystemTreeModel()
+ {
+ this(".");
+ }
+
+ public FileSystemTreeModel(String rootDir)
+ {
+ super(ENCODER, ADAPTER, F.flow(new
File(rootDir).listFiles()).toList());
+ }
+}
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java?rev=1135351&r1=1135350&r2=1135351&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
Tue Jun 14 00:40:55 2011
@@ -57,6 +57,8 @@ public class Index
private static final List<Item> ITEMS = CollectionFactory
.newList(
+ new Item("TreeDemo", "Tree Component Demo", "Demo of
Tree Component"),
+
new Item("InvalidExpressionInDynamicTemplate", "Invalid
Dynamic Expression",
"Invalid expression in a Dynamic Template"),
Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeDemo.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeDemo.java?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeDemo.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeDemo.java
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,38 @@
+// Copyright 2011 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.integration.app1.pages;
+
+import java.io.File;
+
+import org.apache.tapestry5.annotations.InjectComponent;
+import org.apache.tapestry5.corelib.components.Tree;
+import org.apache.tapestry5.integration.app1.FileSystemTreeModel;
+import org.apache.tapestry5.tree.TreeModel;
+
+public class TreeDemo
+{
+ @InjectComponent
+ private Tree fs;
+
+ public TreeModel<File> getFileSystemTreeModel()
+ {
+ return new FileSystemTreeModel();
+ }
+
+ void onActionFromClear()
+ {
+ fs.clearExpansions();
+ }
+}
Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeDemo.tml
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeDemo.tml?rev=1135351&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeDemo.tml
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeDemo.tml
Tue Jun 14 00:40:55 2011
@@ -0,0 +1,15 @@
+<t:border xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
xmlns:p="tapestry:parameter">
+
+ <h1>Tree Demo</h1>
+
+ <t:tree t:id="fs" model="fileSystemTreeModel"/>
+
+ <p>
+ [
+ <t:pagelink page="treeDemo">Redraw</t:pagelink>
+ ]
+ [
+ <t:actionlink t:id="clear">clear expansions</t:actionlink>
+ ]
+ </p>
+</t:border>
\ No newline at end of file
--
Best regards,
Igor Drobiazko
http://tapestry5.de
Re: svn commit: r1135351 - in /tapestry/tapestry5/trunk/tapestry-core/src:
main/java/org/apache/tapestry5/corelib/components/ main/java/org/apache/tapestry5/internal/services/javascript/
main/java/org/apache/tapestry5/tree/ main/resources/org/apache
Posted by Kalle Korhonen <ka...@gmail.com>.
Agree it shouldn't - it's easy to document and fix in a follow-up
release. I started running against several tynamo modules but since
the dependencies have changed enough, it'll take some tweaking before
I have a better picture.
Kalle
On Thu, Jun 16, 2011 at 1:52 PM, Howard Lewis Ship <hl...@gmail.com> wrote:
> Good catch, needs to be fixed, but should it hold up this first alpha
> release?
> On Jun 16, 2011 1:12 PM, "Josh Canfield" <jo...@gmail.com> wrote:
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org
Re: svn commit: r1135351 - in /tapestry/tapestry5/trunk/tapestry-core/src:
main/java/org/apache/tapestry5/corelib/components/ main/java/org/apache/tapestry5/internal/services/javascript/
main/java/org/apache/tapestry5/tree/ main/resources/org/apache
Posted by Howard Lewis Ship <hl...@gmail.com>.
Good catch, needs to be fixed, but should it hold up this first alpha
release?
On Jun 16, 2011 1:12 PM, "Josh Canfield" <jo...@gmail.com> wrote:
Re: svn commit: r1135351 - in /tapestry/tapestry5/trunk/tapestry-core/src:
main/java/org/apache/tapestry5/corelib/components/ main/java/org/apache/tapestry5/internal/services/javascript/
main/java/org/apache/tapestry5/tree/ main/resources/org/apache
Posted by Josh Canfield <jo...@gmail.com>.
> Unfortunately this commit made Tapestry to depend on Java 1.6. Class
> java.util.Deque
> is available starting from Java 1.6.
Another good reason to see about getting hudson to compile and run
unit tests in other versions/implementations of the JVM! :)
On Thu, Jun 16, 2011 at 1:05 PM, Igor Drobiazko
<ig...@gmail.com> wrote:
> Unfortunately this commit made Tapestry to depend on Java 1.6. Class
> java.util.Deque
> is available starting from Java 1.6.
>
> ---------- Forwarded message ----------
> From: <hl...@apache.org>
> Date: Tue, Jun 14, 2011 at 2:40 AM
> Subject: svn commit: r1135351 - in
> /tapestry/tapestry5/trunk/tapestry-core/src:
> main/java/org/apache/tapestry5/corelib/components/
> main/java/org/apache/tapestry5/internal/services/javascript/
> main/java/org/apache/tapestry5/tree/ main/resources/org/apache/tapest...
> To: commits@tapestry.apache.org
>
>
> Author: hlship
> Date: Tue Jun 14 00:40:55 2011
> New Revision: 1135351
>
> URL: http://svn.apache.org/viewvc?rev=1135351&view=rev
> Log:
> Copy TapX Tree component into tapestry-core
>
> Added:
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeExpansionModel.java
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeExpansionModel.java
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModel.java
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModelAdapter.java
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeNode.java
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Tree.tml
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branch.png
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branchend.png
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-sprites.png
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-vpipe.png
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.css
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.js
>
> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FileSystemTreeModel.java
>
> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeDemo.java
>
> tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeDemo.tml
> Modified:
>
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/CoreJavaScriptStack.java
>
> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Tree.java
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,294 @@
> +// Copyright 2011 The Apache Software Foundation
> +//
> +// Licensed 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.tapestry5.corelib.components;
> +
> +import java.util.List;
> +
> +import org.apache.tapestry5.BindingConstants;
> +import org.apache.tapestry5.Block;
> +import org.apache.tapestry5.ComponentResources;
> +import org.apache.tapestry5.Link;
> +import org.apache.tapestry5.MarkupWriter;
> +import org.apache.tapestry5.annotations.Environmental;
> +import org.apache.tapestry5.annotations.Parameter;
> +import org.apache.tapestry5.annotations.Persist;
> +import org.apache.tapestry5.annotations.Property;
> +import org.apache.tapestry5.dom.Element;
> +import org.apache.tapestry5.func.F;
> +import org.apache.tapestry5.func.Flow;
> +import org.apache.tapestry5.func.Worker;
> +import org.apache.tapestry5.ioc.annotations.Inject;
> +import org.apache.tapestry5.json.JSONObject;
> +import org.apache.tapestry5.runtime.RenderCommand;
> +import org.apache.tapestry5.runtime.RenderQueue;
> +import org.apache.tapestry5.services.javascript.JavaScriptSupport;
> +import org.apache.tapestry5.tree.DefaultTreeExpansionModel;
> +import org.apache.tapestry5.tree.TreeExpansionModel;
> +import org.apache.tapestry5.tree.TreeModel;
> +import org.apache.tapestry5.tree.TreeNode;
> +
> +/**
> + * A component used to render a recursive tree structure, with
> expandable/collapsable nodes. The data that is displayed
> + * by the component is provided as a {@link TreeModel}. A secondary model,
> the {@link TreeExpansionModel}, is used
> + * to track which nodes have been expanded. The Tree component uses special
> tricks to support recursive rendering
> + * of the Tree as necessary.
> + *
> + * @since 5.3.0
> + */
> +@SuppressWarnings(
> +{ "rawtypes", "unchecked", "unused" })
> +public class Tree
> +{
> + /**
> + * The model that drives the tree, determining top level nodes and
> making revealing the overall structure of the
> + * tree.
> + */
> + @Parameter(required = true, autoconnect = true)
> + private TreeModel model;
> +
> + /**
> + * Allows the container to specify additional CSS class names for the
> outer DIV element. The outer DIV
> + * always has the class name "t-tree-container"; the additional class
> names are typically used to apply
> + * a specific size and width to the component.
> + */
> + @Parameter(name = "class", defaultPrefix = BindingConstants.LITERAL)
> + private String className;
> +
> + /**
> + * Optional parameter used to inform the container about what TreeNode
> is currently rendering; this
> + * is primarily used when the label parameter is bound.
> + */
> + @Property
> + @Parameter
> + private TreeNode node;
> +
> + /**
> + * Used to control the Tree's expansion model. By default, a persistent
> field inside the Tree
> + * component stores a {@link DefaultTreeExpansionModel}. This parameter
> may be bound when more
> + * control over the implementation of the expansion model, or how it is
> stored, is
> + * required.
> + */
> + @Parameter(allowNull = false, value = "defaultTreeExpansionModel")
> + private TreeExpansionModel expansionModel;
> +
> + /**
> + * Optional parameter used to inform the container about the value of
> the currently rendering TreeNode; this
> + * is often preferable to the TreeNode, and like the node parameter, is
> primarily used when the label parameter
> + * it bound.
> + */
> + @Parameter
> + private Object value;
> +
> + /**
> + * A renderable (usually a {@link Block}) that can render the label for
> a tree node.
> + * This will be invoked after the {@link #value} parameter has been
> updated.
> + */
> + @Property
> + @Parameter(value = "block:defaultRenderTreeNodeLabel")
> + private RenderCommand label;
> +
> + @Environmental
> + private JavaScriptSupport jss;
> +
> + @Inject
> + private ComponentResources resources;
> +
> + @Persist
> + private TreeExpansionModel defaultTreeExpansionModel;
> +
> + private static RenderCommand RENDER_CLOSE_TAG = new RenderCommand()
> + {
> + public void render(MarkupWriter writer, RenderQueue queue)
> + {
> + writer.end();
> + };
> + };
> +
> + private static RenderCommand RENDER_LABEL_SPAN = new RenderCommand()
> + {
> + public void render(MarkupWriter writer, RenderQueue queue)
> + {
> + writer.element("span", "class", "t-tree-label");
> + };
> + };
> +
> + /**
> + * Renders a single node (which may be the last within its containing
> node).
> + * This is a mix of immediate rendering, and queuing up various Blocks
> and Render commands
> + * to do the rest. May recursively render child nodes of the active
> node.
> + *
> + * @param node
> + * to render
> + * @param isLast
> + * if true, add "t-last" attribute to the LI element
> + * @return command to render the node
> + */
> + private RenderCommand toRenderCommand(final TreeNode node, final
> boolean isLast)
> + {
> + return new RenderCommand()
> + {
> + public void render(MarkupWriter writer, RenderQueue queue)
> + {
> + // Inform the component's container about what value is
> being rendered
> + // (this may be necessary to generate the correct label for
> the node).
> + Tree.this.node = node;
> +
> + value = node.getValue();
> +
> + writer.element("li");
> +
> + if (isLast)
> + writer.attributes("class", "t-last");
> +
> + Element e = writer.element("span", "class", "t-tree-icon");
> +
> + if (node.isLeaf())
> + e.addClassName("t-leaf-node");
> + else if (!node.getHasChildren())
> + e.addClassName("t-empty-node");
> +
> + boolean hasChildren = !node.isLeaf() &&
> node.getHasChildren();
> + boolean expanded = hasChildren &&
> expansionModel.isExpanded(node);
> +
> + if (hasChildren)
> + {
> + String clientId = jss.allocateClientId(resources);
> +
> + e.attribute("id", clientId);
> +
> + Link expandChildren =
> resources.createEventLink("expandChildren", node.getId());
> + Link markExpanded =
> resources.createEventLink("markExpanded", node.getId());
> + Link markCollapsed =
> resources.createEventLink("markCollapsed", node.getId());
> +
> + JSONObject spec = new JSONObject("clientId", clientId,
> +
> + "expandChildrenURL", expandChildren.toString(),
> +
> + "markExpandedURL", markExpanded.toString(),
> +
> + "markCollapsedURL", markCollapsed.toString());
> +
> + if (expanded)
> + spec.put("expanded", true);
> +
> + jss.addInitializerCall("treeNode", spec);
> + }
> +
> + writer.end(); // span.tx-tree-icon
> +
> + // From here on in, we're pushing things onto the queue.
> Remember that
> + // execution order is reversed from order commands are
> pushed.
> +
> + queue.push(RENDER_CLOSE_TAG); // li
> +
> + if (expanded)
> + {
> + queue.push(new RenderNodes(node.getChildren()));
> + }
> +
> + queue.push(RENDER_CLOSE_TAG);
> + queue.push(label);
> + queue.push(RENDER_LABEL_SPAN);
> +
> + }
> + };
> + }
> +
> + /** Renders an <ul> element and renders each node recusively
> inside the element. */
> + private class RenderNodes implements RenderCommand
> + {
> + private final Flow<TreeNode> nodes;
> +
> + public RenderNodes(List<TreeNode> nodes)
> + {
> + assert !nodes.isEmpty();
> +
> + this.nodes = F.flow(nodes).reverse();
> + }
> +
> + public void render(MarkupWriter writer, final RenderQueue queue)
> + {
> + writer.element("ul");
> + queue.push(RENDER_CLOSE_TAG);
> +
> + queue.push(toRenderCommand(nodes.first(), true));
> +
> + nodes.rest().each(new Worker<TreeNode>()
> + {
> + public void work(TreeNode element)
> + {
> + queue.push(toRenderCommand(element, false));
> + }
> + });
> + }
> + }
> +
> + public String getContainerClass()
> + {
> + return className == null ? "t-tree-container" : "t-tree-container "
> + className;
> + }
> +
> + Object onExpandChildren(String nodeId)
> + {
> + TreeNode container = model.getById(nodeId);
> +
> + expansionModel.markExpanded(container);
> +
> + return new RenderNodes(container.getChildren());
> + }
> +
> + Object onMarkExpanded(String nodeId)
> + {
> + expansionModel.markExpanded(model.getById(nodeId));
> +
> + return new JSONObject();
> + }
> +
> + Object onMarkCollapsed(String nodeId)
> + {
> + expansionModel.markCollapsed(model.getById(nodeId));
> +
> + return new JSONObject();
> + }
> +
> + public TreeExpansionModel getDefaultTreeExpansionModel()
> + {
> + if (defaultTreeExpansionModel == null)
> + defaultTreeExpansionModel = new DefaultTreeExpansionModel();
> +
> + return defaultTreeExpansionModel;
> + }
> +
> + /**
> + * Returns the actual {@link TreeExpansionModel} in use for this Tree
> component,
> + * as per the expansionModel parameter. This is often, but not always,
> the same
> + * as {@link #getDefaultTreeExpansionModel()}.
> + */
> + public TreeExpansionModel getExpansionModel()
> + {
> + return expansionModel;
> + }
> +
> + public Object getRenderRootNodes()
> + {
> + return new RenderNodes(model.getRootNodes());
> + }
> +
> + /** Clears the tree's {@link TreeExpansionModel}. */
> + public void clearExpansions()
> + {
> + expansionModel.clear();
> + }
> +}
>
> Modified:
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/CoreJavaScriptStack.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/CoreJavaScriptStack.java?rev=1135351&r1=1135350&r2=1135351&view=diff
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/CoreJavaScriptStack.java
> (original)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/javascript/CoreJavaScriptStack.java
> Tue Jun 14 00:40:55 2011
> @@ -69,17 +69,20 @@ public class CoreJavaScriptStack impleme
> ROOT + "/t5-core.js",
>
> ROOT + "/t5-arrays.js",
> -
> +
> ROOT + "/t5-init.js",
> -
> +
> ROOT + "/t5-pubsub.js",
>
> - ROOT + "/tapestry.js" };
> + ROOT + "/tapestry.js",
> +
> + ROOT + "/tree.js" };
>
> // Because of changes to the logic of how stylesheets get incorporated,
> the default stylesheet
> // was removed, the logic for it is now in
> TapestryModule.contributeMarkupRenderer().
>
> - private static final String[] CORE_STYLESHEET = new String[0];
> + private static final String[] CORE_STYLESHEET = new String[]
> + { ROOT + "/tree.css" };
>
> public CoreJavaScriptStack(@Symbol(SymbolConstants.PRODUCTION_MODE)
> boolean productionMode,
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeExpansionModel.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeExpansionModel.java?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeExpansionModel.java
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeExpansionModel.java
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,64 @@
> +// Copyright 2011 The Apache Software Foundation
> +//
> +// Licensed 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.tapestry5.tree;
> +
> +import java.util.Set;
> +
> +import org.apache.tapestry5.BaseOptimizedSessionPersistedObject;
> +import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
> +
> +/**
> + * Manages a Set of String {@link TreeNode} ids.
> + *
> + * @param <T>
> + * @since 5.3.0
> + * @see TreeModel
> + */
> +public class DefaultTreeExpansionModel<T> extends
> BaseOptimizedSessionPersistedObject implements TreeExpansionModel<T>
> +{
> + private final Set<String> expandedIds = CollectionFactory.newSet();
> +
> + public boolean isExpanded(TreeNode<T> node)
> + {
> + assert node != null;
> +
> + return expandedIds.contains(node.getId());
> + }
> +
> + public void markExpanded(TreeNode<T> node)
> + {
> + assert node != null;
> +
> + if (expandedIds.add(node.getId()))
> + markDirty();
> + }
> +
> + public void markCollapsed(TreeNode<T> node)
> + {
> + assert node != null;
> +
> + if (expandedIds.remove(node.getId()))
> + markDirty();
> + }
> +
> + public void clear()
> + {
> + if (!expandedIds.isEmpty())
> + {
> + expandedIds.clear();
> + markDirty();
> + }
> + }
> +}
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/DefaultTreeModel.java
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,189 @@
> +// Copyright 2011 The Apache Software Foundation
> +//
> +// Licensed 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.tapestry5.tree;
> +
> +import java.util.Collections;
> +import java.util.Deque;
> +import java.util.LinkedList;
> +import java.util.List;
> +import java.util.Map;
> +
> +import org.apache.tapestry5.ValueEncoder;
> +import org.apache.tapestry5.func.F;
> +import org.apache.tapestry5.func.Mapper;
> +import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
> +
> +/**
> + * A default implementation of TreeModel that starts with a {@link
> ValueEncoder} (for the element to string conversion),
> + * a {@link TreeModelAdapter}, and a list of root nodes.
> + * <p>
> + * This implementation is <em>not</em> thread safe.
> + *
> + * @param <T>
> + * @since 5.3.0
> + */
> +public class DefaultTreeModel<T> implements TreeModel<T>
> +{
> + private final ValueEncoder<T> encoder;
> +
> + private final TreeModelAdapter<T> adapter;
> +
> + private final List<TreeNode<T>> roots;
> +
> + private final Map<String, TreeNode<T>> cache =
> CollectionFactory.newMap();
> +
> + private final Mapper<T, TreeNode<T>> toTreeNode = new Mapper<T,
> TreeNode<T>>()
> + {
> + public TreeNode<T> map(T value)
> + {
> + return new DefaultTreeNode(value);
> + };
> + };
> +
> + private class DefaultTreeNode implements TreeNode<T>
> + {
> + private final T value;
> +
> + private List<TreeNode<T>> children;
> +
> + DefaultTreeNode(T value)
> + {
> + this.value = value;
> + }
> +
> + public String getId()
> + {
> + return encoder.toClient(value);
> + }
> +
> + public T getValue()
> + {
> + return value;
> + }
> +
> + public boolean isLeaf()
> + {
> + return adapter.isLeaf(value);
> + }
> +
> + public boolean getHasChildren()
> + {
> + return adapter.hasChildren(value);
> + }
> +
> + public List<TreeNode<T>> getChildren()
> + {
> + if (children == null)
> + children =
> F.flow(adapter.getChildren(value)).map(toTreeNode).toList();
> +
> + return children;
> + }
> +
> + public String getLabel()
> + {
> + return adapter.getLabel(value);
> + }
> +
> + }
> +
> + /**
> + * Creates a new model starting from a single root element.
> + *
> + * @param encoder
> + * @param adapter
> + * @param root
> + */
> + public DefaultTreeModel(ValueEncoder<T> encoder, TreeModelAdapter<T>
> adapter, T root)
> + {
> + this(encoder, adapter, Collections.singletonList(root));
> + }
> +
> + /**
> + * Standard constructor.
> + *
> + * @param encoder
> + * used to convert values to strings and vice-versa
> + * @param adapter
> + * adapts elements to the tree
> + * @param roots
> + * defines the root nodes of the model
> + */
> + public DefaultTreeModel(ValueEncoder<T> encoder, TreeModelAdapter<T>
> adapter, List<T> roots)
> + {
> + assert encoder != null;
> + assert adapter != null;
> + assert roots != null;
> + assert !roots.isEmpty();
> +
> + this.encoder = encoder;
> + this.adapter = adapter;
> + this.roots = F.flow(roots).map(toTreeNode).toList();
> + }
> +
> + public List<TreeNode<T>> getRootNodes()
> + {
> + return roots;
> + }
> +
> + public TreeNode<T> getById(String id)
> + {
> + assert id != null;
> +
> + TreeNode<T> result = findById(id);
> +
> + if (result == null)
> + throw new IllegalArgumentException(String.format("Could not
> locate TreeNode '%s'.", id));
> +
> + return result;
> + }
> +
> + private TreeNode<T> findById(String id)
> + {
> + TreeNode<T> result = cache.get(id);
> +
> + if (result != null)
> + return result;
> +
> + Deque<TreeNode<T>> queue = new LinkedList<TreeNode<T>>(roots);
> +
> + while (!queue.isEmpty())
> + {
> + TreeNode<T> node = queue.removeFirst();
> +
> + String nodeId = node.getId();
> +
> + cache.put(nodeId, node);
> +
> + if (nodeId.equals(id))
> + return node;
> +
> + if (!node.isLeaf() && node.getHasChildren())
> + {
> + for (TreeNode<T> child : node.getChildren())
> + {
> + queue.addFirst(child);
> + }
> + }
> + }
> +
> + return null;
> + }
> +
> + public TreeNode<T> find(T element)
> + {
> + return findById(encoder.toClient(element));
> + }
> +
> +}
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeExpansionModel.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeExpansionModel.java?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeExpansionModel.java
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeExpansionModel.java
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,47 @@
> +// Copyright 2011 The Apache Software Foundation
> +//
> +// Licensed 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.tapestry5.tree;
> +
> +import org.apache.tapestry5.corelib.components.Tree;
> +
> +/**
> + * Tracks which nodes of a {@link TreeModel} are currently expanded. The
> {@linkplain DefaultTreeExpansionModel default
> + * implementation} simply stores a set of {@linkplain TreeNode#getId()
> unique node
> + * ids} to identify expanded nodes. The expansion model is updated whenever
> folders are expanded or
> + * collapsed on the client side.
> + *
> + * @since 5.3.0
> + * @see Tree
> + */
> +public interface TreeExpansionModel<T>
> +{
> + /**
> + * Returns true if the node has been previously {@linkplain
> #markExpanded(TreeNode) expanded}.
> + *
> + * @param node
> + * node to check for expansion
> + * @return
> + */
> + boolean isExpanded(TreeNode<T> node);
> +
> + /** Marks the node as expanded. */
> + void markExpanded(TreeNode<T> node);
> +
> + /** Marks the node as collapsed (not expanded). */
> + void markCollapsed(TreeNode<T> node);
> +
> + /** Marks all nodes as collapsed. */
> + void clear();
> +}
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModel.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModel.java?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModel.java
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModel.java
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,59 @@
> +// Copyright 2011 The Apache Software Foundation
> +//
> +// Licensed 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.tapestry5.tree;
> +
> +import java.util.List;
> +
> +import javax.swing.tree.TreeSelectionModel;
> +
> +import org.apache.tapestry5.ValueEncoder;
> +import org.apache.tapestry5.corelib.components.Tree;
> +
> +/**
> + * A model for tree-oriented data used by the {@link Tree} component. The
> default implemention, {@link DefaultTreeModel}
> + * uses a {@link ValueEncoder} and a {@link TreeModelAdapter} to supply the
> + * underlying information.
> + *
> + * @param <T>
> + * type of data in the tree
> + * @since 5.3.0
> + * @see TreeSelectionModel
> + */
> +public interface TreeModel<T>
> +{
> + /**
> + * Returns the node or nodes that are the top level of the tree.
> + */
> + List<TreeNode<T>> getRootNodes();
> +
> + /**
> + * Locates a node in the tree by its unique id.
> + *
> + * @throws IllegalArgumentException
> + * if no such node exists
> + * @see TreeNode#getId()
> + */
> + TreeNode<T> getById(String id);
> +
> + /**
> + * Recursively searches from the root nodes to find the tree node that
> matches
> + * the provided element.
> + *
> + * @param element
> + * to search for
> + * @return matching node, or null if not found
> + */
> + TreeNode<T> find(T element);
> +}
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModelAdapter.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModelAdapter.java?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModelAdapter.java
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeModelAdapter.java
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,53 @@
> +// Copyright 2011 The Apache Software Foundation
> +//
> +// Licensed 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.tapestry5.tree;
> +
> +import java.util.List;
> +
> +/**
> + * Used with {@link DefaultTreeModel} to define how to extract labels and
> child nodes from a value.
> + *
> + * @since 5.3.0
> + */
> +public interface TreeModelAdapter<T>
> +{
> + /**
> + * Determines if the value is a leaf or a (potential) container of
> children.
> + *
> + * @see TreeNode#isLeaf()
> + */
> + boolean isLeaf(T value);
> +
> + /**
> + * Returns true if the value has children (only invoked for non-leaf
> values).
> + *
> + * @see TreeNode#getHasChildren()
> + */
> + boolean hasChildren(T value);
> +
> + /**
> + * Returns the children, in the order they should be presented to the
> client.
> + *
> + * @see TreeNode#getChildren()
> + */
> + List<T> getChildren(T value);
> +
> + /**
> + * Returns a text label for the value, which may be presented to the
> client.
> + *
> + * @see TreeNode#getLabel()
> + */
> + String getLabel(T value);
> +}
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeNode.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeNode.java?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeNode.java
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/tree/TreeNode.java
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,72 @@
> +// Copyright 2011 The Apache Software Foundation
> +//
> +// Licensed 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.tapestry5.tree;
> +
> +import java.util.List;
> +
> +/**
> + * A node within a {@link TreeModel}. In a {@link DefaultTreeModel}, most
> of the node's information
> + * comes via the {@link TreeModelAdapter}.
> + *
> + * @param <T>
> + * type of node
> + * @since 5.3.0
> + */
> +public interface TreeNode<T>
> +{
> + /**
> + * Returns a string Id for the node that uniquely identifies it.
> + *
> + * @return unique string identifying the node
> + * @see TreeModel#getById(String)
> + */
> + String getId();
> +
> + /** Returns the value represented by this node. */
> + T getValue();
> +
> + /**
> + * If true, then this node is a leaf node, which never has children
> (i.e., a file). If false, the node
> + * may have children (i.e., a folder).
> + *
> + * @return true for leaf nodes, false for folder nodes
> + * @see TreeModelAdapter#isLeaf(Object)
> + */
> + boolean isLeaf();
> +
> + /**
> + * Returns true if this non-leaf node has child nodes. This will not be
> invoked for leaf nodes.
> + *
> + * @see TreeModelAdapter#hasChildren(Object)
> + */
> + boolean getHasChildren();
> +
> + /**
> + * Returns the actual children of this non-leaf node, as additional
> nodes.
> + *
> + * @see TreeModelAdapter#getChildren(Object)
> + */
> + List<TreeNode<T>> getChildren();
> +
> + // TODO: Some way to influence the rendered output (i.e., to display
> different icons based on
> + // file type).
> +
> + /**
> + * Returns a textual label for the node. Not all UIs will make use of
> the label, but default UIs will.
> + *
> + * @see TreeModelAdapter#getLabel(Object)
> + */
> + public String getLabel();
> +}
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Tree.tml
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Tree.tml?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Tree.tml
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/Tree.tml
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,11 @@
> +<t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
> xmlns:p="tapestry:parameter">
> +
> + <div class="${containerClass}">
> + <t:delegate to="renderRootNodes"/>
> + </div>
> +
> + <t:block id="defaultRenderTreeNodeLabel">
> + ${node.label}
> + </t:block>
> +
> +</t:container>
> \ No newline at end of file
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branch.png
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branch.png?rev=1135351&view=auto
> ==============================================================================
> Files
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branch.png
> (added) and
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branch.png
> Tue Jun 14 00:40:55 2011 differ
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branchend.png
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branchend.png?rev=1135351&view=auto
> ==============================================================================
> Files
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branchend.png
> (added) and
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-branchend.png
> Tue Jun 14 00:40:55 2011 differ
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-sprites.png
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-sprites.png?rev=1135351&view=auto
> ==============================================================================
> Files
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-sprites.png
> (added) and
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-sprites.png
> Tue Jun 14 00:40:55 2011 differ
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-vpipe.png
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-vpipe.png?rev=1135351&view=auto
> ==============================================================================
> Files
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-vpipe.png
> (added) and
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree-vpipe.png
> Tue Jun 14 00:40:55 2011 differ
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.css
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.css?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.css
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.css
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,84 @@
> +
> +DIV.t-tree-container
> +{
> + padding: 0;
> + margin: 0;
> +}
> +
> +DIV.t-tree-container UL
> +{
> + list-style-type: none;
> + background-image: url(tree-vpipe.png);
> + background-repeat: repeat-y;
> + margin: 0 0 0 12px;
> + padding: 0;
> +}
> +
> +DIV.t-tree-container UL UL
> +{
> + /* Line up the nested list's vertical bar under the element's folder
> icon. */
> + margin: 0 0 0 24px;
> +}
> +
> +
> +DIV.t-tree-container LI {
> + margin: 0;
> + padding: 0 0 0 16px;
> + background-image: url(tree-branch.png);
> + background-repeat: no-repeat;
> + line-height: 1.5;
> +}
> +
> +DIV.t-tree-container LI.t-last
> +{
> + background-color: white;
> + background-image: url(tree-branchend.png);
> +}
> +
> +/* Assume its a collapsed, but expandable, tree node. Later CSS rules
> overwrite this. */
> +
> +SPAN.t-tree-icon {
> + display: inline-block;
> + width: 32px;
> + height: 16px;
> + cursor: pointer;
> + background-image: url(tree-sprites.png);
> + background-position: 0px 0px;
> +}
> +
> +SPAN.t-tree-icon.t-leaf-node {
> + cursor: default;
> + background-position: -32px -16px;
> +}
> +
> +SPAN.t-tree-icon.t-empty-node {
> + cursor: default;
> + background-position: -32px 0px !important;
> +}
> +
> +SPAN.t-tree-expanded {
> + background-position: 0px -16px;
> +}
> +
> +SPAN.t-ajax-wait {
> + width: 16px;
> + height: 16px;
> + display: inline-block;
> + background-image: url(ajax-loader.gif);
> +}
> +
> +SPAN.t-tree-icon.t-expand {
> + width: 16px;
> + height: 16px;
> + background-image: url(expand.png);
> + display: inline-block;
> + cursor: pointer;
> +}
> +
> +SPAN.t-tree-icon.t-collapse {
> + width: 16px;
> + height: 16px;
> + background-image: url(collapse.png);
> + display: inline-block;
> + cursor: pointer;
> +}
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.js
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.js?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.js
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/tree.js
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,138 @@
> +T5.extend(T5, {
> + Tree : {
> +
> + /**
> + * Approximate time per pixel for the hide and reveal
> animations. The
> + * idea is to have small (few children) and large (many
> childen)
> + * animations operate at the same visible rate, even though
> they will
> + * take different amounts of time.
> + */
> + ANIMATION_RATE : .005,
> +
> + /**
> + * Maximum animation time, in seconds. This is necessary for
> very large
> + * animations, otherwise its looks visually odd to see the
> child tree
> + * nodes whip down the screen.
> + */
> + MAX_ANIMATION_DURATION : .5,
> +
> + /** Type of Scriptaculous effect to hide/show child nodes.
> */
> + TOGGLE_TYPE : 'blind',
> +
> + /**
> + * Name of Scriptaculous effects queue to ensure that
> animations do not
> + * overwrite each other.
> + */
> + QUEUE_NAME : 't-tree-updates'
> + }
> +});
> +
> +T5.extendInitializer(function() {
> +
> + var cfg = T5.Tree;
> +
> + function doAnimate(element) {
> + var sublist = $(element).up('li').down("ul");
> +
> + var dim = sublist.getDimensions();
> +
> + var duration = Math.min(dim.height * cfg.ANIMATION_RATE,
> + cfg.MAX_ANIMATION_DURATION)
> +
> + new Effect.toggle(sublist, cfg.TOGGLE_TYPE, {
> + duration : duration,
> + queue : {
> + position : 'end',
> + scope : cfg.QUEUE_NAME
> + }
> + });
> + }
> +
> + function animateRevealChildren(element) {
> + $(element).addClassName("t-tree-expanded");
> +
> + doAnimate(element);
> + }
> +
> + function animateHideChildren(element) {
> + $(element).removeClassName("t-tree-expanded");
> +
> + doAnimate(element);
> + }
> +
> + function initializer(spec) {
> + var loaded = spec.expanded;
> + var expanded = spec.expanded;
> + if (expanded) {
> + $(spec.clientId).addClassName("t-tree-expanded")
> + }
> + var loading = false;
> +
> + function successHandler(reply) {
> + // Remove the Ajax load indicator
> + $(spec.clientId).update("");
> + $(spec.clientId).removeClassName("t-empty-node");
> +
> + var response = reply.responseJSON;
> +
> + Tapestry.loadScriptsInReply(response, function() {
> + var element = $(spec.clientId).up("li");
> + var label =
> element.down("span.t-tree-label");
> +
> + label.insert({
> + after : response.content
> + });
> +
> + // Hide the new sublist so that we can
> animate revealing it.
> + element.down("ul").hide();
> +
> + animateRevealChildren(spec.clientId);
> +
> + loading = false;
> + loaded = true;
> + expanded = true;
> + });
> +
> + }
> +
> + function doLoad() {
> + if (loading)
> + return;
> +
> + loading = true;
> +
> + $(spec.clientId).addClassName("t-empty-node");
> + $(spec.clientId).update("<span
> class='t-ajax-wait'/>");
> +
> + Tapestry.ajaxRequest(spec.expandChildrenURL,
> successHandler);
> + }
> +
> + $(spec.clientId).observe("click", function(event) {
> + event.stop();
> +
> + if (!loaded) {
> +
> + doLoad();
> +
> + return;
> + }
> +
> + // Children have been loaded, just a matter of
> toggling
> + // between showing or hiding the children.
> +
> + var f = expanded ? animateHideChildren :
> animateRevealChildren;
> +
> + f.call(null, spec.clientId);
> +
> + var url = expanded ? spec.markCollapsedURL :
> spec.markExpandedURL;
> +
> + Tapestry.ajaxRequest(url, {});
> +
> + expanded = !expanded;
> + });
> + }
> +
> + return {
> + treeNode : initializer
> + };
> +});
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FileSystemTreeModel.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FileSystemTreeModel.java?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FileSystemTreeModel.java
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/FileSystemTreeModel.java
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,75 @@
> +// Copyright 2011 The Apache Software Foundation
> +//
> +// Licensed 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.tapestry5.integration.app1;
> +
> +import java.io.File;
> +import java.util.List;
> +
> +import org.apache.tapestry5.ValueEncoder;
> +import org.apache.tapestry5.func.F;
> +import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
> +import org.apache.tapestry5.tree.DefaultTreeModel;
> +import org.apache.tapestry5.tree.TreeModelAdapter;
> +
> +public class FileSystemTreeModel extends DefaultTreeModel<File>
> +{
> + private static final ValueEncoder<File> ENCODER = new
> ValueEncoder<File>()
> + {
> +
> + public String toClient(File value)
> + {
> + return value.getPath();
> + }
> +
> + public File toValue(String clientValue)
> + {
> + return new File(clientValue);
> + }
> + };
> +
> + private static final TreeModelAdapter<File> ADAPTER = new
> TreeModelAdapter<File>()
> + {
> +
> + public boolean isLeaf(File value)
> + {
> + return value.isFile();
> + }
> +
> + public boolean hasChildren(File value)
> + {
> + return value.list().length > 0;
> + }
> +
> + public List<File> getChildren(File value)
> + {
> + return CollectionFactory.newList(value.listFiles());
> + }
> +
> + public String getLabel(File value)
> + {
> + return value.getName();
> + }
> + };
> +
> + public FileSystemTreeModel()
> + {
> + this(".");
> + }
> +
> + public FileSystemTreeModel(String rootDir)
> + {
> + super(ENCODER, ADAPTER, F.flow(new
> File(rootDir).listFiles()).toList());
> + }
> +}
>
> Modified:
> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java?rev=1135351&r1=1135350&r2=1135351&view=diff
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
> (original)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
> Tue Jun 14 00:40:55 2011
> @@ -57,6 +57,8 @@ public class Index
> private static final List<Item> ITEMS = CollectionFactory
> .newList(
>
> + new Item("TreeDemo", "Tree Component Demo", "Demo of
> Tree Component"),
> +
> new Item("InvalidExpressionInDynamicTemplate", "Invalid
> Dynamic Expression",
> "Invalid expression in a Dynamic Template"),
>
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeDemo.java
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeDemo.java?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeDemo.java
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/TreeDemo.java
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,38 @@
> +// Copyright 2011 The Apache Software Foundation
> +//
> +// Licensed 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.tapestry5.integration.app1.pages;
> +
> +import java.io.File;
> +
> +import org.apache.tapestry5.annotations.InjectComponent;
> +import org.apache.tapestry5.corelib.components.Tree;
> +import org.apache.tapestry5.integration.app1.FileSystemTreeModel;
> +import org.apache.tapestry5.tree.TreeModel;
> +
> +public class TreeDemo
> +{
> + @InjectComponent
> + private Tree fs;
> +
> + public TreeModel<File> getFileSystemTreeModel()
> + {
> + return new FileSystemTreeModel();
> + }
> +
> + void onActionFromClear()
> + {
> + fs.clearExpansions();
> + }
> +}
>
> Added:
> tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeDemo.tml
> URL:
> http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeDemo.tml?rev=1135351&view=auto
> ==============================================================================
> ---
> tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeDemo.tml
> (added)
> +++
> tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/integration/app1/pages/TreeDemo.tml
> Tue Jun 14 00:40:55 2011
> @@ -0,0 +1,15 @@
> +<t:border xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
> xmlns:p="tapestry:parameter">
> +
> + <h1>Tree Demo</h1>
> +
> + <t:tree t:id="fs" model="fileSystemTreeModel"/>
> +
> + <p>
> + [
> + <t:pagelink page="treeDemo">Redraw</t:pagelink>
> + ]
> + [
> + <t:actionlink t:id="clear">clear expansions</t:actionlink>
> + ]
> + </p>
> +</t:border>
> \ No newline at end of file
>
>
>
>
>
> --
> Best regards,
>
> Igor Drobiazko
> http://tapestry5.de
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org