[ Team LiB ] Previous Section Next Section

15.5 Specifying Bean Information

The YesNoPanel class itself, as well as the MultiLineLabel, Alignment, AnswerEvent, and AnswerListener classes it relies on, are all a required part of our bean. When an application that uses the bean is shipped, it has to include all five class files. There are other kinds of classes, however, that are often bundled with a bean but not intended for use by the application developer. These classes are used at "design time" by the beanbox tool that manipulates the bean. The bean class itself doesn't refer to any of these auxiliary beanbox classes, so it is not dependent on them, and they don't have to be shipped with the bean in finished products.

The first of these optional, auxiliary classes is a BeanInfo class. As explained earlier, a beanbox discovers the properties, events, and methods exported by a bean through introspection based on the Java Reflection API. A bean developer who wants to provide additional information about a bean, or refine the (somewhat rough) information available through introspection, should define a class that implements the BeanInfo interface to provide that information. The ShowBean class, for example, uses the short descriptions it obtained through a BeanInfo as tooltips in its Properties menu.

A BeanInfo class typically subclasses SimpleBeanInfo, which provides a no-op implementation of the BeanInfo interface. When you want to override only one or two methods, it is easier to subclass SimpleBeanInfo than to implement BeanInfo directly. Beanbox tools rely on a naming convention in order to find the BeanInfo class for a given bean: a BeanInfo class should have the same name as the bean, with the string "BeanInfo" appended. Example 15-6 shows an implementation of the YesNoPanelBeanInfo class.

This BeanInfo class specifies a number of pieces of information for our bean:

  • An icon that represents the bean.

  • A BeanDescriptor object, which includes a reference to a Customizer class for the bean. We'll see an implementation of this class later in the chapter.

  • A list of the supported properties of the bean, along with a short description of each one. Some beanbox tools (but not Sun's beanbox) display these strings to the user in some useful way.

  • A method that returns the most commonly customized property of the bean; this is called the "default" property.

  • A reference to a PropertyEditor class for one of the properties. We'll see the implementation of this property editor class later in the chapter.

Besides specifying this information, a BeanInfo class can also provide information about the methods it defines and the events it generates. The various FeatureDescriptor objects that provide information about such things as properties and methods can also include other information not provided by YesNoPanelBeanInfo, such as a localized display name that is distinct from the programmatic name.

If YesNoPanelBeanInfo is available in your classpath when you run ShowBean on the YesNoPanel bean, you'll see an icon displayed in the YesNoPanel tab, and you'll also see tooltips displayed over items in the Properties menu. ShowBean will also have access to the custom PropertyEditor for the messageText property. See Figure 15-1. (Similarly, if the lib/dt.jar file from your Java SDK is in your classpath or has been copied to the jre/lib/ext/ directory, you'll see icons and tooltips for Swing components. "dt" stands for "design time," and the dt.jar file contains bean info, icons, and other resources required at design time but not at runtime.)

Example 15-6. YesNoPanelBeanInfo.java
package je3.beans;
import java.beans.*;
import java.lang.reflect.*;
import java.awt.*;

/**
 * This BeanInfo class provides additional information about the YesNoPanel
 * bean in addition to what can be obtained through  introspection alone.
 **/
public class YesNoPanelBeanInfo extends SimpleBeanInfo {
    /**
     * Return an icon for the bean.  We should really check the kind argument
     * to see what size icon the beanbox wants, but since we only have one
     * icon to offer, we just return it and let the beanbox deal with it
     **/
    public Image getIcon(int kind) { return loadImage("YesNoPanelIcon.gif"); }
    
    /**
     * Return a descriptor for the bean itself.  It specifies a customizer
     * for the bean class.  We could also add a description string here
     **/
    public BeanDescriptor getBeanDescriptor( ) {
        return new BeanDescriptor(YesNoPanel.class,
                                  YesNoPanelCustomizer.class);
    }
    
    /** This is a convenience method for creating PropertyDescriptor objects */
    static PropertyDescriptor prop(String name, String description) {
        try {
            PropertyDescriptor p =
                new PropertyDescriptor(name, YesNoPanel.class);
            p.setShortDescription(description);
            return p;
        }
        catch(IntrospectionException e) { return null; } 
    }

    // Initialize a static array of PropertyDescriptor objects that provide
    // additional information about the properties supported by the bean.
    // By explicitly specifying property descriptors, we are able to provide
    // simple help strings for each property; these would not be available to
    // the beanbox through simple introspection.  We are also able to register
    // a special property editor for the messageText property
    static PropertyDescriptor[  ] props = {
        prop("messageText", "The message text that appears in the bean body"),
        prop("alignment", "The alignment of the message text"),
        prop("yesLabel", "The label for the Yes button"),
        prop("noLabel", "The label for the No button"),
        prop("cancelLabel","The label for the Cancel button"),
        prop("messageFont", "The font for the message"),
        prop("messageColor", "The color of the message text"),
        prop("buttonFont", "The font for the buttons"),
        prop("background", "The background color"),
    };
    static {
        props[0].setPropertyEditorClass(YesNoPanelMessageEditor.class);
    }
    
    /** Return the property descriptors for this bean */
    public PropertyDescriptor[  ] getPropertyDescriptors( ) { return props; }
    
    /** The message property is most often customized; make it the default */
    public int getDefaultPropertyIndex( ) { return 0; }
}
    [ Team LiB ] Previous Section Next Section