All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.myfaces.custom.tree.HtmlTree Maven / Gradle / Ivy

Go to download

JSF components and utilities that can be used with any JSF implementation. This library is compatible with both JSF1.1 and JSF1.2; however for JSF1.2 users there is an alternative build of Tomahawk available that takes advantage of JSF1.2 features to offer some additional benefits.

There is a newer version: 1.1.14
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.myfaces.custom.tree;

import java.io.IOException;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.faces.component.UIViewRoot;
import javax.faces.component.html.HtmlPanelGroup;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;

import org.apache.myfaces.custom.tree.event.TreeSelectionEvent;
import org.apache.myfaces.custom.tree.event.TreeSelectionListener;
import org.apache.myfaces.custom.tree.model.TreeModel;
import org.apache.myfaces.custom.tree.model.TreeModelEvent;
import org.apache.myfaces.custom.tree.model.TreeModelListener;
import org.apache.myfaces.custom.tree.model.TreePath;


/**
 * A tree data component. 
 * Unless otherwise specified, all attributes accept static values or EL expressions.
 * 

* Tree implementation based on javax.swing.JTree. *

*

* The tree model is assigned by using a value binding named model * and is not stored in view state. *

*

* A hierarchy of {@link HtmlTreeNode}objects is used to represent the current * expanded state of the tree. The root node is held as a faces named * * rootNode. *

* * @JSFComponent * name = "t:tree" * tagClass = "org.apache.myfaces.custom.tree.taglib.TreeTag" * tagSuperclass = "org.apache.myfaces.custom.tree.taglib.AbstractTreeTag" * type = "org.apache.myfaces.HtmlTree" * tagHandler = "org.apache.myfaces.custom.tree.taglib.TreeTagHandler" * * @JSFJspProperty name = "headerClass" returnType = "java.lang.String" * @JSFJspProperty name = "footerClass" returnType = "java.lang.String" * @JSFJspProperty name = "expandRoot" returnType = "boolean" literalOnly="true" inheritedTag="true" * @JSFJspProperty name = "style" tagExcluded = "true" * @author Oliver Rossmueller * @version $Revision: 672986 $ $Date: 2008-06-30 23:13:55 -0500 (Mon, 30 Jun 2008) $ */ public class HtmlTree extends HtmlPanelGroup implements TreeModelListener { public static final String COMPONENT_TYPE = "org.apache.myfaces.HtmlTree"; public static final String COMPONENT_FAMILY = "org.apache.myfaces.HtmlTree"; private static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.HtmlTree"; public static final long DEFAULT_EXPIRE_LISTENERS = 8 * 60 * 60 * 1000; // 8 hours private static final String FACET_ROOTNODE = "rootNode"; private static final String PREVIOUS_VIEW_ROOT = HtmlTree.class.getName() + ".PREVIOUS_VIEW_ROOT"; private static final int EVENT_CHANGED = 0; private static final int EVENT_INSERTED = 1; private static final int EVENT_REMOVED = 2; private static final int EVENT_STRUCTURE_CHANGED = 3; private static int counter = 0; private IconProvider iconProvider; private boolean itemStatesRestored = false; private String var; private String nodeClass; private String rowClasses; private String columnClasses; private String selectedNodeClass; private String iconClass; private String iconLine; private String iconNoline; private String iconChildFirst; private String iconChildMiddle; private String iconChildLast; private String iconNodeOpen; private String iconNodeOpenFirst; private String iconNodeOpenMiddle; private String iconNodeOpenLast; private String iconNodeClose; private String iconNodeCloseFirst; private String iconNodeCloseMiddle; private String iconNodeCloseLast; private int uniqueIdCounter = 0; private int[] selectedPath; private int internalId; private Long expireListeners; /** *

* Default constructor. *

*/ public HtmlTree() { internalId = counter++; } /** * @JSFProperty * jspName = "value" * required = "true" * inheritedTag = "true" */ public TreeModel getModel(FacesContext context) { ValueBinding binding = getValueBinding("model"); if (binding != null) { TreeModel model = (TreeModel) binding.getValue(context); if (model != null) { return model; } } return null; } public String createUniqueId(FacesContext context) { return getClientId(context).replaceAll(":", "_") + "_node_" + uniqueIdCounter++; } public void addTreeSelectionListener(TreeSelectionListener listener) { addFacesListener(listener); } public IconProvider getIconProvider() { return iconProvider; } public void setIconProvider(IconProvider iconProvider) { this.iconProvider = iconProvider; } /** * @JSFProperty * @return Returns the var. */ public String getVar() { return getStringValue(var, "var"); } /** * @param var The var to set. */ public void setVar(String var) { this.var = var; } protected String getStringValue(String value, String vbName) { if(value != null) { return value; } ValueBinding vb = getValueBinding(vbName); if(vb != null) { Object obj = vb.getValue(getFacesContext()); if(obj != null) { return obj.toString(); } } return null; } /** * @JSFProperty */ public String getIconLine() { return getStringValue(iconLine, "iconLine"); } public void setIconLine(String iconLine) { this.iconLine = iconLine; } /** * @JSFProperty */ public String getIconNoline() { return getStringValue(iconNoline, "iconNoline"); } public void setIconNoline(String iconNoline) { this.iconNoline = iconNoline; } /** * @JSFProperty */ public String getIconChildFirst() { return getStringValue(iconChildFirst, "iconChildFirst"); } public void setIconChildFirst(String iconChildFirst) { this.iconChildFirst = iconChildFirst; } /** * @JSFProperty */ public String getIconChildMiddle() { return getStringValue(iconChildMiddle, "iconChildMiddle"); } public void setIconChildMiddle(String iconChildMiddle) { this.iconChildMiddle = iconChildMiddle; } /** * @JSFProperty */ public String getIconChildLast() { return getStringValue(iconChildLast, "iconChildLast"); } public void setIconChildLast(String iconChildLast) { this.iconChildLast = iconChildLast; } /** * @JSFProperty */ public String getIconNodeOpen() { return getStringValue(iconNodeOpen, "iconNodeOpen"); } public void setIconNodeOpen(String iconNodeOpen) { this.iconNodeOpen = iconNodeOpen; } /** * @JSFProperty */ public String getIconNodeOpenFirst() { return getStringValue(iconNodeOpenFirst, "iconNodeOpenFirst"); } public void setIconNodeOpenFirst(String iconNodeOpenFirst) { this.iconNodeOpenFirst = iconNodeOpenFirst; } /** * @JSFProperty */ public String getIconNodeOpenMiddle() { return getStringValue(iconNodeOpenMiddle, "iconNodeOpenMiddle"); } public void setIconNodeOpenMiddle(String iconNodeOpenMiddle) { this.iconNodeOpenMiddle = iconNodeOpenMiddle; } /** * @JSFProperty */ public String getIconNodeOpenLast() { return getStringValue(iconNodeOpenLast, "iconNodeOpenLast"); } public void setIconNodeOpenLast(String iconNodeOpenLast) { this.iconNodeOpenLast = iconNodeOpenLast; } /** * @JSFProperty */ public String getIconNodeClose() { return getStringValue(iconNodeClose, "iconNodeClose"); } public void setIconNodeClose(String iconNodeClose) { this.iconNodeClose = iconNodeClose; } /** * @JSFProperty */ public String getIconNodeCloseFirst() { return getStringValue(iconNodeCloseFirst, "iconNodeCloseFirst"); } public void setIconNodeCloseFirst(String iconNodeCloseFirst) { this.iconNodeCloseFirst = iconNodeCloseFirst; } /** * @JSFProperty */ public String getIconNodeCloseMiddle() { return getStringValue(iconNodeCloseMiddle, "iconNodeCloseMiddle"); } public void setIconNodeCloseMiddle(String iconNodeCloseMiddle) { this.iconNodeCloseMiddle = iconNodeCloseMiddle; } /** * @JSFProperty */ public String getIconNodeCloseLast() { return getStringValue(iconNodeCloseLast, "iconNodeCloseLast"); } public void setIconNodeCloseLast(String iconNodeCloseLast) { this.iconNodeCloseLast = iconNodeCloseLast; } /** * @JSFProperty */ public String getNodeClass() { return getStringValue(nodeClass, "nodeClass"); } public void setNodeClass(String nodeClass) { this.nodeClass = nodeClass; } /** * @JSFProperty * @return Returns the rowClasses. */ public String getRowClasses() { return getStringValue(rowClasses, "rowClasses"); } /** * @param rowClasses The rowClasses to set. */ public void setRowClasses(String rowClasses) { this.rowClasses = rowClasses; } /** * @JSFProperty * @return Returns the columnClasses. */ public String getColumnClasses() { return getStringValue(columnClasses, "columnClasses"); } /** * @param columnClasses The columnClasses to set. */ public void setColumnClasses(String columnClasses) { this.columnClasses = columnClasses; } /** * @JSFProperty * @return Returns the selectedNodeClass. */ public String getSelectedNodeClass() { return getStringValue(selectedNodeClass, "selectedNodeClass"); } /** * @param selectedNodeClass The selectedNodeClass to set. */ public void setSelectedNodeClass(String selectedNodeClass) { this.selectedNodeClass = selectedNodeClass; } /** * @JSFProperty */ public String getIconClass() { return getStringValue(iconClass, "iconClass"); } public void setIconClass(String iconClass) { this.iconClass = iconClass; } /** * Time interval the tree will remain registered as a TreeModelListener * without being accessed * * @JSFProperty */ public long getExpireListeners() { if(expireListeners != null) { return expireListeners.longValue(); } ValueBinding vb = getValueBinding("expireListeners"); if(vb != null) { Object obj = vb.getValue(getFacesContext()); if(obj instanceof java.lang.Number) { return ((java.lang.Number)obj).longValue(); } } return DEFAULT_EXPIRE_LISTENERS; } public void setExpireListeners(long expireListeners) { this.expireListeners = new Long(expireListeners); } public String getFamily() { return "org.apache.myfaces.HtmlTree"; } /** * Ensures that the node identified by the specified path is expanded and * viewable. If the last item in the path is a leaf, this will have no * effect. * * @param path the TreePath identifying a node */ public void expandPath(TreePath path, FacesContext context) { // Only expand if not leaf! TreeModel model = getModel(context); if (path != null && model != null && !model.isLeaf(path.getLastPathComponent())) { int[] translatedPath = HtmlTreeNode.translatePath(path, getModel(context)); HtmlTreeNode rootNode = getRootNode(); if (rootNode == null) { createRootNode(context); rootNode = getRootNode(); } if (!rootNode.isExpanded()) { rootNode.setExpanded(true); } rootNode.expandPath(translatedPath, 0); } } /** * Ensures that the node identified by the specified path is collapsed and * viewable. * * @param path the TreePath identifying a node */ public void collapsePath(TreePath path, FacesContext context) { HtmlTreeNode node = findNode(path, context); if (node != null) { node.setExpanded(false); } } public boolean isExpanded(TreePath path, FacesContext context) { if (path == null) { return false; } return findNode(path, context) != null; } private HtmlTreeNode findNode(TreePath path, FacesContext context) { HtmlTreeNode node = getRootNode(); int[] translatedPath = HtmlTreeNode.translatePath(path, getModel(context)); for (int i = 0; i < translatedPath.length; i++) { if (!node.isExpanded()) { return null; } int index = translatedPath[i]; node = (HtmlTreeNode) node.getChildren().get(index); } return node; } public TreePath getSelectionPath() { if (selectedPath == null) { return null; } return HtmlTreeNode.translatePath(selectedPath, getModel(FacesContext.getCurrentInstance())); } public void selectionChanged(HtmlTreeNode node) { TreePath oldPath = null; if (selectedPath != null) { oldPath = HtmlTreeNode.translatePath(selectedPath, getModel(FacesContext.getCurrentInstance())); } selectedPath = node.getTranslatedPath(); if (node.isSelected()) { queueEvent(new TreeSelectionEvent(this, oldPath, node.getPath())); } else { queueEvent(new TreeSelectionEvent(this, oldPath, null)); } } private void createRootNode(FacesContext context) { HtmlTreeNode node; TreeModel model = getModel(context); Object root = model.getRoot(); node = (HtmlTreeNode) context.getApplication().createComponent(HtmlTreeNode.COMPONENT_TYPE); String id = createUniqueId(context); node.setId(id); node.setPath(new TreePath(new Object[]{root})); node.setUserObject(root); node.setLayout(new int[]{HtmlTreeNode.CLOSED_SINGLE}); getFacets().put(FACET_ROOTNODE, node); } public HtmlTreeNode getRootNode() { return (HtmlTreeNode) getFacet(FACET_ROOTNODE); } public Object saveState(FacesContext context) { Object values[] = new Object[24]; values[0] = super.saveState(context); values[1] = iconChildFirst; values[2] = iconChildMiddle; values[3] = iconChildLast; values[4] = iconLine; values[5] = iconNodeClose; values[6] = iconNodeCloseFirst; values[7] = iconNodeCloseLast; values[8] = iconNodeCloseMiddle; values[9] = iconNodeOpen; values[10] = iconNodeOpenFirst; values[11] = iconNodeOpenLast; values[12] = iconNodeOpenMiddle; values[13] = iconNoline; values[14] = var; values[15] = nodeClass; values[16] = selectedNodeClass; values[17] = new Integer(uniqueIdCounter); values[18] = selectedPath; values[19] = iconClass; values[20] = new Integer(internalId); values[21] = expireListeners; values[22] = rowClasses; values[23] = columnClasses; return ((Object) (values)); } public void restoreState(FacesContext context, Object state) { Object values[] = (Object[]) state; super.restoreState(context, values[0]); iconChildFirst = (String) values[1]; iconChildMiddle = (String) values[2]; iconChildLast = (String) values[3]; iconLine = (String) values[4]; iconNodeClose = (String) values[5]; iconNodeCloseFirst = (String) values[6]; iconNodeCloseLast = (String) values[7]; iconNodeCloseMiddle = (String) values[8]; iconNodeOpen = (String) values[9]; iconNodeOpenFirst = (String) values[10]; iconNodeOpenLast = (String) values[11]; iconNodeOpenMiddle = (String) values[12]; iconNoline = (String) values[13]; var = (String) values[14]; nodeClass = (String) values[15]; selectedNodeClass = (String) values[16]; uniqueIdCounter = ((Integer) values[17]).intValue(); selectedPath = (int[]) values[18]; iconClass = (String) values[19]; internalId = ((Integer) values[20]).intValue(); expireListeners = (Long) values[21]; rowClasses = (String) values[22]; columnClasses = (String) values[23]; addToModelListeners(); } public void decode(FacesContext context) { super.decode(context); //Save the current view root for later reference... context.getExternalContext().getRequestMap().put(PREVIOUS_VIEW_ROOT, context.getViewRoot()); //...and remember that this instance needs NO special treatment on // rendering: itemStatesRestored = true; } public void processDecodes(FacesContext context) { addToModelListeners(); super.processDecodes(context); } public void processValidators(FacesContext context) { addToModelListeners(); super.processValidators(context); } public void processUpdates(FacesContext context) { addToModelListeners(); super.processUpdates(context); } public void encodeBegin(FacesContext context) throws IOException { addToModelListeners(); processModelEvents(); HtmlTreeNode node = getRootNode(); if (node == null) { createRootNode(context); } if (!itemStatesRestored) { UIViewRoot previousRoot = (UIViewRoot) context.getExternalContext().getRequestMap().get(PREVIOUS_VIEW_ROOT); if (previousRoot != null) { restoreItemStates(context, previousRoot); } else { //no previous root, means no decode was done //--> a new request } } super.encodeBegin(context); } public void encodeEnd(FacesContext context) throws IOException { super.encodeEnd(context); } public void restoreItemStates(FacesContext facesContext, UIViewRoot previousRoot) { HtmlTree previousTree = (HtmlTree) previousRoot.findComponent(getClientId(facesContext)); if (previousTree != null) { HtmlTreeNode node = previousTree.getRootNode(); if (node != null) { getRootNode().restoreItemState(node); } selectedPath = previousTree.selectedPath; } } public void treeNodesChanged(TreeModelEvent e) { TreePath path = e.getTreePath(); FacesContext context = FacesContext.getCurrentInstance(); HtmlTreeNode node = findNode(path, context); if (node != null) { node.childrenChanged(e.getChildIndices(), context); } } public void treeNodesInserted(TreeModelEvent e) { TreePath path = e.getTreePath(); FacesContext context = FacesContext.getCurrentInstance(); HtmlTreeNode node = findNode(path, context); if (node != null) { node.childrenAdded(e.getChildIndices(), context); } } public void treeNodesRemoved(TreeModelEvent e) { TreePath path = e.getTreePath(); FacesContext context = FacesContext.getCurrentInstance(); HtmlTreeNode node = findNode(path, context); if (node != null) { node.childrenRemoved(e.getChildIndices()); } } public void treeStructureChanged(TreeModelEvent e) { TreePath path = e.getTreePath(); FacesContext context = FacesContext.getCurrentInstance(); if (isExpanded(path, context)) { collapsePath(path, context); expandPath(path, context); } } public boolean equals(Object obj) { if (!(obj instanceof HtmlTree)) { return false; } HtmlTree other = (HtmlTree) obj; return other.getId().equals(getId()); } public int hashCode() { return getClientId(FacesContext.getCurrentInstance()).hashCode(); } public void addToModelListeners() { Collection listeners = getModel(FacesContext.getCurrentInstance()).getTreeModelListeners(); long currentTime = System.currentTimeMillis(); boolean found = false; for (Iterator iterator = listeners.iterator(); iterator.hasNext();) { ModelListener listener = (ModelListener) iterator.next(); if (listener.getId() == internalId) { found = true; } else if (currentTime - listener.getLastAccessTime() > getExpireListeners()) { iterator.remove(); } } if (!found) { listeners.add(new ModelListener(internalId)); } } private void processModelEvents() { Collection listeners = getModel(FacesContext.getCurrentInstance()).getTreeModelListeners(); for (Iterator iterator = listeners.iterator(); iterator.hasNext();) { ModelListener listener = (ModelListener) iterator.next(); if (listener.getId() == internalId) { for (Iterator events = listener.getEvents().iterator(); events.hasNext();) { Event event = (Event) events.next(); event.process(this); events.remove(); } break; } } } public void collapseAll() { HtmlTreeNode root = getRootNode(); FacesContext context = FacesContext.getCurrentInstance(); collapsePath(root.getPath(), context); for (int i = 0; i < root.getChildren().size(); i++) { HtmlTreeNode child = (HtmlTreeNode) (root.getChildren().get(i)); collapsePath(child.getPath(), context); if (!child.isLeaf(context)) { collapseChildren(context, child); } } } private void collapseChildren(FacesContext context, HtmlTreeNode parent) { for (int i = 0; i < parent.getChildren().size(); i++) { HtmlTreeNode child = (HtmlTreeNode) (parent.getChildren().get(i)); collapsePath(child.getPath(), context); if (!child.isLeaf(context)) { collapseChildren(context, child); } } } public void expandAll() { HtmlTreeNode root = getRootNode(); FacesContext context = FacesContext.getCurrentInstance(); expandPath(root.getPath(), context); for (int i = 0; i < root.getChildren().size(); i++) { HtmlTreeNode child = (HtmlTreeNode) (root.getChildren().get(i)); expandPath(child.getPath(), context); if (!child.isLeaf(context)) { expandChildren(context, child); } } } private void expandChildren(FacesContext context, HtmlTreeNode parent) { for (int i = 0; i < parent.getChildren().size(); i++) { HtmlTreeNode child = (HtmlTreeNode) (parent.getChildren().get(i)); expandPath(child.getPath(), context); if (!child.isLeaf(context)) { expandChildren(context, child); } } } private static class ModelListener implements TreeModelListener, Serializable { private long lastAccessTime = System.currentTimeMillis(); private LinkedList events = new LinkedList(); int id; public ModelListener(int id) { this.id = id; } public List getEvents() { lastAccessTime = System.currentTimeMillis(); return events; } public int getId() { return id; } public long getLastAccessTime() { return lastAccessTime; } public void treeNodesChanged(TreeModelEvent e) { events.addLast(new Event(EVENT_CHANGED, e)); } public void treeNodesInserted(TreeModelEvent e) { events.addLast(new Event(EVENT_INSERTED, e)); } public void treeNodesRemoved(TreeModelEvent e) { events.addLast(new Event(EVENT_REMOVED, e)); } public void treeStructureChanged(TreeModelEvent e) { events.addLast(new Event(EVENT_STRUCTURE_CHANGED, e)); } } private static class Event { private int kind; private TreeModelEvent event; public Event(int kind, TreeModelEvent event) { this.kind = kind; this.event = event; } public void process(HtmlTree tree) { switch (kind) { case EVENT_CHANGED: tree.treeNodesChanged(event); break; case EVENT_INSERTED: tree.treeNodesInserted(event); break; case EVENT_REMOVED: tree.treeNodesRemoved(event); break; case EVENT_STRUCTURE_CHANGED: tree.treeStructureChanged(event); break; } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy