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? Suppose 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. The result of this is that 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
package borland.jbcl.control; import borland.jbcl.util.BasicBeanInfo; public class BevelPanelBeanInfo extends BasicBeanInfo { public BevelPanelBeanInfo() { // Basic Info : Class beanClass beanClass = BevelPanel.class; // Basic Info : Class customizerClass //customizerClass (NONE) // Event Info : boolean introspectEvents introspectEvents = true; // Event Info : String[][4] eventSetDescriptors // EventSet, ListenerClass, AddMethod, RemoveMethod //eventSetDescriptors (INTROSPECTED) // Event Info : String[][] eventListenerMethods //eventListenerMethods (INTROSPECTED) // Event Info : int defaultEventIndex //defaultEventIndex (NONE) // Property Info : boolean introspectProperties //introspectProperties (WE WILL SPECIFY) // Property Info : String[][5] propertyDescriptors // Name, ShortDescription, ReadMethod, WriteMethod, Editor (optional) propertyDescriptors = new String[][] { {"background", Res.getString(Res.BI_background), "getBackground", "setBackground"}, {"bevelInner", Res.getString(Res.BI_BevelPanel_bevelInner), "getBevelInner", "setBevelInner", "borland.jbcl.editors.BevelTypeEditor"}, // int {"bevelOuter", Res.getString(Res.BI_BevelPanel_bevelOuter), "getBevelOuter", "setBevelOuter", "borland.jbcl.editors.BevelTypeEditor"}, // int {"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"}, {"soft", Res.getString(Res.BI_BevelPanel_soft), "isSoft", "setSoft"}, {"visible", Res.getString(Res.BI_visible), "isVisible", "setVisible"}, }; // Property Info : int defaultPropertyIndex //defaultPropertyIndex (NONE) // Method Info : boolean introspectMethods introspectMethods = true; // Method Info : String[] methodNames //methodNames (INTROSPECTED) // Method Info : String[][] methodParameters //methodParameters (INTROSPECTED) // Icon Info : Image iconColor16x16 //iconColor16x16 (NONE) // Icon Info : Image iconColor32x32 //iconColor32x32 (NONE) // Icon Info : Image iconMono16x16 //iconMono16x16 (NONE) // Icon Info : Image iconMono32x32 //iconMono32x32 (NONE) // Additional Info : BeanInfo[] additionalBeanInfo //additionalBeanInfo (NONE) } }You might notice that BevelPanelBeanInfo marks as comments code elements that BevelPanel doesn't need, while BasicBeanInfo specifies null or true or false for many values. Either method of specifying explicit information that isn't provided is acceptable.
Frequently you'll find that there are some properties you don't want to give the user of your bean access to at design time. It's possible this may be the case for some events also, although that is unusual. Use a class that implements BeanInfo to "hide" properties and events.
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 or not.
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.
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)
// Property Info : String[][4] propertyDescriptors // Name, ReadMethod, WriteMethod, Editor (optional) propertyDescriptors = new String[][] { {"background", "getBackground", "setBackground"}, {"bevelInner", "getBevelInner", "setBevelInner", "borland.jbcl.editors.BevelTypeEditor"}, // int {"bevelOuter", "getBevelOuter", "setBevelOuter", "borland.jbcl.editors.BevelTypeEditor"}, // int {"enabled", "isEnabled", "setEnabled"}, {"font", "getFont", "setFont"}, {"foreground", "getForeground", "setForeground"}, {"layout", "getLayout", "setLayout"}, {"margins", "getMargins", "setMargins"}, {"soft", "isSoft", "setSoft"}, {"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.
protected Image iconColor16x16 = null; protected Image iconColor32x32 = null; protected Image iconMono16x16 = null protected Image iconMono32x32 = null;Replace the appropriate null with the name of the icon you want to use for your component. For example,
protected Image iconColor32x32 = "snazzyComp.gif";You can also use the Palette Properties dialog box to to specify an image for your component.