Author: mvitenkov
Date: 2008-06-24 08:53:17 -0400 (Tue, 24 Jun 2008)
New Revision: 9183
Added:
trunk/test-applications/facelets/src/main/java/tree/TreeContainer.java
trunk/test-applications/facelets/src/main/java/tree/TreeDndBean.java
trunk/test-applications/facelets/src/main/resources/org/
trunk/test-applications/facelets/src/main/resources/org/richfaces/
trunk/test-applications/facelets/src/main/resources/org/richfaces/simpleTreeData.properties
Modified:
trunk/test-applications/facelets/src/main/webapp/Tree/Tree.xhtml
trunk/test-applications/facelets/src/main/webapp/WEB-INF/faces-config-Tree.xml
Log:
D'n'D API for rich:tree was added.
Added: trunk/test-applications/facelets/src/main/java/tree/TreeContainer.java
===================================================================
--- trunk/test-applications/facelets/src/main/java/tree/TreeContainer.java
(rev 0)
+++ trunk/test-applications/facelets/src/main/java/tree/TreeContainer.java 2008-06-24
12:53:17 UTC (rev 9183)
@@ -0,0 +1,44 @@
+/**
+ *
+ */
+package tree;
+
+import javax.faces.component.UIComponent;
+import javax.faces.event.FacesEvent;
+
+import org.richfaces.component.UITree;
+import org.richfaces.component.UITreeNode;
+
+/**
+ * @author dmorozov
+ *
+ */
+public class TreeContainer {
+
+ /**
+ * Get tree component from event
+ *
+ * @param event tree event
+ * @return tree component
+ */
+ protected UITree getTree(FacesEvent event) {
+ return getTree(event.getComponent());
+ }
+
+ /**
+ * Safe getter of tree component
+ * @param component component to process
+ * @return tree component
+ */
+ protected UITree getTree(UIComponent component) {
+ if (component instanceof UITree) {
+ return ((UITree) component);
+ }
+
+ if (component instanceof UITreeNode) {
+ return ((UITree) component.getParent());
+ }
+
+ return null;
+ }
+}
Added: trunk/test-applications/facelets/src/main/java/tree/TreeDndBean.java
===================================================================
--- trunk/test-applications/facelets/src/main/java/tree/TreeDndBean.java
(rev 0)
+++ trunk/test-applications/facelets/src/main/java/tree/TreeDndBean.java 2008-06-24
12:53:17 UTC (rev 9183)
@@ -0,0 +1,332 @@
+/**
+ *
+ */
+package tree;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+
+import org.ajax4jsf.context.AjaxContext;
+import org.richfaces.component.UITree;
+import org.richfaces.component.UITreeNode;
+import org.richfaces.event.DragEvent;
+import org.richfaces.event.DropEvent;
+import org.richfaces.event.NodeExpandedEvent;
+import org.richfaces.event.NodeSelectedEvent;
+import org.richfaces.model.TreeNode;
+import org.richfaces.model.TreeNodeImpl;
+import org.richfaces.model.TreeRowKey;
+/**
+ * @author mvitenkov
+ *
+ */
+public class TreeDndBean extends TreeContainer {
+ private static final String DATA_PATH1 =
"org/richfaces/simpleTreeData.properties";
+
+ private TreeNode<String> treeNodeLeft;
+
+ private TreeNode<String> treeNodeRight;
+
+ private String leftSelectedNodeTitle;
+
+ private String rightSelectedNodeTitle;
+
+ private UITree leftTree;
+
+ private UITree rightTree;
+
+ /**
+ * Helper tree model creation method from properties object
+ *
+ * @param path node path
+ * @param node parent node
+ * @param properties properties object
+ */
+ private void addNodes(String path, TreeNode<String> node, Properties
properties) {
+ boolean end = false;
+ int counter = 1;
+ while (!end) {
+ String key = path != null ? path + '.' + counter : String.valueOf(counter);
+ String value = properties.getProperty(key);
+ if (value != null) {
+ TreeNodeImpl<String> nodeImpl = new TreeNodeImpl<String>();
+ nodeImpl.setData(value);
+ node.addChild(new Integer(counter), nodeImpl);
+ addNodes(key, nodeImpl, properties);
+ counter++;
+ } else {
+ end = true;
+ }
+ }
+ }
+
+ /**
+ * Init sample tree model
+ *
+ * @return tree model
+ */
+ private TreeNode<String> initPaneTree() {
+ TreeNode<String> rootNode = null;
+ FacesContext facesContext = FacesContext.getCurrentInstance();
+ ExternalContext externalContext = facesContext.getExternalContext();
+
+ InputStream dataStream =
this.getClass().getClassLoader().getResourceAsStream(DATA_PATH1);
+
+ try {
+ Properties properties = new Properties();
+ properties.load(dataStream);
+ rootNode = new TreeNodeImpl<String>();
+ addNodes(null, rootNode, properties);
+ } catch (IOException e) {
+
+ throw new FacesException(e.getMessage(), e);
+
+ } finally {
+ if (dataStream != null) {
+ try {
+ dataStream.close();
+ } catch (IOException e) {
+ externalContext.log(e.getMessage(), e);
+ }
+ }
+ }
+
+ return rootNode;
+ }
+
+ /**
+ * Left tree demo selection handler.
+ * @param event node selection event
+ */
+ public void processLSelection(NodeSelectedEvent event) {
+ UITree tree = (UITree) event.getComponent();
+ leftSelectedNodeTitle = (String) tree.getRowData();
+ }
+
+ /**
+ * Right tree demo selection handler.
+ * @param event node selection event
+ */
+ public void processRSelection(NodeSelectedEvent event) {
+ UITree tree = (UITree) event.getComponent();
+ if (tree != null) {
+ rightSelectedNodeTitle = (String) tree.getRowData();
+ }
+ }
+
+ /**
+ * Left tree value binding
+ * @return the treeNodeLeft
+ */
+ public TreeNode<String> getTreeNodeLeft() {
+ if (treeNodeLeft == null) {
+ treeNodeLeft = initPaneTree();
+ }
+ return treeNodeLeft;
+ }
+
+ /**
+ * Left tree value binding
+ * @param treeNodeLeft
+ * the treeNodeLeft to set
+ */
+ public void setTreeNodeLeft(TreeNode<String> treeNodeLeft) {
+ this.treeNodeLeft = treeNodeLeft;
+ }
+
+ /**
+ * @return the leftSelectedNodeTitle
+ */
+ public String getLeftSelectedNodeTitle() {
+ return leftSelectedNodeTitle;
+ }
+
+ /**
+ * @param leftSelectedNodeTitle
+ * the leftSelectedNodeTitle to set
+ */
+ public void setLeftSelectedNodeTitle(String leftSelectedNodeTitle) {
+ this.leftSelectedNodeTitle = leftSelectedNodeTitle;
+ }
+
+ /**
+ * @return the rightSelectedNodeTitle
+ */
+ public String getRightSelectedNodeTitle() {
+ return rightSelectedNodeTitle;
+ }
+
+ /**
+ * @param rightSelectedNodeTitle
+ * the rightSelectedNodeTitle to set
+ */
+ public void setRightSelectedNodeTitle(String rightSelectedNodeTitle) {
+ this.rightSelectedNodeTitle = rightSelectedNodeTitle;
+ }
+
+ /**
+ * Right tree value binding
+ * @return the treeNodeRight
+ */
+ public TreeNode<String> getTreeNodeRight() {
+ if (treeNodeRight == null) {
+ treeNodeRight = initPaneTree();
+ }
+ return treeNodeRight;
+ }
+
+ /**
+ * Right tree value binding
+ * @param treeNodeRight
+ * the treeNodeRight to set
+ */
+ public void setTreeNodeRight(TreeNode<String> treeNodeRight) {
+ this.treeNodeRight = treeNodeRight;
+ }
+
+ /**
+ * Left tree binding
+ * @return the leftTree
+ */
+ public UITree getLeftTree() {
+ return leftTree;
+ }
+
+ /**
+ * Left tree binding
+ * @param leftTree
+ * the leftTree to set
+ */
+ public void setLeftTree(UITree leftTree) {
+ this.leftTree = leftTree;
+ }
+
+ /**
+ * Right tree binding
+ * @return the rightTree
+ */
+ public UITree getRightTree() {
+ return rightTree;
+ }
+
+ /**
+ * Right tree binding
+ * @param rightTree
+ * the rightTree to set
+ */
+ public void setRightTree(UITree rightTree) {
+ this.rightTree = rightTree;
+ }
+
+ /**
+ * Expand event handler
+ * @param event expand event
+ */
+ public void onExpand(NodeExpandedEvent event) {
+ UITree tree = getTree(event);
+ System.out.println("Tree ('"+tree.getId()+"') node " +
(tree.isExpanded() ? "expanded" : "collapsed") + " " +
tree.getRowKey());
+ }
+
+ /**
+ * Drag event handler
+ * @param dragEvent event handler
+ */
+ public void onDrag(DragEvent dragEvent) {
+ System.out.println("onDrag occured.");
+ System.out.println("DragValue: " + dragEvent.getDragValue());
+ System.out.println("DropValue: " + dragEvent.getDropValue());
+ }
+
+ /**
+ * Sample unique subnode identifier generation
+ *
+ * @param parentNode parent node
+ * @return unique subnode identifier
+ */
+ private Object getNewId(TreeNode parentNode) {
+ Map<Object, TreeNode> childs = new HashMap<Object, TreeNode>();
+ Iterator<Map.Entry<Object, TreeNode>> iter = parentNode.getChildren();
+ while (iter != null && iter.hasNext()) {
+ Map.Entry<Object, TreeNode> entry = iter.next();
+ childs.put(entry.getKey(), entry.getValue());
+ }
+
+ Integer index = 1;
+ while (childs.containsKey(index)) {
+ index++;
+ }
+ return index;
+ }
+
+ /**
+ * Drop event handler
+ * @param dropEvent Drop event
+ */
+ public void onDrop(DropEvent dropEvent) {
+ System.out.println("onDrop occured.");
+ System.out.println("DragValue: " + dropEvent.getDragValue());
+ System.out.println("DropValue: " + dropEvent.getDropValue());
+
+ // resolve drag source attributes
+ UITreeNode srcNode = (dropEvent.getDraggableSource() instanceof UITreeNode) ?
(UITreeNode) dropEvent.getDraggableSource() : null;
+ UITree srcTree = srcNode != null ? srcNode.getUITree() : null;
+ TreeRowKey dragNodeKey = (dropEvent.getDragValue() instanceof TreeRowKey) ? (TreeRowKey)
dropEvent.getDragValue() : null;
+
+ // resolve drag destination attributes
+ UITreeNode destNode = (dropEvent.getSource() instanceof UITreeNode) ? (UITreeNode)
dropEvent.getSource() : null;
+ UITree destTree = destNode != null ? destNode.getUITree() : getTree(dropEvent);
+ TreeRowKey dropNodeKey = (dropEvent.getDropValue() instanceof TreeRowKey) ? (TreeRowKey)
dropEvent.getDropValue() : null;
+
+ FacesContext context = FacesContext.getCurrentInstance();
+
+ if (dropNodeKey != null) {
+ // add destination node for rerender
+ destTree.addRequestKey(dropNodeKey);
+
+ Object state = null;
+ TreeNode draggedNode = null;
+ if (dragNodeKey != null) { // Drag from this or other tree
+ draggedNode = srcTree.getTreeNode(dragNodeKey);
+
+ TreeNode parentNode = draggedNode.getParent();
+ // 1. remove node from tree
+ state = srcTree.removeNode(dragNodeKey);
+ // 2. add parent for rerender
+ Object rowKey = srcTree.getTreeNodeRowKey(parentNode);
+ srcTree.addRequestKey(rowKey);
+ } else if (dropEvent.getDragValue() != null) { // Drag from some drag source
+ draggedNode = new TreeNodeImpl<String>();
+ draggedNode.setData(dropEvent.getDragValue().toString());
+ }
+
+ // generate new node id
+ Object id = getNewId(destTree.getTreeNode(dropNodeKey));
+ destTree.addNode(dropNodeKey, draggedNode, id, state);
+ }
+
+ AjaxContext ac = AjaxContext.getCurrentInstance();
+ // Add destination tree to reRender
+ try {
+ ac.addComponentToAjaxRender(destTree);
+ } catch (Exception e) {
+ System.err.print(e.getMessage());
+ }
+
+ // Add source tree to reRender
+ try {
+ ac.addComponentToAjaxRender(srcTree);
+ } catch (Exception e) {
+ System.err.print(e.getMessage());
+ }
+
+ System.out.println("+++++");
+ }
+}
Added:
trunk/test-applications/facelets/src/main/resources/org/richfaces/simpleTreeData.properties
===================================================================
---
trunk/test-applications/facelets/src/main/resources/org/richfaces/simpleTreeData.properties
(rev 0)
+++
trunk/test-applications/facelets/src/main/resources/org/richfaces/simpleTreeData.properties 2008-06-24
12:53:17 UTC (rev 9183)
@@ -0,0 +1,67 @@
+1=Daniel Defo
+1.1=Robinson Crusoe
+1.1.1=Start In Life
+1.1.2=Slavery And Escape
+1.1.3=Wrecked On A Desert Island
+1.1.4=First Weeks On The Island
+1.1.5=Builds A House - The Journal
+1.1.6=Ill And Conscience-Stricken
+1.1.7=Agricultural Experience
+1.1.8=Surveys His Position
+1.1.9=A Boat
+1.1.10=Tames Goats
+1.1.11=Finds Print Of Man's Foot On The Sand
+1.1.12=A Cave Retreat
+1.1.13=Wreck Of A Spanish Ship
+1.1.14=A Dream Realised
+1.1.15=Friday's Education
+1.1.16=Rescue Of Prisoners From Cannibals
+1.1.17=Visit Of Mutineers
+1.1.18=The Ship Recovered
+1.1.19=Return To England
+1.1.20=Fight Between Friday And A Bear
+2=Edgar Allan Poe
+2.1=Plays
+2.1.1=Politian
+2.2=Short stories
+2.2.1=The Assignation
+2.2.2=Berenice
+2.2.3=The Black Cat
+2.2.4=The Cask of Amontillado
+2.2.5=A Descent into the Maelstrom
+2.3=Poetry
+2.3.1=Alone
+2.3.2=An Enigma
+2.3.3=Annabel Lee
+2.3.4=Bridal Ballad
+3=Henry Wadsworth Longfellow
+3.1=The Song of Hiawatha
+3.1.1=Introduction
+3.1.2=I. The Peace-Pipe
+3.1.3=II. The Four Winds
+3.1.4=III. Hiawatha's Childhood
+3.1.5=IV. Hiawatha and Mudjekeewis
+3.1.6=V. Hiawatha's Fasting
+3.1.7=VI. Hiawatha's Friends
+3.1.8=VII. Hiawatha's Sailing
+3.1.9=VIII. Hiawatha's Fishing
+3.1.10=IX. Hiawatha and the Pearl-Feather
+3.1.11=X. Hiawatha's Wooing
+3.1.12=XI. Hiawatha's Wedding-Feast
+3.1.13=XII. The Son of the Evening Star
+3.1.14=XIII. Blessing the Cornfields
+3.1.15=XIV. Picture-Writing
+3.1.16=XV. Hiawatha's Lamentation
+3.1.17=XVI. Pau-Puk-Keewis
+3.1.18=XVII. The Hunting of Pau-Puk-Keewis
+3.1.19=XVIII. The Death of Kwasind
+3.1.20=XIX. The Ghosts
+3.1.21=XX. The Famine
+3.1.22=XXI. The White Man's Foot
+3.1.23=XXII. Hiawatha's Departure
+3.2=Poetry
+3.2.1=A Psalm Of Life
+3.2.2=Birds Of Passage
+3.2.3=Hiawatha's Childhood
+3.2.4=Hymn To The Night
+
Modified: trunk/test-applications/facelets/src/main/webapp/Tree/Tree.xhtml
===================================================================
--- trunk/test-applications/facelets/src/main/webapp/Tree/Tree.xhtml 2008-06-24 12:44:11
UTC (rev 9182)
+++ trunk/test-applications/facelets/src/main/webapp/Tree/Tree.xhtml 2008-06-24 12:53:17
UTC (rev 9183)
@@ -1,5 +1,34 @@
<f:subview
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:rich="http://richfaces.org/rich" id="treeSubviewID">
+<style type="text/css">
+.LeftTreePane {
+
+}
+
+.RightTreePane {
+
+}
+
+.TreeContainer {
+ overflow: auto;
+ height: 400px;
+ border: 3px inset gray;
+}
+</style>
+<script type="text/javascript">
+ // <![CDATA[
+ function blinkElement(elt) {
+ while (elt.tagName.toLowerCase() != 'table') {
+ elt = elt.parentNode;
+ }
+
+ elt.style.borderColor= '#5555FF';
+ elt.style.borderStyle= 'dotted';
+ elt.style.borderWidth = '3px';
+ setTimeout( function() { this.style.borderStyle = 'none'; }.bind(elt), 300);
+ }
+ // ]]>
+ </script>
<a4j:outputPanel ajaxRendered="true">
<h:messages />
</a4j:outputPanel>
@@ -101,4 +130,65 @@
</rich:tree>
<rich:spacer></rich:spacer>
+ <!-- Drag and Drop API for rich:tree component -->
+ <div style="FONT-WEIGHT: bold;">Drag and Drop example</div>
+ <br />
+ <h:form>
+ <rich:dragIndicator id="treeIndicator">
+ <f:facet name="single">
+ <f:verbatim>{marker} {nodeParam}({treeParam})</f:verbatim>
+ </f:facet>
+ </rich:dragIndicator>
+
+ <h:panelGrid columns="2"
columnClasses="LeftTreePane,RightTreePane">
+
+ <h:panelGroup id="leftContainer" layout="block"
+ styleClass="TreeContainer">
+ <h:outputText escape="false"
+ value="Selected Node: #{treeDndBean.leftSelectedNodeTitle}"
+ id="selectedNodeL" />
+
+ <rich:tree id="leftTree" style="width:300px"
+ nodeSelectListener="#{treeDndBean.processLSelection}"
+ reRender="selectedNodeL" ajaxSubmitSelection="true"
+ switchType="client" value="#{treeDndBean.treeNodeLeft}"
+ changeExpandListener="#{treeDndBean.onExpand}"
+ binding="#{treeDndBean.leftTree}"
+ onselected="window.status='selectedNode: '+event.selectedNode;"
+ onexpand="window.status='expandedNode: '+event.expandedNode"
+ oncollapse="window.status='collapsedNode: '+event.collapsedNode"
+ dropListener="#{treeDndBean.onDrop}"
+ dragListener="#{treeDndBean.onDrag}"
dragIndicator="treeIndicator"
+ acceptedTypes="treeNode" dragType="treeNode"
rowKeyVar="key"
+ var="item" >
+
+ <rich:dndParam name="treeParam" value="leftTree" />
+ </rich:tree>
+
+ </h:panelGroup>
+
+ <h:panelGroup id="rightContainer" layout="block"
+ styleClass="TreeContainer">
+ <h:outputText escape="false"
+ value="Selected Node: #{treeDndBean.rightSelectedNodeTitle}"
+ id="selectedNodeR" />
+
+ <rich:tree id="rightTree" style="width:300px"
+ nodeSelectListener="#{treeDndBean.processRSelection}"
+ reRender="selectedNodeR,rightContainer"
ajaxSubmitSelection="true"
+ switchType="client" value="#{treeDndBean.treeNodeRight}"
+ changeExpandListener="#{treeDndBean.onExpand}"
+ binding="#{treeDndBean.rightTree}"
+ onselected="window.status='selectedNode: '+event.selectedNode;"
+ onexpand="window.status='expandedNode: '+event.expandedNode"
+ oncollapse="window.status='collapsedNode: '+event.collapsedNode"
+ rowKeyVar="key" dropListener="#{treeDndBean.onDrop}"
+ dragListener="#{treeDndBean.onDrag}"
dragIndicator="treeIndicator"
+ acceptedTypes="treeNode" dragType="treeNode"
var="item">
+ <rich:dndParam name="treeParam" value="rightTree" />
+ </rich:tree>
+ </h:panelGroup>
+
+ </h:panelGrid>
+ </h:form>
</f:subview>
Modified: trunk/test-applications/facelets/src/main/webapp/WEB-INF/faces-config-Tree.xml
===================================================================
---
trunk/test-applications/facelets/src/main/webapp/WEB-INF/faces-config-Tree.xml 2008-06-24
12:44:11 UTC (rev 9182)
+++
trunk/test-applications/facelets/src/main/webapp/WEB-INF/faces-config-Tree.xml 2008-06-24
12:53:17 UTC (rev 9183)
@@ -8,6 +8,11 @@
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
+ <managed-bean-name>treeDndBean</managed-bean-name>
+ <managed-bean-class>tree.TreeDndBean</managed-bean-class>
+ <managed-bean-scope>session</managed-bean-scope>
+ </managed-bean>
+ <managed-bean>
<managed-bean-name>pathwayBean</managed-bean-name>
<managed-bean-class>tree.TreeBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>