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.jsfcl.std.property;
042:
043: import java.awt.Component;
044: import java.util.Iterator;
045: import java.util.List;
046:
047: /**
048: * @author eric
049: *
050: * @deprecated
051: */
052: public abstract class SingleChoiceListPropertyEditor extends
053: AbstractPropertyEditor {
054: protected final static Object CHOICE_NOT_FOUND_MARKER = new Object();
055: protected final static int MAX_CHOICE_COUNT_FOR_TAGS = 8;
056:
057: protected List choices;
058: protected Object valueChoice;
059:
060: public void attachToNewDesignProperty() {
061:
062: super .attachToNewDesignProperty();
063: initializeValueChoice();
064: }
065:
066: /**
067: * Gets the property value as a string suitable for presentation
068: * to a human to edit.
069: *
070: * @return The property value as a string suitable for presentation
071: * to a human to edit.
072: * <p> Returns "null" is the value can't be expressed as a string.
073: * <p> If a non-null value is returned, then the PropertyEditor should
074: * be prepared to parse that string back in setAsText().
075: */
076: public String getAsText() {
077:
078: return getStringForChoice(getValueChoice());
079: }
080:
081: protected Object getChoiceForString(String lookFor) {
082: Object result;
083:
084: if (lookFor != null) {
085: lookFor.trim();
086: }
087: result = getChoiceForStringImp(lookFor);
088: if (result == CHOICE_NOT_FOUND_MARKER) {
089: result = getChoiceForStringNotFound(lookFor);
090: }
091: return result;
092: }
093:
094: /**
095: * This method is inteded to be overriden in order to provide more specific
096: * support by subclasses. The base implementation is to return the string
097: * passed in.
098: * @param string
099: * @return
100: */
101: protected Object getChoiceForStringImp(String lookFor) {
102:
103: if (lookFor == null) {
104: lookFor = ""; //NOI18N
105: }
106: for (Iterator iterator = getChoices().iterator(); iterator
107: .hasNext();) {
108: Object object;
109: String string;
110:
111: object = iterator.next();
112: string = getStringForChoice(object);
113: if (lookFor.equalsIgnoreCase(string)) {
114: return object;
115: }
116: }
117: return CHOICE_NOT_FOUND_MARKER;
118: }
119:
120: protected Object getChoiceForStringNotFound(String lookFor) {
121:
122: return lookFor;
123: }
124:
125: public List getChoices() {
126:
127: if (choices == null) {
128: choices = getChoicesImp();
129: }
130: return choices;
131: }
132:
133: protected abstract List getChoicesImp();
134:
135: /**
136: * A PropertyEditor may chose to make available a full custom Component
137: * that edits its property value. It is the responsibility of the
138: * PropertyEditor to hook itself up to its editor Component itself and
139: * to report property value changes by firing a PropertyChange event.
140: * <P>
141: * The higher-level code that calls getCustomEditor may either embed
142: * the Component in some larger property sheet, or it may put it in
143: * its own individual dialog, or ...
144: *
145: * @return A java.awt.Component that will allow a human to directly
146: * edit the current property value. May be null if this is
147: * not supported.
148: */
149: public Component getCustomEditor() {
150:
151: return new SingleChoiceListPanel(this , getDesignProperty());
152: }
153:
154: public String getJavaInitializationString() {
155:
156: return stringToJavaSourceString(getAsText());
157: }
158:
159: /**
160: * This method is inteded to be overriden in order to provide more specific
161: * support by subclasses. The base implementation is to return the result
162: * of toString() on object.
163: * @param string
164: * @return
165: */
166: protected String getStringForChoice(Object object) {
167:
168: if (object == null) {
169: return ""; //NOI18N
170: }
171: return object.toString();
172: }
173:
174: public String[] getTags() {
175: List choices = getChoices();
176: if (choices.size() > MAX_CHOICE_COUNT_FOR_TAGS) {
177: return null;
178: }
179: String[] result = new String[choices.size()];
180: int i = 0;
181: for (Iterator iterator = choices.iterator(); iterator.hasNext(); i++) {
182: result[i] = getStringForChoice(iterator.next());
183: }
184: return result;
185: }
186:
187: public Object getValueChoice() {
188:
189: return valueChoice;
190: }
191:
192: protected Object getValueForChoice(Object object) {
193:
194: return getStringForChoice(object);
195: }
196:
197: protected void initializeValueChoice() {
198:
199: valueChoice = getChoiceForString((String) getValue());
200: }
201:
202: public boolean isPaintable() {
203:
204: // EATTODO: This CHEEZY as all get out, but its the only call I'm pretty sure is
205: // called first, before the others, and not as often as getTags in one pass when
206: // there is need of tags :( I used to have it on getTags, but that gets called too
207: // many times, plus the fact that getTags turns around and immediately causes
208: // items to be rebuild again.
209: // MUST FIND a better way to do this
210: if (wantsAbilityToRefreshChoices()) {
211: refreshChoices();
212: }
213: return super .isPaintable();
214: }
215:
216: protected boolean isUnsetMarker(Object object) {
217:
218: return object == null || "".equals(object); //NOI18N
219: }
220:
221: public void refreshChoices() {
222:
223: choices = null;
224: }
225:
226: /**
227: * Sets the property value by parsing a given String. May raise
228: * java.lang.IllegalArgumentException if either the String is
229: * badly formatted or if this kind of property can't be expressed
230: * as text.
231: *
232: * @param text The string to be parsed.
233: */
234: public void setAsText(String text)
235: throws java.lang.IllegalArgumentException {
236: Object object = getChoiceForString(text);
237: setValueChoice(object);
238: }
239:
240: public void setValueChoice(Object object) {
241:
242: valueChoice = object;
243: setValue(getValueForChoice(object));
244: if (isUnsetMarker(object)) {
245: unsetProperty();
246: }
247: }
248:
249: /**
250: * Determines whether the propertyEditor can provide a custom editor.
251: *
252: * @return True if the propertyEditor can provide a custom editor.
253: */
254: public boolean supportsCustomEditor() {
255:
256: return getChoices().size() > MAX_CHOICE_COUNT_FOR_TAGS;
257: }
258:
259: /*
260: * Provide a refresh choices in order to deal with the fact that NB seems
261: * to be caching the property editors, and we need to make sure that
262: * choices is always up to date.
263: * Will be called when we think its a good time to refresh, keep in mind
264: * may be called many times.
265: * If you list of items is static, no need to answer true.
266: * @author eric
267: */
268: protected boolean wantsAbilityToRefreshChoices() {
269:
270: return false;
271: }
272:
273: }
|