KickJava   Java API By Example, From Geeks To Geeks.

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


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  * InplaceEditor.java
21  *
22  * Created on December 22, 2002, 2:50 PM
23  */

24 package org.openide.explorer.propertysheet;
25
26 import java.awt.Component JavaDoc;
27 import java.awt.event.*;
28
29 import java.beans.PropertyEditor JavaDoc;
30
31 import javax.swing.JComponent JavaDoc;
32 import javax.swing.KeyStroke JavaDoc;
33
34
35 /** Interface defining the contract of reusable inline cell editors for
36  * properties. Generally, this interface will be implemented
37  * on a component subclass. Note
38  * that such components do not have to be concerned about providing
39  * a custom editor button for properties with custom property
40  * editors. If needed, the rendering infrastructure will provide
41  * one.
42  * <P>Inplace editors are designed to be reusable - that is, a single
43  * instance may be reconfigured and reused to edit multiple properties
44  * over its lifespan. The <code>connect()</code> and <code>clear()</code>
45  * methods provide a means of configuring an instance to represent a
46  * property, and then de-configure it when it is no longer needed. The
47  * typical lifecycle of an inplace editor is as follows: <OL><LI>The
48  * user clicks a property in the property sheet.</LI><LI>The property
49  * sheet identifies the property clicked, and locates the correct
50  * inplace editor (either a default one or a custom implementation supplied
51  * by the property or property editor).</LI><LI><code>connect()</code> is
52  * called to configure the editor</LI><LI>The component returned from
53  * <code>getComponent()</code> is displayed on screen and given focus</LI>
54  * <LI>The user enters text or otherwise manipulates the component to change
55  * the value</LI><LI>When the component determines that the user has
56  * either concluded editing (usually pressing Enter) or cancelled editing
57  * (pressing Escape), the inplace editor fires <code>ACTION_SUCCESS</code>
58  * or <code>ACTION_FAILURE</code></LI><LI>The property sheet detects this
59  * action event and removes the editor component</LI><LI>The property sheet
60  * updates the property</LI><LI>The property sheet calls <code>clear()</code>
61  * to dispose of any state or references held by the inplace editor</LI></OL>
62  * <P>If you implement this interface to provide a custom inplace
63  * editor for a particular property, it is wise to also write a
64  * custom PropertyEditor whose <code>paint()</code> method will
65  * paint an image identical to what your editor looks like when
66  * it is instantiated. The simplest way to do this is to create
67  * a renderer instance of your inplace editor, and use it in the
68  * <code>paint()</code> method of your property editor.
69  * <P>The methods of this interface should <strong>never</strong>
70  * be called from any thread except the AWT event thread. The backing
71  * implementation is not thread-safe. This includes <code>ActionEvent</code>s
72  * fired by instances of <code>InplaceEditor</code>.
73  * <P>In no cases should an instance of <code>InplaceEditor</code>
74  * attempt to directly update the value of the represented property
75  * or property editor. If the property should be updated, ensure
76  * that <code>getValue()</code> will return the correct value, and
77  * fire the action command COMMAND_SUCCESS. Implementations
78  * should also not assume that because one of these events has been
79  * fired, that therefore the property editor has been updated with
80  * the new value. Components that display inplace editors
81  * are responsible for the timing of and policy for updates to the represented
82  * properties. Inplace editors merely display the contents of a property
83  * editor, provide a way for the user to edit that value, and notify
84  * the infrastructure when the user has made a change.
85  * <P>Standard implementations of this interface for text entry, combo
86  * boxes and checkboxes are provided by the property sheet infrastructure.
87  * There are several ways to provide a custom inplace editor for use in
88  * the property sheet:<UL><LI><B>Globally</B> - a module supplying a
89  * property editor implementing ExPropertyEditor for a given class may call
90  * <code>PropertyEnv.registerInplaceEditorFactory(InplaceEditor.Factory)</code>
91  * in its <code>attachEnv()</code> method.
92  * When the user invokes an editor operation, the returned inplace editor
93  * will be used.</LI><LI><B>On a per-property basis</B> - A
94  * <code>Node.Property</CODE> may provide a custom inplace editor via hinting.
95  * To do this, the <code>Node.Property</CODE> instance should return an
96  * instance of <code>InplaceEditor</code> from <code>getValue
97  * (&quot;inplaceEditor&quot;)</code></LI></UL>
98  * If both methods are used on the same property, the inplace editor provided
99  * by the per-property hint takes precedence.
100  * @author Tim Boudreau
101  */

