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 java.io.IOException;
044: import java.util.Map;
045: import java.util.Collection;
046:
047: import javax.faces.component.UIComponent;
048: import javax.faces.context.FacesContext;
049: import javax.faces.context.ResponseWriter;
050:
051: import com.sun.rave.web.ui.component.Checkbox;
052: import com.sun.rave.web.ui.component.CheckboxGroup;
053: import com.sun.rave.web.ui.component.Selector;
054: import com.sun.rave.web.ui.model.Option;
055: import com.sun.rave.web.ui.theme.Theme;
056: import com.sun.rave.web.ui.theme.ThemeStyles;
057: import com.sun.rave.web.ui.util.ConversionUtilities;
058: import com.sun.rave.web.ui.util.ThemeUtilities;
059:
060: /**
061: * The <code>CheckboxGroupRenderer</code> renders a <code>CheckboxGroup</code>
062: * component as set of checkboxes. The <code>CheckboxGroupRenderer</code>
063: * creates an instance of <code>Checkbox</code> for each
064: * <code>Option</code> instance in the <code>Array</code>, <code>Map</code>, or
065: * <code>Collection</code> returned by the <code>CheckboxGroup</code>
066: * <code>getItems()</code> method and renders them. It also creates
067: * a <code>Label</code> component and renders it as the label for the group.
068: * <p>
069: * Zero or more checkboxes may be selected.
070: * The value of the <code>CheckboxGroup</code> will determine
071: * which checkboxes shall be initially selected and subsequetly hold
072: * the current selections.
073: * </p>
074: * <p>
075: * The checkboxes are rendered as a single column or some number of
076: * rows and columns. The rows and columns are rendered as a table as
077: * defined by the {@link com.sun.rave.web.ui.renderer.RowColumnRenderer} superclass.
078: * The elements
079: * that make up the checkbox occupy a cell in the table.
080: * The style class selector for the group elements is identified by a java
081: * constants defined in the {@link com.sun.rave.web.ui.theme.ThemeStyles} class.
082: * </p>
083: * <ul>
084: * <li>CHECKBOX_GROUP for the TABLE element.</li>
085: * <li>CHECKBOX_GROUP_CAPTION for the TD element containing the group label</li>
086: * <li>CHECKBOX_GROUP_LABEL for the LABEL element used as the CAPTION</li>
087: * <li>CHECKBOX_GROUP_LABEL_DISABLED for the LABEL used as the CAPTION if the
088: * group is disabled</li>
089: * <li>CHECKBOX_GROUP_ROW_EVEN for even TR elements</li>
090: * <li>CHECKBOX_GROUP_ROW_ODD for odd TR elements</li>
091: * <li>CHECKBOX_GROUP_CELL_EVEN for even TD elements</li>
092: * <li>CHECKBOX_GROUP_CELL_ODD for odd TD elements</li>
093: * <li>CHECKBOX for the INPUT element</li>
094: * <li>CHECKBOX_DISABLED for the INPUT element for disabled checkbox</li>
095: * <li>CHECKBOX_LABEL for a LABEL element of a checkbox</li>
096: * <li>CHECKBOX_LABEL_DISABLED for a LABEL element of a disabled checkbox</li>
097: * <li>CHECKBOX_IMAGE for an IMG element of a checkbox</li>
098: * <li>CHECKBOX_IMAGE_DISABLED for an IMG element of a disabled checkbox</li>
099: * </ul>
100: * <p>
101: * The <code>name</code> property of each checkbox is the component id of the
102: * <code>CheckboxGroup</code> instance. The id of a <code>Checkbox</code>
103: * component is <em>cbgrpid_N</em> where <em>cbgrpid</em> is the id of the
104: * <code>CheckboxGroup</code> instance and <em>_N</em> is the nth checkbox.
105: * </p>
106: * <p>
107: * The <code>CheckboxGroup</code> is decoded by identifying the
108: * <code>CheckboxGroup</code> instance component id which is
109: * returned as a request parameter. It represents the name attribute
110: * of the selected checkbox's <input> element. The values of the
111: * identified request parameter are assigned as the submitted value of the
112: * <code>CheckboxGroup</code> component.
113: * </p>
114: * <p>
115: * If the items property of the <code>CheckboxGroup</code> is null or
116: * zero length, no output is produced.
117: * </p>
118: */
119: public class CheckboxGroupRenderer extends SelectorGroupRenderer {
120:
121: private final String MSG_COMPONENT_NOT_CHECKBOXGROUP = "CheckboxGroupRenderer only renders CheckboxGroup components.";//NOI18N
122:
123: /**
124: * Creates a new instance of CheckboxGroupRenderer
125: */
126: public CheckboxGroupRenderer() {
127: super ();
128: }
129:
130: /**
131: * Ensure that the component to be rendered is a CheckboxGroup instance.
132: * Actual rendering occurs during the <code>renderEnd</code> method.
133: *
134: * @param context FacesContext for the request we are processing.
135: * @param component UIComponent to be decoded.
136: */
137: public void renderStart(FacesContext context,
138: UIComponent component, ResponseWriter writer)
139: throws IOException {
140:
141: // Bail out if the component is not a CheckboxGroup component.
142: if (!(component instanceof CheckboxGroup)) {
143: throw new IllegalArgumentException(
144: MSG_COMPONENT_NOT_CHECKBOXGROUP);
145: }
146: }
147:
148: /**
149: * CheckboxGroupRenderer renders the entire CheckboxGroup
150: * component within the renderEnd method.
151: *
152: * @param context FacesContext for the request we are processing.
153: * @param component UIComponent to be decoded.
154: */
155: public void renderEnd(FacesContext context, UIComponent component,
156: ResponseWriter writer) throws IOException {
157:
158: // Use only the cols value. If not valid render a single column.
159: // If there are more items than columns, render additional rows.
160: //
161: CheckboxGroup cbgrp = (CheckboxGroup) component;
162:
163: Theme theme = ThemeUtilities.getTheme(context);
164: renderSelectorGroup(context, component, theme, writer, cbgrp
165: .getColumns());
166: }
167:
168: /**
169: * Return a Checkbox component to render.
170: *
171: * @param context <code>FacesContext</code> for the current request
172: * @param component <code>CheckboxGroup</code> component rendered
173: * @param theme <code>Theme</code> for the component
174: * @param option the <code>Option</code> being rendered.
175: */
176: protected UIComponent getSelectorComponent(FacesContext context,
177: UIComponent component, Theme theme, String id, Option option) {
178:
179: CheckboxGroup cbgrp = (CheckboxGroup) component;
180:
181: Checkbox cb = new Checkbox();
182: cb.setId(id);
183: cb.setParent(cbgrp);
184: cb.setName(cbgrp.getClientId(context));
185: cb.setImageURL(option.getImage());
186: cb.setSelectedValue(option.getValue());
187: cb.setLabel(option.getLabel());
188: cb.setDisabled(cbgrp.isDisabled());
189: cb.setReadOnly(cbgrp.isReadOnly());
190: cb.setTabIndex(cbgrp.getTabIndex());
191:
192: //<RAVE>
193: // Bug Fix: 6274989
194: if (option.getTooltip() != null) {
195: cb.setToolTip(option.getTooltip());
196: } else {
197: cb.setToolTip(cbgrp.getToolTip());
198: }
199:
200: //mbohm 6300361,6300362
201: //transfer event attributes from cbgrp to cb
202: //see RowColumnRenderer.renderRowColumnLayout
203: transferEventAttributes(cbgrp, cb);
204: //</RAVE>
205:
206: // Default to not selected
207: //
208: cb.setSelected(null);
209:
210: // Need to check the submittedValue for immediate condition
211: //
212: String[] subValue = (String[]) cbgrp.getSubmittedValue();
213: if (subValue == null) {
214: if (isSelected(option, cbgrp.getSelected())) {
215: cb.setSelected(cb.getSelectedValue());
216: }
217: } else if (subValue.length != 0) {
218: Object selectedValue = cb.getSelectedValue();
219: String selectedValueAsString = ConversionUtilities
220: .convertValueToString(component, selectedValue);
221: for (int i = 0; i < subValue.length; ++i) {
222: if (subValue[i] != null
223: && subValue[i].equals(selectedValueAsString)) {
224: cb.setSelected(cb.getSelectedValue());
225: break;
226: }
227: }
228: }
229:
230: return cb;
231: }
232:
233: /**
234: * Return true if the <code>item</item> argument is the currently
235: * selected checkbox. Equality is determined by the <code>equals</code>
236: * method of the object instance stored as the <code>value</code> of
237: * <code>item</code>. Return false otherwise.
238: *
239: * @param item the current checkbox being rendered.
240: * @param currentValue the value of the current selected checkbox.
241: */
242: private boolean isSelected(Option item, Object currentValue) {
243: // How is the selected value determined ?
244: // Is it the Selection value on CheckboxGroup or
245: // the boolean value on the current Selection being processed ?
246: //
247: Object value = item.getValue();
248: if (value == null || currentValue == null) {
249: return false;
250: }
251: if (currentValue instanceof Map) {
252: return ((Map) currentValue).containsValue(value);
253: } else if (currentValue instanceof Collection) {
254: return ((Collection) currentValue).contains(value);
255: } else if (currentValue instanceof Object[]) {
256: Object[] selectedValues = (Object[]) currentValue;
257: for (int i = 0; i < selectedValues.length; ++i) {
258: if (value.equals(selectedValues[i])) {
259: return true;
260: }
261: }
262: }
263: return false;
264:
265: }
266:
267: /**
268: * The style constants defined in {@link com.sun.rave.web.ui.theme.ThemeStyles} mapped
269: * to the value of constants defined in
270: * {@link com.sun.rave.web.ui.renderer.SelectorGroupRenderer}.
271: */
272: protected String[] styles = { ThemeStyles.CHECKBOX_GROUP, /* GRP */
273: ThemeStyles.CHECKBOX_GROUP_CAPTION, /* GRP_CAPTION */
274: ThemeStyles.CHECKBOX_GROUP_LABEL, /* GRP_LABEL */
275: ThemeStyles.CHECKBOX_GROUP_LABEL_DISABLED, /* GRP_LABEL_DIS */
276: ThemeStyles.CHECKBOX_GROUP_ROW_EVEN, /* GRP_ROW_EVEN */
277: ThemeStyles.CHECKBOX_GROUP_ROW_ODD, /* GRP_ROW_EVEN */
278: ThemeStyles.CHECKBOX_GROUP_CELL_EVEN, /* GRP_CELL_EVEN */
279: ThemeStyles.CHECKBOX_GROUP_CELL_ODD, /* GRP_CELL_ODD */
280: ThemeStyles.CHECKBOX, /* INPUT */
281: ThemeStyles.CHECKBOX_DISABLED, /* INPUT_DIS */
282: ThemeStyles.CHECKBOX_LABEL, /* LABEL */
283: ThemeStyles.CHECKBOX_LABEL_DISABLED, /* LABEL_DIS */
284: ThemeStyles.CHECKBOX_IMAGE, /* IMAGE */
285: ThemeStyles.CHECKBOX_IMAGE_DISABLED, /* IMAGE_DIS */
286: ThemeStyles.LABEL_LEVEL_ONE_TEXT, /* LABEL_LVL1 */
287: ThemeStyles.LABEL_LEVEL_TWO_TEXT, /* LABEL_LVL2 */
288: ThemeStyles.LABEL_LEVEL_THREE_TEXT /* LABLE_LVL3 */
289: };
290:
291: /**
292: * Return style constants for a <code>Checkbox</code> component.
293: */
294: protected String[] getStyles() {
295: return styles;
296: }
297: }
|