📄 htmltreerenderer.java
字号:
/* * Copyright 2004 The Apache Software Foundation. * * Licensed 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.tree2;import org.apache.myfaces.component.html.util.AddResource;import org.apache.myfaces.renderkit.html.HtmlRendererUtils;import org.apache.myfaces.renderkit.html.HTML;import org.apache.myfaces.renderkit.JSFAttr;import javax.faces.component.NamingContainer;import javax.faces.component.UIComponent;import javax.faces.component.UICommand;import javax.faces.component.UIGraphic;import javax.faces.component.UIViewRoot;import javax.faces.component.UIParameter;import javax.faces.context.FacesContext;import javax.faces.context.ResponseWriter;import javax.faces.render.Renderer;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.util.List;import java.util.Map;import java.util.Iterator;import java.net.URLDecoder;import javax.servlet.http.Cookie;import java.util.HashMap;/** * @author Sean Schofield * @author Chris Barlow * @author Hans Bergsten (Some code taken from an example in his O'Reilly JavaServer Faces book. Copied with permission) * @version $Revision: 1.13 $ $Date: 2005/03/16 19:32:01 $ */public class HtmlTreeRenderer extends Renderer{ protected static final String TOGGLE_SPAN = "org.apache.myfaces.tree.TOGGLE_SPAN"; protected static final String ROOT_NODE_ID = "0"; private static final String JAVASCRIPT_ENCODED = "org.apache.myfaces.tree.JAVASCRIPT_ENCODED"; private static final String NAV_COMMAND = "org.apache.myfaces.tree.NAV_COMMAND"; private static final String ENCODING = "UTF-8"; private static final String ATTRIB_DELIM = ";"; private static final String ATTRIB_KEYVAL = "="; private static final String NODE_STATE_EXPANDED = "x"; private static final String NODE_STATE_CLOSED = "c"; private final static String SEPARATOR = String.valueOf(NamingContainer.SEPARATOR_CHAR); private static final int NOTHING = 0; private static final int CHILDREN = 1; private static final int EXPANDED = 2; private static final int LINES = 4; private static final int LAST = 8; // see superclass for documentation public boolean getRendersChildren() { return true; } public void decode(FacesContext context, UIComponent component) { super.decode(context, component); // see if one of the nav nodes was clicked, if so, then toggle appropriate node String nodeId = null; HtmlTree tree = (HtmlTree)component; String originalNodeId = tree.getNodeId(); if (getBoolean(component, JSFAttr.CLIENT_SIDE_TOGGLE, true)) { Map cookieMap = context.getExternalContext().getRequestCookieMap(); Cookie treeCookie = (Cookie)cookieMap.get(component.getId()); if (treeCookie == null || treeCookie.getValue() == null) { return; } String nodeState = null; Map attrMap = getCookieAttr(treeCookie); Iterator i = attrMap.keySet().iterator(); while (i.hasNext()) { nodeId = (String)i.next(); nodeState = (String)attrMap.get(nodeId); if (NODE_STATE_EXPANDED.equals(nodeState)) { tree.setNodeId(nodeId); if (!tree.isNodeExpanded()) { tree.toggleExpanded(); } tree.setNodeId(originalNodeId); } else if (NODE_STATE_CLOSED.equals(nodeState)) { tree.setNodeId(nodeId); if (tree.isNodeExpanded()) { tree.toggleExpanded(); } tree.setNodeId(originalNodeId); } } } else { nodeId = (String)context.getExternalContext().getRequestParameterMap().get(tree.getId() + SEPARATOR + NAV_COMMAND); if (nodeId == null || nodeId.equals("")) { return; } tree.setNodeId(nodeId); tree.toggleExpanded(); tree.setNodeId(originalNodeId); } } public void encodeBegin(FacesContext context, UIComponent component) throws IOException { // write javascript functions encodeJavascript(context, component); } /** * Renders the whole tree. It generates a <code><span></code> element with an <code>id</code> * attribute if the component has been given an explicit ID. The model nodes are rendered * recursively by the private <code>encodeNodes</code> method. * * @param context FacesContext * @param component The component whose children are to be rendered * @throws IOException */ public void encodeChildren(FacesContext context, UIComponent component) throws IOException { HtmlTree tree = (HtmlTree)component; boolean showRootNode = getBoolean(tree, JSFAttr.SHOW_ROOT_NODE, true); if (!component.isRendered()) return; if (tree.getValue() == null) return; ResponseWriter out = context.getResponseWriter(); String clientId = null; if (component.getId() != null && !component.getId().startsWith(UIViewRoot.UNIQUE_ID_PREFIX)) { clientId = component.getClientId(context); } boolean isOuterSpanUsed = false; if (clientId != null) { isOuterSpanUsed = true; out.startElement("span", component); out.writeAttribute("id", clientId, "id"); } if (showRootNode) { // encode the tree (starting with the root node) encodeTree(context, out, tree, null, 0); } else { tree.setNodeId("0"); TreeNode rootNode = tree.getNode(); List rootChildren = rootNode.getChildren(); int kidId = 0; for (int i = 0; i < rootChildren.size(); i++) { encodeTree(context, out, tree, ROOT_NODE_ID, kidId++); } } tree.setNodeId(null); if (isOuterSpanUsed) { out.endElement("span"); } } /** * Encodes the tree and its children. * * @param context FacesContext * @param out ResponseWriter * @param tree HtmlTree * @param parentId The parent's node id (where parent is the parent of the node we are about to render.) * @param childCount If this node is a child of another node, the count indicates which child number it is * (used to construct the id of the next node to render.) * @throws IOException */ protected void encodeTree(FacesContext context, ResponseWriter out, HtmlTree tree, String parentId, int childCount) throws IOException { boolean clientSideToggle = getBoolean(tree, JSFAttr.CLIENT_SIDE_TOGGLE, true); String nodeId = (parentId != null) ? parentId + NamingContainer.SEPARATOR_CHAR + childCount : ROOT_NODE_ID; String spanId = TOGGLE_SPAN + ":" + tree.getId() + ":" + nodeId; tree.setNodeId(nodeId); TreeNode node = tree.getNode(); // encode the current node HtmlRendererUtils.writePrettyLineSeparator(context); beforeNodeEncode(context, out, tree); encodeCurrentNode(context, out, tree); afterNodeEncode(context, out); // only encode the children if clientSideToggle is true or if this node is expanded (regardless of clientSideToggle) if (clientSideToggle == true || tree.isNodeExpanded()) { int kidId = 0; String currId = tree.getNodeId(); List children = node.getChildren(); // if client side toggling is on, add a span to be used for displaying/hiding children if (clientSideToggle) { out.startElement(HTML.SPAN_ELEM, tree); out.writeAttribute(HTML.ID_ATTR, spanId, null); if (tree.isNodeExpanded()) { out.writeAttribute(HTML.STYLE_ATTR, "display:block", null); } else { out.writeAttribute(HTML.STYLE_ATTR, "display:none", null); } } for (int i = 0; i < children.size(); i++) { encodeTree(context, out, tree, currId, kidId++); } if (clientSideToggle) { out.endElement(HTML.SPAN_ELEM); } } } /** * Encodes the current node. It is protected so that custom {@link Renderer}s can extend it. That might be useful * if you would like to render additional per node information besides the tree node. * * @param context FacesContext * @param out ResponseWriter * @param tree HtmlTree * @throws IOException */ protected void encodeCurrentNode(FacesContext context, ResponseWriter out, HtmlTree tree) throws IOException { TreeNode node = tree.getNode(); // set configurable values boolean showRootNode = getBoolean(tree, JSFAttr.SHOW_ROOT_NODE, true); boolean showNav = getBoolean(tree, JSFAttr.SHOW_NAV, true); boolean showLines = getBoolean(tree, JSFAttr.SHOW_LINES, true); boolean clientSideToggle = getBoolean(tree, JSFAttr.CLIENT_SIDE_TOGGLE, true); if (clientSideToggle) { // we must show the nav icons if client side toggle is enabled (regardless of what user says) showNav = true; } UIComponent nodeTypeFacet = tree.getFacet(node.getType()); UIComponent nodeImgFacet = null; if (nodeTypeFacet == null) { throw new IllegalArgumentException("Unable to locate facet with the name: " + node.getType()); } // render node padding String[] pathInfo = tree.getPathInformation(tree.getNodeId()); int paddingLevel = pathInfo.length - 1; for (int i = (showRootNode ? 0 : 1); i < paddingLevel; i++) { boolean lastChild = tree.isLastChild((String)pathInfo[i]); String lineSrc = (!lastChild && showLines) ? getImageSrc(context, tree, "line-trunk.gif") : getImageSrc(context, tree, "spacer.gif"); out.startElement(HTML.TD_ELEM, tree); out.writeAttribute(HTML.WIDTH_ATTR, "19", null); out.writeAttribute(HTML.HEIGHT_ATTR, "100%", null); out.writeURIAttribute("background", lineSrc, null); out.startElement(HTML.IMG_ELEM, tree); out.writeURIAttribute(HTML.SRC_ATTR, lineSrc, null); out.writeAttribute(HTML.WIDTH_ATTR, "19", null); out.writeAttribute(HTML.HEIGHT_ATTR, "18", null); out.writeAttribute(HTML.BORDER_ATTR, "0", null); out.endElement(HTML.IMG_ELEM); out.endElement(HTML.TD_ELEM); } if (showNav) { nodeImgFacet = encodeNavigation(context, out, tree); } // render node out.startElement(HTML.TD_ELEM, tree); if (nodeImgFacet != null) { encodeRecursive(context, nodeImgFacet); } encodeRecursive(context, nodeTypeFacet); out.endElement(HTML.TD_ELEM); } protected void beforeNodeEncode(FacesContext context, ResponseWriter out, HtmlTree tree) throws IOException { out.startElement(HTML.TABLE_ELEM, null); out.writeAttribute(HTML.CELLPADDING_ATTR, "0", null);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -