KickJava   Java API By Example, From Geeks To Geeks.

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


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
20 package org.openide.explorer.propertysheet;
21
22 import org.openide.explorer.propertysheet.editors.EnhancedCustomPropertyEditor;
23 import org.openide.nodes.Node.*;
24 import org.openide.util.NbBundle;
25
26 import java.awt.Component JavaDoc;
27 import java.awt.Container JavaDoc;
28 import java.awt.event.*;
29
30 import java.beans.PropertyChangeEvent JavaDoc;
31 import java.beans.PropertyChangeListener JavaDoc;
32 import java.beans.PropertyEditor JavaDoc;
33 import java.beans.PropertyVetoException JavaDoc;
34 import java.beans.VetoableChangeListener JavaDoc;
35
36 import java.lang.reflect.InvocationTargetException JavaDoc;
37
38 import java.text.MessageFormat JavaDoc;
39 import java.util.logging.Level JavaDoc;
40 import java.util.logging.Logger JavaDoc;
41
42 import javax.swing.*;
43 import javax.swing.event.*;
44 import org.netbeans.modules.openide.explorer.UIException;
45
46 /** An implementation of PropertyDisplayer.EDITABLE which manages communication
47  * with a custom editor, to replace that aspect of PropertyPanel's behavior.
48  *
49  * @author Tim Boudreau
50  */

