KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > form > RADComponent


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.netbeans.modules.form;
21
22 import java.beans.*;
23 import java.util.*;
24 import java.lang.reflect.Method JavaDoc;
25 import org.netbeans.modules.form.RADProperty.FakePropertyDescriptor;
26
27 import org.openide.*;
28 import org.openide.nodes.*;
29 import org.openide.util.NbBundle;
30 import org.openide.util.datatransfer.NewType;
31
32 import org.netbeans.modules.form.codestructure.*;
33
34 /**
35  *
36  * @author Ian Formanek
37  */

38
39 public class RADComponent /*implements FormDesignValue, java.io.Serializable*/ {
40
41     // -----------------------------------------------------------------------------
42
// Static variables
43

44 // public static final String SYNTHETIC_PREFIX = "synthetic_"; // NOI18N
45
// public static final String PROP_NAME = SYNTHETIC_PREFIX + "Name"; // NOI18N
46
public static final String JavaDoc PROP_NAME = "variableName"; // NOI18N
47

48     static final NewType[] NO_NEW_TYPES = {};
49     static final RADProperty[] NO_PROPERTIES = {};
50
51     // -----------------------------------------------------------------------------
52
// Private variables
53

54     private static int idCounter;
55
56     private String JavaDoc id = Integer.toString(++idCounter);
57
58     private Class JavaDoc beanClass;
59     private Object JavaDoc beanInstance;
60     private BeanInfo beanInfo;
61     private BeanInfo fakeBeanInfo;
62     private String JavaDoc missingClassName;
63 // private String componentName;
64

65 // private boolean readOnly;
66

67     protected Node.PropertySet[] propertySets;
68     private Node.Property[] syntheticProperties;
69     private RADProperty[] beanProperties1;
70     private RADProperty[] beanProperties2;
71     private EventProperty[] eventProperties;
72     private Map otherProperties;
73     private List actionProperties;
74
75     private RADProperty[] knownBeanProperties;
76     private Event[] knownEvents; // must be grouped by EventSetDescriptor
77

78     private PropertyChangeListener propertyListener;
79
80     private Map auxValues;
81     protected Map nameToProperty;
82
83     private RADComponent parentComponent;
84
85     private FormModel formModel;
86     private boolean inModel;
87
88     private RADComponentNode componentNode;
89
90     private CodeExpression componentCodeExpression;
91
92 // private String gotoMethod;
93

94     private String JavaDoc storedName; // component name preserved e.g. for remove undo
95

96     private boolean valid = true;
97     // -----------------------------------------------------------------------------
98
// Constructors & Initialization
99

100     /** Called to initialize the component with specified FormModel.
101      * @param formModel the FormModel of the form into which this component
102      * will be added
103      */

104     public boolean initialize(FormModel formModel) {
105         if (this.formModel == null) {
106             this.formModel = formModel;
107 // readOnly = formModel.isReadOnly();
108

109             // properties and events will be created on first request
110
clearProperties();
111
112 // if (beanClass != null)
113
// createCodeExpression();
114

115             return true;
116         }
117         else if (this.formModel != formModel)
118             throw new IllegalStateException JavaDoc(
119                 "Cannot initialize metacomponent with another form model"); // NOI18N
120
return false;
121     }
122
123     public void setParentComponent(RADComponent parentComp) {
124         parentComponent = parentComp;
125     }
126
127     /** Initializes the bean instance represented by this meta component.
128      * A default instance is created for the given bean class.
129      * The meta component is fully initialized after this method returns.
130      * @param beanClass the bean class to be represented by this meta component
131      */

132     public Object JavaDoc initInstance(Class JavaDoc beanClass) throws Exception JavaDoc {
133         if (beanClass == null)
134             throw new NullPointerException JavaDoc();
135
136         if (this.beanClass != beanClass && this.beanClass != null) {
137             beanInfo = null;
138             fakeBeanInfo = null;
139             clearProperties();
140         }
141
142         this.beanClass = beanClass;
143
144         Object JavaDoc bean = createBeanInstance();
145         getBeanInfo(); // force BeanInfo creation here - will be needed, may fail
146
setBeanInstance(bean);
147
148         return beanInstance;
149     }
150
151     /** Sets the bean instance represented by this meta component.
152      * The meta component is fully initialized after this method returns.
153      * @param beanInstance the bean to be represented by this meta component
154      */

155     public void setInstance(Object JavaDoc beanInstance) {
156         if (this.beanClass != beanInstance.getClass()){
157             beanInfo = null;
158             fakeBeanInfo = null;
159         }
160             
161         clearProperties();
162
163         this.beanClass = beanInstance.getClass();
164
165         getBeanInfo(); // force BeanInfo creation here - will be needed, may fail
166
setBeanInstance(beanInstance);
167
168         getAllBeanProperties();
169         for (int i=0; i < knownBeanProperties.length; i++) {
170             try {
171                 knownBeanProperties[i].reinstateProperty();
172             }
173             catch (Exception JavaDoc ex) {
174                 ErrorManager.getDefault()
175                     .notify(ErrorManager.INFORMATIONAL, ex);
176             }
177         }
178     }
179
180     /** Updates the bean instance - e.g. when setting a property requires
181      * to create new instance of the bean.
182      */

183     public void updateInstance(Object JavaDoc beanInstance) {
184         if (this.beanInstance != null && this.beanClass == beanInstance.getClass())
185             setBeanInstance(beanInstance);
186             // should properties also be reinstated?
187
// formModel.fireFormChanged() ?
188
else
189             setInstance(beanInstance);
190     }
191
192     /**
193      * Called to create the instance of the bean. This method is called if the
194      * initInstance method is used; using the setInstance method, the bean
195      * instance is set directly.
196      * @return the instance of the bean that will be used during design time
197      */

198     protected Object JavaDoc createBeanInstance() throws Exception JavaDoc {
199 // throws InstantiationException, IllegalAccessException
200
return CreationFactory.createDefaultInstance(beanClass);
201     }
202
203     /** Sets directly the bean instance. Can be overriden.
204      */

205     protected void setBeanInstance(Object JavaDoc beanInstance) {
206         if (beanClass == null) { // bean class not set yet
207
beanClass = beanInstance.getClass();
208 // createCodeExpression();
209
}
210         this.beanInstance = beanInstance;
211     }
212
213     void setInModel(boolean in) {
214         if (inModel != in) {
215             inModel = in;
216             formModel.updateMapping(this, in);
217             if (in)
218                 createCodeExpression();
219             else
220                 releaseCodeExpression();
221         }
222     }
223
224     void setNodeReference(RADComponentNode node) {
225         this.componentNode = node;
226     }
227
228     protected void createCodeExpression() {
229         // create expression object
230
if (componentCodeExpression == null) {
231             CodeStructure codeStructure = formModel.getCodeStructure();
232             componentCodeExpression = codeStructure.createExpression(
233                                    FormCodeSupport.createOrigin(this));
234             codeStructure.registerExpression(componentCodeExpression);
235         }
236         // make sure a variable is attached
237
if (formModel.getTopRADComponent() != this && componentCodeExpression.getVariable() == null) {
238             formModel.getCodeStructure().createVariableForExpression(
239                                            componentCodeExpression,
240                                            0x30DF, // default type
241
storedName);
242         }
243     }
244
245 /* final void removeCodeExpression() {
246         if (componentCodeExpression != null) {
247             CodeVariable var = componentCodeExpression.getVariable();
248             if (var != null)
249                 storedName = var.getName();
250             CodeStructure.removeExpression(componentCodeExpression);
251         }
252     } */

253
254     final void releaseCodeExpression() {
255         if (componentCodeExpression != null) {
256             CodeVariable var = componentCodeExpression.getVariable();
257             if (var != null) {
258                 storedName = var.getName();
259                 formModel.getCodeStructure()
260                     .removeExpressionFromVariable(componentCodeExpression);
261             }
262         }
263     }
264
265     // -----------------------------------------------------------------------------
266
// Public interface
267

268     private boolean testMode = Boolean.getBoolean("netbeans.form.layout_test"); // NOI18N
269

270     public final String JavaDoc getId() {
271         return testMode ? getName() : id;
272     }
273
274     public final boolean isReadOnly() {
275         return formModel.isReadOnly(); //readOnly;
276
}
277
278     /** Provides access to the Class of the bean represented by this RADComponent
279      * @return the Class of the bean represented by this RADComponent
280      */

281     public final Class JavaDoc getBeanClass() {
282         return beanClass;
283     }
284
285     public final String JavaDoc getMissingClassName() {
286         return missingClassName;
287     }
288
289     public final void setMissingClassName(String JavaDoc className) {
290         missingClassName = className;
291     }
292     
293     /** Provides access to the real instance of the bean represented by this RADComponent
294      * @return the instance of the bean represented by this RADComponent
295      */

296     public final Object JavaDoc getBeanInstance() {
297         return beanInstance;
298     }
299
300     public final RADComponent getParentComponent() {
301         return parentComponent;
302     }
303
304     public final boolean isParentComponent(RADComponent comp) {
305         if (comp == null)
306             return false;
307
308         do {
309             comp = comp.getParentComponent();
310             if (comp == this)
311                 return true;
312         }
313         while (comp != null);
314
315         return false;
316     }
317
318 // /** FormDesignValue implementation.
319
// * @return description of the design value.
320
// */
321
// public String getDescription() {
322
// return getName();
323
// }
324
//
325
// /** FormDesignValue implementation.
326
// * Provides a value which should be used during design-time as real value
327
// * of the property (in case that RADComponent is used as property value).
328
// * @return the bean instance of RADComponent
329
// */
330
// public Object getDesignValue() {
331
// return getBeanInstance();
332
// }
333

334     public Object JavaDoc cloneBeanInstance(Collection relativeProperties) {
335         Object JavaDoc clone;
336         try {
337             clone = createBeanInstance();
338         }
339         catch (Exception JavaDoc ex) { // ignore, this should not fail
340
org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
341             return null;
342         }
343
344         FormUtils.copyPropertiesToBean(getKnownBeanProperties(),
345                                        clone,
346                                        relativeProperties);
347         return clone;
348     }
349
350     /** Provides access to BeanInfo of the bean represented by this RADComponent
351      * @return the BeanInfo of the bean represented by this RADComponent
352      */

353     public BeanInfo getBeanInfo() {
354         if (beanInfo == null) {
355             try {
356                 beanInfo = FormUtils.getBeanInfo(beanClass);
357             } catch (Error JavaDoc err) { // Issue 74002
358
org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, err);
359                 beanInfo = new FakeBeanInfo();
360             } catch (IntrospectionException ex) {
361                 org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ex);
362                 beanInfo = new FakeBeanInfo();
363             }
364         }
365         if(isValid()) {
366             return beanInfo;
367         } else {
368             if (fakeBeanInfo == null) {
369         fakeBeanInfo = new FakeBeanInfo();
370         }
371             return fakeBeanInfo ;
372         }
373     }
374     
375     /** This method can be used to check whether the bean represented by this
376      * RADComponent has hidden-state.
377      * @return true if the component has hidden state, false otherwise
378      */

