KickJava   Java API By Example, From Geeks To Geeks.

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


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.*;
27 import java.awt.event.ActionEvent JavaDoc;
28 import java.awt.event.WindowAdapter JavaDoc;
29 import java.awt.event.WindowEvent JavaDoc;
30 import java.awt.event.WindowListener JavaDoc;
31
32 import java.beans.*;
33
34 import java.lang.ref.WeakReference JavaDoc;
35
36 import javax.swing.AbstractAction JavaDoc;
37 import javax.swing.JDialog JavaDoc;
38 import org.openide.util.Exceptions;
39
40
41 /** Action to invoke the custom editor.
42  *
43  * @author Tim Boudreau
44  */

45 class CustomEditorAction extends AbstractAction JavaDoc {
46     private Invoker invoker;
47     private WeakReference JavaDoc<PropertyModel> modelRef = null;
48
49     /** Creates a new instance of CustomEditorAction */
50     public CustomEditorAction(Invoker invoker) {
51         this.invoker = invoker;
52         putValue(SMALL_ICON, PropUtils.getCustomButtonIcon());
53     }
54
55     public CustomEditorAction(Invoker invoker, PropertyModel mdl) {
56         this(invoker);
57
58         if (mdl != null) {
59             // System.err.println("Creating custom editor action for model " + mdl);
60
modelRef = new WeakReference JavaDoc<PropertyModel>(mdl);
61         }
62     }
63
64     public void actionPerformed(ActionEvent JavaDoc ae) {
65         if (PropUtils.isLoggable(CustomEditorAction.class)) {
66             PropUtils.log(CustomEditorAction.class, "CustomEditorAction invoked " + ae); //NOI18N
67
}
68
69         if (!invoker.allowInvoke()) {
70             if (PropUtils.isLoggable(CustomEditorAction.class)) {
71                 PropUtils.log(
72                     CustomEditorAction.class,
73                     "Invoker (" + invoker.getClass() + " allowInvoke() returned false. Aborting."
74                 ); //NOI18N
75
}
76
77             return;
78         }
79
80         PropertyModel refd = (modelRef != null) ? modelRef.get() : null;
81
82         //get the feature descriptor in question
83
FeatureDescriptor fd = invoker.getSelection();
84
85         final Property p = (fd instanceof Property) ? (Property) fd : null;
86
87         //if it's not a property...
88
if (p == null) {
89             if (PropUtils.isLoggable(CustomEditorAction.class)) {
90                 PropUtils.log(
91                     CustomEditorAction.class,
92                     "Cant invoke custom " + "editor on " + fd + " it is null or not a Property." + "Aborting."
93                 ); //NOI18N
94
}
95
96             //Somebody invoked it from the keyboard on an expandable set
97
Toolkit.getDefaultToolkit().beep();
98
99             return;
100         }
101
102         final java.beans.PropertyEditor JavaDoc editor = PropUtils.getPropertyEditor(p);
103
104         //Create a new PropertyEnv to carry the values of the Property to the editor
105
PropertyEnv env = null;
106
107         if (editor instanceof ExPropertyEditor) {
108             if (PropUtils.isLoggable(CustomEditorAction.class)) {
109                 PropUtils.log(CustomEditorAction.class, "Editor is an " + "ExPropertyEditor, attaching a PropertyEnv"); //NOI18N
110
}
111
112             env = new PropertyEnv();
113             env.setFeatureDescriptor(fd);
114
115             if (invoker instanceof SheetTable) {
116                 if (PropUtils.isLoggable(CustomEditorAction.class)) {
117                     PropUtils.log(
118                         CustomEditorAction.class, "env.setBeans to " + invoker.getReusablePropertyEnv().getBeans()
119                     ); //NOI18N
120
}
121
122                 env.setBeans(invoker.getReusablePropertyEnv().getBeans());
123             }
124
125             //Set up the editor with any hints from the property
126
((ExPropertyEditor) editor).attachEnv(env);
127         }
128
129         //if there is no custom property editor...
130
if (!editor.supportsCustomEditor()) {
131             if (PropUtils.isLoggable(CustomEditorAction.class)) {
132                 PropUtils.log(
133                     CustomEditorAction.class,
134                     "Cant invoke custom " + "editor for editor " + editor + " - it returns false " +
135                     "from supportsCustomEditor()."
136                 ); //NOI18N
137
}
138
139             //Somebody invoked it from the keyboard on an editor w/o custom editor
140
Toolkit.getDefaultToolkit().beep();
141
142             return;
143         }
144
145         final Component curComp = invoker.getCursorChangeComponent();
146
147         Cursor cur = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
148         curComp.setCursor(cur);
149         try { //#64007 start - reset cursor in case of a runtime exception
150

151         // customEditing = true;
152
Object JavaDoc partialValue = invoker.getPartialValue();
153
154         //Okay, we can display a custom editor.
155
//If the user has already typed something in a text field, pass it to the editor,
156
//even if they haven't updated the value yet
157
if (partialValue != null) {
158             try {
159                 if ((editor.getValue() == null) // Fix #13339
160
||!(partialValue.toString().equals(editor.getAsText()))) {
161                     if (!(editor instanceof PropUtils.DifferentValuesEditor)) {
162                         editor.setAsText(partialValue.toString());
163                     }
164                 }
165             } catch (ProxyNode.DifferentValuesException dve) {
166                 // old value will be set back
167
} catch (Exception JavaDoc ite) {
168                 // old value will be set back
169
}
170         }
171
172         //horrible, I need the nodes anyway
173
final PropertyModel mdl = (refd == null) ? new NodePropertyModel(p, null) : refd;
174         String JavaDoc fdName;
175
176         if ((mdl instanceof ExPropertyModel && (((ExPropertyModel) mdl).getFeatureDescriptor() != null))) {
177             fdName = ((ExPropertyModel) mdl).getFeatureDescriptor().getDisplayName();
178         } else {
179             fdName = null;
180         }
181
182         //Support hinting of the title
183
String JavaDoc suppliedTitle = (String JavaDoc) p.getValue("title"); //NOI18N
184
final String JavaDoc title = (suppliedTitle == null)
185             ? ((fd.getDisplayName() == null)
186             ? //XXX does this ever happen??
187
NbBundle.getMessage(CustomEditorAction.class, "FMT_CUSTOM_DLG_NOPROPNAME_TITLE",
188                 fdName == null ? invoker.getBeanName() : fdName
189             )
190             : ((fd.getDisplayName().equals(invoker.getBeanName())) ? invoker.getBeanName() :
191                 NbBundle.getMessage(CustomEditorAction.class, "FMT_CUSTOM_DLG_TITLE",
192                 invoker.getBeanName(), fd.getDisplayName())
193             )) : suppliedTitle; //NOI18N
194

195         final PropertyDialogManager pdm = new PropertyDialogManager(
196                 NbBundle.getMessage(
197                     CustomEditorAction.class, "PS_EditorTitle", //NOI18N
198
(title == null) ? "" : title, // NOI18N
199
p.getValueType()
200                 ), true, editor, mdl, env
201             );
202
203         boolean shouldListen = !(pdm.getComponent() instanceof EnhancedCustomPropertyEditor) &&
204             (p.canWrite() && (invoker.wantAllChanges() || ((env == null) || env.isChangeImmediate())));
205
206         final PropertyChangeListener pcl = (!shouldListen) ? null
207                                                            : (new PropertyChangeListener() {
208                     private boolean updating = false;
209
210                     public void propertyChange(PropertyChangeEvent pce) {
211                         if (updating) {
212                             return;
213                         }
214
215                         updating = true;
216
217                         try {
218                             boolean success = PropUtils.updateProp(mdl, editor, title);
219
220                             if (success) {
221                                 invoker.valueChanged(editor);
222                             } else {
223                                 invoker.failed();
224                             }
225                         } finally {
226                             updating = false;
227                         }
228                     }
229                 });
230
231         if (pcl != null) {
232             editor.addPropertyChangeListener(pcl);
233         }
234
235         final java.awt.Window JavaDoc w = pdm.getDialog();
236
237         WindowListener JavaDoc wl = new WindowAdapter JavaDoc() {
238                 public void windowClosed(WindowEvent JavaDoc e) {
239                     if (pdm.getComponent() instanceof EnhancedCustomPropertyEditor) {
240                         if (!pdm.wasCancelled() && !closedOption && pdm.wasOK() && !pdm.wasReset()) {
241                             try {
242                                 invoker.valueChanged(pdm.getEditor());
243                             } catch (Exception JavaDoc ex) {
244                                 //do nothing
245
}
246                         }
247                     }
248
249                     invoker.editorClosed();
250                     w.removeWindowListener(this);
251
252                     if (pcl != null) {
253                         editor.removePropertyChangeListener(pcl);
254                     }
255
256                     // customEditing=false;
257
}
258
259                 public void windowOpened(WindowEvent JavaDoc e) {
260                     invoker.editorOpened();
261                     curComp.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
262                 }
263
264                 // MCF ISSUE 44366
265
public void windowClosing(WindowEvent JavaDoc ev) {
266                     if (PropUtils.isLoggable(CustomEditorAction.class)) {
267                         PropUtils.log(CustomEditorAction.class, "CustomerEditorAction windowClosing event");
268                     }
269
270                     closedOption = true;
271                 }
272
273                 // MCF ISSUE 44366
274
boolean closedOption = false;
275             };
276
277         //Don't set customEditing for non-dialog custom property editors - another
278
//editor can be opened at the same time
279
if (w instanceof JDialog JavaDoc) {
280             JDialog JavaDoc jd = (JDialog JavaDoc) w;
281             jd.getAccessibleContext().setAccessibleName(title);
282
283             if (fd.getShortDescription() != null) {
284                 jd.getAccessibleContext().setAccessibleDescription(fd.getShortDescription());
285             }
286
287             w.addWindowListener(wl);
288         } else if (w instanceof Frame) {
289             ((Frame) w).addWindowListener(wl);
290         }
291
292         invoker.editorOpening();
293
294         try {
295             PropUtils.addExternallyEdited(p);
296             w.setVisible(true);
297             PropUtils.removeExternallyEdited(p);
298         } catch (Exception JavaDoc ex) {
299             Exceptions.printStackTrace(ex);
300         }
301         
302         } finally { //#64007 end - reset cursor in case of a runtime exception
303
curComp.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
304         }
305     }
306
307     static interface Invoker {
308         /** Get the selected object that should be edited */
309         public FeatureDescriptor getSelection();
310
311         /** If the value displayed has been edited but not committed, get
312          * the partial edit to set in the custom editor */

313         public Object JavaDoc getPartialValue();
314
315         /** Get the component which is invoking the custom editor, and
316          * should have its cursor changed while the dialog is being opened
317          * (the cursor change will actually happen on its ancestor root pane)*/

318         public Component getCursorChangeComponent();
319
320         /** Get the name of the bean, if any, that owns the property - this
321          * value is used as part of the window title */

322         public String JavaDoc getBeanName();
323
324         /** Callback in case the invoker wants to do something before the
325          * window is opened */

326         public void editorOpening();
327
328         /** Callback to notify the invoker that the window has opened */
329         public void editorOpened();
330
331         /** Callback to notify the invoker that the window has closed. If
332          * the invoker should behave differently in response to a failed
333          * edit than in response to a successful one, set a flag to false
334          * when editorOpening() is called, and set it to true if failed()
335          * is called, and do your processing here. */

336         public void editorClosed();
337
338         /** Called if the value is changed successfully */
339         public void valueChanged(PropertyEditor editor);
340
341         /** Allow an invoker to block invocation of the custom editor if it
342          * is not in an appropriate state */

343         public boolean allowInvoke();
344
345         /** Called if an update was attempted but the value was illegal */
346         public void failed();
347
348         /** Should valueUpdated be called even if the editor is not ExPropertyEditor?
349          * PropertyPanel will need this to update inline editors; the property
350          * sheet will repaint anyway and doesn't. */

351         public boolean wantAllChanges();
352
353         public ReusablePropertyEnv getReusablePropertyEnv();
354     }
355 }
356
Popular Tags