1 /*
2 * $Id: ButtonRenderer.java,v 1.105.4.1 2007/08/30 19:26:18 rlubke Exp $
3 */
4
5 /*
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
7 *
8 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
9 *
10 * The contents of this file are subject to the terms of either the GNU
11 * General Public License Version 2 only ("GPL") or the Common Development
12 * and Distribution License("CDDL") (collectively, the "License"). You
13 * may not use this file except in compliance with the License. You can obtain
14 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
15 * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
16 * language governing permissions and limitations under the License.
17 *
18 * When distributing the software, include this License Header Notice in each
19 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
20 * Sun designates this particular file as subject to the "Classpath" exception
21 * as provided by Sun in the GPL Version 2 section of the License file that
22 * accompanied this code. If applicable, add the following below the License
23 * Header, with the fields enclosed by brackets [] replaced by your own
24 * identifying information: "Portions Copyrighted [year]
25 * [name of copyright owner]"
26 *
27 * Contributor(s):
28 *
29 * If you wish your version of this file to be governed by only the CDDL or
30 * only the GPL Version 2, indicate your decision by adding "[Contributor]
31 * elects to include this software in this distribution under the [CDDL or GPL
32 * Version 2] license." If you don't indicate a single choice of license, a
33 * recipient has the option to distribute your version of this file under
34 * either the CDDL, the GPL Version 2 or to extend the choice of license to
35 * its licensees as provided above. However, if you add GPL Version 2 code
36 * and therefore, elected the GPL Version 2 license, then the option applies
37 * only if the new code is made subject to such option by the copyright
38 * holder.
39 */
40
41 // ButtonRenderer.java
42
43 package com.sun.faces.renderkit.html_basic;
44
45 import java.io.IOException;
46 import java.util.Map;
47 import java.util.logging.Level;
48
49 import javax.faces.component.UICommand;
50 import javax.faces.component.UIComponent;
51 import javax.faces.context.FacesContext;
52 import javax.faces.context.ResponseWriter;
53 import javax.faces.event.ActionEvent;
54
55 import com.sun.faces.renderkit.AttributeManager;
56 import com.sun.faces.renderkit.RenderKitUtils;
57
58 /**
59 * <B>ButtonRenderer</B> is a class that renders the current value of
60 * <code>UICommand<code> as a Button.
61 */
62
63 public class ButtonRenderer extends HtmlBasicRenderer {
64
65 private static final String[] ATTRIBUTES =
66 AttributeManager.getAttributes(AttributeManager.Key.COMMANDBUTTON);
67
68 // ---------------------------------------------------------- Public Methods
69
70
71 @Override
72 public void decode(FacesContext context, UIComponent component) {
73
74 rendererParamsNotNull(context, component);
75
76 if (!shouldDecode(component)) {
77 return;
78 }
79
80 if (wasClicked(context, component) && !isReset(component)) {
81 component.queueEvent(new ActionEvent(component));
82
83 if (logger.isLoggable(Level.FINE)) {
84 logger.fine("This command resulted in form submission " +
85 " ActionEvent queued.");
86 logger.log(Level.FINE,
87 "End decoding component {0}",
88 component.getId());
89 }
90 }
91
92 }
93
94
95 @Override
96 public void encodeBegin(FacesContext context, UIComponent component)
97 throws IOException {
98
99 rendererParamsNotNull(context, component);
100
101 if (!shouldEncode(component)) {
102 return;
103 }
104
105 // Which button type (SUBMIT, RESET, or BUTTON) should we generate?
106 String type = getButtonType(component);
107
108 ResponseWriter writer = context.getResponseWriter();
109 assert(writer != null);
110
111 String label = "";
112 Object value = ((UICommand) component).getValue();
113 if (value != null) {
114 label = value.toString();
115 }
116 String imageSrc = (String) component.getAttributes().get("image");
117 writer.startElement("input", component);
118 writeIdAttributeIfNecessary(context, writer, component);
119 String clientId = component.getClientId(context);
120 if (imageSrc != null) {
121 writer.writeAttribute("type", "image", "type");
122 writer.writeURIAttribute("src", src(context, imageSrc), "image");
123 writer.writeAttribute("name", clientId, "clientId");
124 } else {
125 writer.writeAttribute("type", type, "type");
126 writer.writeAttribute("name", clientId, "clientId");
127 writer.writeAttribute("value", label, "value");
128 }
129
130 RenderKitUtils.renderPassThruAttributes(writer,
131 component,
132 ATTRIBUTES);
133 RenderKitUtils.renderXHTMLStyleBooleanAttributes(writer, component);
134
135 String styleClass = (String)
136 component.getAttributes().get("styleClass");
137 if (styleClass != null && styleClass.length() > 0) {
138 writer.writeAttribute("class", styleClass, "styleClass");
139 }
140 writer.endElement("input");
141
142 }
143
144 @Override
145 public void encodeEnd(FacesContext context, UIComponent component)
146 throws IOException {
147
148 rendererParamsNotNull(context, component);
149
150 }
151
152 // --------------------------------------------------------- Private Methods
153
154
155 /**
156 * @param context the <code>FacesContext</code> for the current request
157 * @param imageURI the base URI of the image to use for the button
158 * @return the encoded result for the base imageURI
159 */
160 private static String src(FacesContext context, String imageURI) {
161
162 if (imageURI == null) {
163 return "";
164 }
165
166 String u = context.getApplication().getViewHandler()
167 .getResourceURL(context, imageURI);
168 return (context.getExternalContext().encodeResourceURL(u));
169
170 }
171
172
173 /**
174 * <p>Determine if this component was activated on the client side.</p>
175 *
176 * @param context the <code>FacesContext</code> for the current request
177 * @param component the component of interest
178 * @return <code>true</code> if this component was in fact activated,
179 * otherwise <code>false</code>
180 */
181 private static boolean wasClicked(FacesContext context,
182 UIComponent component) {
183
184 // Was our command the one that caused this submission?
185 // we don' have to worry about getting the value from request parameter
186 // because we just need to know if this command caused the submission. We
187 // can get the command name by calling currentValue. This way we can
188 // get around the IE bug.
189 String clientId = component.getClientId(context);
190 Map<String, String> requestParameterMap = context.getExternalContext()
191 .getRequestParameterMap();
192 if (requestParameterMap.get(clientId) == null) {
193 StringBuilder builder = new StringBuilder(clientId);
194 String xValue = builder.append(".x").toString();
195 builder.setLength(clientId.length());
196 String yValue = builder.append(".y").toString();
197 return (requestParameterMap.get(xValue) != null
198 && requestParameterMap.get(yValue) != null);
199 }
200 return true;
201
202 }
203
204 /**
205 * @param component the component of interest
206 * @return <code>true</code> if the button represents a <code>reset</code>
207 * button, otherwise <code>false</code>
208 */
209 private static boolean isReset(UIComponent component) {
210
211 return ("reset".equals(component.getAttributes().get("type")));
212
213 }
214
215 /**
216 * <p>If the component's type attribute is null or not equal
217 * to <code>reset</code> or <code>submit</code>, default to
218 * <code>submit</code>.
219 * @param component the component of interest
220 * @return the type for this button
221 */
222 private static String getButtonType(UIComponent component) {
223
224 String type = (String) component.getAttributes().get("type");
225 if (type == null || (!"reset".equals(type) && !"submit".equals(type))) {
226 type = "submit";
227 // This is needed in the decode method
228 component.getAttributes().put("type", type);
229 }
230 return type;
231
232 }
233
234
235 } // end of class ButtonRenderer