102 public interface InplaceEditor {
103     /** Action command that tells the property sheet to update
104      * the property's value with the value from this inplace editor and close
105      * the inplace editor. */

106     public static final String JavaDoc COMMAND_SUCCESS = "success"; //NOI18N
107

108     /** Action command that tells the property sheet that editing
109      * is completed, but the value should not be updated, the
110      * editor should simply be removed. */

111     public static final String JavaDoc COMMAND_FAILURE = "failure"; //NOI18N
112

113     /** Connect this editor with a property editor. The
114      * <code>PropertyEditor</code> instance will already be
115      * initialized with the initial value, and if it is an
116      * instance of ExPropertyEditor, <code>ExPropertyEditor.attachEnv(env)</code>
117      * will already have been called. The <code>PropertyEnv</code>
118      * instance is passed to allow rendering hints to be passed to
119      * the <code>InplaceEditor</code> instance. <P> Implementations
120      * which may be connected to <code>PropertyEditor</code> instances
121      * that do not implement <code>ExPropertyEditor</code> must handle
122      * the case that the <code>env</code> property may be null.
123      * @param pe The property editor
124      * @param env An instance of PropertyEnv, if the editor is an instance of ExPropertyEditor,
125      * or null if it is not */

126     public void connect(PropertyEditor JavaDoc pe, PropertyEnv env);
127
128     /** Returns the physical inplace editor component that should be displayed
129      * on-screen. Typical implementations of this
130      * interface are <code>JComponent</code> subclasses which implement this interface
131      * and simply return <code>this</code> from this method. If you
132      * implement this interface separately from the inplace editor
133      * component, it is expected that the same component instance
134      * will be returned from this instance from the first time
135      * <code>connect()</code> is called, until such a time as <code>clear()</code>
136      * is called.
137      * @return The component that should be displayed to the user to edit the property */

138     public JComponent JavaDoc getComponent();
139
140     /** Dispose of any state and references to the property or value being
141      * edited, to avoid memory leaks due to held references. The property display
142      * code will call this once an inplace editor component has been closed.
143      * A call to this method should return the inplace editor to the state it
144      * is in after its constructor is called. */

145     public void clear();
146
147     /** Returns the value currently displayed or selected in the editor. This
148      * may or may not correspond to the current value of the Property being
149      * represented, and may not represent a valid final value for the property,
150      * but rather represents the edit in progress. <P> This method may return
151      * a <code>String</code>, in which case the property editor will be updated
152      * using its <code>setAsText()</code> method, and the value taken from the
153      * property editor. Implementations are free to also return either null when
154      * appropriate, a String appropriate for use with the property editor's
155      * <code>setAsText()</code> method, or an object instance compatible with the property in question's
156      * <code>setValue()</code> method.
157      * @return The value currently shown in the editor component provided by
158      * <code>getComponent()</code>
159      */

160     public Object JavaDoc getValue();
161
162     /** Set the value to be <i>displayed</i> in the inplace editor. Implementations
163      * should take care to avoid triggering a property change event in the
164      * property editor connected to this inplace editor. This method is used
165      * to restore the partial value of an editor in the case that some
166      * external event causes it to be temporarily removed. <P> This method
167      * is optional, and primarily useful for editors that support text entry.
168      * Editors which do not support text entry may supply an empty implementation
169      * of this method. <P> It is required that <code>setValue()</code> for
170      * a given <code>InplaceEditor</code> be able to handle any possible
171      * type that it can return from <code>getValue()</code>, since it is
172      * used to temporarily cache and then restore the value mid-edit.
173      * @param o The value that should be displayed in the editor component. This
174      * should be an object the component is capable of displaying. It may be
175      * a String or any other object type, provided the component is capable
176      * of displaying it. This method will only ever be called with a value
177      * object supplied from <code>getValue()</code>, so this method should
178      * be compatible with anything that <code>getValue()</code> on a given
179      * <code>InplaceEditor</code> implementation may return */

180     public void setValue(Object JavaDoc o);
181
182     /** Indicates whether an inplace editor supports the direct entry of text or not.
183      * In particular, this method is used to support managing the background
184      * color of the editor component. The default selection color is
185      * used by the property sheet to indicate selection in the property sheet. Editors
186      * supporting text entry should not have their background color set to
187      * the default selection color, so that the user may distinguish selected
188      * text (which would otherwise have the same background color whether it
189      * were selected or not).
190      * @return True if the editor component supplied by <code>getComponent()</code> supports
191      * direct text entry by the user. */

192     public boolean supportsTextEntry();
193
194     /** Restore the inplace editor to the value returned by the property editor's
195      * <code>getValue()</code> method, discarding any edits.
196      * @throws NullPointerException If called before a call to <code>connect()</code> or after a call to
197      * <code>clear()</code>, since in that case the property editor is null.
198      */

199     public void reset();
200
201     /** Add an action listener to the InplaceEditor. Note that the
202      * source property for ActionEvents fired by an InplaceEditor
203      * <strong>must</strong> be an instance of InplaceEditor. The
204      * property sheet infrastructure will recognize two action
205      * commands: <code>COMMAND_SUCCESS</code> and <code>COMMAND_FAILURE</code>.
206      * Other action events
207      * (such as may be generated by a component subclass implementing
208      * this interface) may be fired, but will be ignored by the
209      * property sheet infrastructure.
210      * @param al The action listener to add */

211     public void addActionListener(ActionListener al);
212
213     /** Remove an action listener from an InplaceEditor.
214      * @param al The action listener to remove */

215     public void removeActionListener(ActionListener al);
216
217     /** Keystrokes that should be ignored by the containing component when
218      * this inplace editor is open, even if they are in the <code>InputMap</code>
219      * of the container.<P>
220      * JTable (and potentially other components) will respond to
221      * keystrokes sent to an embedded component. In particular, this
222      * is a problem in JDK 1.4 with embedded JComboBoxes - the down
223      * arrow key, used for combo box navigation, also changes the selection
224      * and closes the editor. Since it is not always possible to determine reliably the
225      * keystrokes an inplace editor will consume at instantiation
226      * time, this allows them to be specified explicitly, so the table
227      * knows what to ignore.
228      * @return The keystrokes a container of the editor component should ignore even if they
229      * are mapped to actions in it. */

230     public KeyStroke JavaDoc[] getKeyStrokes();
231
232     /** Get the <code>java.beans.PropertyEditor</code>
233      * instance associated with this
234      * inplace editor. For efficiency, client code uses
235      * this method to cache the property editor being
236      * used, rather than perform gratuitous lookups of the
237      * property editor on the property it represents.
238      * Inplace editor implementations are expected to cache
239      * the property editor they are initialized with until <code>clear()</code>
240      * is called.
241      * @return The property editor this InplaceEditor represents */

242     public PropertyEditor JavaDoc getPropertyEditor();
243
244     /** Inplace editors cache the property model used to update a
245      * property value at the conclusion of editing. After a call to
246      * <code>setPropertyModel()</code> this method should return the
247      * property model that should be updated with the value from this
248      * inplace editor. After a subsequent call to <code>clear()</code>
249      * this method should return null. <P> Under no circumstances
250      * should an InplaceEditor implementation attempt to modify the
251      * property model - this is the job of the infrastructure that
252      * instantiated the InplaceEditor.
253      * @return The property model representing the property being edited */

254     public PropertyModel getPropertyModel();
255
256     /** Set the property model that should be updated in the event of a
257      * change.
258      * @param pm The property model this inplace editor will represent */

259     public void setPropertyModel(PropertyModel pm);
260
261     /** Returns true if a component is one the inplace editor instantiated.
262      * The property sheet tracks focus and will close an inplace editor
263      * if focus is lost to an unknown component. Since inplace editors may
264      * instantiate popup components that can receive focus, if focus is
265      * lost while an inplace editor is open, the property sheet will query
266      * the current inplace editor to ensure that the recipient of focus is
267      * truly not a child of the inplace editor. For most InplaceEditor
268      * implementations, it is safe simply to return false from this method.
269      * @param c A component which has received focus
270      * @return True if the passed component was instantiated by the inplace editor as part of
271      * its normal operation (for example, a popup which is not a child of
272      * whatever is returned from <code>getComponent()</code>in the component
273      * hierarchy, but which is effectively part of the editor). */

274     public boolean isKnownComponent(Component JavaDoc c);
275
276     /** A factory for inplace editor instances. A module may provide a property
277      * editor which provides a custom inplace editor for any properties
278      * of the type it edits. This is accomplished as follows: <UL><LI>The
279      * property editor must implement <code>ExPropertyEditor</code>.</LI><LI>
280      * In the <code>attachEnv()</code> method of that interface, it must call
281      * <code>env.registerInplaceEditorFactory()</code>, passing an instance
282      * of <code>InplaceEditor.Factory</code>. If a user attempts to edit
283      * the property, the inplace editor returned from <code>Factory.getInplaceEditor()</code>
284      * will be used.</LI></UL>
285      * <p><strong>A note about using InplaceEditor instances to render properties:</strong>
286      * If a custom property editor is, as is encouraged, using an instance of its
287      * InplaceEditor to paint the value rendered in table cells, this method <strong>
288      * must not</strong> return the instance being used for rendering - that instance
289      * may be reconfigured at any time with a different value in order to paint
290      * another cell on the property sheet. */

291     public interface Factory {
292         /** Fetch or create an inplace editor instance. The system guarantees that
293          * there will never be more than one open inplace editor at a time, so it is
294          * safe to return the same static instance repeatedly from this method - when the
295          * editor is opened, it will be configured for the property it is editing.
296          * The optimal approach to implementing this method is to create the editor
297          * on the first call, and maintain a reference to it using a static field,
298          * so a single instance may be shared, but hold the reference to it using
299          * <code>java.lang.ref.WeakReference</code> or
300          * <code>java.lang.ref.SoftReference</code>, so that the instance may be
301          * garbage collected if it is no longer needed.
302          * @return An inplace editor instance
303          */

304         public InplaceEditor getInplaceEditor();
305     }
306 }
307
Popular Tags