The JavaBeans standards were designed, in part, to facilitate the use of tools such as JBuilder. Regular naming and carefully designed method signatures allow JBuilder to examine component code and identify component features. This capability of examining a bean and extracting information about it automatically is called introspection.
What if you don't want to use the JavaBeans design and naming conventions or you have existing classes that don't use them? Or what if you don't want to give the user of your bean access to every property at design time? To handle these situations, create a class that implements the BeanInfo interface.
By creating a class that implements BeanInfo, you provide explicit information about your JavaBeans component. Creating a BeanInfo class for your component is optional; it is necessary only when you want to provide explicit information about a bean to JBuilder, and not have JBuilder derive the information it needs through automatic introspection.
This chapter covers these topics about using the BeanInfo interface:
If your component does not conform to the design and naming standards, you can create a BeanInfo class to deliver information about it to JBuilder and other tools. With every feature, JBuilder looks first for an information class that implements BeanInfo. If it doesn't find it, JBuilder uses direct examination of the component's code to find conforming properties, methods, and events. Because of this strict order of examination, you can use the BeanInfo classes in two ways:
public class MyComponentBeanInfo implements java.beans.BeanInfo
static final class beanClass=borland.samples.comptest.MyComponent.class; public BeanDescriptor getBeanDescriptor() { try{ return new BeanDescriptor(beanClass); //no customizer for this bean } catch(IntrospectionException ie){ return null; } }In the code above, the BeanDescriptor object's constructor takes an argument that sets its beanClass property to the name of the component being explained (MyComponent). Optionally, it could also take an argument to set the customizerClass property to the name of the component's special editor (if any).
static final String[] eventSetNames = {"content"}; static final String[] eventListeners = {"borland.samples.comptest.ContentListener"}; static final String[] eventListenerMethods = {"contentChanging","contentChanged"}; public EventSetDescriptor[] getEventSetDescriptors() { try{ EventSetDescriptor[] esds = new EventSetDescriptor[eventSetNames.length]; for (int i=0; i<esds.length; i++) esds[i] = new EventSetDescriptor(beanClass, eventSetNames[i], eventListeners[i], eventListenerMethods[i], "addContentListener", "removeContentListener"); return esds; } catch(IntrospectionException ie) { } return null; }eventSetNames is an array of all event sets generated by MyComponent. eventListeners is an array of all listener interfaces, and eventListenerMethods is an array of all event registration methods used by event sets that MyComponent generates.
static final String[] propNames = {"quantity", "name", "tags", "background"}; static final String[] readers = {"getQ", "getName", "getTagArray", "getBKColor"}; static final String[] writers = {"setQ", "setName", "setTagArray", "setBKColor"}; static final String[] propTypes = {"int", "java.lang.String", "java.lang.String[]", "java.awt.Color"}; public PropertyDescriptor[] getPropertyDescriptors() { try{ PropertyDescriptor[] pds = new PropertyDescriptor[proNames.length]; for (int i=0; i<pds.length; i++) pds[i] = new PropertyDescriptor(propNames[i]; beanClass, readers[i]; writers[i]); return pds; } catch(IntrospectionException ie){ } return null; }eventSetNames holds all the names of all event sets MyComponent generates, eventListeners contains the names of all listener interfaces, and eventListenerMethods contains the names of the event registration methods used by event sets MyComponent generates.
static final String[] methodNames = {"process", "reinitialize"}: static final String[][] methodParams = { {}, {"java.lang.String", "java.lang.String"}; public MethodDescriptor[] getMethodDescriptors() { try{ MethodDescriptor[] mds = new MethodDescriptor[methodNames.length]; for (int i=0; i<mds.length; i++) { Class[] params = new Class[methodParams[i].length]; for (int j=0; j<params.length; j++) params[j] = Class.forName(methodParams[i][j]); java.lang.reflect.Method m = beanClass.getMethod(methodNames[i], params); mds[i] = new MethodDescriptor(m); } return mds; } catch(IntrospectionException ie) { } catch(ClassNotFoundException cnfe){ } catch(NoSuchMethodException nsme) { } return null; }methodNames contains the names of all of MyComponent's methods, and methodParams contains all the parameters of the methods. Note that process() takes no parameters.
SimpleBeanInfo implements the BeanInfo interface, but all of the interface methods return null. As a result, JBuilder looks at the code to find that information directly.
Create an information class by extending SimpleBeanInfo and naming the class by appending "BeanInfo" to your component class name. Then, for any feature that does not comply with the JavaBeans design and naming specifications, override the interface method and provide your own descriptor objects. For example, if MyComponent has properties and events that comply with the specification but its methods are noncompliant, simply override the getMethodDescriptors() method and provide a MethodDescriptor object to explain the bean's methods.
You can also use the BasicBeanInfo class to provide partial information about your bean.
// Basic Info // BeanInfo implementation
The code contains several comments.
For example, if your bean doesn't use a customizer, remove the customizerClass declaration and the accompanying code comments.
For example, if you want to describe the properties in your bean, define the propertyDescriptors array. BasicBeanInfo includes source code comments that outlines the syntax you must use.
The one field you must define is the beanClass field.
Here is the BevelPanelBeanInfo class for the BevelPanel component that extends BasicBeanInfo:
package borland.jbcl.control; import borland.jbcl.util.BasicBeanInfo; public class BevelPanelBeanInfo extends BasicBeanInfo implements java.io.Serializable { public BevelPanelBeanInfo() { beanClass = BevelPanel.class; propertyDescriptors = new String[][] { {"background", Res.getString(Res.BI_background), "getBackground", "setBackground"}, {"bevelInner", Res.getString(Res.BI_BevelPanel_bevelInner), "getBevelInner", "setBevelInner", borland.jbcl.editors.BevelTypeEditor.class.getName()}, // int {"bevelOuter", Res.getString(Res.BI_BevelPanel_bevelOuter), "getBevelOuter", "setBevelOuter", borland.jbcl.editors.BevelTypeEditor.class.getName()}, // int {"doubleBuffered", Res.getString(Res.BI_doubleBuffered), "isDoubleBuffered", "setDoubleBuffered"}, {"enabled", Res.getString(Res.BI_enabled), "isEnabled", "setEnabled"}, {"font", Res.getString(Res.BI_font), "getFont", "setFont"}, {"foreground", Res.getString(Res.BI_foreground), "getForeground", "setForeground"}, {"layout", Res.getString(Res.BI_layout), "getLayout", "setLayout"}, {"margins", Res.getString(Res.BI_margins), "getMargins", "setMargins"}, {"opaque", Res.getString(Res.BI_opaque), "isOpaque", "setOpaque"}, {"soft", Res.getString(Res.BI_BevelPanel_soft), "isSoft", "setSoft"}, {"toolTipText", Res.getString(Res.BI_toolTipText), "getToolTipText", "setToolTipText"}, {"textureName", Res.getString(Res.BI_texture), "getTextureName", "setTextureName", borland.jbcl.editors.FileNameEditor.class.getName()}, {"visible", Res.getString(Res.BI_visible), "isVisible", "setVisible"}, }; } }BevelPanelBeanInfo defines the beanClass field and then creates a String array of property descriptors that describe each property that is accessible from the Component Inspector. Because no other fields are needed, all the other information has been deleted from the class.
There are two ways to hide a property or event so that it doesn't appear in JBuilder's Component Inspector and isn't available at design time to other visual tools. Which one you choose depends on whether the properties or events follow the JavaBeans design and naming conventions.
If all the properties or events follow the JavaBeans standard, follow these steps to hide a property or event:
For events, implement the getEventDescriptions() method, including code to instantiate an array of EventDescription objects containing information on each event you want to be available at design time. Omit those events you want to hide.
If some of the properties or events don't follow the JavaBeans standard, follow these steps to hide a property or event:
For events, implement the getEventDescriptions() method, including code to instantiate an array of EventDescription objects containing information on each event.
// Hide the model property modelProperty.setHidden(true)
propertyDescriptors = new String[][] { {"background", Res.getString(Res.BI_background), "getBackground", "setBackground"}, {"bevelInner", Res.getString(Res.BI_BevelPanel_bevelInner), "getBevelInner", "setBevelInner", borland.jbcl.editors.BevelTypeEditor.class.getName()}, // int {"bevelOuter", Res.getString(Res.BI_BevelPanel_bevelOuter), "getBevelOuter", "setBevelOuter", borland.jbcl.editors.BevelTypeEditor.class.getName()}, // int {"doubleBuffered", Res.getString(Res.BI_doubleBuffered), "isDoubleBuffered", "setDoubleBuffered"}, {"enabled", Res.getString(Res.BI_enabled), "isEnabled", "setEnabled"}, {"font", Res.getString(Res.BI_font), "getFont", "setFont"}, {"foreground", Res.getString(Res.BI_foreground), "getForeground", "setForeground"}, {"layout", Res.getString(Res.BI_layout), "getLayout", "setLayout"}, {"margins", Res.getString(Res.BI_margins), "getMargins", "setMargins"}, {"opaque", Res.getString(Res.BI_opaque), "isOpaque", "setOpaque"}, {"soft", Res.getString(Res.BI_BevelPanel_soft), "isSoft", "setSoft"}, {"toolTipText", Res.getString(Res.BI_toolTipText), "getToolTipText", "setToolTipText"}, {"textureName", Res.getString(Res.BI_texture), "getTextureName", "setTextureName", borland.jbcl.editors.FileNameEditor.class.getName()}, {"visible", Res.getString(Res.BI_visible), "isVisible", "setVisible"}, };Note how BevelTypeEditor is the fourth parameter for the bevelInner and bevelOuter property descriptors. Follow this same pattern and specify your property editor class as the fourth parameter for the property descriptor of your property. If your property doesn't have a property editor, you can omit the fourth parameter or specify it as "null".
protected int defaultEventIndex = <index>;Specify the position of the default event in the set of events described in the getEventDescriptors() method as the value of <index>. To indicate that no event is to be the default, specify a defaultEventIndex value of -1.
Although you can also specify a default property for your bean, default properties have no meaning in the JBuilder environment.
To create a BeanInfo class for your bean,
JBuilder creates a BeanInfo class for your bean and displays it in the Component Tree. To see the code JBuilder generated for you, click the Source tab.
You can add any modifications you'd like to make directly in the source code, or you can make your changes using BeansExpress and regenerate the file again. After asking you if you want to replace the existing file, JBuilder regenerates the BeanInfo class.
For complete information about using BeansExpress including generating BeanInfo classes, see Creating JavaBeans with BeansExpress.