379     public boolean hasHiddenState() {
380         String JavaDoc name = beanClass.getName();
381         if (name.startsWith("javax.") // NOI18N
382
|| name.startsWith("java.") // NOI18N
383
|| name.startsWith("org.openide.")) // NOI18N
384
return false;
385
386         return getBeanInfo().getBeanDescriptor()
387                                 .getValue("hidden-state") != null; // NOI18N
388
}
389
390     public CodeExpression getCodeExpression() {
391         return componentCodeExpression;
392     }
393
394     /** Getter for the name of the metacomponent - it maps to variable name
395      * declared for the instance of the component in the generated java code.
396      * It is a unique identification of the component within a form, but it may
397      * change (currently editable as "Variable Name" in code gen. properties).
398      * @return current value of the Name property
399      */

400     public String JavaDoc getName() {
401         if (componentCodeExpression != null) {
402             CodeVariable var = componentCodeExpression.getVariable();
403             if (var != null)
404                 return var.getName();
405         }
406         return storedName;
407     }
408
409     /** Setter for the name of the component - it is the name of the
410      * component's node and the name of the variable declared for the component
411      * in the generated code.
412      * @param value new name of the component
413      */

414     public void setName(String JavaDoc name) {
415         if (componentCodeExpression == null)
416             return;
417
418         CodeVariable var = componentCodeExpression.getVariable();
419         if (var == null || name.equals(var.getName()))
420             return;
421         // [maybe we should handle the component name differently if there is
422
// no variable for the component]
423

424         if (!org.openide.util.Utilities.isJavaIdentifier(name)) {
425             IllegalArgumentException JavaDoc iae =
426                 new IllegalArgumentException JavaDoc("Invalid component name"); // NOI18N
427
ErrorManager.getDefault().annotate(
428                 iae, ErrorManager.USER, null,
429                 FormUtils.getBundleString("ERR_INVALID_COMPONENT_NAME"), // NOI18N
430
null, null);
431             throw iae;
432         }
433
434         if (formModel.getCodeStructure().isVariableNameReserved(name)) {
435             IllegalArgumentException JavaDoc iae =
436                 new IllegalArgumentException JavaDoc("Component name already in use: "+name); // NOI18N
437
ErrorManager.getDefault().annotate(
438                 iae, ErrorManager.USER, null,
439                 FormUtils.getBundleString("ERR_COMPONENT_NAME_ALREADY_IN_USE"), // NOI18N
440
null, null);
441             throw iae;
442         }
443
444         i18nComponentRename(name); // do before the component has new name
445

446         String JavaDoc oldName = var.getName();
447
448         formModel.getCodeStructure().renameVariable(oldName, name);
449
450         renameDefaultEventHandlers(oldName, name);
451         // [possibility of renaming default event handlers should be probably
452
// configurable in options]
453

454         formModel.fireSyntheticPropertyChanged(this, PROP_NAME,
455                                                oldName, name);
456
457         if (getNodeReference() != null)
458             getNodeReference().updateName();
459     }
460
461     void setStoredName(String JavaDoc name) {
462         storedName = name;
463     }
464
465     private void renameDefaultEventHandlers(String JavaDoc oldComponentName,
466                                             String JavaDoc newComponentName)
467     {
468         boolean renamed = false; // whether any handler was renamed
469
FormEvents formEvents = null;
470
471         Event[] events = getKnownEvents();
472         for (int i=0; i < events.length; i++) {
473             String JavaDoc[] handlers = events[i].getEventHandlers();
474             for (int j=0; j < handlers.length; j++) {
475                 String JavaDoc handlerName = handlers[j];
476                 int idx = handlerName.indexOf(oldComponentName);
477                 if (idx >= 0) {
478                     if (formEvents == null)
479                          formEvents = getFormModel().getFormEvents();
480                     String JavaDoc newHandlerName = formEvents.findFreeHandlerName(
481                         handlerName.substring(0, idx)
482                         + newComponentName
483                         + handlerName.substring(idx + oldComponentName.length())
484                     );
485                     formEvents.renameEventHandler(handlerName, newHandlerName);
486                 }
487             }
488         }
489
490         if (renamed && getNodeReference() != null)
491             getNodeReference().fireComponentPropertySetsChange();
492     }
493
494 /*
495     / ** Restore name of component. If stored name is already in use or is
496      * null then create a new name. * /
497     void useStoredName() {
498         if (storedName == null && componentName != null
499             //&& !formModel.getVariablePool().isReserved(componentName)
500             ) {
501             formModel.getVariablePool().reserveName(componentName);
502             return;
503         }
504         
505         String oldName = componentName;
506         componentName = storedName;
507
508         if (storedName == null || formModel.getVariablePool().isReserved(storedName)) {
509             componentName = formModel.getVariablePool().getNewName(beanClass);
510         }
511         
512         formModel.getVariablePool().createVariable(componentName, beanClass);
513
514 // formModel.fireFormChanged();
515         
516         if (getNodeReference() != null) {
517             getNodeReference().updateName();
518         }
519     }
520
521     / ** @return component name preserved between Cut and Paste * /
522     String getStoredName() {
523         return storedName;
524     }
525
526     / ** Can be called to store the component name into special variable to preserve it between Cut and Paste * /
527     void storeName() {
528         storedName = componentName;
529     }
530 */

