15.7 Defining a Complex Property Editor
There
is another YesNoPanel property value that requires
a property editor. The messageText property of
YesNoPanel can specify a multiline message to be
displayed in the panel. This property requires a property editor
because simple beanbox programs like ShowBean
don't distinguish between single-line and multiline
string types; the JTextField object it uses for
text input doesn't allow the user to enter multiple
lines of text. For this reason, we define the
YesNoPanelMessageEditor class and register it with
the PropertyDescriptor for the message property,
as shown in Example 15-6.Example 15-8 shows the
definition of this property editor. This is a more complex editor
that supports the creation of a custom editor component and graphical
display of the value. Note that this example implements
PropertyEditor directly, which means that it must
handle registration and notification of
PropertyChangeListener objects.
getCustomEditor( ) returns an editor component for
multiline strings. Figure 15-1 shows this custom
editor within a dialog box created by the ShowBean
program. Note that the Ok button in
this figure is part of the ShowBean dialog, not
part of the property editor itself.The
paintValue( ) method displays the value of the
messageText property. This multiline value
doesn't typically fit in the small rectangle of
screen space allowed for the property, so paintValue(
) displays instructions for popping up the custom editor,
which allows the user to inspect and edit the property value.
ShowBean does not use the paintValue(
) method, however.
Example 15-8. YesNoPanelMessageEditor.java
package je3.beans;
import java.beans.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
/**
* This class is a custom editor for the messageText property of the
* YesNoPanel bean. It is necessary because the default editor for
* properties of type String does not allow multi-line strings
* to be entered.
*/
public class YesNoPanelMessageEditor implements PropertyEditor {
protected String value; // The value we will be editing.
public void setValue(Object o) { value = (String) o; }
public Object getValue( ) { return value; }
public void setAsText(String s) { value = s; }
public String getAsText( ) { return value; }
public String[ ] getTags( ) { return null; } // not enumerated;
no tags
// Say that we allow custom editing.
public boolean supportsCustomEditor( ) { return true; }
// Return the custom editor.
This just creates and returns a TextArea
// wrapped in a JScrollPane to edit the multi-line text.
// But it also registers a listener on the text
area to update the value
// as the user types and to fire the property
change events that property
// editors are required to fire.
public Component getCustomEditor( ) {
final JTextArea t = new JTextArea(value, 5, 30); // 5 rows, 30 cols
t.getDocument( ).addDocumentListener(new DocumentListener( ) {
public void insertUpdate(DocumentEvent e) { update( ); }
public void changedUpdate(DocumentEvent e) { update( ); }
public void removeUpdate(DocumentEvent e) { update( ); }
public void update( ) {
value = t.getText( );
listeners.firePropertyChange(null, null, null);
}
});
return new JScrollPane(t);
}
// Visual display of the value, for use with the custom editor.
// Just print some instructions and hope they fit in the box.
// This could be more sophisticated.
public boolean isPaintable( ) { return true; }
public void paintValue(Graphics g, Rectangle r) {
g.setClip(r);
g.drawString("Click to edit...", r.x+5, r.y+15);
}
// Important method for code generators. Note that it really ought to
// escape any quotes or backslashes in value before returning the string.
public String getJavaInitializationString( )
{ return "\" + value + "\"; }
// This code uses the PropertyChangeSupport class to maintain a list of
// listeners interested in the edits we make to the value.
protected PropertyChangeSupport listeners =
new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener l) {
listeners.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
listeners.removePropertyChangeListener(l);
}
}