import org.primefaces.event.NodeSelectEvent;
import org.primefaces.event.NodeUnselectEvent;
import org.primefaces.event.NodeExpandEvent;
import org.primefaces.event.NodeCollapseEvent;
import org.primefaces.event.TreeDragDropEvent;
import javax.faces.component.UIComponent;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.HashMap;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.lang.StringBuilder;
import javax.faces.context.FacesContext;
import org.primefaces.model.TreeNode;
import javax.faces.event.FacesEvent;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.PhaseId;
import org.primefaces.component.tree.UITreeNode;
import org.primefaces.util.Constants;
import org.primefaces.model.TreeNode;
private static final Collection<String> EVENT_NAMES = Collections.unmodifiableCollection(Arrays.asList("select","unselect", "expand", "collapse", "dragdrop", "contextMenu"));
private Map<String,UITreeNode> nodes;
public UITreeNode getUITreeNodeByType(String type) {
UITreeNode node = getTreeNodes().get(type);
if(node == null)
throw new javax.faces.FacesException("Unsupported tree node type:" + type);
else
return node;
}
private boolean isRequestSource(FacesContext context) {
return this.getClientId(context).equals(context.getExternalContext().getRequestParameterMap().get(Constants.RequestParams.PARTIAL_SOURCE_PARAM));
}
public boolean isNodeExpandRequest(FacesContext context) {
return context.getExternalContext().getRequestParameterMap().containsKey(this.getClientId(context) + "_expandNode");
}
public boolean isSelectionRequest(FacesContext context) {
return context.getExternalContext().getRequestParameterMap().containsKey(this.getClientId(context) + "_instantSelection");
}
public static String CONTAINER_CLASS = "ui-tree ui-widget ui-widget-content ui-corner-all";
public static String CONTAINER_RTL_CLASS = "ui-tree ui-tree-rtl ui-widget ui-widget-content ui-corner-all";
public static String HORIZONTAL_CONTAINER_CLASS = "ui-tree ui-tree-horizontal ui-widget ui-widget-content ui-corner-all";
public static String ROOT_NODES_CLASS = "ui-tree-container";
public static String PARENT_NODE_CLASS = "ui-treenode ui-treenode-parent";
public static String LEAF_NODE_CLASS = "ui-treenode ui-treenode-leaf";
public static String CHILDREN_NODES_CLASS = "ui-treenode-children";
public static String NODE_CONTENT_CLASS_V = "ui-treenode-content";
public static String SELECTABLE_NODE_CONTENT_CLASS_V = "ui-treenode-content ui-tree-selectable";
public static String NODE_CONTENT_CLASS_H = "ui-treenode-content ui-state-default ui-corner-all";
public static String SELECTABLE_NODE_CONTENT_CLASS_H = "ui-treenode-content ui-tree-selectable ui-state-default ui-corner-all";
public static String EXPANDED_ICON_CLASS_V = "ui-tree-toggler ui-icon ui-icon-triangle-1-s";
public static String COLLAPSED_ICON_CLASS_V = "ui-tree-toggler ui-icon ui-icon-triangle-1-e";
public static String COLLAPSED_ICON_RTL_CLASS_V = "ui-tree-toggler ui-icon ui-icon-triangle-1-w";
public static String EXPANDED_ICON_CLASS_H = "ui-tree-toggler ui-icon ui-icon-minus";
public static String COLLAPSED_ICON_CLASS_H = "ui-tree-toggler ui-icon ui-icon-plus";
public static String LEAF_ICON_CLASS = "ui-treenode-leaf-icon";
public static String NODE_ICON_CLASS = "ui-treenode-icon ui-icon";
public static String NODE_LABEL_CLASS = "ui-treenode-label ui-corner-all";
public Map<String,UITreeNode> getTreeNodes() {
if(nodes == null) {
nodes = new HashMap<String,UITreeNode>();
for(UIComponent child : getChildren()) {
UITreeNode node = (UITreeNode) child;
nodes.put(node.getType(), node);
}
}
return nodes;
}
@Override
public Collection<String> getEventNames() {
return EVENT_NAMES;
}
@Override
public void queueEvent(FacesEvent event) {
FacesContext context = getFacesContext();
if(isRequestSource(context) && event instanceof AjaxBehaviorEvent) {
Map<String,String> params = context.getExternalContext().getRequestParameterMap();
String eventName = params.get(Constants.RequestParams.PARTIAL_BEHAVIOR_EVENT_PARAM);
String clientId = this.getClientId(context);
FacesEvent wrapperEvent = null;
AjaxBehaviorEvent behaviorEvent = (AjaxBehaviorEvent) event;
if(eventName.equals("expand")) {
this.setRowKey(params.get(clientId + "_expandNode"));
TreeNode expandedNode = this.getRowNode();
expandedNode.setExpanded(true);
wrapperEvent = new NodeExpandEvent(this, behaviorEvent.getBehavior(), expandedNode);
}
else if(eventName.equals("collapse")) {
this.setRowKey(params.get(clientId + "_collapseNode"));
TreeNode collapsedNode = this.getRowNode();
collapsedNode.setExpanded(false);
wrapperEvent = new NodeCollapseEvent(this, behaviorEvent.getBehavior(), collapsedNode);
}
else if(eventName.equals("select")) {
setRowKey(params.get(clientId + "_instantSelection"));
wrapperEvent = new NodeSelectEvent(this, behaviorEvent.getBehavior(), this.getRowNode());
}
else if(eventName.equals("unselect")) {
setRowKey(params.get(clientId + "_instantUnselection"));
wrapperEvent = new NodeUnselectEvent(this, behaviorEvent.getBehavior(), this.getRowNode());
}
else if(eventName.equals("dragdrop")) {
int dndIndex = Integer.parseInt(params.get(clientId + "_dndIndex"));
wrapperEvent = new TreeDragDropEvent(this, behaviorEvent.getBehavior(), dragNode, dropNode, dndIndex);
}
else if(eventName.equals("contextMenu")) {
setRowKey(params.get(clientId + "_contextMenuNode"));
wrapperEvent = new NodeSelectEvent(this, behaviorEvent.getBehavior(), this.getRowNode(), true);
}
wrapperEvent.setPhaseId(behaviorEvent.getPhaseId());
super.queueEvent(wrapperEvent);
this.setRowKey(null);
}
else {
super.queueEvent(event);
}
}
private boolean isToggleRequest(FacesContext context) {
Map<String,String> params = context.getExternalContext().getRequestParameterMap();
String clientId = getClientId(context);
return params.get(clientId + "_expandNode") != null || params.get(clientId + "_collapseNode") != null;
}
public boolean isDragDropRequest(FacesContext context) {
Map<String,String> params = context.getExternalContext().getRequestParameterMap();
String clientId = getClientId(context);
String source = context.getExternalContext().getRequestParameterMap().get(Constants.RequestParams.PARTIAL_SOURCE_PARAM);
return clientId.equals(source) && params.get(clientId + "_dragdrop") != null;
}
@Override
public void processDecodes(FacesContext context) {
if(isToggleRequest(context)) {
this.decode(context);
}
else {
super.processDecodes(context);
}
}
@Override
public void processValidators(FacesContext context) {
if(!isToggleRequest(context)) {
super.processValidators(context);
}
}
@Override
public void processUpdates(FacesContext context) {
if(isToggleRequest(context)) {
this.updateSelection(context);
}
else {
super.processUpdates(context);
}
}
public boolean isCheckboxSelection() {
String selectionMode = this.getSelectionMode();
return selectionMode != null && selectionMode.equals("checkbox");
}
public boolean isRTL() {
return this.getDir().equalsIgnoreCase("rtl");
}
private TreeNode dragNode;
private TreeNode dropNode;
TreeNode getDragNode() {
return dragNode;
}
void setDragNode(TreeNode dragNode) {
this.dragNode = dragNode;
}
TreeNode getDropNode() {
return dropNode;
}
void setDropNode(TreeNode dropNode) {
this.dropNode = dropNode;
}
@Override
protected boolean shouldVisitNode(TreeNode node) {
return this.isDynamic() ? (node.isExpanded() || node.getParent() == null) : true;
}
@Override
protected void processColumnChildren(FacesContext context, PhaseId phaseId, String nodeKey) {
setRowKey(nodeKey);
TreeNode treeNode = this.getRowNode();
if(treeNode == null)
return;
String treeNodeType = treeNode.getType();
for(UIComponent child : getChildren()) {
if(child instanceof UITreeNode && child.isRendered()) {
UITreeNode uiTreeNode = (UITreeNode) child;
if(!treeNodeType.equals(uiTreeNode.getType()))
continue;
for(UIComponent grandkid : child.getChildren()) {
if(!grandkid.isRendered())
continue;
if(phaseId == PhaseId.APPLY_REQUEST_VALUES)
grandkid.processDecodes(context);
else if(phaseId == PhaseId.PROCESS_VALIDATIONS)
grandkid.processValidators(context);
else if(phaseId == PhaseId.UPDATE_MODEL_VALUES)
grandkid.processUpdates(context);
else
throw new IllegalArgumentException();
}
}
}
}