531
532     /** Allows to add an auxiliary <name, value> pair, which is persistent
533      * in Gandalf. The current value can be obtained using
534      * getAuxValue(aux_property_name) method. To remove aux value for specified
535      * property name, use setAuxValue(name, null).
536      * @param key name of the aux property
537      * @param value new value of the aux property or null to remove it
538      */

539     public void setAuxValue(String JavaDoc key, Object JavaDoc value) {
540         if (auxValues == null) {
541             if (value == null)
542                 return;
543             auxValues = new TreeMap();
544         }
545         auxValues.put(key, value);
546     }
547
548     /** Allows to obtain an auxiliary value for specified aux property name.
549      * @param key name of the aux property
550      * @return null if the aux value for specified name is not set
551      */

552     public Object JavaDoc getAuxValue(String JavaDoc key) {
553         return auxValues != null ? auxValues.get(key) : null;
554     }
555
556     /** Provides access to the FormModel class which manages the form in which
557      * this component has been added.
558      * @return the FormModel which manages the form into which this component
559      * has been added
560      */

561     public final FormModel getFormModel() {
562         return formModel;
563     }
564
565     public final boolean isInModel() {
566         return inModel;
567     }
568
569     /** @return the map of all component's aux value-pairs of <String, Object>
570      */

571     public Map getAuxValues() {
572         return auxValues;
573     }
574
575     /** Support for new types that can be created in this node.
576      * @return array of new type operations that are allowed
577      */

578     public NewType[] getNewTypes() {
579         return NO_NEW_TYPES;
580     }
581
582     public Node.PropertySet[] getProperties() {
583         if (propertySets == null) {
584             ArrayList propSets = new ArrayList(5);
585             createPropertySets(propSets);
586             propertySets = new Node.PropertySet[propSets.size()];
587             propSets.toArray(propertySets);
588         }
589         return propertySets;
590     }
591
592     public RADProperty[] getAllBeanProperties() {
593         if (knownBeanProperties == null) {
594             createBeanProperties();
595         }
596
597         return knownBeanProperties;
598     }
599
600     public RADProperty[] getKnownBeanProperties() {
601         return knownBeanProperties != null ? knownBeanProperties : NO_PROPERTIES;
602     }
603
604     public Iterator getBeanPropertiesIterator(FormProperty.Filter filter,
605                                               boolean fromAll)
606     {
607         return new PropertyIterator(
608                    fromAll ? getAllBeanProperties() : getKnownBeanProperties(),
609                    filter);
610     }
611
612     /** Provides access to the Node which represents this RADComponent
613      * @return the RADComponentNode which represents this RADComponent
614      */

615     public RADComponentNode getNodeReference() {
616         return componentNode;
617     }
618
619     // -----------------------------------------------------------------------------
620
// Access to component Properties
621

