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.component;
042:
043: import com.sun.rave.web.ui.util.ComponentUtilities;
044: import java.util.Iterator;
045:
046: import javax.faces.component.EditableValueHolder;
047: import javax.faces.component.UIComponent;
048: import javax.faces.context.FacesContext;
049:
050: /**
051: *
052: * @author Ken Paulsen
053: */
054: public class Property extends PropertyBase implements ComplexComponent {
055:
056: public static final String CONTENT_FACET = "content"; //NOI18N
057: public static final String HELPTEXT_FACET = "helpText"; //NOI18N
058: public static final String LABEL_FACET = "label"; //NOI18N
059:
060: /**
061: * Constructor.
062: */
063: public Property() {
064: super ();
065: }
066:
067: /**
068: * <p> This method calculates the proper <code>UIComponent</code> that
069: * should be used when the label property is used with this
070: * component.</p>
071: *
072: * <p> This method provides the implementation for
073: * {@link com.sun.rave.web.ui.component.ComplexComponent}</p>
074: *
075: * @param context The <code>FacesContext</code>.
076: *
077: * @return The <code>id</code> of the label target.
078: */
079: public String getPrimaryElementID(FacesContext context) {
080: // Check for "content" Facet first
081: UIComponent contentFacet = (UIComponent) getFacets().get(
082: "content");
083:
084: // The field component is the one that is labelled
085: UIComponent labeledComponent = null;
086:
087: if (contentFacet == null) {
088: // If there is no facet, assume that the content is specified
089: // as a child of this component. Search for a
090: // required EditableValueHolderamong the children
091: labeledComponent = findLabeledComponent(this , true);
092: } else {
093: // If a facet has been specified, see if the facet is a required
094: // EditableValueHolder or search for a required EditableValueHolder
095: // among the children of the facet component
096: labeledComponent = findLabeledComponent(contentFacet, false);
097: }
098:
099: if (labeledComponent != null) {
100: // Return an absolute path (relative is harder to calculate)
101: // NOTE: Label component does not fully support relative anyway,
102: // NOTE: the ":" I'm adding isn't necessary... however, it doesn't
103: // NOTE: hurt and if Label ever does support relative paths, the
104: // NOTE: ":" prefix is needed to specify a full path.
105: // NOTE:
106: // NOTE: Don't use ComplexComponent here, the Label component will.
107: return ":" + labeledComponent.getClientId(context); // NOI18N
108: }
109: return null;
110: }
111:
112: /**
113: * <p> This method checks the component, children, and facets to see if
114: * any of them are <code>EditableValueHolder</code>s. The first one
115: * found is returned, null
116: * otherwise.</p>
117: *
118: * @param comp The <code>UIComponent</code> to check.
119: * @param skip Flag indicating the initial component should be ignored
120: *
121: * @return The first <code>EditableValueHolder</code>, null if not found.
122: */
123: private static UIComponent findLabeledComponent(UIComponent comp,
124: boolean skip) {
125: if (!skip) {
126: // Check to see if comp is an EditableValueHolder
127: if (comp instanceof EditableValueHolder) {
128: return comp;
129: }
130: }
131:
132: // Next check children and facets
133: Iterator it = comp.getFacetsAndChildren();
134: while (it.hasNext()) {
135: comp = findLabeledComponent((UIComponent) it.next(), false);
136: if (comp != null) {
137: return comp;
138: }
139: }
140:
141: // Not found
142: return null;
143: }
144:
145: /**
146: * Return the a component that represents the content of the property.
147: * If a facet called <code>content</code> does not exist <code>null</code>
148: * is returned.
149: */
150: public UIComponent getContentComponent() {
151: return getFacet(CONTENT_FACET);
152: }
153:
154: /**
155: * Return the component that implements help text.
156: * If a facet named <code>helpText</code> is found
157: * that component is returned. Otherwise a <code>HelpInline</code>
158: * component is returned. It is assigned the id</br>
159: * <code>getId() + "_helpText"</code></br>
160: * <p>
161: * If the facet is not defined then the returned <code>HelpInline</code>
162: * component is re-intialized every time this method is called.
163: * </p>
164: * <p>
165: * If <code>getHelpeText</code> returns null, null is returned.
166: * </p>
167: *
168: * @return a help text facet component
169: */
170: public UIComponent getHelpTextComponent() {
171:
172: UIComponent component = getFacet(HELPTEXT_FACET);
173: if (component != null) {
174: return component;
175: }
176:
177: String helpText = getHelpText();
178: if (helpText == null) {
179: return null;
180: }
181:
182: HelpInline helpInline = new HelpInline();
183: helpInline.setText(helpText);
184: helpInline.setId(ComponentUtilities.createPrivateFacetId(this ,
185: HELPTEXT_FACET));
186: helpInline.setParent(this );
187: helpInline.setType("field"); //NOI18N
188:
189: return helpInline;
190:
191: }
192:
193: /**
194: * Return the component that implements a label.
195: * If a facet named <code>label</code> is found
196: * that component is returned. Otherwise a <code>Label</code> component
197: * is returned. It is assigned the id</br>
198: * <code>getId() + "_label"</code></br>
199: * <p>
200: * If the facet is not defined then the returned <code>Label</code>
201: * component is re-intialized every time this method is called.
202: * </p>
203: *
204: * @return a label facet component
205: */
206: public UIComponent getLabelComponent() {
207:
208: UIComponent component = getFacet(LABEL_FACET);
209: if (component != null) {
210: return component;
211: }
212:
213: if (getLabel() == null) {
214: return null;
215: }
216:
217: component = ComponentUtilities.getPrivateFacet(this ,
218: LABEL_FACET, true);
219:
220: if (component == null) {
221: Label label = new Label();
222: label.setId(ComponentUtilities.createPrivateFacetId(this ,
223: LABEL_FACET));
224: label.setText(getLabel());
225: String id = getPrimaryElementID(FacesContext
226: .getCurrentInstance());
227: label.setFor(id);
228: ComponentUtilities
229: .putPrivateFacet(this, LABEL_FACET, label);
230: component = label;
231: }
232:
233: return component;
234: }
235: }
|