KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > explorer > propertysheet > IndexedPropertyEditor


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.openide.explorer.propertysheet;
20
21 import org.openide.nodes.*;
22 import org.openide.util.NbBundle;
23 import org.openide.util.Utilities;
24 import org.openide.util.actions.SystemAction;
25 import org.openide.util.datatransfer.NewType;
26
27 import java.awt.Component JavaDoc;
28
29 import java.beans.*;
30
31 import java.lang.reflect.Array JavaDoc;
32 import java.lang.reflect.InvocationTargetException JavaDoc;
33
34 import java.util.*;
35
36 import javax.swing.event.ChangeEvent JavaDoc;
37 import javax.swing.event.ChangeListener JavaDoc;
38 import org.netbeans.modules.openide.explorer.UIException;
39
40
41 /**
42 * This class encapsulates working with indexed properties.
43 */

44 class IndexedPropertyEditor extends Object JavaDoc implements ExPropertyEditor {
45     //XXX this class should be rewritten
46
//and moved to the Nodes package where it belongs - TDB
47
// -----------------------------------------------------------------------------
48
// Private variables
49
private Object JavaDoc[] array;
50     private PropertyEnv env;
51     private PropertyChangeSupport propertySupport = new PropertyChangeSupport(this);
52     private Node.IndexedProperty indexedProperty = null;
53     private IndexedEditorPanel currentEditorPanel;
54
55     // -----------------------------------------------------------------------------
56
// init
57
public IndexedPropertyEditor() {
58     }
59
60     // -----------------------------------------------------------------------------
61
// ExPropertyEditor implementation
62
public void attachEnv(PropertyEnv env) {
63         this.env = env;
64         env.setChangeImmediate(false);
65
66         FeatureDescriptor details = env.getFeatureDescriptor();
67
68         if (details instanceof Node.IndexedProperty) {
69             indexedProperty = (Node.IndexedProperty) details;
70         } else {
71             throw new IllegalStateException JavaDoc("This is not an array: " + details); // NOI18N
72
}
73     }
74
75     // -----------------------------------------------------------------------------
76
// PropertyEditor implementation
77
public void setValue(Object JavaDoc value) {
78         if (value == null) {
79             array = null;
80             firePropertyChange();
81
82             return;
83         }
84
85         if (!value.getClass().isArray()) {
86             throw new IllegalArgumentException JavaDoc(
87                 (env != null) ? ("Property whose value is not an array " + env.getFeatureDescriptor().getName())
88                               : "Unknown property - not attached yet."
89             ); //NOI18N
90
}
91
92         if (value.getClass().getComponentType().isPrimitive()) {
93             array = Utilities.toObjectArray(value);
94         } else {
95             array = (Object JavaDoc[]) Array.newInstance(value.getClass().getComponentType(), ((Object JavaDoc[]) value).length);
96             System.arraycopy(value, 0, array, 0, array.length);
97         }
98
99         firePropertyChange();
100     }
101
102     public Object JavaDoc getValue() {
103         if (array == null) {
104             return null;
105         }
106
107         if (indexedProperty.getElementType().isPrimitive()) {
108             return Utilities.toPrimitiveArray(array);
109         }
110
111         return array;
112     }
113
114     public boolean isPaintable() {
115         return false;
116     }
117
118     public void paintValue(java.awt.Graphics JavaDoc gfx, java.awt.Rectangle JavaDoc box) {
119     }
120
121     public String JavaDoc getJavaInitializationString(int index) {
122         if (array[index] == null) {
123             return "null"; // NOI18N
124
}
125
126         try {
127             indexedProperty.getIndexedPropertyEditor().setValue(array[index]);
128
129             return indexedProperty.getIndexedPropertyEditor().getJavaInitializationString();
130         } catch (NullPointerException JavaDoc e) {
131             return "null"; // NOI18N
132
}
133     }
134
135     public String JavaDoc getJavaInitializationString() {
136         if (array == null) {
137             return ""; // NOI18N
138
}
139
140         StringBuffer JavaDoc buf = new StringBuffer JavaDoc("new "); // NOI18N
141
buf.append(indexedProperty.getElementType().getName());
142
143         // empty array
144
if (array.length == 0) {
145             buf.append("[0]"); // NOI18N
146
} else
147         // non-empty array
148
{
149             buf.append("[] {\n\t"); // NOI18N
150

151             for (int i = 0; i < array.length; i++) {
152                 try {
153                     indexedProperty.getIndexedPropertyEditor().setValue(array[i]);
154                     buf.append(indexedProperty.getIndexedPropertyEditor().getJavaInitializationString());
155                 } catch (NullPointerException JavaDoc e) {
156                     buf.append("null"); // NOI18N
157
}
158
159                 if (i != (array.length - 1)) {
160                     buf.append(",\n\t"); // NOI18N
161
} else {
162                     buf.append("\n"); // NOI18N
163
}
164             }
165
166             buf.append("}"); // NOI18N
167
}
168
169         return buf.toString();
170     }
171
172     public String JavaDoc getAsText() {
173         if (array == null) {
174             return "null"; // NOI18N
175
}
176
177         StringBuffer JavaDoc buf = new StringBuffer JavaDoc("["); // NOI18N
178
PropertyEditor p = null;
179
180         if (indexedProperty != null) {
181             p = indexedProperty.getIndexedPropertyEditor();
182         }
183
184         for (int i = 0; i < array.length; i++) {
185             if (p != null) {
186                 p.setValue(array[i]);
187
188                 // bugfix #27361, append property's value as text instead of java initialization string
189
buf.append(p.getAsText());
190             } else {
191                 buf.append("null"); // NOI18N
192
}
193
194             if (i != (array.length - 1)) {
195                 buf.append(", "); // NOI18N
196
}
197         }
198
199         buf.append("]"); // NOI18N
200

201         return buf.toString();
202     }
203
204     public void setAsText(String JavaDoc text) throws java.lang.IllegalArgumentException JavaDoc {
205         if (text.equals("null")) { // NOI18N
206
setValue(null);
207
208             return;
209         }
210
211         if (text.equals("[]")) { // NOI18N
212
setValue(Array.newInstance(indexedProperty.getElementType(), 0));
213
214             return;
215         }
216
217         int i1 = text.indexOf('[');
218
219         if ((i1 < 0) || ((i1 + 1) >= text.length())) {
220             i1 = 0;
221         } else {
222             i1++;
223         }
224
225         int i2 = text.lastIndexOf(']');
226
227         if (i2 < 0) {
228             i2 = text.length();
229         }
230
231         if ((i2 < i1) || (i2 > text.length())) {
232             return;
233         } else {
234         }
235
236         try {
237             PropertyEditor p = indexedProperty.getIndexedPropertyEditor();
238
239             if (p == null) { //Test for no editor, it's not guaranteed there will be one
240
throw new IllegalStateException JavaDoc("Indexed type has no property " + "editor");
241             }
242
243             text = text.substring(i1, i2);
244
245             StringTokenizer tok = new StringTokenizer(text, ","); // NOI18N
246
java.util.List JavaDoc<Object JavaDoc> list = new LinkedList<Object JavaDoc>();
247
248             while (tok.hasMoreTokens()) {
249                 String JavaDoc s = tok.nextToken();
250                 p.setAsText(s.trim());
251                 list.add(p.getValue());
252             }
253
254             Object JavaDoc[] a = list.toArray((Object JavaDoc[]) Array.newInstance(getConvertedType(), list.size()));
255             setValue(a);
256         } catch (Exception JavaDoc x) {
257             IllegalArgumentException JavaDoc iae = new IllegalArgumentException JavaDoc();
258             UIException.annotateUser(iae, getString("EXC_ErrorInIndexedSetter"),
259                                      getString("EXC_ErrorInIndexedSetter"), x,
260                                      new Date());
261             throw iae;
262         }
263     }
264
265     public String JavaDoc[] getTags() {
266         return null;
267     }
268
269     public Component JavaDoc getCustomEditor() {
270         if (array == null) {
271             array = (Object JavaDoc[]) Array.newInstance(getConvertedType(), 0);
272             firePropertyChange();
273         }
274
275         Node dummy = new DisplayIndexedNode(0);
276
277         // beware - this will function only if the DisplayIndexedNode has
278
// one property on the first sheet and the property is of type
279
// ValueProp
280
Node.Property prop = dummy.getPropertySets()[0].getProperties()[0];
281
282         Node.Property[] np = new Node.Property[] { prop };
283         currentEditorPanel = new IndexedEditorPanel(createRootNode(), np);
284
285         return currentEditorPanel;
286     }
287
288     public boolean supportsCustomEditor() {
289         return true;
290     }
291
292     public void addPropertyChangeListener(PropertyChangeListener listener) {
293         propertySupport.addPropertyChangeListener(listener);
294     }
295
296     public void removePropertyChangeListener(PropertyChangeListener listener) {
297         propertySupport.removePropertyChangeListener(listener);
298     }
299
300     // other methods ........................................................................
301
private Node createRootNode() {
302         DisplayIndexedNode[] n = new DisplayIndexedNode[array.length];
303
304         for (int i = 0; i < n.length; i++) {
305             n[i] = new DisplayIndexedNode(i);
306         }
307
308         MyIndexedRootNode idr = new MyIndexedRootNode(n);
309         Index ind = (Index) idr.getCookie(Index.class);
310
311         for (int i = 0; i < n.length; i++) {
312             ind.addChangeListener(org.openide.util.WeakListeners.change(n[i], ind));
313         }
314
315         return idr;
316     }
317
318     /**
319      * Converts indexedProperty.getElementType() class
320      */

321     private Class JavaDoc getConvertedType() {
322         Class JavaDoc type = indexedProperty.getElementType();
323
324         if (type.isPrimitive()) {
325             type = Utilities.getObjectType(type);
326         }
327
328         return type;
329     }
330
331     void firePropertyChange() {
332         propertySupport.firePropertyChange("value", null, null); // NOI18N
333
}
334
335     private static String JavaDoc getString(String JavaDoc key) {
336         return NbBundle.getBundle(IndexedPropertyEditor.class).getString(key);
337     }
338
339     /**
340      * Makes an attempt to create new value of the property. Usefull
341      * especially when enlarging the array.
342      */

343     private Object JavaDoc defaultValue() {
344         Object JavaDoc value = null;
345
346         if (indexedProperty.getElementType().isPrimitive()) {
347             if (getConvertedType().equals(Integer JavaDoc.class)) {
348                 value = new Integer JavaDoc(0);
349             }
350
351             if (getConvertedType().equals(Boolean JavaDoc.class)) {
352                 value = Boolean.FALSE;
353             }
354
355             if (getConvertedType().equals(Byte JavaDoc.class)) {
356                 value = new Byte JavaDoc((byte) 0);
357             }
358
359             if (getConvertedType().equals(Character JavaDoc.class)) {
360                 value = new Character JavaDoc('\u0000');
361             }
362
363             if (getConvertedType().equals(Double JavaDoc.class)) {
364                 value = new Double JavaDoc(0d);
365             }
366
367             if (getConvertedType().equals(Float JavaDoc.class)) {
368                 value = new Float JavaDoc(0f);
369             }
370
371             if (getConvertedType().equals(Long JavaDoc.class)) {
372                 value = new Long JavaDoc(0L);
373             }
374
375             if (getConvertedType().equals(Short JavaDoc.class)) {
376                 value = new Short JavaDoc((short) 0);
377             }
378         } else {
379             try {
380                 value = getConvertedType().newInstance();
381             } catch (Exception JavaDoc x) {
382                 // ignore any exception - if this fails just
383
// leave null as the value
384
}
385         }
386
387         return value;
388     }
389
390     /**
391      * Node displayed in TableSheetView. Encapsulates a value of
392      * one element in the array.
393      */

394     class DisplayIndexedNode extends AbstractNode implements ChangeListener JavaDoc {
395         private int index;
396
397         public DisplayIndexedNode(int index) {
398             super(Children.LEAF);
399             this.index = index;
400             setName(Integer.toString(index));
401             setDisplayName(Integer.toString(index));
402         }
403
404         protected SystemAction[] createActions() {
405             try {
406                 return new SystemAction[] {
407                     SystemAction.get(Class.forName("org.openide.actions.MoveUpAction").asSubclass(SystemAction.class)), // NOI18N
408
SystemAction.get(Class.forName("org.openide.actions.MoveDownAction").asSubclass(SystemAction.class)), // NOI18N
409
};
410             } catch (ClassNotFoundException JavaDoc cnfe) {
411                 // silently ignore in case we are in standalone library
412
// without these actions
413
}
414
415             return null;
416         }
417
418         // Create a property sheet:
419
protected Sheet createSheet() {
420             Sheet sheet = super.createSheet();
421             Sheet.Set props = sheet.get(Sheet.PROPERTIES);
422
423             if (props == null) {
424                 props = Sheet.createPropertiesSet();
425                 sheet.put(props);
426             }
427
428             props.put(new ValueProp());
429
430             return sheet;
431         }
432
433         /**
434          * Destroy doesn't do regular destroy here
435          * but changes the whole array and recreates
436          * the node hierarchy. Does *not* even call super.destroy()!
437          */

438         public void destroy() throws java.io.IOException JavaDoc {
439             Object JavaDoc[] newArray = (Object JavaDoc[]) Array.newInstance(getConvertedType(), array.length - 1);
440             System.arraycopy(array, 0, newArray, 0, index);
441             System.arraycopy(array, index + 1, newArray, index, array.length - index - 1);
442
443             // throw away the old array!
444
array = newArray;
445             IndexedPropertyEditor.this.firePropertyChange();
446
447             if (currentEditorPanel != null) {
448                 currentEditorPanel.getExplorerManager().setRootContext(createRootNode());
449             }
450         }
451
452         /**
453          * Listens on parent node. Assumes that parent node is
454          * Indexed node !
455          */

456         public void stateChanged(ChangeEvent JavaDoc e) {
457             Node parent = getParentNode();
458             Index i = (Index) parent.getCookie(Index.class);
459
460             if (i != null) {
461                 int currentIndex = i.indexOf(this);
462
463                 if (currentIndex != index) {
464                     if (currentIndex > index) {
465                         // first swap the values in array
466
// the condition is there in order react by swapping
467
// the values only on one of the two nodes
468
Object JavaDoc tmp = array[index];
469                         array[index] = array[currentIndex];
470                         array[currentIndex] = tmp;
471                     }
472
473                     // update the index variable and change the name
474
index = currentIndex;
475                     DisplayIndexedNode.this.firePropertyChange(null, null, null);
476                     setDisplayName(Integer.toString(index));
477                     IndexedPropertyEditor.this.firePropertyChange();
478                 }
479             }
480         }
481
482         private class ValueProp extends PropertySupport {
483             public ValueProp() {
484                 super(
485                     indexedProperty.getName(), indexedProperty.getElementType(), indexedProperty.getDisplayName(),
486                     indexedProperty.getShortDescription(), indexedProperty.canRead(), indexedProperty.canWrite()
487                 );
488             }
489
490             public Object JavaDoc getValue() {
491                 if (index < array.length) {
492                     return array[index];
493                 } else {
494                     return null;
495                 }
496             }
497
498             public void setValue(Object JavaDoc value)
499             throws IllegalArgumentException JavaDoc, IllegalAccessException JavaDoc, InvocationTargetException JavaDoc {
500                 Object JavaDoc oldVal = array[index];
501                 array[index] = value;
502                 DisplayIndexedNode.this.firePropertyChange(this.getName(), oldVal, value);
503                 IndexedPropertyEditor.this.firePropertyChange();
504             }
505
506             public PropertyEditor getPropertyEditor() {
507                 return indexedProperty.getIndexedPropertyEditor();
508             }
509         }
510     }
511
512     /** Root node in the TableSheetView. This node should
513      * not be displayed.
514      */

515     private class MyIndexedRootNode extends IndexedNode {
516         public MyIndexedRootNode(Node[] ch) {
517             getChildren().add(ch);
518             setName("IndexedRoot"); // NOI18N
519
setDisplayName(NbBundle.getBundle(IndexedPropertyEditor.class).getString("CTL_Index"));
520         }
521
522         public NewType[] getNewTypes() {
523             NewType nt = new NewType() {
524                     public void create() {
525                         if (array != null) {
526                             Object JavaDoc[] newArray = (Object JavaDoc[]) Array.newInstance(getConvertedType(), array.length + 1);
527                             System.arraycopy(array, 0, newArray, 0, array.length);
528
529                             // throw away the old array!
530
array = newArray;
531                             array[array.length - 1] = defaultValue();
532                         } else {
533                             // throw away the old array!
534
array = (Object JavaDoc[]) Array.newInstance(getConvertedType(), 1);
535                             array[0] = defaultValue();
536                         }
537
538                         IndexedPropertyEditor.this.firePropertyChange();
539
540                         DisplayIndexedNode din = new DisplayIndexedNode(array.length - 1);
541                         getChildren().add(new Node[] { din });
542
543                         Index i = (Index) getCookie(Index.class);
544                         i.addChangeListener(org.openide.util.WeakListeners.change(din, i));
545                     }
546                 };
547
548             return new NewType[] { nt };
549         }
550     }
551 }
552
Popular Tags