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: package org.netbeans.beaninfo.editors;
043:
044: import java.awt.*;
045: import java.beans.*;
046: import java.util.*;
047: import javax.swing.JList;
048: import javax.swing.JScrollPane;
049: import org.openide.explorer.propertysheet.ExPropertyEditor;
050: import org.openide.explorer.propertysheet.PropertyEnv;
051: import org.openide.explorer.propertysheet.editors.XMLPropertyEditor;
052: import org.openide.nodes.Node;
053:
054: /** A property editor for array of Strings.
055: * @author Ian Formanek
056: */
057: public class StringArrayEditor implements XMLPropertyEditor,
058: StringArrayCustomizable, ExPropertyEditor {
059:
060: // constants for XML persistence
061: private static final String XML_STRING_ARRAY = "StringArray"; // NOI18N
062: private static final String XML_STRING_ITEM = "StringItem"; // NOI18N
063: private static final String ATTR_COUNT = "count"; // NOI18N
064: private static final String ATTR_INDEX = "index"; // NOI18N
065: private static final String ATTR_VALUE = "value"; // NOI18N
066:
067: // private fields
068: private String[] strings;
069: private PropertyChangeSupport support;
070: private boolean editable = true;
071: private String separator = ",";
072:
073: public StringArrayEditor() {
074: support = new PropertyChangeSupport(this );
075: }
076:
077: public Object getValue() {
078: return strings;
079: }
080:
081: public void setValue(Object value) {
082: strings = (String[]) value;
083: support.firePropertyChange("", null, null); // NOI18N
084: }
085:
086: // -----------------------------------------------------------------------------
087: // StringArrayCustomizable implementation
088:
089: /** Used to acquire the current value from the PropertyEditor
090: * @return the current value of the property
091: */
092: public String[] getStringArray() {
093: return (String[]) getValue();
094: }
095:
096: /** Used to modify the current value in the PropertyEditor
097: * @param value the new value of the property
098: */
099: public void setStringArray(String[] value) {
100: setValue(value);
101: }
102:
103: // end of StringArrayCustomizable implementation
104:
105: protected final String getStrings(boolean quoted) {
106: if (strings == null)
107: return "null"; // NOI18N
108:
109: StringBuilder buf = new StringBuilder();
110: for (int i = 0; i < strings.length; i++) {
111: // XXX handles in-string escapes if quoted
112: if (quoted) {
113: buf.append('"').append(strings[i]).append('"');
114: } else {
115: buf.append(strings[i]);
116: }
117: if (i != strings.length - 1) {
118: buf.append(separator);
119: buf.append(' '); // NOI18N
120: }
121: }
122:
123: return buf.toString();
124: }
125:
126: public String getAsText() {
127: return getStrings(false);
128: }
129:
130: public void setAsText(String text) {
131: if ("null".equals(text)) { // NOI18N
132: setValue(null);
133: return;
134: }
135: StringTokenizer tok = new StringTokenizer(text, separator);
136: java.util.List<String> list = new LinkedList<String>();
137: while (tok.hasMoreTokens()) {
138: String s = tok.nextToken();
139: list.add(s.trim());
140: }
141: String[] a = list.toArray(new String[list.size()]);
142: setValue(a);
143: }
144:
145: public String getJavaInitializationString() {
146: if (strings == null)
147: return "null"; // NOI18N
148: // [PENDING - wrap strings ???]
149: StringBuilder buf = new StringBuilder("new String[] {"); // NOI18N
150: buf.append(getStrings(true));
151: buf.append('}'); // NOI18N
152: return buf.toString();
153: }
154:
155: public String[] getTags() {
156: return null;
157: }
158:
159: public boolean isPaintable() {
160: return false;
161: }
162:
163: public void paintValue(Graphics g, Rectangle rectangle) {
164: }
165:
166: public boolean supportsCustomEditor() {
167: //Don't show custom editor if it's just going to show
168: //an empty component
169: if (!editable && (strings == null || strings.length == 0)) {
170: return false;
171: } else {
172: return true;
173: }
174: }
175:
176: public Component getCustomEditor() {
177: if (editable) {
178: return new StringArrayCustomEditor(this );
179: } else {
180: return new JScrollPane(new JList(getStringArray()));
181: }
182: }
183:
184: public void addPropertyChangeListener(
185: PropertyChangeListener propertyChangeListener) {
186: support.addPropertyChangeListener(propertyChangeListener);
187: }
188:
189: public void removePropertyChangeListener(
190: PropertyChangeListener propertyChangeListener) {
191: support.removePropertyChangeListener(propertyChangeListener);
192: }
193:
194: // -------------------------------------------
195: // XMLPropertyEditor implementation
196:
197: /** Called to store current property value into XML subtree.
198: * @param doc The XML document to store the XML in - should be used for
199: * creating nodes only
200: * @return the XML DOM element representing a subtree of XML from which
201: the value should be loaded
202: */
203: public org.w3c.dom.Node storeToXML(org.w3c.dom.Document doc) {
204: org.w3c.dom.Element arrayEl = doc
205: .createElement(XML_STRING_ARRAY);
206: int count = strings != null ? strings.length : 0;
207: arrayEl.setAttribute(ATTR_COUNT, Integer.toString(count));
208:
209: for (int i = 0; i < count; i++) {
210: org.w3c.dom.Element itemEl = doc
211: .createElement(XML_STRING_ITEM);
212: itemEl.setAttribute(ATTR_INDEX, Integer.toString(i));
213: itemEl.setAttribute(ATTR_VALUE, strings[i]);
214: arrayEl.appendChild(itemEl);
215: }
216:
217: return arrayEl;
218: }
219:
220: /** Called to load property value from specified XML subtree.
221: * If succesfully loaded, the value should be available via getValue().
222: * An IOException should be thrown when the value cannot be restored from
223: * the specified XML element
224: * @param element the XML DOM element representing a subtree of XML from
225: * which the value should be loaded
226: * @exception IOException thrown when the value cannot be restored from
227: the specified XML element
228: */
229: public void readFromXML(org.w3c.dom.Node element)
230: throws java.io.IOException {
231: if (!XML_STRING_ARRAY.equals(element.getNodeName()))
232: throw new java.io.IOException();
233:
234: org.w3c.dom.NamedNodeMap attributes = element.getAttributes();
235: String[] stringArray;
236: org.w3c.dom.Node countNode = null;
237: int count = 0;
238:
239: if ((countNode = attributes.getNamedItem(ATTR_COUNT)) != null
240: && (count = Integer.parseInt(countNode.getNodeValue())) > 0) {
241: stringArray = new String[count];
242: org.w3c.dom.NodeList items = element.getChildNodes();
243: org.w3c.dom.Element itemEl;
244:
245: for (int i = 0; i < items.getLength(); i++) {
246: if (items.item(i).getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
247: itemEl = (org.w3c.dom.Element) items.item(i);
248: if (XML_STRING_ITEM.equals(itemEl.getNodeName())) {
249: String indexStr = itemEl
250: .getAttribute(ATTR_INDEX);
251: String valueStr = itemEl
252: .getAttribute(ATTR_VALUE);
253: if (indexStr != null && valueStr != null) {
254: int index = Integer.parseInt(indexStr);
255: if (index >= 0 && index < count)
256: stringArray[index] = valueStr;
257: }
258: }
259: }
260: }
261: } else
262: stringArray = new String[0];
263:
264: setValue(stringArray);
265: }
266:
267: public void attachEnv(PropertyEnv env) {
268: FeatureDescriptor d = env.getFeatureDescriptor();
269: readEnv(env.getFeatureDescriptor());
270: }
271:
272: final void readEnv(FeatureDescriptor d) {
273: if (d instanceof Node.Property) {
274: editable = ((Node.Property) d).canWrite();
275: } else if (d instanceof PropertyDescriptor) {
276: editable = ((PropertyDescriptor) d).getWriteMethod() != null;
277: } else {
278: editable = true;
279: }
280:
281: Object v = d.getValue("item.separator"); // NOI18N
282: if (v instanceof String) {
283: separator = (String) v;
284: }
285: }
286: }
|