Author: nbelaevski
Date: 2010-11-29 15:52:25 -0500 (Mon, 29 Nov 2010)
New Revision: 20216
Added:
trunk/examples/iteration-demo/src/main/webapp/images/compress.png
trunk/examples/iteration-demo/src/main/webapp/images/folder.png
trunk/examples/iteration-demo/src/main/webapp/images/folder_key.png
trunk/examples/iteration-demo/src/main/webapp/images/folder_page.png
trunk/examples/iteration-demo/src/main/webapp/images/page_white_cup.png
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeModel.java
Modified:
trunk/examples/iteration-demo/src/main/java/org/richfaces/demo/model/tree/TreeModelBean.java
trunk/examples/iteration-demo/src/main/java/org/richfaces/demo/model/tree/adaptors/Entry.java
trunk/examples/iteration-demo/src/main/resources/org/richfaces/demo/model/tree/tree-model-data.xml
trunk/examples/iteration-demo/src/main/webapp/treeModel.xhtml
trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataModelTuple.java
trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataVisitor.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTree.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeModelKey.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelImpl.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderBase.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeNodeRendererBase.java
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeNodeState.java
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js
Log:
https://jira.jboss.org/browse/RF-9680
Modified:
trunk/examples/iteration-demo/src/main/java/org/richfaces/demo/model/tree/TreeModelBean.java
===================================================================
---
trunk/examples/iteration-demo/src/main/java/org/richfaces/demo/model/tree/TreeModelBean.java 2010-11-29
20:44:15 UTC (rev 20215)
+++
trunk/examples/iteration-demo/src/main/java/org/richfaces/demo/model/tree/TreeModelBean.java 2010-11-29
20:52:25 UTC (rev 20216)
@@ -3,10 +3,15 @@
*/
package org.richfaces.demo.model.tree;
+import javax.faces.FacesException;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
-import javax.xml.bind.JAXB;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.Unmarshaller.Listener;
+import org.richfaces.demo.model.tree.adaptors.Entry;
import org.richfaces.demo.model.tree.adaptors.Root;
/**
@@ -22,7 +27,27 @@
private Root root;
private void initializeRoot() {
- root =
JAXB.unmarshal(TreeModelBean.class.getResource("tree-model-data.xml"),
Root.class);
+
+ try {
+ JAXBContext context = JAXBContext.newInstance(Root.class);
+ Unmarshaller unmarshaller = context.createUnmarshaller();
+ unmarshaller.setListener(new Listener() {
+ @Override
+ public void afterUnmarshal(Object target, Object parent) {
+ super.afterUnmarshal(target, parent);
+
+ if (parent instanceof Entry) {
+ ((Entry) target).setParent((Entry) parent);
+ }
+
+ }
+ });
+
+
+ root = (Root)
unmarshaller.unmarshal(TreeModelBean.class.getResource("tree-model-data.xml"));
+ } catch (JAXBException e) {
+ throw new FacesException(e.getMessage(), e);
+ }
}
public Root getRoot() {
Modified:
trunk/examples/iteration-demo/src/main/java/org/richfaces/demo/model/tree/adaptors/Entry.java
===================================================================
---
trunk/examples/iteration-demo/src/main/java/org/richfaces/demo/model/tree/adaptors/Entry.java 2010-11-29
20:44:15 UTC (rev 20215)
+++
trunk/examples/iteration-demo/src/main/java/org/richfaces/demo/model/tree/adaptors/Entry.java 2010-11-29
20:52:25 UTC (rev 20216)
@@ -21,11 +21,18 @@
*/
package org.richfaces.demo.model.tree.adaptors;
+import java.util.List;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+
/**
* @author Nick Belaevski
* mailto:nbelaevski@exadel.com
@@ -38,8 +45,28 @@
@XmlAttribute
private String name;
+ private Entry parent;
+
+ public String getPath() {
+ List<Entry> entries = Lists.newLinkedList();
+
+ Entry entry = this;
+ while (entry != null) {
+ entries.add(0, entry);
+ entry = entry.getParent();
+ }
+
+ return Joiner.on(" -> ").join(entries);
+ }
+
+ public void processClick() {
+ FacesContext context = FacesContext.getCurrentInstance();
+
+ context.addMessage(null, new FacesMessage(getPath()));
+ }
+
public String toString() {
- return this.getClass().getSimpleName() + "[" + name + "]";
+ return getClass().getSimpleName() + " [" + getName() + "]";
}
public String getName() {
@@ -53,4 +80,12 @@
public void click() {
}
+ public Entry getParent() {
+ return parent;
+ }
+
+ public void setParent(Entry parent) {
+ this.parent = parent;
+ }
+
}
Modified:
trunk/examples/iteration-demo/src/main/resources/org/richfaces/demo/model/tree/tree-model-data.xml
===================================================================
---
trunk/examples/iteration-demo/src/main/resources/org/richfaces/demo/model/tree/tree-model-data.xml 2010-11-29
20:44:15 UTC (rev 20215)
+++
trunk/examples/iteration-demo/src/main/resources/org/richfaces/demo/model/tree/tree-model-data.xml 2010-11-29
20:52:25 UTC (rev 20216)
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<root>
- <!-- project name="ajax4jsf">
+ <project name="ajax4jsf">
<sourceDirectory name="src/main/java">
<package name="org.ajax4jsf">
<class name="FastFilter.java" />
@@ -22,10 +22,10 @@
<package name="org.ajax4jsf.javascript">
</package>
</sourceDirectory>
- </project -->
+ </project>
<project name="richfaces">
- <!-- sourceDirectory name="src/main/java">
+ <sourceDirectory name="src/main/java">
<package name="org.richfaces">
</package>
<package name="org.richfaces.component">
@@ -52,7 +52,7 @@
<file name="FunctionalSpecification-1.0.doc" />
<file name="Requirements-1.0.doc" />
</directory>
- </directory -->
+ </directory>
<directory name="src">
<directory name="main">
<directory name="config">
Added: trunk/examples/iteration-demo/src/main/webapp/images/compress.png
===================================================================
--- trunk/examples/iteration-demo/src/main/webapp/images/compress.png
(rev 0)
+++ trunk/examples/iteration-demo/src/main/webapp/images/compress.png 2010-11-29 20:52:25
UTC (rev 20216)
@@ -0,0 +1,7 @@
+�PNG
+
+
+��BQA�t#��݈��U+YH]�.��6�,��.�t�BJ7""�U�-b��̴�������I�����܇��������3`���V��T�>wGU���ca��^=v���u�������js��kO�m�T�֘�؉�cf�n�ŕ��o��S�
+�w����{�&���
\ No newline at end of file
Added: trunk/examples/iteration-demo/src/main/webapp/images/folder.png
===================================================================
--- trunk/examples/iteration-demo/src/main/webapp/images/folder.png
(rev 0)
+++ trunk/examples/iteration-demo/src/main/webapp/images/folder.png 2010-11-29 20:52:25
UTC (rev 20216)
@@ -0,0 +1,11 @@
+�PNG
+
+
+���ݬ����2OT�O�1W��/�`z����8%�;O;�9P#�9B�����}�^��nO������;�����Ǫo��~
+���d���~�Ed�p�ɳ_��_
+�u�I�
+��B�
+�!
+CF(N��߃J,$���k����(!���TA��F*$X����(�}�f�R�/�x�Q��
+�E�q��x!��i3,�mf?Oԓn����A�Q�
\ No newline at end of file
Added: trunk/examples/iteration-demo/src/main/webapp/images/folder_key.png
===================================================================
--- trunk/examples/iteration-demo/src/main/webapp/images/folder_key.png
(rev 0)
+++ trunk/examples/iteration-demo/src/main/webapp/images/folder_key.png 2010-11-29
20:52:25 UTC (rev 20216)
@@ -0,0 +1,7 @@
+�PNG
+
+
+b�������l���Hɜ�#�->����J�-������
\ No newline at end of file
Added: trunk/examples/iteration-demo/src/main/webapp/images/folder_page.png
===================================================================
--- trunk/examples/iteration-demo/src/main/webapp/images/folder_page.png
(rev 0)
+++ trunk/examples/iteration-demo/src/main/webapp/images/folder_page.png 2010-11-29
20:52:25 UTC (rev 20216)
@@ -0,0 +1,9 @@
+�PNG
+
+
+�+��Z�։�����啗�9��n��@MLk�Z!�jȅ֯-\1�eS�s~�������J-��0e����U�l���ʖ����?]:���fh�BU�
+s��w��v����[���d@ʤ�����p Z�jU��睼p �L�9z��)d���k`Z6��j���B�{
+ h�E?�\�F�~0_����XŻ���{lc�^-e��@&mesm�t)��P�����ԛ�ō˯����#��H��-i�s9��@�r|�
\ No newline at end of file
Added: trunk/examples/iteration-demo/src/main/webapp/images/page_white_cup.png
===================================================================
--- trunk/examples/iteration-demo/src/main/webapp/images/page_white_cup.png
(rev 0)
+++ trunk/examples/iteration-demo/src/main/webapp/images/page_white_cup.png 2010-11-29
20:52:25 UTC (rev 20216)
@@ -0,0 +1,7 @@
+�PNG
+
+
+>������,i6��V�g�ш�p����>���G�.��ç�O�m�5~}�B���yt:�3��f���9'L�\�ە��i��n�h4�e����I�R��Ár���Z.�C"��q*�b(Db�/�N���~
+�/�J铠�n�l6�|6�q��@�R�ŽL&�
+�ڥHB�$�z��=*>'�5�RyW���b1�h�Z, �Bp:����Z!NO��B�KX�V�g�d���� h >���=��Yp*�%�h�2��#��k�M�\�:�����{�F`k��
\ No newline at end of file
Modified: trunk/examples/iteration-demo/src/main/webapp/treeModel.xhtml
===================================================================
--- trunk/examples/iteration-demo/src/main/webapp/treeModel.xhtml 2010-11-29 20:44:15 UTC
(rev 20215)
+++ trunk/examples/iteration-demo/src/main/webapp/treeModel.xhtml 2010-11-29 20:52:25 UTC
(rev 20216)
@@ -12,19 +12,44 @@
</h:head>
<h:body>
- <h:messages id="messages" />
+ <a4j:outputPanel ajaxRendered="true">
+ <h:messages id="messages" />
+ </a4j:outputPanel>
<h:form id="form">
<it:tree id="tree" var="node" toggleType="ajax">
+ <it:treeNode>
+ <a4j:commandLink value="#{node}" action="#{node.processClick}"
/>
+ </it:treeNode>
+
<it:treeModelAdaptor nodes="#{treeModelBean.root.projects}">
+ <it:treeNode iconExpanded="/images/folder_key.png"
iconCollapsed="/images/folder_key.png">
+ <a4j:commandLink value="#{node}"
action="#{node.processClick}" />
+ </it:treeNode>
+
<it:treeModelAdaptor nodes="#{node.sourceDirectories}">
+ <it:treeNode iconExpanded="/images/page_white_cup.png"
iconCollapsed="/images/page_white_cup.png">
+ <a4j:commandLink value="#{node}"
action="#{node.processClick}" />
+ </it:treeNode>
+
<it:treeModelAdaptor nodes="#{node.packages}">
<it:treeModelAdaptor nodes="#{node.classes}" />
</it:treeModelAdaptor>
</it:treeModelAdaptor>
<it:treeModelRecursiveAdaptor roots="#{node.commonDirectories}"
nodes="#{node.directories}">
+ <it:treeNode iconExpanded="/images/folder_page.png"
iconCollapsed="/images/folder.png">
+ <a4j:commandLink value="#{node}"
action="#{node.processClick}" />
+ </it:treeNode>
+
<it:treeModelRecursiveAdaptor roots="#{node.archiveFiles}"
nodes="#{node.archiveEntries}">
+
+ <it:treeNode rendered="#{node.class.simpleName eq
'ArchiveFile'}"
+ iconExpanded="/images/compress.png"
+ iconCollapsed="/images/compress.png">
+ <a4j:commandLink value="#{node}"
action="#{node.processClick}" />
+ </it:treeNode>
+
<it:treeModelAdaptor rendered="#{node.class.simpleName eq
'ArchiveEntry'}"
nodes="#{node.archiveEntryFiles}" />
</it:treeModelRecursiveAdaptor>
@@ -33,5 +58,10 @@
</it:treeModelAdaptor>
</it:tree>
</h:form>
+
+ <h:panelGroup style="position: absolute; bottom: 20px; left: 20px; right:
20px;">
+ <hr />
+ This demo uses icons taken from <a
href="http://www.famfamfam.com/lab/icons/silk/">http://www.f...
+ </h:panelGroup>
</h:body>
</html>
Modified:
trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataModelTuple.java
===================================================================
---
trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataModelTuple.java 2010-11-29
20:44:15 UTC (rev 20215)
+++
trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataModelTuple.java 2010-11-29
20:52:25 UTC (rev 20216)
@@ -21,6 +21,9 @@
*/
package org.richfaces.model;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
/**
* @author Nick Belaevski
*
@@ -44,5 +47,13 @@
public Object getData() {
return data;
}
-
+
+ @Override
+ public String toString() {
+ ToStringHelper helper = Objects.toStringHelper(this);
+ helper.add("rowKey", rowKey);
+ helper.add("data", data);
+
+ return helper.toString();
+ }
}
Modified: trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataVisitor.java
===================================================================
---
trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataVisitor.java 2010-11-29
20:44:15 UTC (rev 20215)
+++
trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataVisitor.java 2010-11-29
20:52:25 UTC (rev 20216)
@@ -31,5 +31,8 @@
public void enterNode();
public void exitNode();
-
+
+ public void beforeChildrenVisit();
+
+ public void afterChildrenVisit();
}
Modified: trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTree.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTree.java 2010-11-29
20:44:15 UTC (rev 20215)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/component/AbstractTree.java 2010-11-29
20:52:25 UTC (rev 20216)
@@ -69,6 +69,7 @@
import org.richfaces.event.TreeToggleListener;
import org.richfaces.event.TreeToggleSource;
import org.richfaces.model.DeclarativeTreeDataModelImpl;
+import org.richfaces.model.DeclarativeTreeModel;
import org.richfaces.model.SwingTreeNodeDataModelImpl;
import org.richfaces.model.TreeDataModel;
import org.richfaces.model.TreeDataModelTuple;
@@ -131,9 +132,11 @@
selection
}
+ @SuppressWarnings("unused")
@Attribute(generate = false, signature = @Signature(returnType = Void.class,
parameters = TreeSelectionChangeEvent.class))
private MethodExpression selectionChangeListener;
+ @SuppressWarnings("unused")
@Attribute(generate = false, signature = @Signature(returnType = Void.class,
parameters = TreeToggleListener.class))
private MethodExpression toggleListener;
@@ -233,13 +236,10 @@
return converter;
}
- public AbstractTreeNode findTreeNodeComponent() {
- FacesContext facesContext = getFacesContext();
-
- String nodeType = getNodeType();
- Iterator<UIComponent> matchingNodes =
Iterators.filter(getChildren().iterator(),
+ protected AbstractTreeNode findTreeNodeComponent(String nodeType, UIComponent
parentComponent) {
+ Iterator<UIComponent> matchingNodes =
Iterators.filter(parentComponent.getChildren().iterator(),
new MatchingTreeNodePredicate(nodeType));
-
+
boolean hasNodes = matchingNodes.hasNext();
if (hasNodes) {
Iterator<UIComponent> renderedTreeNodes =
Iterators.filter(matchingNodes, ComponentPredicates.isRendered());
@@ -249,7 +249,40 @@
return null;
}
}
+
+ return null;
+ }
+ protected UIComponent getCurrentComponent() {
+ ExtendedDataModel<?> dataModel = getExtendedDataModel();
+ if (dataModel instanceof DeclarativeTreeModel) {
+ return ((DeclarativeTreeModel) dataModel).getCurrentComponent();
+ }
+
+ return this;
+ }
+
+ @Override
+ public void setRowKeyAndData(FacesContext facesContext, Object rowKey, Object
localRowData) {
+ super.setRowKeyAndData(facesContext, rowKey, localRowData);
+ }
+
+ public AbstractTreeNode findTreeNodeComponent() {
+ FacesContext facesContext = getFacesContext();
+
+ String nodeType = getNodeType();
+
+ UIComponent component = getCurrentComponent();
+
+ AbstractTreeNode treeNodeComponent = findTreeNodeComponent(nodeType, component);
+ if (treeNodeComponent == null && component != this) {
+ treeNodeComponent = findTreeNodeComponent(nodeType, this);
+ }
+
+ if (treeNodeComponent != null) {
+ return treeNodeComponent;
+ }
+
if (Strings.isNullOrEmpty(nodeType)) {
if (getAttributes().put(DEFAULT_TREE_NODE_CREATED, Boolean.TRUE) != null) {
return null;
@@ -462,6 +495,16 @@
public void exitNode() {
}
+
+ public void beforeChildrenVisit() {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void afterChildrenVisit() {
+ // TODO Auto-generated method stub
+
+ }
});
}
@@ -506,6 +549,8 @@
return;
}
+ dataVisitor.beforeChildrenVisit();
+
Iterator<TreeDataModelTuple> childrenTuples = model.children();
while (childrenTuples.hasNext()) {
TreeDataModelTuple tuple = childrenTuples.next();
@@ -522,6 +567,8 @@
dataVisitor.exitNode();
}
+
+ dataVisitor.afterChildrenVisit();
}
@Override
Modified:
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeModelKey.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeModelKey.java 2010-11-29
20:44:15 UTC (rev 20215)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeModelKey.java 2010-11-29
20:52:25 UTC (rev 20216)
@@ -89,6 +89,6 @@
@Override
public String toString() {
- return getModelId() + '.' + getModelKey();
+ return getModelId() + "." + getModelKey();
}
}
Modified:
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelImpl.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelImpl.java 2010-11-29
20:44:15 UTC (rev 20215)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeDataModelImpl.java 2010-11-29
20:52:25 UTC (rev 20216)
@@ -45,7 +45,7 @@
* @author Nick Belaevski
*
*/
-public class DeclarativeTreeDataModelImpl extends
TreeSequenceKeyModel<DeclarativeModelKey, Object> {
+public class DeclarativeTreeDataModelImpl extends
TreeSequenceKeyModel<DeclarativeModelKey, Object> implements DeclarativeTreeModel {
private static final Logger LOGGER = RichfacesLogger.MODEL.getLogger();
@@ -159,7 +159,7 @@
this.contextMap = contextMap;
}
- protected UIComponent getCurrentComponent() {
+ public UIComponent getCurrentComponent() {
return currentComponent;
}
Copied: trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeModel.java
(from rev 20215,
trunk/ui/iteration/api/src/main/java/org/richfaces/model/TreeDataVisitor.java)
===================================================================
--- trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeModel.java
(rev 0)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/model/DeclarativeTreeModel.java 2010-11-29
20:52:25 UTC (rev 20216)
@@ -0,0 +1,34 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.model;
+
+import javax.faces.component.UIComponent;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public interface DeclarativeTreeModel {
+
+ public UIComponent getCurrentComponent();
+
+}
Modified:
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderBase.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderBase.java 2010-11-29
20:44:15 UTC (rev 20215)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeEncoderBase.java 2010-11-29
20:52:25 UTC (rev 20216)
@@ -22,6 +22,7 @@
package org.richfaces.renderkit;
import java.io.IOException;
+import java.util.LinkedList;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
@@ -31,10 +32,57 @@
import org.richfaces.component.AbstractTree;
import org.richfaces.component.AbstractTreeNode;
import org.richfaces.component.util.HtmlUtil;
+import org.richfaces.model.TreeDataModelTuple;
import org.richfaces.model.TreeDataVisitor;
abstract class TreeEncoderBase implements TreeDataVisitor {
+ /**
+ * @author Nick Belaevski
+ *
+ */
+ private static final class QueuedData {
+
+ private boolean encoded = false;
+
+ private boolean visited = false;
+
+ //TODO - should be part of tree state
+ private boolean leaf;
+
+ private TreeDataModelTuple tuple;
+
+ public QueuedData(TreeDataModelTuple tuple, boolean leaf) {
+ super();
+ this.tuple = tuple;
+ this.leaf = leaf;
+ }
+
+ public boolean isEncoded() {
+ return encoded;
+ }
+
+ public void setEncoded(boolean encoded) {
+ this.encoded = encoded;
+ }
+
+ public void makeVisited() {
+ this.visited = true;
+ }
+
+ public boolean isVisited() {
+ return visited;
+ }
+
+ public TreeDataModelTuple getTuple() {
+ return tuple;
+ }
+
+ public boolean isLeaf() {
+ return leaf;
+ }
+ }
+
static final String TREE_NODE_STATE_ATTRIBUTE = "__treeNodeState";
protected final FacesContext context;
@@ -43,6 +91,8 @@
protected final AbstractTree tree;
+ private LinkedList<QueuedData> queuedDataList = new
LinkedList<QueuedData>();
+
public TreeEncoderBase(FacesContext context, AbstractTree tree) {
super();
this.context = context;
@@ -54,28 +104,80 @@
tree.walkModel(context, this);
}
- public void enterNode() {
- TreeNodeState state;
- if (tree.isLeaf()) {
- state = TreeNodeState.leaf;
+ protected void flushParentNode() throws IOException {
+ if (queuedDataList.isEmpty()) {
+ return;
+ }
+
+ QueuedData data = queuedDataList.getLast();
+ if (!data.isEncoded()) {
+ data.setEncoded(true);
+ tree.setRowKeyAndData(context, data.getTuple().getRowKey(),
data.getTuple().getData());
+
+ TreeNodeState nodeState = getNodeState(data.isLeaf(), false);
+
+ writeTreeNodeStartElement(nodeState);
+ tree.findTreeNodeComponent().encodeAll(context);
+ }
+ }
+
+ private TreeNodeState getNodeState(boolean leaf, boolean visited) {
+ TreeNodeState nodeState;
+ if (leaf) {
+ nodeState = TreeNodeState.leaf;
+ } else if (visited) {
+ nodeState = TreeNodeState.expandedNoChildren;
+ } else if (tree.isExpanded()) {
+ nodeState = TreeNodeState.expanded;
} else {
- if (tree.isExpanded()) {
- state = TreeNodeState.expanded;
- } else {
- state = TreeNodeState.collapsed;
- }
+ nodeState = TreeNodeState.collapsed;
}
+ return nodeState;
+ }
+
+ public void beforeChildrenVisit() {
+ if (!queuedDataList.isEmpty()) {
+ queuedDataList.getLast().makeVisited();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.richfaces.model.TreeDataVisitor#afterChildrenVisit()
+ */
+ public void afterChildrenVisit() {
+ // TODO Auto-generated method stub
+ }
+
+ public void enterNode() {
+ TreeDataModelTuple tuple = new TreeDataModelTuple(tree.getRowKey(),
tree.getRowData());
+ QueuedData queuedData = new QueuedData(tuple, tree.isLeaf());
+
try {
- writeTreeNodeStartElement(state);
- tree.findTreeNodeComponent().encodeAll(context);
+ flushParentNode();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
+
+ tree.setRowKeyAndData(context, tuple.getRowKey(), tuple.getData());
+ queuedDataList.add(queuedData);
}
public void exitNode() {
+ QueuedData data = queuedDataList.removeLast();
+
+ tree.setRowKeyAndData(context, data.getTuple().getRowKey(),
data.getTuple().getData());
+ if (!data.isEncoded()) {
+ try {
+ writeTreeNodeStartElement(getNodeState(data.isLeaf(),
data.isVisited()));
+ tree.findTreeNodeComponent().encodeAll(context);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
try {
writeTreeNodeEndElement();
} catch (IOException e) {
@@ -106,10 +208,9 @@
private void emitClientToggleEvent(AbstractTreeNode treeNode, TreeNodeState
nodeState) {
if
(treeNode.getClientId(context).equals(context.getAttributes().get(TreeNodeRendererBase.AJAX_TOGGLED_NODE_ATTRIBUTE)))
{
- TreeNodeState submittedState = ((Boolean)
(context.getAttributes().get(TreeNodeRendererBase.AJAX_TOGGLED_NODE_STATE_ATTRIBUTE)))
- ? TreeNodeState.expanded : TreeNodeState.collapsed;
+ TreeNodeState initialState = (TreeNodeState)
context.getAttributes().get(TreeNodeRendererBase.AJAX_TOGGLED_NODE_STATE_ATTRIBUTE);
- if (submittedState == nodeState || nodeState == TreeNodeState.leaf) {
+ if (initialState.isDifferentThan(nodeState)) {
AjaxContext ajaxContext = AjaxContext.getCurrentInstance(context);
ajaxContext.appendOncomplete(new
JSFunction("RichFaces.ui.TreeNode.emitToggleEvent",
treeNode.getClientId(context)));
}
Modified:
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeNodeRendererBase.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeNodeRendererBase.java 2010-11-29
20:44:15 UTC (rev 20215)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeNodeRendererBase.java 2010-11-29
20:52:25 UTC (rev 20216)
@@ -63,9 +63,10 @@
AbstractTreeNode treeNode = (AbstractTreeNode) component;
- boolean expanded = Boolean.valueOf(newToggleState);
- if (treeNode.isExpanded() ^ expanded) {
- new TreeToggleEvent(treeNode, expanded).queue();
+ boolean initialState = treeNode.isExpanded();
+ boolean newState = Boolean.valueOf(newToggleState);
+ if (initialState ^ newState) {
+ new TreeToggleEvent(treeNode, newState).queue();
}
PartialViewContext pvc = context.getPartialViewContext();
@@ -73,7 +74,7 @@
pvc.getRenderIds().add(treeNode.getClientId(context) +
MetaComponentResolver.META_COMPONENT_SEPARATOR_CHAR +
AbstractTreeNode.SUBTREE_META_COMPONENT_ID);
context.getAttributes().put(AJAX_TOGGLED_NODE_ATTRIBUTE,
component.getClientId(context));
- context.getAttributes().put(AJAX_TOGGLED_NODE_STATE_ATTRIBUTE,
expanded);
+ context.getAttributes().put(AJAX_TOGGLED_NODE_STATE_ATTRIBUTE,
initialState ? TreeNodeState.expanded : TreeNodeState.collapsed);
}
}
}
@@ -141,8 +142,8 @@
if (toggleType == SwitchType.client || nodeState ==
TreeNodeState.collapsed) {
encodeIconForNodeState(context, tree, treeNode,
TreeNodeState.collapsed, iconCollapsed);
}
-
- if (toggleType == SwitchType.client || nodeState ==
TreeNodeState.expanded) {
+
+ if (toggleType == SwitchType.client || nodeState ==
TreeNodeState.expanded || nodeState == TreeNodeState.expandedNoChildren) {
encodeIconForNodeState(context, tree, treeNode,
TreeNodeState.expanded, iconExpanded);
}
}
@@ -162,6 +163,7 @@
protected void addClientEventHandlers(FacesContext facesContext, UIComponent
component) {
AbstractTreeNode treeNode = (AbstractTreeNode) component;
+ //TODO check node state
//TODO check toggle/selection types
TreeRenderingContext renderingContext = TreeRenderingContext.get(facesContext);
renderingContext.addHandlers(treeNode);
Modified: trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeNodeState.java
===================================================================
---
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeNodeState.java 2010-11-29
20:44:15 UTC (rev 20215)
+++
trunk/ui/iteration/ui/src/main/java/org/richfaces/renderkit/TreeNodeState.java 2010-11-29
20:52:25 UTC (rev 20216)
@@ -29,28 +29,46 @@
public boolean isLeaf() {
return false;
}
- },
+
+ @Override
+ public boolean isDifferentThan(TreeNodeState anotherState) {
+ return anotherState != expandedNoChildren &&
super.isDifferentThan(anotherState);
+ }
+
+ },
+ expandedNoChildren("rf-tr-nd-exp rf-tr-nd-exp-nc",
"rf-trn-hnd-lf", "rf-trn-ico-exp") {
+ @Override
+ public boolean isLeaf() {
+ return false;
+ }
+
+ @Override
+ public boolean isDifferentThan(TreeNodeState anotherState) {
+ return anotherState != expanded &&
super.isDifferentThan(anotherState);
+ }
+ },
collapsed("rf-tr-nd-colps", "rf-trn-hnd-colps",
"rf-trn-ico-colps") {
@Override
public boolean isLeaf() {
return false;
}
- },
+ },
leaf("rf-tr-nd-lf", "rf-trn-hnd-lf", "rf-trn-ico-lf")
{
@Override
public boolean isLeaf() {
return true;
}
+
};
private String nodeClass;
private String handleClass;
-
+
private String iconClass;
private String customIconClass;
-
+
private TreeNodeState(String nodeClass, String defaultHandleClass, String iconClass)
{
this.nodeClass = nodeClass;
this.handleClass = HtmlUtil.concatClasses(defaultHandleClass,
"rf-trn-hnd");
@@ -59,7 +77,11 @@
}
public abstract boolean isLeaf();
-
+
+ public boolean isDifferentThan(TreeNodeState anotherState) {
+ return anotherState != this;
+ }
+
public String getNodeClass() {
return nodeClass;
}
Modified:
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js
===================================================================
---
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js 2010-11-29
20:44:15 UTC (rev 20215)
+++
trunk/ui/iteration/ui/src/main/resources/META-INF/resources/org.richfaces/tree.js 2010-11-29
20:52:25 UTC (rev 20216)
@@ -153,8 +153,12 @@
return this.__rootElt.hasClass("rf-tr-nd-lf");
},
+ __canBeToggled: function() {
+ return !this.isLeaf() &&
!this.__rootElt.hasClass("rf-tr-nd-exp-nc");
+ },
+
toggle: function() {
- if (this.isLeaf()) {
+ if (!this.__canBeToggled()) {
return;
}