51 final class CustomEditorDisplayer implements PropertyDisplayer_Editable {
52     private int updatePolicy = UPDATE_ON_CONFIRMATION;
53     private Property prop;
54     private PropertyEnv env = null;
55     private PropertyEditor editor = null;
56     private Component JavaDoc customEditor = null;
57     boolean ignoreChanges = false;
58     private PropertyChangeListener JavaDoc editorListener = null;
59     private EnvListener envListener = null;
60     private PropertyModel model = null;
61     private Object JavaDoc originalValue = null;
62
63     /**
64      * Utility field used by event firing mechanism.
65      */

66     private javax.swing.event.EventListenerList JavaDoc listenerList = null;
67     private boolean ignoreChanges2 = false;
68
69     //Some property panel specific, package private hacks
70
private PropertyChangeListener JavaDoc remoteEnvListener = null;
71     private VetoableChangeListener JavaDoc remotevEnvListener = null;
72
73     /** Creates a new instance of CustomEditorDisplayer */
74     public CustomEditorDisplayer(Property prop) {
75         this.prop = prop;
76     }
77
78     public CustomEditorDisplayer(Property prop, PropertyModel mdl) {
79         this(prop);
80         model = mdl;
81     }
82
83     public void setUpdatePolicy(int i) {
84         this.updatePolicy = i;
85
86         if (env != null) {
87             env.setChangeImmediate(i != UPDATE_ON_EXPLICIT_REQUEST);
88         }
89     }
90
91     private Component JavaDoc getCustomEditor() {
92         if (customEditor == null) {
93             customEditor = getPropertyEditor().getCustomEditor();
94         }
95
96         return customEditor;
97     }
98
99     PropertyEditor getPropertyEditor() { //Package private for unit tests
100

101         if (editor == null) {
102             setPropertyEditor(PropUtils.getPropertyEditor(getProperty()));
103         }
104
105         return editor;
106     }
107
108     private void setPropertyEditor(PropertyEditor editor) {
109         if (this.editor != null) {
110             detachFromPropertyEditor(this.editor);
111
112             //set ignore changes even so - we may get the same property editor
113
//again, in which case we're still listening to it
114
ignoreChanges = true;
115         }
116
117         this.editor = editor;
118
119         try {
120             if (editor != null) {
121                 if (!editor.supportsCustomEditor()) {
122                     throw new IllegalArgumentException JavaDoc(
123                         "Property editor " + editor + " for property " + getProperty() +
124                         " does not support a custom editor."
125                     ); //NOI18N
126
}
127
128                 try {
129                     originalValue = editor.getValue();
130                 } catch (Exception JavaDoc e) {
131                     //dve or other, don't worry
132
}
133
134                 //Issue 39437 - PropertyPanel in custom editor mode
135
//expects a PropertyEnv even if the editor is not
136
//an ExPropertyEditor.
137
PropertyEnv env = new PropertyEnv();
138
139                 //Use the hack to access the real underlying FD, for, e.g.,
140
//core.projects.FileStateEditor
141
env.setFeatureDescriptor(EditorPropertyDisplayer.findFeatureDescriptor(this));
142                 setPropertyEnv(env);
143
144                 if (editor instanceof ExPropertyEditor) {
145                     ((ExPropertyEditor) editor).attachEnv(env);
146                 }
147
148                 attachToPropertyEditor(editor);
149             }
150         } finally {
151             ignoreChanges = false;
152         }
153     }
154
155     private void setPropertyEnv(PropertyEnv env) {
156         if (this.env != null) {
157             detachFromEnv(this.env);
158         }
159
160         this.env = env;
161
162         if (env != null) {
163             env.setChangeImmediate(getUpdatePolicy() != UPDATE_ON_EXPLICIT_REQUEST);
164             attachToEnv(env);
165         }
166     }
167
168     private void attachToEnv(PropertyEnv env) {
169         env.addPropertyChangeListener(getEnvListener());
170         env.addVetoableChangeListener(getEnvListener());
171         env.setBeans(EditorPropertyDisplayer.findBeans(this));
172     }
173
174     private void detachFromEnv(PropertyEnv env) {
175         env.removePropertyChangeListener(getEnvListener());
176         env.removeVetoableChangeListener(getEnvListener());
177     }
178
179     private void attachToPropertyEditor(PropertyEditor editor) {
180         // editor.addPropertyChangeListener(WeakListeners.propertyChange(getEditorListener(), editor));
181
editor.addPropertyChangeListener(getEditorListener());
182     }
183
184     private void detachFromPropertyEditor(PropertyEditor editor) {
185         editor.removePropertyChangeListener(getEditorListener());
186     }
187
188     private PropertyChangeListener JavaDoc getEditorListener() {
189         if (editorListener == null) {
190             editorListener = new EditorListener();
191         }
192
193         return editorListener;
194     }
195
196     private EnvListener getEnvListener() {
197         if (envListener == null) {
198             envListener = new EnvListener();
199         }
200
201         return envListener;
202     }
203
204     public boolean commit() throws IllegalArgumentException JavaDoc {
205         // System.err.println("COMMIT - " + getProperty().getDisplayName());
206
try {
207             ignoreChanges = true;
208
209             PropertyEditor editor = getPropertyEditor();
210             Object JavaDoc entered = getEnteredValue();
211
212             // System.err.println("COMMIT - entered value: " + entered);
213
try {
214                 if ((entered != null) && entered.equals(getProperty().getValue())) {
215                     // System.err.println(" entered value matches property value, return false");
216
return false;
217                 }
218             } catch (Exception JavaDoc e) {
219                 //IllegalAccessException, etc.
220
// System.err.println(" caught an exception, aborting");
221
Logger.getLogger(CustomEditorDisplayer.class.getName()).log(Level.WARNING, null, e);
222
223                 try {
224                     if (getProperty().canRead()) {
225                         editor.setValue(model.getValue());
226                     }
227                 } catch (ProxyNode.DifferentValuesException dve) {
228                     // ok - no problem here, it was just the old value
229
} catch (Exception JavaDoc ex) {
230                     PropertyDialogManager.notify(ex);
231                 }
232
233                 return false;
234             }
235
236             PropertyEnv env = getPropertyEnv();
237
238             Exception JavaDoc exception = PropUtils.updatePropertyEditor(editor, entered);
239
240             if (exception == null) {
241                 if ((env != null) && PropertyEnv.STATE_NEEDS_VALIDATION.equals(env.getState())) {
242                     String JavaDoc msg = env.silentlySetState(env.STATE_VALID, entered);
243
244                     System.err.println(" result of silent set state: " + msg);
245
246                     //something vetoed the change
247
if ((msg != null) && !PropertyEnv.STATE_VALID.equals(env.getState())) {
248                         IllegalArgumentException JavaDoc iae = new IllegalArgumentException JavaDoc("Error setting value"); //NOI18N
249

250                         UIException.annotateUser(iae, null, msg, null, null);
251
252                         //set the state to invalid
253
if (!env.STATE_INVALID.equals(env.getState())) {
254                             env.silentlySetState(env.STATE_INVALID, null);
255                         }
256
257                         throw iae;
258                     }
259                 }
260             }
261
262             Object JavaDoc res = Boolean.FALSE;
263
264             if (exception == null) {
265                 res = PropUtils.noDlgUpdateProp(getModel(), editor);
266                 originalValue = editor.getValue();
267
268                 if (res instanceof Exception JavaDoc && (!(res instanceof ProxyNode.DifferentValuesException))) {
269                     exception = (Exception JavaDoc) res;
270                 }
271
272                 if (res instanceof InvocationTargetException JavaDoc || res instanceof IllegalAccessException JavaDoc) {
273                     PropertyDialogManager.notify((Exception JavaDoc) res);
274                 }
275             }
276
277             if (exception != null) {
278                 if (exception instanceof IllegalArgumentException JavaDoc) {
279                     throw (IllegalArgumentException JavaDoc) exception;
280                 } else {
281                     PropertyDialogManager.notify(exception);
282
283                     IllegalArgumentException JavaDoc iae = new IllegalArgumentException JavaDoc("Error setting value"); //NOI18N
284
UIException.annotateUser(iae, null,
285                                              PropUtils.findLocalizedMessage(exception,
286                                                                             entered,
287                                                                             getProperty().getDisplayName()),
288                                              exception, null);
289                     throw iae;
290                 }
291             }
292
293             boolean result = Boolean.TRUE.equals(res);
294
295             if (result) {
296                 fireActionPerformed();
297             }
298
299             return result;
300         } finally {
301             ignoreChanges = false;
302         }
303     }
304
305     PropertyModel getModel() {
306         if (model == null) {
307             return new NodePropertyModel(getProperty(), null);
308         } else {
309             return model;
310         }
311     }
312
313     void setModel(PropertyModel mdl) {
314         model = mdl;
315     }
316
317     public PropertyEnv getPropertyEnv() {
318         return env;
319     }
320
321     public Component JavaDoc getComponent() {
322         return getCustomEditor();
323     }
324
325     public Object JavaDoc getEnteredValue() {
326         PropertyEditor editor = getPropertyEditor();
327         Object JavaDoc result;
328
329         if (customEditor instanceof EnhancedCustomPropertyEditor) {
330             result = ((EnhancedCustomPropertyEditor) customEditor ).getPropertyValue();
331         } else {
332             result = editor.getValue(); //editor.getAsText(); //XXX getValue?
333
}
334
335         return result;
336     }
337
338     public Property getProperty() {
339         return prop;
340     }
341
342     public int getUpdatePolicy() {
343         return updatePolicy;
344     }
345
346     public String JavaDoc isModifiedValueLegal() {
347         boolean legal = true;
348         String JavaDoc msg = null;
349         PropertyEditor editor = getPropertyEditor();
350
351         // System.err.println("IS MODIFIED VALUE LEGAL");
352
if (env != null) {
353             legal = env.getState() != env.STATE_INVALID;
354
355             System.err.println(" Attempting to validate env");
356
357             if (legal && env.STATE_NEEDS_VALIDATION.equals(env.getState())) {
358                 msg = env.silentlySetState(env.STATE_VALID, getEnteredValue());
359
360                 // System.err.println(" silentlySetState returned: " + msg);
361
legal = msg == null;
362             }
363         } else if (editor instanceof EnhancedCustomPropertyEditor) {
364             Object JavaDoc entered = ((EnhancedCustomPropertyEditor) editor).getPropertyValue();
365
366             try {
367                 editor.setValue(entered);
368             } catch (IllegalStateException JavaDoc ise) {
369                 legal = false;
370                 msg = PropUtils.findLocalizedMessage(ise, entered, getProperty().getDisplayName());
371             }
372         }
373
374         if (!legal && (msg == null)) {
375             // System.err.println(" not legal, constructing message");
376
msg = MessageFormat.format(
377                     NbBundle.getMessage(CustomEditorDisplayer.class, "FMT_CannotUpdateProperty"),
378                     new Object JavaDoc[] { editor.getValue(), getProperty().getDisplayName() }
379                 ); //NOI18N
380
}
381
382         return msg;
383     }
384
385     public boolean isValueModified() {
386         PropertyEditor editor = getPropertyEditor();
387         boolean result = editor.getValue() != originalValue;
388
389         if (!result && editor instanceof EnhancedCustomPropertyEditor) {
390             Object JavaDoc entered = ((EnhancedCustomPropertyEditor) editor).getPropertyValue();
391
392             if (entered != null) {
393                 result = entered.equals(originalValue);
394             } else {
395                 result = originalValue == null;
396             }
397         }
398
399         return result;
400     }
401
402     public void refresh() {
403         //do nothing
404
}
405
406     public void reset() {
407         try {
408             originalValue = getProperty().getValue();
409             getPropertyEditor().setValue(originalValue);
410         } catch (Exception JavaDoc e) {
411             //should not happen - the value came from the property
412
Logger.getLogger(CustomEditorDisplayer.class.getName()).log(Level.WARNING, null, e);
413         }
414     }
415
416     /** Sets whether or not this component is enabled.
417      *
418      * all panel components gets disabled when enabled parameter is set false
419      * @param enabled flag defining the action.
420      */

421     public void setEnabled(boolean enabled) {
422         // System.err.println("SET ENABLED:" + enabled);
423
Component JavaDoc custEditor = (Container JavaDoc) getComponent();
424
425         if (custEditor instanceof Container JavaDoc) {
426             setEnabled((Container JavaDoc) custEditor, enabled);
427         }
428
429         custEditor.setEnabled(enabled);
430     }
431
432     public void setEnabled(Container JavaDoc c, boolean enabled) {
433         Component JavaDoc[] comp = c.getComponents();
434
435         for (int i = 0; i < comp.length; i++) {
436             if (!(comp[i] instanceof JScrollBar)) {
437                 comp[i].setEnabled(false);
438             } else {
439                 ((JScrollBar) comp[i]).setFocusable(enabled);
440             }
441
442             if (comp[i] instanceof Container JavaDoc) {
443                 boolean ignore = false;
444
445                 if (comp[i] instanceof JComponent) {
446                     //Issue 38065 - form editor doesn't want checkbox enabled,
447
//but for compatibility we need to drill through the entire
448
//subtree (otherwise JFileChoosers, etc., will have enabled
449
//components even though setEnabled(false) was called on them).
450
Boolean JavaDoc val = (Boolean JavaDoc) ((JComponent) comp[i]).getClientProperty("dontEnableMe"); //NOI18N
451

452                     if (val != null) {
453                         ignore = val.booleanValue();
454                     }
455                 }
456
457                 if (!ignore) {
458                     setEnabled((Container JavaDoc) comp[i], enabled);
459                 }
460             }
461         }
462
463         c.setEnabled(enabled);
464     }
465
466     public void setEnteredValue(Object JavaDoc o) {
467         PropUtils.updatePropertyEditor(getPropertyEditor(), o);
468     }
469
470     public void setActionCommand(String JavaDoc val) {
471     }
472
473     public String JavaDoc getActionCommand() {
474         return null;
475     }
476
477     /**
478      * Registers ActionListener to receive events.
479      * @param listener The listener to register.
480      */

481     public synchronized void addActionListener(java.awt.event.ActionListener JavaDoc listener) {
482         if (listenerList == null) {
483             listenerList = new EventListenerList();
484         }
485
486         listenerList.add(ActionListener.class, listener);
487     }
488
489     /**
490      * Removes ActionListener from the list of listeners.
491      * @param listener The listener to remove.
492      */

493     public synchronized void removeActionListener(java.awt.event.ActionListener JavaDoc listener) {
494         listenerList.remove(ActionListener.class, listener);
495     }
496
497     /**
498      * Notifies all registered listeners about the event.
499      *
500      * @param event The event to be fired
501      */

502     private void fireActionPerformed() {
503         ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "userChangedValue"); //NOI18N
504

505         if (listenerList == null) {
506             return;
507         }
508
509         Object JavaDoc[] listeners = listenerList.getListenerList();
510
511         for (int i = listeners.length - 2; i >= 0; i -= 2) {
512             if (listeners[i] == ActionListener.class) {
513                 ((ActionListener) listeners[i + 1]).actionPerformed(event);
514             }
515         }
516     }
517
518     /**
519      * Registers ChangeListener to receive events.
520      * @param listener The listener to register.
521      */

522     public synchronized void addChangeListener(ChangeListener JavaDoc listener) {
523         if (listenerList == null) {
524             listenerList = new EventListenerList();
525         }
526
527         listenerList.add(ChangeListener JavaDoc.class, listener);
528     }
529
530     /**
531      * Removes ChangeListener from the list of listeners.
532      * @param listener The listener to remove.
533      */

534     public synchronized void removeChangeListener(ChangeListener JavaDoc listener) {
535         listenerList.remove(ChangeListener JavaDoc.class, listener);
536     }
537
538     /**
539      * Notifies all registered listeners about the event.
540      *
541      * @param event The event to be fired
542      */

543     private void fireStateChanged() {
544         ChangeEvent JavaDoc event = new ChangeEvent JavaDoc(this);
545
546         if (listenerList == null) {
547             return;
548         }
549
550         Object JavaDoc[] listeners = listenerList.getListenerList();
551
552         for (int i = listeners.length - 2; i >= 0; i -= 2) {
553             if (listeners[i] == ChangeListener JavaDoc.class) {
554                 ((ChangeListener JavaDoc) listeners[i + 1]).stateChanged(event);
555             }
556         }
557     }
558
559     void setRemoteEnvListener(PropertyChangeListener JavaDoc l) {
560         // System.err.println(" setRemoteEnvListener on " + System.identityHashCode(this) + " to " + l);
561
remoteEnvListener = l;
562     }
563
564     void setRemoteEnvVetoListener(VetoableChangeListener JavaDoc vl) {
565         remotevEnvListener = vl;
566     }
567
568     private class EnvListener implements PropertyChangeListener JavaDoc, VetoableChangeListener JavaDoc {
569         public void propertyChange(PropertyChangeEvent JavaDoc evt) {
570             fireStateChanged();
571
572             // System.err.println(" Custom displayer got a property change");
573
//Propagate changes to a property panel
574
if (remoteEnvListener != null) {
575                 remoteEnvListener.propertyChange(evt);
576
577                 // } else {
578
// System.err.println("But nobody is listening!");
579
}
580         }
581
582         public void vetoableChange(PropertyChangeEvent JavaDoc evt)
583         throws PropertyVetoException JavaDoc {
584             if (remotevEnvListener != null) {
585                 remotevEnvListener.vetoableChange(evt);
586             }
587         }
588     }
589
590     private class EditorListener implements PropertyChangeListener JavaDoc {
591         public void propertyChange(PropertyChangeEvent JavaDoc evt) {
592             // System.err.println("Property change on CustomEditorDisplayer from " + evt.getSource() + " new value=" + evt.getNewValue());
593
if (ignoreChanges) {
594                 // System.err.println(" ignoring");
595
return;
596             }
597
598             if (ExPropertyEditor.PROP_VALUE_VALID.equals(evt.getPropertyName())) {
599                 // System.err.println(" value valid - ignoring");
600
return;
601             }
602
603             if (ignoreChanges2) {
604                 return;
605             }
606
607             ignoreChanges2 = true;
608
609             if (getUpdatePolicy() != UPDATE_ON_EXPLICIT_REQUEST) {
610                 commit();
611
612                 // } else {
613
// System.err.println(" policy is UPDATE_ON_EXPLICIT_REQUEST - ignoring");
614
}
615
616             fireStateChanged();
617             ignoreChanges2 = false;
618         }
619     }
620
621 }
622
Popular Tags