RichTree Drag and Drop Exception
mazumder.sanjay Dec 16, 2008 1:38 PMHi Friends,
I am using Seam for developing my application. In one scenario i need to use rich:tree component with drag and drop behavior.
But i am getting problem with droplistener method. As it is giving the null pointer exception. Could you please send me some demo of how to implement this feature into my application.
Following are the codes which I've used:
--------------------------------------------------------------
dnd.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<style>
.col1, .col2 {
width:50%;
vertical-align:top;
}
.rich-table-cell, .rich-table{
border:none;
}
.indicatorPicture {
width: 80px;
}
</style>
<rich:dragIndicator id="indicator1" >
<f:facet name="single">
<h:graphicImage styleClass="indicatorPicture" value="/richfaces/jQuery/images/{draggedImage}" />
</f:facet>
</rich:dragIndicator>
<rich:dragIndicator id="indicator2" />
<h:form>
<h:panelGrid columns="2" width="100%" columnClasses="col1,col2">
<rich:tree ajaxKeys="#{null}" style="width:300px" nodeSelectListener="#{simpleTreeDndBean.processSelection}"
reRender="selectedNode" ajaxSubmitSelection="true" switchType="client" dragIndicator="indicator2"
value="#{simpleTreeDndBean.treeNode}" var="item" id="tree" treeNodeVar="treeNode"
dropListener="#{simpleTreeDndBean.dropListener}" nodeFace="#{treeNode.parent.parent == null ? 'node' : 'leaf'}">
<rich:treeNode type="node" acceptedTypes="pic" icon="#{treeNode.icon}" iconLeaf="#{treeNode.leafIcon}">
<h:outputText value="#{item}"/>
</rich:treeNode>
<rich:treeNode type="leaf" dragType="pic">
<rich:dndParam name="label" type="drag">#{item}</rich:dndParam>
<h:outputText value="#{item}"/>
</rich:treeNode>
</rich:tree>
<rich:panel id="selectedNode">
<rich:dataGrid id="selectedNodeGrid" style="display: #{!empty simpleTreeDndBean.selectedNodeChildren ? '' : 'none'}" value="#{simpleTreeDndBean.selectedNodeChildren}" var="item" columns="3" border="0">
<rich:dragSupport dragIndicator="indicator1" dragType="pic" dragValue="#{item}" reRender="selectedNodeGrid">
<rich:dndParam name="draggedImage" value="#{item.data}"/>
</rich:dragSupport>
<h:graphicImage value="/richfaces/jQuery/images/#{item.data}" />
</rich:dataGrid>
</rich:panel>
</h:panelGrid>
</h:form>
</ui:composition>
-------------------------------------------
DemoTreeNodeImpl.java
package com.mct.mctApps.sessionbean;
//package org.richfaces.demo.tree;
import org.jboss.seam.annotations.Name;
import org.richfaces.model.TreeNodeImpl;
@Name("demoTreeNodeImpl")
public class DemoTreeNodeImpl<T> extends TreeNodeImpl<T>{
private String type;
/**
* @return the type
*/
public String getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(String type) {
this.type = type;
}
}
---------------------------------------------------------
simple-tree-data-dnd.properties
#path=name - type
1=Unsorted - node
1.1=pic1.jpg - leaf
1.2=pic2.jpg - leaf
1.3=pic3.jpg - leaf
1.4=pic4.jpg - leaf
1.5=pic5.jpg - leaf
1.6=pic6.jpg - leaf
2 = Favorites - node
2.1=pic7.jpg - leaf
3 =Trash - node
3.1=pic8.jpg - leaf
----------------------------------------------------------
SimpleTreeDndBean.java
/**
* License Agreement.
*
* JBoss RichFaces - Ajax4jsf Component Library
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.richfaces.demo.tree;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
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.UIDragSupport;
import org.richfaces.component.UITree;
import org.richfaces.component.UITreeNode;
import org.richfaces.component.html.HtmlTree;
import org.richfaces.event.DropEvent;
import org.richfaces.event.NodeSelectedEvent;
import org.richfaces.model.TreeNode;
import org.richfaces.model.TreeRowKey;
public class SimpleTreeDndBean {
private TreeNode rootNode = null;
private List<TreeNode<String>> selectedNodeChildren = new ArrayList<TreeNode<String>>();
private String nodeTitle;
private static final String DATA_PATH = "/richfaces/tree/examples/simple-tree-data-dnd.properties";
private void addNodes(String path, TreeNode 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) {
DemoTreeNodeImpl nodeImpl = new DemoTreeNodeImpl();
String[] splittedValue = value.split(" - ");
if (splittedValue.length > 1) {
nodeImpl.setData(splittedValue[0]);
nodeImpl.setType(splittedValue[1]);
node.addChild(new Integer(counter), nodeImpl);
}
addNodes(key, nodeImpl, properties);
counter++;
} else {
end = true;
}
}
}
private void loadTree() {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
InputStream dataStream = externalContext.getResourceAsStream(DATA_PATH);
try {
Properties properties = new Properties();
properties.load(dataStream);
rootNode = new DemoTreeNodeImpl();
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);
}
}
}
}
public void processSelection(NodeSelectedEvent event) {
HtmlTree tree = (HtmlTree) event.getComponent();
nodeTitle = (String) tree.getRowData();
selectedNodeChildren.clear();
TreeNode<String> currentNode = tree.getModelTreeNode(tree.getRowKey());
DemoTreeNodeImpl<String> demoCurrentNodeImpl = currentNode instanceof DemoTreeNodeImpl ? (DemoTreeNodeImpl) currentNode : null;
if (currentNode.isLeaf() && (demoCurrentNodeImpl != null && demoCurrentNodeImpl.getType().toLowerCase().equals("leaf") demoCurrentNodeImpl == null )) {
selectedNodeChildren.add(currentNode);
} else {
Iterator<Map.Entry<Object, TreeNode<String>>> it = currentNode.getChildren();
while (it != null && it.hasNext()) {
Map.Entry<Object, TreeNode<String>> entry = it.next();
selectedNodeChildren.add(entry.getValue());
}
}
}
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;
}
public void dropListener(DropEvent dropEvent) {
// resolve drag destination attributes
UITreeNode destNode = (dropEvent.getSource() instanceof UITreeNode) ? (UITreeNode) dropEvent.getSource() : null;
UITree destTree = destNode != null ? destNode.getUITree() : null;
TreeRowKey dropNodeKey = (dropEvent.getDropValue() instanceof TreeRowKey) ? (TreeRowKey) dropEvent.getDropValue() : null;
TreeNode droppedInNode = dropNodeKey != null ? destTree.getTreeNode(dropNodeKey) : null;
// 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;
TreeNode draggedNode = dragNodeKey != null ? srcTree.getTreeNode(dragNodeKey) : null;
if (dropEvent.getDraggableSource() instanceof UIDragSupport && srcTree == null && draggedNode == null && dropEvent.getDragValue() instanceof TreeNode) {
srcTree = destTree;
draggedNode = (TreeNode) dropEvent.getDragValue();
dragNodeKey = srcTree.getTreeNodeRowKey(draggedNode) instanceof TreeRowKey ? (TreeRowKey) srcTree.getTreeNodeRowKey(draggedNode) : null;
}
// Note: check if we dropped node on to itself or to item instead of
// folder here
if (droppedInNode != null && (droppedInNode.equals(draggedNode) droppedInNode.getParent().getParent() != null draggedNode.getParent().getParent() == null)) {
System.out.println("Warning: Can't drop on itself or to pic itself! Also can't move folders");
return;
}
FacesContext context = FacesContext.getCurrentInstance();
if (dropNodeKey != null) {
// add destination node for rerender
destTree.addRequestKey(dropNodeKey);
Object state = null;
if (dragNodeKey != null) { // Drag from this or other tree
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);
if (dropEvent.getDraggableSource() instanceof UIDragSupport) {
selectedNodeChildren.remove(draggedNode);
// if node was gragged in it's parent place dragged node to
// the end of selected nodes in grid
if (droppedInNode.equals(parentNode)) {
selectedNodeChildren.add(draggedNode);
}
}
} else if (dropEvent.getDragValue() != null) { // Drag from some
// drag source
draggedNode = new DemoTreeNodeImpl<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());
}
}
public List<TreeNode<String>> getSelectedNodeChildren() {
return selectedNodeChildren;
}
public void setSelectedNodeChildren(List<TreeNode<String>> selectedNodeChildren) {
this.selectedNodeChildren = selectedNodeChildren;
}
public TreeNode getTreeNode() {
if (rootNode == null) {
loadTree();
}
return rootNode;
}
public String getNodeTitle() {
return nodeTitle;
}
public void setNodeTitle(String nodeTitle) {
this.nodeTitle = nodeTitle;
}
}