622     Node.Property[] getSyntheticProperties() {
623         if (syntheticProperties == null)
624             syntheticProperties = createSyntheticProperties();
625         return syntheticProperties;
626     }
627
628     RADProperty[] getBeanProperties1() {
629         if (beanProperties1 == null)
630             createBeanProperties();
631         return beanProperties1;
632     }
633
634     RADProperty[] getBeanProperties2() {
635         if (beanProperties2 == null)
636             createBeanProperties();
637         return beanProperties2;
638     }
639
640     EventProperty[] getEventProperties() {
641         if (eventProperties == null)
642             createEventProperties();
643         return eventProperties;
644     }
645     
646     List getActionProperties() {
647         if (actionProperties == null) {
648             createBeanProperties();
649         }
650         return actionProperties;
651     }
652
653     protected Node.Property getPropertyByName(String JavaDoc name,
654                                               Class JavaDoc propertyType,
655                                               boolean fromAll)
656     {
657         Node.Property prop = (Node.Property) nameToProperty.get(name);
658         if (prop == null && fromAll) {
659             if (beanProperties1 == null && !name.startsWith("$")) // NOI18N
660
createBeanProperties();
661             if (eventProperties == null && name.startsWith("$")) // NOI18N
662
createEventProperties();
663
664             prop = (Node.Property) nameToProperty.get(name);
665         }
666         return prop != null
667                  && (propertyType == null
668                      || propertyType.isAssignableFrom(prop.getClass())) ?
669                prop : null;
670     }
671
672     /**
673      * @return bean or event property
674      */

675     public Node.Property getPropertyByName(String JavaDoc name) {
676         return getPropertyByName(name, null, true);
677     }
678
679     public final RADProperty getBeanProperty(String JavaDoc name) {
680         return (RADProperty) getPropertyByName(name, RADProperty.class, true);
681     }
682
683     final Node.Property getSyntheticProperty(String JavaDoc name) {
684         for (Node.Property prop : getSyntheticProperties()) {
685             if (prop.getName().equals(name))
686                 return prop;
687         }
688         return null;
689     }
690
691     public RADProperty[] getFakeBeanProperties(String JavaDoc[] propNames, Class JavaDoc[] propertyTypes) {
692         FakeBeanInfo fbi = (FakeBeanInfo) getBeanInfo();
693         fbi.removePropertyDescriptors();
694         for (int i = 0; i < propNames.length; i++) {
695             fbi.addPropertyDescriptor(propNames[i], propertyTypes[i]);
696         }
697         return getBeanProperties(propNames);
698     }
699     
700     public RADProperty[] getBeanProperties(String JavaDoc[] propNames) {
701         RADProperty[] properties = new RADProperty[propNames.length];
702         PropertyDescriptor[] descriptors = null;
703         
704         boolean empty = knownBeanProperties == null;
705         int validCount = 0;
706         List newProps = null;
707         Object JavaDoc[] propAccessClsf = null;
708         Object JavaDoc[] propParentChildDepClsf = null;
709
710         int descIndex = 0;
711         for (int i=0; i < propNames.length; i++) {
712             String JavaDoc name = propNames[i];
713             if (name == null)
714                 continue;
715
716             RADProperty prop;
717             if (!empty) {
718                 Object JavaDoc obj = nameToProperty.get(name);
719                 prop = obj instanceof RADProperty ? (RADProperty) obj : null;
720             }
721             else prop = null;
722
723             if (prop == null) {
724                 if (descriptors == null) {
725                     descriptors = getBeanInfo().getPropertyDescriptors();
726                     if (descriptors.length == 0)
727                         break;
728                 }
729                 int j = descIndex;
730                 do {
731                     if (descriptors[j].getName().equals(name)) {
732                         if (propAccessClsf == null) {
733                             propAccessClsf = FormUtils.getPropertiesAccessClsf(beanClass);
734                             propParentChildDepClsf = FormUtils.getPropertiesParentChildDepsClsf(beanClass);
735                         }
736
737                         prop = createBeanProperty(descriptors[j], propAccessClsf, propParentChildDepClsf);
738
739                         if (!empty) {
740                             if (newProps == null)
741                                 newProps = new ArrayList();
742                             newProps.add(prop);
743                         }
744                         descIndex = j + 1;
745                         if (descIndex == descriptors.length
746                                          && i+1 < propNames.length)
747                             descIndex = 0; // go again from beginning
748
break;
749                     }
750                     j++;
751                     if (j == descriptors.length)
752                         j = 0;
753                 }
754                 while (j != descIndex);
755             }
756             if (prop != null) {
757                 properties[i] = prop;
758                 validCount++;
759             }
760             else { // force all properties creation, there might be more
761
// properties than from BeanInfo [currently just ButtonGroup]
762
properties[i] = (RADProperty)
763                                 getPropertyByName(name, RADProperty.class, true);
764                 empty = false;
765                 newProps = null;
766             }
767         }
768
769         if (empty) {
770             if (validCount == properties.length)
771                 knownBeanProperties = properties;
772             else if (validCount > 0) {
773                 knownBeanProperties = new RADProperty[validCount];
774                 for (int i=0,j=0; i < properties.length; i++)
775                     if (properties[i] != null)
776                         knownBeanProperties[j++] = properties[i];
777             }
778         }
779         else if (newProps != null) { // just for consistency, should not occur
780
RADProperty[] knownProps =
781                 new RADProperty[knownBeanProperties.length + newProps.size()];
782             System.arraycopy(knownBeanProperties, 0,
783                              knownProps, 0,
784                              knownBeanProperties.length);
785             for (int i=0; i < newProps.size(); i++)
786                 knownProps[i + knownBeanProperties.length] = (RADProperty)
787                                                              newProps.get(i);
788
789             knownBeanProperties = knownProps;
790         }
791
792         return properties;
793     }
794
795     public Event getEvent(String JavaDoc name) {
796         Object JavaDoc prop = nameToProperty.get(name);
797         if (prop == null && eventProperties == null) {
798             createEventProperties();
799             prop = nameToProperty.get(name);
800         }
801         return prop instanceof EventProperty ?
802                ((EventProperty)prop).getEvent() : null;
803     }
804
805     public Event[] getEvents(String JavaDoc[] eventNames) {
806         Event[] events = new Event[eventNames.length];
807         EventSetDescriptor[] eventSets = null;
808
809         boolean empty = knownEvents == null;
810         int validCount = 0;
811         List newEvents = null;
812
813         int setIndex = 0;
814         int methodIndex = 0;
815
816         for (int i=0; i < eventNames.length; i++) {
817             String JavaDoc name = eventNames[i];
818             if (name == null)
819                 continue;
820
821             boolean fullName = name.startsWith("$"); // NOI18N
822

823             Event event;
824             if (!empty) {
825                 Object JavaDoc obj = nameToProperty.get(name);
826                 event = obj instanceof EventProperty ?
827                         ((EventProperty)obj).getEvent() : null;
828             }
829             else event = null;
830
831             if (event == null) {
832                 if (eventSets == null) {
833                     eventSets = getBeanInfo().getEventSetDescriptors();
834                     if (eventSets.length == 0)
835                         break;
836                 }
837                 int j = setIndex;
838                 do {
839                     Method JavaDoc[] methods = eventSets[j].getListenerMethods();
840                     if (methods.length > 0) {
841                         int k = methodIndex;
842                         do {
843                             String JavaDoc eventFullId =
844                                 FormEvents.getEventIdName(methods[k]);
845                             String JavaDoc eventId = fullName ?
846                                 eventFullId : methods[k].getName();
847                             if (eventId.equals(name)) {
848                                 event = createEventProperty(eventFullId,
849                                                             eventSets[j],
850                                                             methods[k])
851                                                 .getEvent();
852                                 if (!empty) {
853                                     if (newEvents == null)
854                                         newEvents = new ArrayList();
855                                     newEvents.add(event);
856                                 }
857                                 methodIndex = k + 1;
858                                 break;
859                             }
860                             k++;
861                             if (k == methods.length)
862                                 k = 0;
863                         }
864                         while (k != methodIndex);
865                     }
866
867                     if (event != null) {
868                         if (methodIndex == methods.length) {
869                             methodIndex = 0;
870                             setIndex = j + 1; // will continue in new set
871
if (setIndex == eventSets.length
872                                             && i+1 < eventNames.length)
873                                 setIndex = 0; // go again from beginning
874
}
875                         else setIndex = j; // will continue in the same set
876
break;
877                     }
878
879                     j++;
880                     if (j == eventSets.length)
881                         j = 0;
882                     methodIndex = 0;
883                 }
884                 while (j != setIndex);
885             }
886             if (event != null) {
887                 events[i] = event;
888                 validCount++;
889             }
890         }
891
892         if (empty) {
893             if (validCount == events.length)
894                 knownEvents = events;
895             else if (validCount > 0) {
896                 knownEvents = new Event[validCount];
897                 for (int i=0,j=0; i < events.length; i++)
898                     if (events[i] != null)
899                         knownEvents[j++] = events[i];
900             }
901         }
902         else if (newEvents != null) { // just for consistency, should not occur
903
Event[] known = new Event[knownEvents.length + newEvents.size()];
904             System.arraycopy(knownEvents, 0, known, 0, knownEvents.length);
905             for (int i=0; i < newEvents.size(); i++)
906                 known[i + knownEvents.length] = (Event) newEvents.get(i);
907
908             knownEvents = known;
909         }
910
911         return events;
912     }
913
914     /** @return all events of the component grouped by EventSetDescriptor
915      */

916     public Event[] getAllEvents() {
917         if (knownEvents == null || eventProperties == null) {
918             if (eventProperties == null)
919                 createEventProperties();
920             else {
921                 knownEvents = new Event[eventProperties.length];
922                 for (int i=0; i < eventProperties.length; i++)
923                     knownEvents[i] = eventProperties[i].getEvent();
924             }
925         }
926
927         return knownEvents;
928     }
929
930     // Note: events must be grouped by EventSetDescriptor
931
public Event[] getKnownEvents() {
932         return knownEvents != null ? knownEvents : FormEvents.NO_EVENTS;
933     }
934
935     // ---------
936
// events
937

938     void attachDefaultEvent() {
939         Event event = null;
940
941         int eventIndex = getBeanInfo().getDefaultEventIndex();
942         if (eventIndex < getEventProperties().length && eventIndex >= 0)
943             event = eventProperties[eventIndex].getEvent();
944         else
945             for (int i=0; i < eventProperties.length; i++) {
946                 Event e = eventProperties[i].getEvent();
947                 if ("actionPerformed".equals(e.getListenerMethod().getName())) { // NOI18N
948
event = e;
949                     break;
950                 }
951             }
952
953         if (event != null)
954             getFormModel().getFormEvents().attachEvent(event, null, null);
955     }
956
957     // -----------------------------------------------------------------------------
958
// Properties
959

