KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.beans.FeatureDescriptor JavaDoc;
22 import java.beans.PropertyChangeListener JavaDoc;
23 import java.beans.PropertyChangeSupport JavaDoc;
24 import java.beans.PropertyVetoException JavaDoc;
25 import java.beans.VetoableChangeListener JavaDoc;
26 import java.beans.VetoableChangeSupport JavaDoc;
27
28
29 /**
30  * PropertyEnv is a class which allows an object (such as a
31  * Node.Property instance) to communicate hints to property
32  * editor instances that affect the behavior or visual
33  * rendering of the property in a <code>PropertySheet</code>
34  * or <code>PropertyPanel</code> component. An instance of
35  * PropertyEnv is passed to the <code>attachEnv()</code>
36  * method of property editors implementing ExPropertyEditor.
37  * Such property editors may then call <code>
38  * env.getFeatureDescriptor().get("someHintString")</code>
39  * to retrieve hints that affect their behavior from the
40  * Node.Property object whose properties they are displaying.
41  * <p>
42  * The other purpose of the of this interface is to
43  * enable communication between the {@link java.beans.PropertyEditor} and
44  * the {@link PropertySheet} or {@link PropertyPanel}.
45  * The custom property editor can get into a state when the visual state
46  * does not represent valid value and in such case needs to disable OK button.
47  * To handle that the property editor has to keep reference to its associated
48  * {@link PropertyEnv} and switch it into invalid state by calling
49  * <code>setState({@link PropertyEnv#STATE_INVALID})</code>
50  * as soon as the content of the custom property editor is invalid and then
51  * back by
52  * <code>setState({@link PropertyEnv#STATE_VALID})</code>
53  * when the custom property editor becomes valid once again. As a reaction
54  * to these calls the displayer of the custom property editor (for example
55  * dialog with OK button) is supposed to disable and re-enable the button.
56  * <p>
57  * Also it can happen that the property editor is complex and cannot decide whether
58  * the value is valid quickly. Just knows that it needs to be validated.
59  * For that purpose it wants to be informed when user presses the OK button and
60  * do the complex validation then. For that purpose there is the {@link PropertyEnv#STATE_NEEDS_VALIDATION}
61  * state. The property editor needs to use it and attach a listener to
62  * be notified when the user presses the OK button:
63  * <pre>
64  * class Validate implements VetoableChangeListener {
65  * public void vetoableChange(VetoableChangeEvent ev) throws PropertyVetoException {
66  * if (PROP_STATE.equals(ev.getPropertyName())) {
67  * if (!doTheComplexValidationOk()) {
68  * throw new PropertyVetoException(...);
69  * }
70  * }
71  * // otherwise allow the switch to ok state
72  * }
73  * }
74  * Validate v = new Validate();
75  * env.setState(STATE_NEEDS_VALIDATION);
76  * env.addVetoableChangeListener(v);
77  * </pre>
78  * When the state is {@link PropertyEnv#STATE_NEEDS_VALIDATION} the OK button
79  * of the surrounding dialog shall be enabled and when pressed the vetoable
80  * listener notified about the expected change from
81  * {@link PropertyEnv#STATE_NEEDS_VALIDATION} to {@link PropertyEnv#STATE_VALID}
82  * which can either be accepted or vetoed.
83  *
84  *
85  * @author dstrupl
86  */

87 public class PropertyEnv {
88     /** Name of the state property. */
89     public static final String JavaDoc PROP_STATE = "state"; //NOI18N
90

91     /**
92      * One possible value for the setState/getState methods. With this
93      * value the editor is in a valid state.
94      */

95     public static final Object JavaDoc STATE_VALID = "valid"; //NOI18N
96

97     /**
98      * One possible value for the setState/getState methods.
99      * This one means that the editor does not know its state and
100      * it has to validate it later.
101      */

102     public static final Object JavaDoc STATE_NEEDS_VALIDATION = "needs_validation"; //NOI18N
103

104     /**
105      * One possible value for the setState/getState methods. With this
106      * one the editor is in invalid state (Ok button on custom editor
107      * panel is disabled and an invalid glyph shown on the property panel).
108      */

109     public static final Object JavaDoc STATE_INVALID = "invalid"; // NOI18N
110
static final String JavaDoc PROP_CHANGE_IMMEDIATE = "changeImmediate"; // NOI18N
111
static final FeatureDescriptor JavaDoc dummyDescriptor = new FeatureDescriptor JavaDoc();
112
113     /** The value returned from getFeatureDescriptor. */
114     private FeatureDescriptor JavaDoc featureDescriptor = dummyDescriptor;
115
116     /** The value returned from getBeans.*/
117     private Object JavaDoc[] beans;
118
119     /** Current state. */
120     private Object JavaDoc state = STATE_VALID;
121
122     /** The support is lazy initialized in getSupport. */
123     private VetoableChangeSupport JavaDoc support;
124
125     /** change support here */
126     private PropertyChangeSupport JavaDoc change;
127
128     /**
129      * The value of this field is basically taken from
130      * the property panel. The property panel is responsible
131      * for propagating the value to this field by calling
132      * setchangeImmediate.
133      */

134     private boolean changeImmediate = true;
135     InplaceEditor.Factory factory = null;
136     boolean editable = true;
137
138     /** Default constructor has package access -
139      * we do not want the instances to be created outside
140      * our package.
141      */

142     PropertyEnv() {
143     }
144
145     /**
146      * Array of beans that the edited property belongs to.
147      */

148     public Object JavaDoc[] getBeans() {
149         return beans;
150     }
151
152     /**
153      * Array of nodes that the edited property belongs to.
154      */

155     void setBeans(Object JavaDoc[] beans) {
156         this.beans = beans;
157     }
158
159     /**
160      * Feature descritor that describes the property. It is feature
161      * descriptor so one can plug in PropertyDescritor and also Node.Property
162      * which both inherit from FeatureDescriptor
163      */

164     public FeatureDescriptor JavaDoc getFeatureDescriptor() {
165         return featureDescriptor;
166     }
167
168     /**
169      * Feature descritor that describes the property. It is feature
170      * descriptor so one can plug in PropertyDescritor and also Node.Property
171      * which both inherit from FeatureDescriptor
172      */

173     void setFeatureDescriptor(FeatureDescriptor JavaDoc desc) {
174         if (desc == null) {
175             throw new IllegalArgumentException JavaDoc("Cannot set FeatureDescriptor to null."); //NOI18N
176
}
177
178         this.featureDescriptor = desc;
179
180         if (featureDescriptor != null) {
181             Object JavaDoc obj = featureDescriptor.getValue(PROP_CHANGE_IMMEDIATE);
182
183             if (obj instanceof Boolean JavaDoc) {
184                 setChangeImmediate(((Boolean JavaDoc) obj).booleanValue());
185             }
186         }
187     }
188
189     // [PENDING]
190

191     /** The editor may be able to edit properties of different classes. It can decide to
192      * be able to edit descendants of a base class.*/

193
194     //Class propertyClass; // read-only property
195

196     /**
197      * A setter that should be used by the property editor
198      * to change the state of the environment.
199      * Even the state property is bound, changes made from the editor itself
200      * are allowed without restrictions.
201      */

202     public void setState(Object JavaDoc newState) {
203         if (getState().equals(newState)) {
204             // no change, no fire vetoable and property change
205
return;
206         }
207
208         try {
209             getSupport().fireVetoableChange(PROP_STATE, getState(), newState);
210             state = newState;
211
212             // always notify state change
213
getChange().firePropertyChange(PROP_STATE, null, newState);
214         } catch (PropertyVetoException JavaDoc pve) {
215             // and notify the user that the change cannot happen
216
PropertyDialogManager.notify(pve);
217         }
218     }
219
220     /** Allow setting of state without triggering a dialog. */
221     String JavaDoc silentlySetState(Object JavaDoc newState, Object JavaDoc newValue) {
222         if (getState().equals(newState)) {
223             // no change, no fire vetoable and property change
224
return null;
225         }
226
227         try {
228             getSupport().fireVetoableChange(PROP_STATE, getState(), newState);
229             state = newState;
230
231             // always notify state change
232
getChange().firePropertyChange(PROP_STATE, null, newState);
233         } catch (PropertyVetoException JavaDoc pve) {
234             // and notify the user that the change cannot happen
235
pve.printStackTrace();
236
237             String JavaDoc name = (getFeatureDescriptor() == null) ? null : getFeatureDescriptor().getDisplayName();
238
239             return PropUtils.findLocalizedMessage(pve, newValue, name);
240         }
241
242         return null;
243     }
244
245     /**
246      * A getter for the current state of the environment.
247      * @return one of the constants STATE_VALID, STATE_INVALID,
248      * STATE_NEEDS_VALIDATION.
249      */

250     public Object JavaDoc getState() {
251         return state;
252     }
253
254     /**
255      * Vetoable change listener: listenning here you will be notified
256      * when the state of the environment is being changed (when the setState
257      * method is being called). You can veto the change and provide
258      * a displayable information in the thrown exception. Use
259      * the ErrorManager annotaion feature for the your exception to modify
260      * the message and severity.
261      */

262     public void addVetoableChangeListener(VetoableChangeListener JavaDoc l) {
263         getSupport().addVetoableChangeListener(l);
264     }
265
266     /**
267      * Property change listener: listenning here you will be notified
268      * when the state of the environment is has been changed.
269      * @since 2.20
270      */

271     public void addPropertyChangeListener(PropertyChangeListener JavaDoc l) {
272         getChange().addPropertyChangeListener(l);
273     }
274
275     /**
276      * Vetoable change listener removal.
277      */

278     public void removeVetoableChangeListener(VetoableChangeListener JavaDoc l) {
279         getSupport().removeVetoableChangeListener(l);
280     }
281
282     /**
283      * Removes Property change listener.
284      * @since 2.20
285      */

286     public void removePropertyChangeListener(PropertyChangeListener JavaDoc l) {
287         getChange().removePropertyChangeListener(l);
288     }
289
290     /** Getter for property changeImmediate.
291      * @return Value of property changeImmediate.
292      */

293     boolean isChangeImmediate() {
294         return changeImmediate;
295     }
296
297     /** Setter for property changeImmediate.
298      * @param changeImmediate New value of property changeImmediate.
299      */

300     void setChangeImmediate(boolean changeImmediate) {
301         this.changeImmediate = changeImmediate;
302     }
303
304     /**
305      * Lazy initialization of the VetoableChangeSupport.
306      */

307     private synchronized VetoableChangeSupport JavaDoc getSupport() {
308         if (support == null) {
309             support = new VetoableChangeSupport JavaDoc(this);
310         }
311
312         return support;
313     }
314
315     /**
316      * Lazy initialization of the PropertyChangeSupport.
317      */

318     private synchronized PropertyChangeSupport JavaDoc getChange() {
319         if (change == null) {
320             change = new PropertyChangeSupport JavaDoc(this);
321         }
322
323         return change;
324     }
325
326     /**Register a factory for InplaceEditor instances that the property
327      * sheet should use as an inline editor for the property.
328      * This allows modules to supply custom inline editors globally
329      * for a type. It can be overridden on a property-by-property
330      * basis for properties that supply a hint for an inplace editor
331      * using <code>getValue(String)</code>.
332      * @see org.openide.nodes.Node.Property
333      * @see org.openide.explorer.propertysheet.InplaceEditor
334      */

335     public void registerInplaceEditorFactory(InplaceEditor.Factory factory) {
336         this.factory = factory;
337     }
338
339     InplaceEditor getInplaceEditor() {
340         InplaceEditor result;
341
342         if (factory != null) {
343             result = factory.getInplaceEditor();
344         } else {
345             result = null;
346         }
347
348         return result;
349     }
350
351     void setEditable(boolean editable) {
352         this.editable = editable;
353     }
354
355     boolean isEditable() {
356         return editable;
357     }
358
359     public String JavaDoc toString() {
360         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
361         sb.append(getClass().getName());
362         sb.append("@"); //NOI18N
363
sb.append(System.identityHashCode(this));
364         sb.append("[state="); //NOI18N
365
sb.append(
366             (state == STATE_NEEDS_VALIDATION) ? "STATE_NEEDS_VALIDATION"
367                                               : ((state == STATE_INVALID) ? "STATE_INVALID" : "STATE_VALID")
368         ); //NOI18N
369
sb.append(", "); //NOI18N
370

371         if (factory != null) {
372             sb.append("InplaceEditorFactory=" + factory.getClass().getName()); //NOI18N
373
sb.append(", "); //NOI18N
374
}
375
376         sb.append("editable="); //NOI18N
377
sb.append(editable);
378         sb.append(", isChangeImmediate="); //NOI18N
379
sb.append(isChangeImmediate());
380         sb.append(", featureDescriptor="); //NOI18N
381
sb.append(getFeatureDescriptor().getDisplayName());
382
383         return sb.toString();
384     }
385 }
386
Popular Tags