[ Team LiB ] Previous Section Next Section

15.8 Defining a Bean Customizer

A bean may want to provide some way for the user of a beanbox program to customize its properties other than by setting them one at a time. A bean can do this by creating a Customizer class for itself and registering the customizer class with the BeanDescriptor object returned by its BeanInfo class, as in Example 15-6.

A customizer must be some kind of GUI component that is suitable for display in a dialog box created by the beanbox. In addition, a customizer must implement the Customizer interface. This interface consists of methods for adding and removing property change event listeners and a setObject( ) method that the beanbox calls to tell the customizer what bean object it is customizing. Whenever the user makes a change to the bean through the customizer, the customizer sends a PropertyChangeEvent to any interested listeners. Finally, like a property editor, a customizer must have a no-argument constructor, so it can easily be instantiated by a beanbox.

Example 15-9 shows a customizer for our YesNoPanel bean. This customizer displays a panel that has the same layout as a YesNoPanel, but it substitutes a TextArea object for the message display and three TextField objects for the three buttons that the dialog can display. These text entry areas allow the user to enter values for the messageText, yesLabel, noLabel, and cancelLabel properties. Figure 15-2 shows this customizer panel displayed within a dialog box created by a beanbox program. Again, note that the Done button is part of the beanbox dialog, not part of the customizer itself. ShowBean does not support the use of customizers, so this example cannot be demonstrated with that program.

Figure 15-2. The customizer dialog for the YesNoPanel bean
Example 15-9. YesNoPanelCustomizer.java
package je3.beans;
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.beans.*;

 * This class is a customizer for the YesNoPanel bean.  It displays a
 * JTextArea and three JTextFields where the user can enter the main message
 * and the labels for each of the three buttons.  It does not allow the
 * alignment property to be set.
public class YesNoPanelCustomizer extends JComponent
    implements Customizer, DocumentListener
    protected YesNoPanel bean;     // The bean being customized
    protected JTextArea message;   // For entering the message    
    protected JTextField fields[  ]; // For entering button text

    // The bean box calls this method to tell us what object to customize.
    // This method will always be called before the customizer is displayed,
    // so it is safe to create the customizer GUI here.
    public void setObject(Object o) {
        bean = (YesNoPanel)o;   // save the object we're customizing
        // Put a label at the top of the panel.
        this.setLayout(new BorderLayout( ));
        this.add(new JLabel("Enter the message to appear in the panel:"),
        // And a big text area below it for entering the message.
        message = new JTextArea(bean.getMessageText( ), 5, 35);
        message.getDocument( ).addDocumentListener(this);
        this.add(new JScrollPane(message), "Center");
        // Then add a row of textfields for entering the button labels.
        JPanel buttonbox = new JPanel( );                   // The row container
        buttonbox.setLayout(new GridLayout(1, 0, 25, 10)); // Equally spaced
        this.add(buttonbox, BorderLayout.SOUTH);           // Put row on bottom
        // Now go create three JTextFields to put in this row.  But actually
        // position a JLabel above each, so create a container for each
        // JTextField+JLabel combination.
        fields = new JTextField[3];               // Array of TextFields.
        String[  ] labels = new String[  ] {          // Labels for each.
            "Yes Button Label", "No Button Label", "Cancel Button Label"};
        String[  ] values = new String[  ] {          // Initial values of each.
            bean.getYesLabel( ), bean.getNoLabel( ), bean.getCancelLabel( )};
        for(int i = 0; i < 3; i++) {
            JPanel p = new JPanel( );               // Create a container.
            p.setLayout(new BorderLayout( ));       // Give it a BorderLayout.
            p.add(new JLabel(labels[i]), "North"); // Put a label on the top.
            fields[i] = new JTextField(values[i]); // Create the text field.
            p.add(fields[i], "Center");            // Put it below the label.
            buttonbox.add(p);                      // Add container to row.
            // register listener for the JTextField
            fields[i].getDocument( ).addDocumentListener(this);

    // Give ourselves some space around the outside of the panel.
    public Insets getInsets( ) { return new Insets(10, 10, 10, 10); }
    // These are the methods defined by the DocumentListener interface. Whenever 
    // the user types a character in the JTextArea or JTextFields, they will be
    // called.  They all just call the internal method update( ) below.
    public void changedUpdate(DocumentEvent e) { update(e); }
    public void insertUpdate(DocumentEvent e) { update(e); }
    public void removeUpdate(DocumentEvent e) { update(e); }

    // Updates the appropriate property of the bean and fires a
    // property changed event, as all customizers are required to do.
    // Note that we are not required to fire an event for every keystroke.
    void update(DocumentEvent e) {
        Document doc = e.getDocument( );     // What document was updated?
        if (doc == message.getDocument( ))   
            bean.setMessageText(message.getText( ));
        else if (doc == fields[0].getDocument( ))
            bean.setYesLabel(fields[0].getText( ));
        else if (doc == fields[1].getDocument( ))
            bean.setNoLabel(fields[1].getText( ));
        else if (doc == fields[2].getDocument( ))
            bean.setCancelLabel(fields[2].getText( ));
        listeners.firePropertyChange(null, null, null);

    // This code uses the PropertyChangeSupport class to maintain a list of
    // listeners interested in the edits we make to the bean.
    protected PropertyChangeSupport listeners =new PropertyChangeSupport(this);
    public void addPropertyChangeListener(PropertyChangeListener l) {
    public void removePropertyChangeListener(PropertyChangeListener l) {
    [ Team LiB ] Previous Section Next Section