2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
* InplaceEditorFactory.java
44
* Created on January 4, 2003, 4:52 PM
46
package org.openide.explorer.propertysheet;
48
import java.awt.Toolkit;
49
import java.beans.PropertyChangeEvent;
50
import java.beans.PropertyChangeListener;
51
import javax.swing.JTextField;
52
import org.openide.explorer.propertysheet.editors.EnhancedPropertyEditor;
53
import org.openide.nodes.Node.Property;
55
import java.beans.PropertyEditor;
57
import javax.swing.BorderFactory;
58
import javax.swing.JComponent;
59
import org.openide.util.WeakListeners;
61
/** Factory providing inplace editor implementations. Provides appropriate
62
* InplaceEditor implementations, depending on the type of the property, the
63
* results of PropertyEditor.getTags(), or any hinting provided by the property
64
* editor or PropertyEnv to use a custom inplace editor implementation.
65
* Configures the editor returned and attaches it to the property in question.
66
* @author Tim Boudreau
68
final class InplaceEditorFactory {
69
private InplaceEditor checkbox = null;
70
private InplaceEditor text = null;
71
private InplaceEditor combo = null;
72
private InplaceEditor radio = null;
73
private ReusablePropertyEnv reusableEnv;
74
private boolean tableUI;
75
int radioButtonMax = -1;
76
private boolean useLabels = false;
77
private boolean useRadioBoolean = PropUtils.forceRadioButtons;
79
InplaceEditorFactory(boolean tableUI, ReusablePropertyEnv env) {
80
this.tableUI = tableUI;
81
this.reusableEnv = env;
83
//reset editors when windows theme is changing (classic <-> xp)
84
PropertyChangeListener weakListener = WeakListeners.propertyChange( new PropertyChangeListener() {
85
public void propertyChange(PropertyChangeEvent evt) {
91
}, Toolkit.getDefaultToolkit() );
92
Toolkit.getDefaultToolkit().addPropertyChangeListener( "win.xpstyle.themeActive", weakListener ); //NOI18N
95
/** Set a threshold number of tags below which a radio button, not a
96
* combo box editor should be used */
97
void setRadioButtonMax(int i) {
101
/** Set whether or not radio and checkbox editors should show the property
103
void setUseLabels(boolean val) {
107
void setUseRadioBoolean(boolean val) {
108
useRadioBoolean = val;
111
/**Lazily create (or create a new instance of) the radio button editor */
112
private InplaceEditor getRadioEditor(boolean newInstance) {
113
RadioInplaceEditor result;
116
result = new RadioInplaceEditor(tableUI);
119
radio = new RadioInplaceEditor(tableUI);
121
//Mainly for debugging
122
((JComponent) radio).setName(
123
"RadioEditor for " + getClass().getName() + "@" + System.identityHashCode(this)
127
result = (RadioInplaceEditor) radio;
130
result.setUseTitle(useLabels);
135
/**Lazily create (or create a new instance of) the combo box editor */
136
private InplaceEditor getComboBoxEditor(boolean newInstance) {
138
return new ComboInplaceEditor(tableUI);
142
combo = new ComboInplaceEditor(tableUI);
144
//Mainly for debugging
145
((JComponent) combo).setName(
146
"ComboInplaceEditor for " + getClass().getName() + "@" + System.identityHashCode(this)
153
/**Lazily create (or create a new instance of) the string editor */
154
private InplaceEditor getStringEditor(boolean newInstance) {
156
return new StringInplaceEditor();
160
text = new StringInplaceEditor();
162
//Mainly for debugging
163
((JComponent) text).setName(
164
"StringEditor for " + getClass().getName() + "@" + System.identityHashCode(this)
171
/**Lazily create (or create a new instance of) the checkbox editor */
172
private InplaceEditor getCheckboxEditor(boolean newInstance) {
173
CheckboxInplaceEditor result;
176
result = new CheckboxInplaceEditor();
178
if (checkbox == null) {
179
checkbox = new CheckboxInplaceEditor();
181
//Mainly for debugging
182
((JComponent) checkbox).setName(
183
"CheckboxEditor for " + getClass().getName() + "@" + System.identityHashCode(this)
187
result = (CheckboxInplaceEditor) checkbox;
190
result.setUseTitle(useLabels);
192
return (InplaceEditor) result;
195
/** Factory method that returns an appropriate inplace
196
* editor for an object. Special handling is provided for
197
* instances of Node.Property which can provide hints or
198
* even their own legacy inplace editor implementation.
199
* <P>The returned instance will be connected to the
200
* object (the component provided by getComponent() will
201
* render the property object correctly with no additional
202
* intervention needed. If <code>newInstance</code> is
203
* true, will create a new instance of the inplace editor
204
* component (for use with PropertyPanel and other cases
205
* where multiple inplace esditors can be displayed at the
206
* same time); otherwise a shared instance will be configured
207
* and returned.<P> Note that for the case of unknown object
208
* types (non Node.Property objects), the returned InplaceEditor
209
* will have no way of knowing how to update the object with
210
* a new value, and client code must listen for actions on
211
* the InplaceEditor and do this manually - the update method
212
* of the InplaceEditor will do nothing. */
213
public InplaceEditor getInplaceEditor(Property p, boolean newInstance) {
214
PropertyEnv env = new PropertyEnv();
215
env.setBeans(reusableEnv.getBeans());
217
return getInplaceEditor(p, env, newInstance);
220
InplaceEditor getInplaceEditor(Property p, PropertyEnv env, boolean newInstance) {
221
PropertyEditor ped = PropUtils.getPropertyEditor(p);
222
InplaceEditor result = (InplaceEditor) p.getValue("inplaceEditor"); //NOI18N
223
env.setFeatureDescriptor(p);
224
env.setEditable(p.canWrite());
226
if (ped instanceof ExPropertyEditor) {
227
ExPropertyEditor epe = (ExPropertyEditor) ped;
229
//configure the editor/propertyenv
232
if (result == null) {
233
result = env.getInplaceEditor();
235
} else if (ped instanceof EnhancedPropertyEditor) {
236
//handle legacy inplace custom editors
237
EnhancedPropertyEditor enh = (EnhancedPropertyEditor) ped;
239
if (enh.hasInPlaceCustomEditor()) {
240
//Use our wrapper component to handle this
241
result = new WrapperInplaceEditor(enh);
245
//Okay, the result is null, provide one of the standard inplace editors
246
if (result == null) {
247
Class c = p.getValueType();
249
if ((c == Boolean.class) || (c == Boolean.TYPE)) {
250
if (ped instanceof PropUtils.NoPropertyEditorEditor) {
252
result = getStringEditor(newInstance);
254
boolean useRadioButtons = useRadioBoolean || (p.getValue("stringValues") != null); //NOI18N
255
result = useRadioButtons ? getRadioEditor(newInstance) : getCheckboxEditor(newInstance);
257
} else if (ped.getTags() != null) {
258
if (ped.getTags().length <= radioButtonMax) {
259
result = getRadioEditor(newInstance);
261
result = getComboBoxEditor(newInstance);
264
result = getStringEditor(newInstance);
268
if (!tableUI && Boolean.FALSE.equals(p.getValue("canEditAsText"))) { //NOI18N
269
result.getComponent().setEnabled(false);
272
result.clear(); //XXX shouldn't need to do this!
273
result.setPropertyModel(new NodePropertyModel(p, env.getBeans()));
274
result.connect(ped, env);
278
if( result instanceof JTextField )
279
result.getComponent().setBorder(BorderFactory.createEmptyBorder(0,3,0,0));
281
result.getComponent().setBorder(BorderFactory.createEmptyBorder());