KickJava   Java API By Example, From Geeks To Geeks.

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


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  * WrapperInplaceEditor.java
21  *
22  * Created on January 4, 2003, 4:30 PM
23  */

24 package org.openide.explorer.propertysheet;
25
26 import java.util.logging.Level JavaDoc;
27 import java.util.logging.Logger JavaDoc;
28 import org.openide.explorer.propertysheet.editors.EnhancedPropertyEditor;
29
30 import java.awt.BorderLayout JavaDoc;
31 import java.awt.Component JavaDoc;
32 import java.awt.event.*;
33
34 import java.lang.reflect.*;
35
36 import java.util.*;
37
38 import javax.swing.*;
39 import javax.swing.event.EventListenerList JavaDoc;
40 import javax.swing.text.JTextComponent JavaDoc;
41
42
43 /** Wrapper for legacy inplace custom editors supplied the deprecated
44  * <code>EnhancedPropertyEditor</code>. Attempts to allow them to behave
45  * correctly, but does not guarantee it.
46  * <P>Note that this class does <strong>not</strong>
47  * support using AWT components as inplace editors.
48  * <P> Note that this class is not considered reusable, unlike other inplace
49  * editors. Each time a legacy inline editor is needed, a new instance of
50  * this class should be created.
51  *
52  * @author Tim Boudreau
53  */

54 class WrapperInplaceEditor extends JPanel implements InplaceEditor, ActionListener, FocusListener {
55     /** The enhanced property editor we will wrap */
56     private EnhancedPropertyEditor enh;
57
58     /** The obligatory property model */
59     private PropertyModel mdl;
60
61     /** The legacy component returned by enh.getCustomInPlaceEditor() */
62     private Component JavaDoc legacy = null;
63
64     /** Listener list */
65     private transient List JavaDoc<ActionListener> actionListenerList;
66
67     /** True if adding an ActionListener to the legacy component using
68      * reflection succeeded */

69     private boolean listenerAdded = false;
70     private boolean suspendEvents = false;
71
72     /**
73      * Utility field used by event firing mechanism.
74      */

75     private javax.swing.event.EventListenerList JavaDoc listenerList = null;
76
77     /** Create a new instance */
78     WrapperInplaceEditor(EnhancedPropertyEditor enh) {
79         this.enh = enh;
80         setLayout(new BorderLayout JavaDoc());
81         getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "enter"); //NOI18N
82
getActionMap().put("enter", new EnterKbdAction()); //NOI18N
83
}
84
85     /** Forward focus events from within the legacy component to the
86      * infrastructure, so editor will be properly removed if focus changes */

87     public void focusGained(FocusEvent e) {
88         e.setSource(this);
89         fireFocusGained(e);
90     }
91
92     /** Forward focus events from within the legacy component to the
93      * infrastructure, so editor will be properly removed if focus changes */

94     public void focusLost(FocusEvent e) {
95         e.setSource(this);
96         fireFocusLost(e);
97     }
98
99     public void clear() {
100         if (legacy != null) {
101             removeAll();
102
103             if (listenerAdded) {
104                 tryRemoveActionListener(legacy);
105             }
106
107             legacy.removeFocusListener(this);
108             legacy = null;
109         }
110
111         enh = null;
112         listenerAdded = false;
113     }
114
115     /** Uses reflection to find an addActionListener method if present, and
116      * if so, adds this WrapperInplaceEditor as an action listener */

117     private boolean tryAddActionListener(Component JavaDoc comp) {
118         try {
119             Method m = comp.getClass().getMethod("addActionListener", new Class JavaDoc[] { ActionListener.class }); //NOI18N
120

121             if (m != null) {
122                 m.invoke(comp, this);
123
124                 return true;
125             }
126         } catch (Exception JavaDoc e) {
127             //No big deal
128
}
129
130         return false;
131     }
132
133     /** Uses reflection to try to remove an this WrapperInplaceEditor as an
134      * action listener on the component in question */