960     protected void clearProperties() {
961         if (nameToProperty != null)
962             nameToProperty.clear();
963         else nameToProperty = new HashMap();
964
965         propertySets = null;
966         syntheticProperties = null;
967         beanProperties1 = null;
968         beanProperties2 = null;
969         knownBeanProperties = null;
970         eventProperties = null;
971         knownEvents = null;
972     }
973
974     protected void createPropertySets(List propSets) {
975         if (beanProperties1 == null)
976             createBeanProperties();
977
978         ResourceBundle bundle = FormUtils.getBundle();
979
980         Node.PropertySet ps;
981         propSets.add(new Node.PropertySet(
982                 "properties", // NOI18N
983
bundle.getString("CTL_PropertiesTab"), // NOI18N
984
bundle.getString("CTL_PropertiesTabHint")) // NOI18N
985
{
986             public Node.Property[] getProperties() {
987                 return getBeanProperties1();
988             }
989         });
990
991         if(isValid()) {
992             Iterator entries = otherProperties.entrySet().iterator();
993             while (entries.hasNext()) {
994                 Map.Entry entry = (Map.Entry)entries.next();
995                 final String JavaDoc category = (String JavaDoc)entry.getKey();
996                 ps = new Node.PropertySet(category, category, category) {
997                     public Node.Property[] getProperties() {
998                         if (otherProperties == null) {
999                             createBeanProperties();
1000                        }
1001                        return (Node.Property[])otherProperties.get(category);
1002                    }
1003                };
1004                //ps.setValue("tabName", category); // NOI18N
1005
propSets.add(ps);
1006            }
1007        
1008            if (beanProperties2.length > 0)
1009                propSets.add(new Node.PropertySet(
1010                        "properties2", // NOI18N
1011
bundle.getString("CTL_Properties2Tab"), // NOI18N
1012
bundle.getString("CTL_Properties2TabHint")) // NOI18N
1013
{
1014                    public Node.Property[] getProperties() {
1015                        return getBeanProperties2();
1016                    }
1017                });
1018        
1019            ps = new Node.PropertySet(
1020                    "events", // NOI18N
1021
bundle.getString("CTL_EventsTab"), // NOI18N
1022
bundle.getString("CTL_EventsTabHint")) // NOI18N
1023
{
1024                public Node.Property[] getProperties() {
1025                    return getEventProperties();
1026                }
1027            };
1028
1029            ps.setValue("tabName", bundle.getString("CTL_EventsTab")); // NOI18N
1030
propSets.add(ps);
1031        
1032        }
1033        
1034        ps = new Node.PropertySet(
1035                "synthetic", // NOI18N
1036
bundle.getString("CTL_SyntheticTab"), // NOI18N
1037
bundle.getString("CTL_SyntheticTabHint")) // NOI18N
1038
{
1039            public Node.Property[] getProperties() {
1040                return getSyntheticProperties();
1041            }
1042        };
1043        ps.setValue("tabName", bundle.getString("CTL_SyntheticTab_Short")); // NOI18N
1044
propSets.add(ps);
1045    }
1046
1047    protected Node.Property[] createSyntheticProperties() {
1048        return FormEditor.getCodeGenerator(formModel).getSyntheticProperties(this);
1049    }
1050
1051    private void createBeanProperties() {
1052        ArrayList prefProps = new ArrayList();
1053        ArrayList normalProps = new ArrayList();
1054        ArrayList expertProps = new ArrayList();
1055        Map otherProps = new TreeMap();
1056        List actionProps = new LinkedList();
1057
1058        Object JavaDoc[] propsCats = FormUtils.getPropertiesCategoryClsf(
1059                                 beanClass, getBeanInfo().getBeanDescriptor());
1060        Object JavaDoc[] propsAccess = FormUtils.getPropertiesAccessClsf(beanClass);
1061        Object JavaDoc[] propParentChildDepClsf = FormUtils.getPropertiesParentChildDepsClsf(beanClass);
1062
1063        PropertyDescriptor[] props = getBeanInfo().getPropertyDescriptors();
1064        for (int i = 0; i < props.length; i++) {
1065            PropertyDescriptor pd = props[i];
1066            boolean action = (pd.getValue("action") != null); // NOI18N
1067
Object JavaDoc category = pd.getValue("category"); // NOI18N
1068
List listToAdd;
1069            
1070            if ((category == null) || (!(category instanceof String JavaDoc))) {
1071                Object JavaDoc propCat = FormUtils.getPropertyCategory(pd, propsCats);
1072                if (propCat == FormUtils.PROP_PREFERRED)
1073                    listToAdd = prefProps;
1074                else if (propCat == FormUtils.PROP_NORMAL)
1075                    listToAdd = normalProps;
1076                else if (propCat == FormUtils.PROP_EXPERT)
1077                    listToAdd = expertProps;
1078                else continue; // PROP_HIDDEN
1079

1080            } else {
1081                listToAdd = (List)otherProps.get(category);
1082                if (listToAdd == null) {
1083                    listToAdd = new ArrayList();
1084                    otherProps.put(category, listToAdd);
1085                }
1086            }
1087            
1088            FormProperty prop = (FormProperty) nameToProperty.get(pd.getName());
1089            if (prop == null)
1090                prop = createBeanProperty(pd, propsAccess, propParentChildDepClsf);
1091
1092            if (prop != null) {
1093                listToAdd.add(prop);
1094                if (action) {
1095                    Object JavaDoc actionName = pd.getValue("actionName"); // NOI18N
1096
if (actionName instanceof String JavaDoc) {
1097                        prop.setValue("actionName", actionName); // NOI18N
1098
}
1099                    actionProps.add(prop);
1100                }
1101            }
1102        }
1103
1104        changePropertiesExplicitly(prefProps, normalProps, expertProps);
1105
1106        int prefCount = prefProps.size();
1107        int normalCount = normalProps.size();
1108        int expertCount = expertProps.size();
1109        int otherCount = 0;
1110
1111        if (prefCount > 0) {
1112            beanProperties1 = new RADProperty[prefCount];
1113            prefProps.toArray(beanProperties1);
1114            if (normalCount + expertCount > 0) {
1115                normalProps.addAll(expertProps);
1116                beanProperties2 = new RADProperty[normalCount + expertCount];
1117                normalProps.toArray(beanProperties2);
1118            }
1119            else beanProperties2 = new RADProperty[0];
1120        }
1121        else {
1122            beanProperties1 = new RADProperty[normalCount];
1123            normalProps.toArray(beanProperties1);
1124            if (expertCount > 0) {
1125                beanProperties2 = new RADProperty[expertCount];
1126                expertProps.toArray(beanProperties2);
1127            }
1128            else beanProperties2 = new RADProperty[0];
1129        }
1130        
1131        Iterator entries = otherProps.entrySet().iterator();
1132        RADProperty[] array = new RADProperty[0];
1133        while (entries.hasNext()) {
1134            Map.Entry entry = (Map.Entry)entries.next();
1135            ArrayList catProps = (ArrayList)entry.getValue();
1136            otherCount += catProps.size();
1137            entry.setValue(catProps.toArray(array));
1138        }
1139        otherProperties = otherProps;
1140        
1141        FormUtils.reorderProperties(beanClass, beanProperties1);
1142        FormUtils.reorderProperties(beanClass, beanProperties2);
1143
1144        knownBeanProperties = new RADProperty[beanProperties1.length
1145                              + beanProperties2.length + otherCount];
1146        System.arraycopy(beanProperties1, 0,
1147                         knownBeanProperties, 0,
1148                         beanProperties1.length);
1149        System.arraycopy(beanProperties2, 0,
1150                         knownBeanProperties, beanProperties1.length,
1151                         beanProperties2.length);
1152        
1153        int where = beanProperties1.length + beanProperties2.length;
1154        
1155        entries = otherProperties.entrySet().iterator();
1156        while (entries.hasNext()) {
1157            Map.Entry entry = (Map.Entry)entries.next();
1158            RADProperty[] catProps = (RADProperty[])entry.getValue();
1159            System.arraycopy(catProps, 0,
1160                knownBeanProperties, where,
1161                catProps.length);
1162            where += catProps.length;
1163        }
1164
1165        actionProperties = actionProps;
1166    }
1167
1168    private void createEventProperties() {
1169        EventSetDescriptor[] eventSets = getBeanInfo().getEventSetDescriptors();
1170
1171        List eventPropList = new ArrayList(eventSets.length * 5);
1172
1173        for (int i=0; i < eventSets.length; i++) {
1174            EventSetDescriptor desc = eventSets[i];
1175            Method JavaDoc[] methods = desc.getListenerMethods();
1176            for (int j=0; j < methods.length; j++) {
1177                String JavaDoc eventId = FormEvents.getEventIdName(methods[j]);
1178                Object JavaDoc prop = nameToProperty.get(eventId);
1179                if (prop == null)
1180                    prop = createEventProperty(eventId, desc, methods[j]);
1181                eventPropList.add(prop);
1182            }
1183        }
1184
1185        EventProperty[] eventProps = new EventProperty[eventPropList.size()];
1186        eventPropList.toArray(eventProps);
1187
1188        knownEvents = new Event[eventProps.length];
1189        for (int i=0; i < eventProps.length; i++)
1190            knownEvents[i] = eventProps[i].getEvent();
1191
1192        FormUtils.sortProperties(eventProps);
1193        eventProperties = eventProps;
1194    }
1195
1196    protected RADProperty createBeanProperty(PropertyDescriptor desc,
1197                                             Object JavaDoc[] propAccessClsf,
1198                                             Object JavaDoc[] propParentChildDepClsf)
1199    {
1200        if (desc.getPropertyType() == null)
1201            return null;
1202
1203        RADProperty prop = null;
1204        if(desc instanceof FakePropertyDescriptor){
1205            try {
1206                prop = new FakeRADProperty(this, (FakePropertyDescriptor) desc);
1207            } catch (IntrospectionException ex) { // should not happen
1208
ex.printStackTrace();
1209        return null;
1210            }
1211        } else {
1212            prop = new RADProperty(this, desc);
1213        }
1214
1215    int access = FormUtils.getPropertyAccess(desc, propAccessClsf);
1216    if (access != 0)
1217        prop.setAccessType(access);
1218
1219        String JavaDoc parentChildDependency = FormUtils.getPropertyParentChildDependency(
1220                                         desc, propParentChildDepClsf);
1221        if (parentChildDependency != null)
1222            prop.setValue(parentChildDependency, Boolean.TRUE);
1223
1224    setPropertyListener(prop);
1225
1226    // prop.addPropertyChangeListener(getPropertyListener());
1227
nameToProperty.put(desc.getName(), prop);
1228
1229        return prop;
1230    }
1231 
1232    protected EventProperty createEventProperty(String JavaDoc eventId,
1233                                                EventSetDescriptor eventDesc,
1234                                                Method JavaDoc eventMethod)
1235    {
1236        EventProperty prop = new EventProperty(new Event(this,
1237                                                         eventDesc,
1238                                                         eventMethod),
1239                                               eventId);
1240        nameToProperty.put(eventId, prop);
1241        return prop;
1242    }
1243
1244    /** Called to modify original bean properties obtained from BeanInfo.
1245     * Properties may be added, removed etc. - due to specific needs.
1246     */

