001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.form;
043:
044: import java.awt.Component;
045: import java.awt.event.ActionEvent;
046: import java.awt.event.ActionListener;
047: import java.beans.*;
048: import java.lang.reflect.InvocationTargetException;
049: import java.util.Collection;
050: import java.util.logging.Level;
051: import java.util.logging.Logger;
052: import org.jdesktop.beansbinding.Converter;
053: import org.jdesktop.beansbinding.Validator;
054: import org.openide.nodes.Node;
055:
056: import org.openide.nodes.PropertySupport;
057:
058: public class BindingProperty extends
059: PropertySupport.ReadWrite<MetaBinding> {
060: public static final String PROP_NAME = "name"; // NOI18N
061: public static final String PROP_NULL_VALUE = "nullValue"; // NOI18N
062: public static final String PROP_INCOMPLETE_VALUE = "incompleteValue"; // NOI18N
063: public static final String PROP_VALIDATOR = "validator"; // NOI18N
064: public static final String PROP_CONVERTER = "converter"; // NOI18N
065: private RADComponent bindingComponent;
066: private BindingDescriptor bindingDescriptor;
067: private MetaBinding binding;
068: private Property nameProperty;
069: private Property nullValueProperty;
070: private Property incompleteValueProperty;
071: private Property validatorProperty;
072: private Property converterProperty;
073:
074: public BindingProperty(RADComponent metacomp, BindingDescriptor desc) {
075: super (desc.getPath(), MetaBinding.class, desc.getDisplayName(),
076: desc.getShortDescription());
077: bindingComponent = metacomp;
078: bindingDescriptor = desc;
079: FormProperty prop = (FormProperty) bindingComponent
080: .getPropertyByName(bindingDescriptor.getPath());
081: if (prop == null) {
082: // Can we have a component with a binding property and no regular property?
083: prop = bindingComponent.getAllBeanProperties()[0];
084: }
085: if (prop != null) {
086: String name = FormUtils
087: .getBundleString("MSG_Binding_NullProperty"); // NOI18N
088: nullValueProperty = new Property(prop, "nullValue", desc
089: .getValueType(), name, name, false); // NOI18N
090: name = FormUtils
091: .getBundleString("MSG_Binding_IncompletePathProperty"); // NOI18N
092: incompleteValueProperty = new Property(prop,
093: "incompletePathValue", desc.getValueType(), name,
094: name, false); // NOI18N
095: name = FormUtils.getBundleString("MSG_Binding_Validator"); // NOI18N
096: validatorProperty = new Property(prop, "validator",
097: Validator.class, name, name, true); // NOI18N
098: name = FormUtils.getBundleString("MSG_Binding_Converter"); // NOI18N
099: converterProperty = new Property(prop, "converter",
100: Converter.class, name, name, true); // NOI18N
101: name = FormUtils.getBundleString("MSG_Binding_Name"); // NOI18N
102: nameProperty = new Property(prop, "name", String.class,
103: name, name, true); // NOI18N
104: }
105: }
106:
107: @Override
108: public String getHtmlDisplayName() {
109: return binding != null ? "<b>" + getDisplayName() : null; // NOI18N
110: }
111:
112: public MetaBinding getValue() {
113: return binding;
114: }
115:
116: public void setValue(MetaBinding val) {
117: MetaBinding old = binding;
118: if ((old == null) && (val != null)) {
119: FormEditor.updateProjectForBeansBinding(bindingComponent
120: .getFormModel());
121: getFormModel().raiseVersionLevel(
122: FormModel.FormVersion.NB60,
123: FormModel.FormVersion.NB60);
124: // To make sure that undo restores value of the corresponding property correctly
125: Node.Property prop = bindingComponent
126: .getPropertyByName(bindingDescriptor.getPath());
127: if (prop instanceof FormProperty) {
128: FormProperty fprop = (FormProperty) prop;
129: if (fprop.isChanged()) {
130: try {
131: fprop.restoreDefaultValue();
132: } catch (Exception ex) {
133: // ignore
134: }
135: }
136: } else {
137: try {
138: prop.restoreDefaultValue();
139: } catch (Exception ex) {
140: // ignore
141: }
142: }
143: }
144: binding = val;
145: FormEditor.getBindingSupport(getFormModel())
146: .changeBindingInModel(old, binding);
147:
148: getFormModel().fireBindingChanged(getBindingComponent(),
149: getBindingPath(), null, old, binding);
150: RADComponentNode node = getBindingComponent()
151: .getNodeReference();
152: if (node != null) {
153: node.firePropertyChangeHelper(null, null, null); // this will cause resetting the bean property (e.g. JTable.model)
154: }
155: }
156:
157: @Override
158: public boolean supportsDefaultValue() {
159: return true;
160: }
161:
162: @Override
163: public void restoreDefaultValue() {
164: setValue(null);
165: try {
166: validatorProperty.restoreDefaultValue();
167: converterProperty.restoreDefaultValue();
168: nameProperty.restoreDefaultValue();
169: nullValueProperty.setValue(null);
170: incompleteValueProperty.setValue(null);
171: } catch (Exception ex) {
172: Logger.getLogger(getClass().getName()).log(Level.INFO,
173: ex.getMessage(), ex);
174: }
175: Node.Property prop = bindingComponent
176: .getPropertyByName(bindingDescriptor.getPath());
177: if ((prop != null) && prop.supportsDefaultValue()) {
178: try {
179: prop.restoreDefaultValue();
180: } catch (Exception ex) {
181: Logger.getLogger(getClass().getName()).log(Level.INFO,
182: ex.getMessage(), ex);
183: }
184: }
185: }
186:
187: @Override
188: public boolean isDefaultValue() {
189: return (getValue() == null);
190: }
191:
192: @Override
193: public PropertyEditor getPropertyEditor() {
194: return new BindingPropertyEditor();
195: }
196:
197: public RADComponent getBindingComponent() {
198: return bindingComponent;
199: }
200:
201: public BindingDescriptor getBindingDescriptor() {
202: return bindingDescriptor;
203: }
204:
205: String getBindingPath() {
206: return bindingDescriptor.getPath();
207: }
208:
209: Class getBindingValueType() {
210: return bindingDescriptor.getValueType();
211: }
212:
213: private FormModel getFormModel() {
214: return bindingComponent.getFormModel();
215: }
216:
217: FormProperty getNullValueProperty() {
218: return nullValueProperty;
219: }
220:
221: FormProperty getIncompleteValueProperty() {
222: return incompleteValueProperty;
223: }
224:
225: FormProperty getValidatorProperty() {
226: return validatorProperty;
227: }
228:
229: FormProperty getConverterProperty() {
230: return converterProperty;
231: }
232:
233: FormProperty getNameProperty() {
234: return nameProperty;
235: }
236:
237: public FormProperty getSubProperty(String propName) {
238: if (PROP_NAME.equals(propName)) {
239: return getNameProperty();
240: } else if (PROP_NULL_VALUE.equals(propName)) {
241: return getNullValueProperty();
242: } else if (PROP_INCOMPLETE_VALUE.equals(propName)) {
243: return getIncompleteValueProperty();
244: } else if (PROP_CONVERTER.equals(propName)) {
245: return getConverterProperty();
246: } else if (PROP_VALIDATOR.equals(propName)) {
247: return getValidatorProperty();
248: } else {
249: return null;
250: }
251: }
252:
253: // -----
254:
255: private class BindingPropertyEditor extends PropertyEditorSupport { //implements ExPropertyEditor
256:
257: private BindingCustomizer customizer;
258: private ActionListener customizerListener;
259:
260: @Override
261: public String getAsText() {
262: RADComponent boundComp = null;
263: String path = null;
264: if (binding != null) {
265: boundComp = binding.getSource();
266: path = binding.getSourcePath();
267: }
268:
269: if (boundComp == null)
270: return ""; // NOI18N
271:
272: return path != null ? boundComp.getName() + "[" + path
273: + "]" : // NOI18N
274: boundComp.getName();
275: }
276:
277: @Override
278: public void setAsText(String text) {
279: if ("".equals(text)) { // NOI18N
280: setValue(null);
281: } else {
282: int idx = text.indexOf('['); // NOI18N
283: String compName = idx >= 0 ? text.substring(0, idx)
284: : text;
285: RADComponent boundComp = getFormModel()
286: .findRADComponent(compName);
287: if (boundComp != null) {
288: String path = idx >= 0 ? text.substring(idx + 1,
289: text.length() - 1) : ""; // NOI18N
290: if (!path.equals("")) { // NOI18N
291: if (boundComp != getBindingComponent()
292: || !path.equals(getBindingPath())) {
293: setValue(new MetaBinding(boundComp, path,
294: getBindingComponent(),
295: getBindingPath()));
296: }
297: } else if (boundComp != getBindingComponent()
298: && Collection.class
299: .isAssignableFrom(getBindingValueType())
300: && getBindingValueType().equals(
301: boundComp.getBeanClass())) { // bind directly to the component
302: setValue(new MetaBinding(boundComp, null,
303: getBindingComponent(), getBindingPath()));
304: }
305: }
306: }
307: }
308:
309: @Override
310: public boolean supportsCustomEditor() {
311: return true;
312: }
313:
314: @Override
315: public Component getCustomEditor() {
316: if (customizer == null) {
317: customizer = new BindingCustomizer(BindingProperty.this );
318: customizerListener = new ActionListener() {
319: public void actionPerformed(ActionEvent ev) {
320: setValue(customizer.getBinding());
321: }
322: };
323: }
324: customizer.setBinding((MetaBinding) getValue());
325: return customizer.getDialog(customizerListener);
326: }
327:
328: }
329:
330: static class Property extends FormProperty {
331: private Object value;
332: private boolean supportsDefaultValue;
333:
334: Property(FormProperty prop, String name, Class type,
335: String displayName, String description,
336: boolean supportsDefaultValue) {
337: // PENDING override getContextPath
338: super (new FormPropertyContext.SubProperty(prop), name,
339: type, displayName, description);
340: this .supportsDefaultValue = supportsDefaultValue;
341: }
342:
343: public Object getTargetValue() throws IllegalAccessException,
344: InvocationTargetException {
345: return value;
346: }
347:
348: public void setTargetValue(Object value)
349: throws IllegalAccessException,
350: IllegalArgumentException, InvocationTargetException {
351: this .value = value;
352: }
353:
354: @Override
355: public boolean supportsDefaultValue() {
356: return supportsDefaultValue;
357: }
358:
359: @Override
360: public void restoreDefaultValue()
361: throws IllegalAccessException,
362: InvocationTargetException {
363: super.restoreDefaultValue();
364: getCurrentEditor().setValue(getValue());
365: }
366:
367: }
368:
369: }
|