135     private boolean tryRemoveActionListener(Component JavaDoc comp) {
136         try {
137             Method m = comp.getClass().getMethod("removeActionListener", new Class JavaDoc[] { ActionListener.class }); //NOI18N
138

139             if (m != null) {
140                 m.invoke(comp, this);
141
142                 return true;
143             }
144         } catch (Exception JavaDoc e) {
145             //This is ok
146
}
147
148         return false;
149     }
150
151     /** Action listener implementation. The WarpperInplaceEditor is added
152      * as an action listener to the legacy inplace editor component. Any
153      * action event coming from the legacy component will trigger refiring as
154      * InplaceEditor.ACTION_SUCCESS indicating a completed edit. */

155     public void actionPerformed(ActionEvent ae) {
156         fireAction(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, InplaceEditor.COMMAND_SUCCESS));
157     }
158
159     /** Connect to the underlying property editor. Will add the component
160      * to this WrapperInplaceEditor's component hierarchy and start listening
161      * on it for action and focus events */

162     public void connect(java.beans.PropertyEditor JavaDoc pe, PropertyEnv env) {
163         if (legacy != null) {
164             //Should never be called twice without a clear(), but just in case
165
clear();
166         }
167
168         if (pe != enh) {
169             enh = (EnhancedPropertyEditor) pe;
170         }
171
172         Component JavaDoc comp = getLegacyInplaceEditor();
173         add(comp, BorderLayout.CENTER);
174         listenerAdded = tryAddActionListener(comp);
175         comp.addFocusListener(this);
176     }
177
178     public JComponent getComponent() {
179         return this;
180     }
181
182     /** Will check if the underlying component is a combo box, and if so
183      * suppress the arrow keys. Doesn't try to do anything special for
184      * other components. */

185     public KeyStroke[] getKeyStrokes() {
186         if (getLegacyInplaceEditor() instanceof JComboBox) {
187             return ComboInplaceEditor.cbKeyStrokes;
188         } else {
189             return null;
190         }
191     }
192
193     public java.beans.PropertyEditor JavaDoc getPropertyEditor() {
194         return enh;
195     }
196
197     public PropertyModel getPropertyModel() {
198         return mdl;
199     }
200
201     public Object JavaDoc getValue() {
202         return enh.getValue();
203     }
204
205     public void handleInitialInputEvent(InputEvent e) {
206         //do something?
207
}
208
209     public boolean isKnownComponent(Component JavaDoc c) {
210         return isAncestorOf(c);
211     }
212
213     /** Makes a best effort attempt to set the value appropriately on the
214      * custom editor if it is a combo box or text component. */

215     public void reset() {
216         suspendEvents = true;
217
218         try {
219             if (legacy instanceof JTextComponent JavaDoc) {
220                 ((JTextComponent JavaDoc) legacy).setText(enh.getAsText());
221             } else if (legacy instanceof JComboBox) {
222                 if (((JComboBox) legacy).isEditable()) {
223                     if (((JComboBox) legacy).getEditor().getEditorComponent().isShowing()) {
224                         ((JComboBox) legacy).getEditor().setItem(enh.getValue());
225                     }
226                 } else {
227                     ((JComboBox) legacy).setSelectedItem(enh.getValue());
228                 }
229             }
230         } catch (Exception JavaDoc e) {
231             //What we are doing here is dangerous and may fail depending on
232
//the implementation of the legacy editor, so log the exception
233
//but don't notify the user
234
Logger.getLogger(WrapperInplaceEditor.class.getName()).log(Level.WARNING, "Failure resetting legacy editor", e); //NOI18N
235
} finally {
236             suspendEvents = false;
237         }
238     }
239
240     public void setPropertyModel(PropertyModel pm) {
241         mdl = pm;
242     }
243
244     public void setValue(Object JavaDoc o) {
245         suspendEvents = true;
246
247         try {
248             if (legacy instanceof JTextComponent JavaDoc) {
249                 ((JTextComponent JavaDoc) legacy).setText(o.toString());
250             } else if (legacy instanceof JComboBox) {
251                 if (((JComboBox) legacy).isEditable()) {
252                     if (((JComboBox) legacy).getEditor().getEditorComponent().isShowing()) {
253                         ((JComboBox) legacy).getEditor().setItem(o.toString());
254                     }
255                 } else {
256                     ((JComboBox) legacy).setSelectedItem(o);
257                 }
258             }
259         } catch (Exception JavaDoc e) {
260             //What we are doing here is dangerous and may fail depending on
261
//the implementation of the legacy editor, so log the exception
262
//but don't notify the user
263
Logger.getLogger(WrapperInplaceEditor.class.getName()).log(Level.WARNING, "Failure resetting legacy editor", e); //NOI18N
264
} finally {
265             suspendEvents = false;
266         }
267     }
268
269     /** Attempts to give a reasonable answer for text components and
270      * combo boxes; for everything else, returns false */