1247    protected void changePropertiesExplicitly(List prefProps,
1248                                              List normalProps,
1249                                              List expertProps) {
1250         // hack for buttons - add fake property for ButtonGroup
1251
if (getBeanInstance() instanceof javax.swing.AbstractButton JavaDoc)
1252            try {
1253                RADProperty prop = new ButtonGroupProperty(this);
1254                setPropertyListener(prop);
1255// prop.addPropertyChangeListener(getPropertyListener());
1256
nameToProperty.put(prop.getName(), prop);
1257
1258                Object JavaDoc propCategory = FormUtils.getPropertyCategory(
1259                    prop.getPropertyDescriptor(),
1260                    FormUtils.getPropertiesCategoryClsf(
1261                        beanClass, getBeanInfo().getBeanDescriptor()));
1262
1263                if (propCategory == FormUtils.PROP_PREFERRED)
1264                    prefProps.add(prop);
1265                else normalProps.add(prop);
1266            }
1267            catch (IntrospectionException ex) {} // should not happen
1268
}
1269
1270    protected PropertyChangeListener createPropertyListener() {
1271        return new PropertyListenerConvertor();
1272    }
1273
1274    protected void setPropertyListener(FormProperty property) {
1275        if (propertyListener == null)
1276            propertyListener = createPropertyListener();
1277        if (propertyListener != null) {
1278            property.addPropertyChangeListener(propertyListener);
1279            if (propertyListener instanceof FormProperty.ValueConvertor)
1280                property.addValueConvertor((FormProperty.ValueConvertor)propertyListener);
1281        }
1282    }
1283// protected PropertyChangeListener getPropertyListener() {
1284
// if (propertyListener == null)
1285
// propertyListener = createPropertyListener();
1286
// return propertyListener;
1287
// }
1288

1289    /** Listener class for listening to changes in component's properties.
1290     */

1291    private class PropertyListenerConvertor implements PropertyChangeListener, FormProperty.ValueConvertor {
1292        public void propertyChange(PropertyChangeEvent evt) {
1293            Object JavaDoc source = evt.getSource();
1294            if (!(source instanceof FormProperty))
1295                return;
1296
1297            FormProperty property = (FormProperty) source;
1298            String JavaDoc propName = property.getName();
1299            String JavaDoc eventName = evt.getPropertyName();
1300
1301            if (FormProperty.PROP_VALUE.equals(eventName)
1302                || FormProperty.PROP_VALUE_AND_EDITOR.equals(eventName))
1303            { // property value has changed (or value and editor together)
1304
i18nPropertyChanged(evt);
1305
1306                Object JavaDoc oldValue = evt.getOldValue();
1307                Object JavaDoc newValue = evt.getNewValue();
1308                formModel.fireComponentPropertyChanged(
1309                              RADComponent.this, propName, oldValue, newValue);
1310
1311                if (getNodeReference() != null) { // propagate the change to node
1312
if (FormProperty.PROP_VALUE_AND_EDITOR.equals(eventName)) {
1313                        oldValue = ((FormProperty.ValueWithEditor)oldValue).getValue();
1314                        newValue = ((FormProperty.ValueWithEditor)newValue).getValue();
1315                    }
1316
1317                    getNodeReference().firePropertyChangeHelper(
1318// null, null, null);
1319
propName, oldValue, newValue);
1320                }
1321            }
1322            else if (FormProperty.CURRENT_EDITOR.equals(eventName)) {
1323                // property editor has changed - don't fire to FormModel,
1324
// only to component node
1325
if (getNodeReference() != null)
1326                    getNodeReference().firePropertyChangeHelper(
1327                                            propName, null, null);
1328            }
1329        }
1330
1331        public Object JavaDoc convert(Object JavaDoc value, FormProperty property) {
1332            return i18nPropertyConvert(value, property);
1333        }
1334    }
1335
1336    // -----
1337
// i18n automation
1338

1339    Object JavaDoc i18nPropertyConvert(Object JavaDoc value, FormProperty property) {
1340        if (isInModel() && formModel.isUndoRedoRecording()
1341                && property.getPropertyContext().getFormModel() != null) {
1342            Object JavaDoc val = FormProperty.getEnclosedValue(value);
1343            Object JavaDoc intVal = I18nSupport.internationalizeProperty(val, property, RADComponent.this);
1344            if (intVal != val)
1345                return intVal;
1346        }
1347        return value; // do nothing
1348
}
1349
1350    void i18nComponentRename(String JavaDoc newName) {
1351        if (isInModel()) {
1352            I18nSupport.componentRenamed(this, newName);
1353        }
1354    }
1355
1356    void i18nPropertyChanged(PropertyChangeEvent ev) {
1357        if (isInModel() && formModel.isFormLoaded()) {
1358            I18nSupport.updateStoredValue(
1359                    FormProperty.getEnclosedValue(ev.getOldValue()), // in case it is ValueWithEditor
1360
FormProperty.getEnclosedValue(ev.getNewValue()), // in case it is ValueWithEditor
1361
(FormProperty)ev.getSource(),
1362                    RADComponent.this);
1363        }
1364    }
1365
1366    // ----------
1367

