001 package org.apache.myfaces.tobago.renderkit.html.scarborough.standard.tag;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one or more
005 * contributor license agreements. See the NOTICE file distributed with
006 * this work for additional information regarding copyright ownership.
007 * The ASF licenses this file to You under the Apache License, Version 2.0
008 * (the "License"); you may not use this file except in compliance with
009 * the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019
020 /*
021 * Created 07.02.2003 16:00:00.
022 * $Id: TreeRenderer.java 652070 2008-04-28 06:38:01Z bommel $
023 */
024
025 import org.apache.myfaces.tobago.component.AbstractUITree;
026 import org.apache.myfaces.tobago.context.ResourceManagerUtil;
027 import org.apache.myfaces.tobago.context.TobagoFacesContext;
028 import org.apache.myfaces.tobago.renderkit.LayoutableRendererBase;
029 import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
030 import org.apache.myfaces.tobago.renderkit.html.HtmlConstants;
031 import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtil;
032 import org.apache.myfaces.tobago.renderkit.util.RenderUtil;
033 import org.apache.myfaces.tobago.util.ComponentUtil;
034 import org.apache.myfaces.tobago.util.FastStringWriter;
035 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
036
037 import javax.faces.component.NamingContainer;
038 import javax.faces.component.UIComponent;
039 import javax.faces.context.FacesContext;
040 import javax.faces.context.ResponseWriter;
041 import java.io.IOException;
042
043 public class TreeRenderer extends LayoutableRendererBase {
044
045 /**
046 * Resources to display the tree.
047 */
048 private static final String[] TREE_IMAGES = {
049 "openfoldericon.gif",
050 "foldericon.gif",
051 "unchecked.gif",
052 "uncheckedDisabled.gif",
053 "checked.gif",
054 "checkedDisabled.gif",
055 "new.gif",
056 "T.gif",
057 "L.gif",
058 "I.gif",
059 "Lminus.gif",
060 "Tminus.gif",
061 "Rminus.gif",
062 "Lplus.gif",
063 "Tplus.gif",
064 "Rplus.gif",
065 "treeMenuOpen.gif",
066 "treeMenuClose.gif",
067 };
068
069 private static final String SCRIPT = "script/tobago-tree.js";
070
071 public void prepareRender(FacesContext facesContext, UIComponent component) throws IOException {
072 super.prepareRender(facesContext, component);
073 if (facesContext instanceof TobagoFacesContext) {
074 // todo: this may be removed, it is twice on the page 1. in the header 2. in the ScriptLoader
075 ((TobagoFacesContext) facesContext).getScriptFiles().add(SCRIPT);
076 }
077 }
078
079
080 @Override
081 public void decode(FacesContext facesContext, UIComponent component) {
082 if (ComponentUtil.isOutputOnly(component)) {
083 return;
084 }
085
086 AbstractUITree tree = (AbstractUITree) component;
087 tree.setValid(true);
088 }
089
090 public static boolean isSelectable(AbstractUITree tree) {
091 return tree.isSelectableTree();
092 }
093
094 public static String createJavascriptVariable(String clientId) {
095 return clientId == null
096 ? null
097 : clientId.replace(NamingContainer.SEPARATOR_CHAR, '_');
098 }
099
100 @Override
101 public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
102 // will be rendered in encodeEnd()
103 }
104
105 @Override
106 public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
107
108 AbstractUITree tree = (AbstractUITree) component;
109
110 String clientId = tree.getClientId(facesContext);
111 UIComponent root = tree.getRoot();
112
113 TobagoResponseWriter writer = HtmlRendererUtil.getTobagoResponseWriter(facesContext);
114
115 writer.startElement(HtmlConstants.DIV, tree);
116 writer.writeClassAttribute();
117 writer.writeStyleAttribute();
118
119 writer.startElement(HtmlConstants.INPUT, tree);
120 writer.writeAttribute(HtmlAttributes.TYPE, "hidden", false);
121 writer.writeNameAttribute(clientId);
122 writer.writeIdAttribute(clientId);
123 writer.writeAttribute(HtmlAttributes.VALUE, ";", false);
124 writer.endElement(HtmlConstants.INPUT);
125
126 writer.startElement(HtmlConstants.INPUT, tree);
127 writer.writeAttribute(HtmlAttributes.TYPE, "hidden", false);
128 writer.writeNameAttribute(clientId + AbstractUITree.MARKER);
129 writer.writeIdAttribute(clientId + AbstractUITree.MARKER);
130 writer.writeAttribute(HtmlAttributes.VALUE, "", false);
131 writer.endElement(HtmlConstants.INPUT);
132
133 if (isSelectable(tree)) {
134 writer.startElement(HtmlConstants.INPUT, tree);
135 writer.writeAttribute(HtmlAttributes.TYPE, "hidden", false);
136 writer.writeNameAttribute(clientId + AbstractUITree.SELECT_STATE);
137 writer.writeIdAttribute(clientId + AbstractUITree.SELECT_STATE);
138 writer.writeAttribute(HtmlAttributes.VALUE, ";", false);
139 writer.endElement(HtmlConstants.INPUT);
140 }
141
142 String scriptTexts = createJavascript(facesContext);
143
144 HtmlRendererUtil.writeScriptLoader(facesContext, new String[]{SCRIPT}, new String[]{scriptTexts});
145
146 RenderUtil.encode(facesContext, root);
147
148 writer.endElement(HtmlConstants.DIV);
149 }
150
151 private String createJavascript(FacesContext facesContext) throws IOException {
152 StringBuilder sb = new StringBuilder(128);
153
154 sb.append("{\n");
155
156 sb.append(" var treeResourcesHelp = new Object();\n");
157 for (String images : TREE_IMAGES) {
158 sb.append(" treeResourcesHelp[\"");
159 sb.append(images);
160 sb.append("\"] = \"");
161 sb.append(ResourceManagerUtil.getImageWithPath(facesContext, "image/" + images));
162 sb.append("\";\n");
163 }
164 sb.append(" \n treeResourcesHelp.getImage = function (name) {\n");
165 sb.append(" var result = this[name];\n");
166 sb.append(" if (result) {\n");
167 sb.append(" return result;\n");
168 sb.append(" } else {\n");
169 sb.append(" return \"");
170 sb.append(ResourceManagerUtil.getImageWithPath(facesContext, "image/blank.gif"));
171 sb.append("\";\n");
172 sb.append(" }\n");
173 sb.append(" };\n \n");
174 sb.append("}");
175 return sb.toString();
176 }
177
178 protected String getNodesAsJavascript(FacesContext facesContext, UIComponent root) throws IOException {
179 ResponseWriter writer = facesContext.getResponseWriter();
180 FastStringWriter stringWriter = new FastStringWriter();
181 facesContext.setResponseWriter(writer.cloneWithWriter(stringWriter));
182 RenderUtil.encode(facesContext, root);
183 facesContext.setResponseWriter(writer);
184 return stringWriter.toString();
185 }
186
187 protected String nodeStateId(FacesContext facesContext, UIComponent node) {
188 // this must do the same as nodeStateId() in tree.js
189 String clientId = node.getClientId(facesContext);
190 int last = clientId.lastIndexOf(':') + 1;
191 return clientId.substring(last);
192 }
193 }