271     public boolean supportsTextEntry() {
272         if (legacy instanceof JTextComponent JavaDoc) {
273             return true;
274         } else if ((legacy instanceof JComboBox) && ((JComboBox) legacy).isEditable()) {
275             return true;
276         } else {
277             return false;
278         }
279     }
280
281     /** Fetch (and cache, in case no caching is done in the property editor)
282      * the component we want to wrap */

283     private Component JavaDoc getLegacyInplaceEditor() {
284         if (legacy == null) {
285             legacy = enh.getInPlaceCustomEditor();
286         }
287
288         return legacy;
289     }
290
291     public synchronized void addActionListener(ActionListener listener) {
292         if (actionListenerList == null) {
293             actionListenerList = new ArrayList<ActionListener>();
294         }
295
296         actionListenerList.add(listener);
297     }
298
299     public synchronized void removeActionListener(ActionListener listener) {
300         if (actionListenerList != null) {
301             actionListenerList.remove(listener);
302         }
303     }
304
305     void fireAction(ActionEvent event) {
306         if (suspendEvents) {
307             return;
308         }
309
310         List JavaDoc list;
311
312         synchronized (this) {
313             if (actionListenerList == null) {
314                 return;
315             }
316
317             list = (List JavaDoc) ((ArrayList) actionListenerList).clone();
318         }
319
320         for (int i = 0; i < list.size(); i++) {
321             ((ActionListener) list.get(i)).actionPerformed(event);
322         }
323     }
324
325     /**
326      * Registers FocusListener to receive events.
327      * @param listener The listener to register.
328      */

329     public synchronized void addFocusListener(FocusListener listener) {
330         if (listenerList == null) {
331             listenerList = new EventListenerList JavaDoc();
332         }
333
334         listenerList.add(FocusListener.class, listener);
335         super.addFocusListener(listener);
336     }
337
338     /**
339      * Removes FocusListener from the list of listeners.
340      * @param listener The listener to remove.
341      */

342     public synchronized void removeFocusListener(FocusListener listener) {
343         listenerList.remove(java.awt.event.FocusListener JavaDoc.class, listener);
344         super.removeFocusListener(listener);
345     }
346
347     /**
348      * Notifies all registered listeners about the event.
349      *
350      * @param event The event to be fired
351      */

352     private void fireFocusGained(FocusEvent event) {
353         if (listenerList == null) {
354             return;
355         }
356
357         Object JavaDoc[] listeners = listenerList.getListenerList();
358
359         for (int i = listeners.length - 2; i >= 0; i -= 2) {
360             if (listeners[i] == java.awt.event.FocusListener JavaDoc.class) {
361                 ((java.awt.event.FocusListener JavaDoc) listeners[i + 1]).focusGained(event);
362             }
363         }
364     }
365
366     /**
367      * Notifies all registered listeners about the event.
368      *
369      * @param event The event to be fired
370      */

371     private void fireFocusLost(FocusEvent event) {
372         if (listenerList == null) {
373             return;
374         }
375
376         Object JavaDoc[] listeners = listenerList.getListenerList();
377
378         for (int i = listeners.length - 2; i >= 0; i -= 2) {
379             if (listeners[i] == java.awt.event.FocusListener JavaDoc.class) {
380                 ((java.awt.event.FocusListener JavaDoc) listeners[i + 1]).focusLost(event);
381             }
382         }
383     }
384
385     /** A keyboard action to listen for pressing enter to take the value and
386      * close the editor */

387     private class EnterKbdAction extends AbstractAction {
388         public void actionPerformed(ActionEvent ae) {
389             fireAction(new ActionEvent(WrapperInplaceEditor.this, ActionEvent.ACTION_PERFORMED, COMMAND_SUCCESS));
390         }
391     }
392 }
393
Popular Tags