1368    private static class PropertyIterator implements java.util.Iterator JavaDoc {
1369        private FormProperty[] properties;
1370        private FormProperty.Filter filter;
1371
1372        private FormProperty next;
1373        private int index;
1374
1375        PropertyIterator(FormProperty[] properties,
1376                         FormProperty.Filter filter)
1377        {
1378            this.properties = properties;
1379            this.filter = filter;
1380        }
1381
1382        public boolean hasNext() {
1383            if (next == null)
1384                next = getNextProperty();
1385            return next != null;
1386        }
1387
1388        public Object JavaDoc next() {
1389            if (next == null)
1390                next = getNextProperty();
1391            if (next != null) {
1392                Object JavaDoc prop = next;
1393                next = null;
1394                return prop;
1395            }
1396            throw new NoSuchElementException();
1397        }
1398
1399        public void remove() {
1400            throw new UnsupportedOperationException JavaDoc();
1401        }
1402
1403        private FormProperty getNextProperty() {
1404            while (index < properties.length) {
1405                FormProperty prop = properties[index++];
1406                if (filter.accept(prop))
1407                    return prop;
1408            }
1409            return null;
1410        }
1411    }
1412
1413    // ----------
1414
/*
1415    // Serialization of RADComponent was made for copy/pasting - JDK on
1416    // Mac OS X used to force the serialization for the transferable object
1417    // though it could just keep the instance (copied within one JVM) - as it
1418    // works normally on other OSes. Issue 12050.
1419
1420    Object writeReplace() {
1421        return new Replace(this);
1422    }
1423
1424    private static class Replace implements java.io.Serializable {
1425        private FormDataObject dobj;
1426        private String compId;
1427
1428        Replace(RADComponent comp) {
1429            // reference to RADComponent is stored; we expect the form
1430            // containing the component remains opened all the time
1431            dobj = FormEditorSupport.getFormDataObject(comp.getFormModel());
1432            compId = comp.getId();
1433        }
1434
1435        Object readResolve() { // throws java.io.ObjectStreamException
1436            FormModel[] forms = FormEditorSupport.getOpenedForms();
1437            for (int i=0; i < forms.length; i++) {
1438                FormModel form = forms[i];
1439                if (dobj.equals(FormEditorSupport.getFormDataObject(form)))
1440                    return form.getMetaComponent(compId);
1441            }
1442            return null; // or throw some exception?
1443        }
1444    }
1445*/

1446
1447    // -----------------------------------------------------------------------------
1448
// Debug methods
1449

1450    public java.lang.String JavaDoc toString() {
1451        return super.toString() + ", name: "+getName()+", class: "+getBeanClass()+", beaninfo: "+getBeanInfo() + ", instance: "+getBeanInstance(); // NOI18N
1452
}
1453
1454    public void debugChangedValues() {
1455    }
1456
1457    // ----------
1458
// a reference to a metacomponent - used instead of a metacomponent, may
1459
// become invalid when the component is removed
1460

1461    interface ComponentReference {
1462        RADComponent getComponent();
1463    }
1464
1465    // ------------------------------------
1466
// some hacks for ButtonGroup "component" ...
1467

1468    // pseudo-property for buttons - holds ButtonGroup in which button
1469
// is placed; kind of "reversed" property
1470
static class ButtonGroupProperty extends RADProperty {
1471        ButtonGroupProperty(RADComponent comp) throws IntrospectionException {
1472            super(comp,
1473                  new FakePropertyDescriptor("buttonGroup", // NOI18N
1474
javax.swing.ButtonGroup JavaDoc.class));
1475            setAccessType(DETACHED_READ | DETACHED_WRITE);
1476            setShortDescription(FormUtils.getBundleString("HINT_ButtonGroup")); // NOI18N
1477
}
1478
1479        public boolean supportsDefaultValue() {
1480            return true;
1481        }
1482
1483        public Object JavaDoc getDefaultValue() {
1484            return null;
1485        }
1486
1487        public PropertyEditor getExpliciteEditor() {
1488            return new ButtonGroupPropertyEditor();
1489        }
1490
1491        String JavaDoc getWholeSetterCode(String JavaDoc groupName) {
1492            return groupName != null ?
1493                groupName + ".add(" + getRADComponent().getName() + ");" : // NOI18N
1494
null;
1495        }
1496    }
1497
1498    // property editor for selecting ButtonGroup (for ButtonGroupProperty)
1499
public static class ButtonGroupPropertyEditor extends ComponentChooserEditor {
1500        public ButtonGroupPropertyEditor() {
1501            super();
1502            setBeanTypes(new Class JavaDoc[] { javax.swing.ButtonGroup JavaDoc.class });
1503            setComponentCategory(NONVISUAL_COMPONENTS);
1504        }
1505        
1506        public String JavaDoc getDisplayName() {
1507            return NbBundle.getBundle(getClass()).getString("CTL_ButtonGroupPropertyEditor_DisplayName"); // NOI18N
1508
}
1509    }
1510    
1511    public void setValid(boolean valid){
1512        this.valid = valid;
1513    }
1514    
1515    protected boolean isValid() {
1516        return valid;
1517    }
1518    
1519    private class FakeBeanInfo extends SimpleBeanInfo {
1520        
1521        private List propertyDescriptors = new ArrayList();
1522        
1523        public BeanDescriptor getBeanDescriptor() {
1524            return (beanInfo == this) ? null : beanInfo.getBeanDescriptor();
1525        }
1526
1527        public PropertyDescriptor[] getPropertyDescriptors() {
1528            return (PropertyDescriptor[]) propertyDescriptors.toArray(
1529                        new PropertyDescriptor[propertyDescriptors.size()]);
1530        }
1531
1532        public EventSetDescriptor[] getEventSetDescriptors() {
1533        return new EventSetDescriptor[0];
1534        }
1535
1536        void addPropertyDescriptor(String JavaDoc propertyName, Class JavaDoc propertyClass) {
1537            try {
1538                propertyDescriptors.add(new FakePropertyDescriptor(propertyName, propertyClass));
1539            } catch (IntrospectionException ex) {
1540                ex.printStackTrace(); // should not happen
1541
}
1542        }
1543                
1544        void addPropertyDescriptor(PropertyDescriptor pd) {
1545            propertyDescriptors.add(pd);
1546        }
1547        
1548        void removePropertyDescriptors() {
1549            propertyDescriptors.clear();
1550        }
1551    }
1552}
1553
Popular Tags