001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package com.sun.rave.web.ui.renderer;
042:
043: import com.sun.rave.web.ui.component.Icon;
044: import com.sun.rave.web.ui.component.Label;
045: import com.sun.rave.web.ui.theme.Theme;
046: import com.sun.rave.web.ui.theme.ThemeImages;
047: import com.sun.rave.web.ui.theme.ThemeStyles;
048: import com.sun.rave.web.ui.util.ConversionUtilities;
049: import com.sun.rave.web.ui.util.LogUtil;
050: import com.sun.rave.web.ui.util.MessageUtil;
051: import com.sun.rave.web.ui.util.RenderingUtilities;
052: import com.sun.rave.web.ui.util.ThemeUtilities;
053:
054: import java.io.IOException;
055: import java.text.MessageFormat;
056: import java.util.ArrayList;
057: import java.util.Iterator;
058: import java.util.List;
059: import java.util.Map;
060:
061: import javax.faces.FacesException;
062: import javax.faces.component.EditableValueHolder;
063: import javax.faces.component.NamingContainer;
064: import javax.faces.component.UIComponent;
065: import javax.faces.component.UIParameter;
066: import javax.faces.context.FacesContext;
067: import javax.faces.context.ResponseWriter;
068: import javax.faces.render.Renderer;
069:
070: /**
071: * <p>Renderer for a {@link Label} component.</p>
072: */
073:
074: public class LabelRenderer extends Renderer {
075:
076: // ======================================================== Static Variables
077:
078: /**
079: * <p>The set of additional String pass-through attributes to be rendered
080: * if we actually create a <code><label></code> element.</p>
081: */
082: private static final String[] EVENT_NAMES = { "onClick",
083: "onMouseDown", "onMouseUp", // NOI18N
084: "onMouseOver", "onMouseMove", "onMouseOut" // NOI18N
085: };
086:
087: public boolean getRendersChildren() {
088: return true;
089: }
090:
091: public void encodeChildren(FacesContext context,
092: UIComponent component) throws IOException {
093: return;
094: }
095:
096: /**
097: * <p>Render the appropriate element attributes, followed by the
098: * label content, depending on whether the <code>for</code> property
099: * is set or not.</p>
100: *
101: * @param context <code>FacesContext</code> for the current request
102: * @param component <code>EditableValueHolder</code> component whose
103: * submitted value is to be stored
104: * @exception IOException if an input/output error occurs
105: */
106: public void encodeEnd(FacesContext context, UIComponent component)
107: throws IOException {
108:
109: if (!(component instanceof Label)) {
110: Object[] params = { component.toString(),
111: this .getClass().getName(), Label.class.getName() };
112: String message = MessageUtil.getMessage(
113: "com.sun.rave.web.ui.resources.LogMessages", //NOI18N
114: "Label.renderer", params); //NOI18N
115: throw new FacesException(message);
116: }
117:
118: Label label = (Label) component;
119:
120: if (LogUtil.fineEnabled(LabelRenderer.class)) {
121: LogUtil.fine(LabelRenderer.class, "Label.renderAttributes", // NOI18N
122: new Object[] { label.getId(), label.getFor() });
123: }
124:
125: EditableValueHolder comp = label.getLabeledComponent();
126: boolean requiredFlag = label.isRequiredIndicator();
127: boolean errorFlag = false;
128:
129: if (!label.isHideIndicators() && comp != null) {
130: Object o = ((UIComponent) comp).getAttributes().get(
131: "readOnly");
132: if (o != null && o instanceof Boolean
133: && o.equals(Boolean.TRUE)) {
134: requiredFlag = false;
135: errorFlag = false;
136: } else {
137: requiredFlag = comp.isRequired();
138: errorFlag = !comp.isValid();
139: }
140: }
141:
142: Theme theme = ThemeUtilities.getTheme(context);
143: String styleClass = getThemeStyleClass(label, theme, errorFlag);
144: ResponseWriter writer = context.getResponseWriter();
145:
146: startElement(label, (UIComponent) comp, styleClass, writer,
147: context);
148:
149: if (requiredFlag) {
150: writer.write("\n"); //NOI18N
151: RenderingUtilities.renderComponent(label.getRequiredIcon(
152: theme, context), context);
153:
154: }
155: if (errorFlag) {
156: writer.write("\n"); //NOI18N
157: RenderingUtilities.renderComponent(label.getErrorIcon(
158: theme, context, false), context);
159: }
160:
161: // Render the label text
162: String value = formatLabelText(context, label);
163: if (value != null) {
164: writer.write("\n"); //NOI18N
165: writer.writeText(value, "text"); //NOI18N
166: writer.writeText("\n", null); //NOI18N
167: }
168:
169: // Note: the for attribute has been set, so we render the end of
170: // the label tag *before* we render the children. Otherwise we
171: // will inadvertently set the font for the child components.
172: writer.endElement(label.getElement());
173:
174: Iterator children = label.getChildren().iterator();
175: while (children.hasNext()) {
176: RenderingUtilities.renderComponent((UIComponent) children
177: .next(), context);
178: writer.writeText("\n", null); //NOI18N
179: }
180:
181: if (LogUtil.finestEnabled(LabelRenderer.class)) {
182: LogUtil.finest(LabelRenderer.class, "Label.renderEnd"); // NOI18N
183: }
184: }
185:
186: private void startElement(Label label,
187: UIComponent labeledComponent, String styleClass,
188: ResponseWriter writer, FacesContext context)
189: throws IOException {
190:
191: writer.startElement(label.getElement(), label);
192: writer.writeAttribute("id", label.getClientId(context), "id"); //NOI18N
193: String id = label.getLabeledComponentId(context);
194: if (id != null) {
195: writer.writeAttribute("for", id, "for");
196: }
197:
198: RenderingUtilities.renderStyleClass(context, writer, label,
199: styleClass);
200:
201: if (label.getStyle() != null) {
202: writer.writeAttribute("style", label.getStyle(), "style"); //NOI18N
203: }
204: // Render the "toolTip" properties
205: String toolTip = label.getToolTip();
206: if (toolTip != null) {
207: writer.writeAttribute("title", toolTip, "toolTip"); // NOI18N
208: }
209: writeEvents(label, writer);
210: }
211:
212: /**
213: * <p>Return the text to be rendered for this label. This will be either
214: * the literal value of the <code>text</code> property, or the use of
215: * that value as a <code>MessageFormat</code> string, using nested
216: * <code>UIParameter</code> children as the source of replacement values.</p>
217: *
218: * @param context <code>FacesContext</code> for the current request
219: * @param label <code>Label</code> we are rendering
220: */
221: private String formatLabelText(FacesContext context, Label label) {
222: String text = ConversionUtilities.convertValueToString(label,
223: label.getValue());
224: text = text.concat(" ");
225: if (label.getChildCount() == 0) {
226: return text;
227: }
228: List list = new ArrayList();
229: Iterator kids = label.getChildren().iterator();
230: while (kids.hasNext()) {
231: UIComponent kid = (UIComponent) kids.next();
232: if (kid instanceof UIParameter) {
233: list.add(((UIParameter) kid).getValue());
234: }
235: }
236: if (list.size() == 0) {
237: return text;
238: }
239: return MessageFormat.format(text, list.toArray(new Object[list
240: .size()]));
241: }
242:
243: private String getThemeStyleClass(Label label, Theme theme,
244: boolean errorFlag) {
245:
246: String style = null;
247: int level = label.getLabelLevel();
248:
249: if (errorFlag) {
250: style = theme
251: .getStyleClass(ThemeStyles.CONTENT_ERROR_LABEL_TEXT);
252: } else if (level == 1) {
253: style = theme
254: .getStyleClass(ThemeStyles.LABEL_LEVEL_ONE_TEXT);
255: } else if (level == 2) {
256: style = theme
257: .getStyleClass(ThemeStyles.LABEL_LEVEL_TWO_TEXT);
258: } else if (level == 3) {
259: style = theme
260: .getStyleClass(ThemeStyles.LABEL_LEVEL_THREE_TEXT);
261: }
262: return style;
263: }
264:
265: private void writeEvents(Label label, ResponseWriter writer)
266: throws IOException {
267:
268: Map attributes = label.getAttributes();
269: Object value;
270: int length = EVENT_NAMES.length;
271: for (int i = 0; i < length; i++) {
272: value = attributes.get(EVENT_NAMES[i]);
273: if (value != null) {
274: if (value instanceof String) {
275: writer.writeAttribute(EVENT_NAMES[i].toLowerCase(),
276: (String) value, EVENT_NAMES[i]);
277: } else {
278: writer.writeAttribute(EVENT_NAMES[i].toLowerCase(),
279: value.toString(), EVENT_NAMES[i]);
280: }
281: }
282: }
283: }
284: }
|