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-2006 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: /*
042: * IntEditor.java
043: *
044: * Created on February 28, 2003, 2:15 PM
045: */
046:
047: package org.netbeans.beaninfo.editors;
048:
049: import java.util.Arrays;
050: import org.netbeans.beaninfo.editors.ExPropertyEditorSupport.EnvException;
051: import org.netbeans.core.UIExceptions;
052: import org.openide.explorer.propertysheet.*;
053: import org.openide.util.NbBundle;
054:
055: /** An editor for primitive integer types which allows hinting of tag
056: * values and handles whitespace in setAsText better than the default
057: * JDK one. The following hints are supported:
058: * <UL><LI><B>stringKeys</B> - an array of Strings that should be supplied
059: * from getTags()</LI><LI><B>intValues - an array of ints corresponding to
060: * the values represented by stringKeys. <I>This hint must be present if
061: * the stringKeys hint is used, and the arrays must be of the same length.</LI>
062: * <LI><B>codeValues</B> - an array of strings that should be returned from
063: * getJavaInitializationString. This hint is optional when using the
064: * aforementioned hints. <P>These hints will also work for the Integer
065: * editor, which wraps an instance of this editor.
066: *
067: * @author Tim Boudreau
068: * @version 1.0
069: */
070: public class IntEditor extends ExPropertyEditorSupport {
071:
072: public static final String KEYS = "stringKeys"; //NOI18N
073: public static final String VALS = "intValues"; //NOI18N
074: public static final String CODE_VALS = "codeValues"; //NOI18N
075: String[] keys = null;
076: String[] code = null;
077: int[] values = null;
078:
079: /** Creates a new instance of IntEditor */
080: public IntEditor() {
081: }
082:
083: protected void attachEnvImpl(PropertyEnv env) {
084: keys = (String[]) env.getFeatureDescriptor().getValue(KEYS);
085: values = (int[]) env.getFeatureDescriptor().getValue(VALS);
086: code = (String[]) env.getFeatureDescriptor()
087: .getValue(CODE_VALS);
088: }
089:
090: /** Validate that the values supplied by the PropertyEnv are proper,
091: * so there's not an obscure ArrayIndexOutOfBoundsException some time
092: * later because bad information was supplied. */
093: protected void validateEnv(PropertyEnv env) {
094: //fail fast validation of illegal values
095: boolean valid = keys == null && values == null && code == null;
096: if (!valid) {
097: valid = keys != null && values != null;
098: if (!valid) {
099: throw new EnvException(
100: "You must specify both an array of keys and an "
101: + //NOI18N
102: "array of values if you specify one. Keys="
103: + //NOI18N
104: arrToStr(keys) + " Values="
105: + arrToStr(values)); //NOI18N
106: } else {
107: valid = keys.length == values.length;
108: if (valid) {
109: valid = keys.length > 0 && values.length > 0;
110: }
111:
112: if (!valid) {
113: throw new EnvException(
114: "The arrays of keys and values must have the same "
115: + //NOI18N
116: "length and the length must be > 0. keys.length ="
117: + //NOI18N
118: keys.length + " values.length="
119: + values.length + " Keys="
120: + //NOI18N
121: arrToStr(keys) + " Values="
122: + arrToStr(values)); //NOI18N
123: } else {
124: if (code != null) {
125: valid = code.length == keys.length;
126: if (valid) {
127: valid = code.length > 0;
128: }
129: if (!valid) {
130: throw new EnvException(
131: "The arrays of keys and values and codes must all"
132: + //NOI18N
133: " have the same length, > 0. keys.length ="
134: + //NOI18N
135: keys.length
136: + " values.length="
137: + values.length
138: + //NOI18N
139: " Code.length="
140: + code.length
141: + " Keys="
142: + //NOI18N
143: arrToStr(keys) + " Values="
144: + arrToStr(values)
145: + " Code=" + arrToStr(code)); //NOI18N
146: }
147: }
148: }
149: }
150: }
151: }
152:
153: private static final String arrToStr(int[] s) {
154: if (s == null)
155: return "null"; //NOI18N
156: StringBuffer out = new StringBuffer(s.length * 3);
157: for (int i = 0; i < s.length; i++) {
158: out.append(s[i]);
159: if (i != s.length - 1) {
160: out.append(','); //NOI18N
161: }
162: }
163: return out.toString();
164: }
165:
166: public String getAsText() {
167: Integer i = (Integer) getValue();
168: String result;
169: if (i != null) {
170: if (keys != null) {
171: int intVal = i.intValue();
172: int idx = -1;
173: for (int j = 0; j < values.length; j++) {
174: if (values[j] == intVal) {
175: idx = j;
176: break;
177: }
178: }
179: if (idx != -1) {
180: result = keys[((Integer) super .getValue())
181: .intValue()];
182: } else {
183: throw new IllegalArgumentException(
184: "This property editor uses a set of keyed values, "
185: + //NOI18N
186: "and the current value, " //NOI18N
187: + i + ", is not specified."); //NOI18N
188: }
189: } else {
190: result = getValue().toString();
191: }
192: } else {
193: result = NbBundle.getMessage(IntEditor.class, "NULL"); //NOI18N
194: }
195: return result;
196: }
197:
198: private void doSetAsText(String s) {
199: //fixes issue 23077, confusing error message from NFE.
200: //IllegalArgumentException is a more correct exception to throw
201: //anyway
202: try {
203: setValue(Integer.valueOf(s));
204: } catch (NumberFormatException nfe) {
205: String msg = NbBundle.getMessage(IntEditor.class,
206: "EXC_ILLEGAL_VALUE_TEXT")
207: + s; //NOI18N
208: RuntimeException iae = new IllegalArgumentException(msg); //NOI18N
209: UIExceptions.annotateUser(iae, msg, msg, nfe,
210: new java.util.Date());
211: throw iae;
212: }
213: }
214:
215: public void setAsText(String s) {
216: s = s.trim();
217: if (keys == null) {
218: doSetAsText(s);
219: } else {
220: //use the keys, translate to an int value
221: int idx = Arrays.asList(keys).indexOf(s);
222: if ((idx == -1) || (idx > values.length - 1)) {
223: StringBuffer msg = new StringBuffer();
224: msg.append(NbBundle.getMessage(IntEditor.class,
225: "EXC_ILLEGAL_STRING_TEXT_FIRST")); //NOI18N
226: msg.append(s);
227: msg.append(NbBundle.getMessage(IntEditor.class,
228: "EXC_ILLEGAL_STRING_TEXT_SECOND")); //NOI18N
229: msg.append(arrToStr(keys));
230: String message = msg.toString();
231: RuntimeException iae = new IllegalArgumentException(
232: message);
233: UIExceptions.annotateUser(iae, message, message, iae,
234: new java.util.Date());
235: throw iae;
236: } else {
237: setValue(Integer.valueOf(idx));
238: }
239: }
240: }
241:
242: public Object getValue() {
243: Integer v = (Integer) super .getValue();
244: if (values != null) {
245: v = Integer.valueOf(values[v.intValue()]);
246: }
247: return v;
248: }
249:
250: //issue 34037 - make setValue calls with illegal values fail-fast
251: public void setValue(Object value) {
252: if ((value instanceof Integer) || (value == null)) {
253: super .setValue(value);
254: } else {
255: throw new IllegalArgumentException(
256: "Argument to IntEditor.setValue() must be Integer, but was "
257: + //NOI18N
258: value.getClass().getName() + "(=" + //NOI18N
259: value.toString() + ")"); //NOI18N
260: }
261: }
262:
263: public String[] getTags() {
264: return keys;
265: }
266:
267: public String getJavaInitializationString() {
268: String result;
269: if (code == null) {
270: result = getValue().toString();
271: } else {
272: result = code[((Integer) getValue()).intValue()];
273: }
274: return result;
275: }
276: }
|