-->

Beans - In Depth

< http://www.geocities.com/SiliconValley/Lakes/3767/b-indep.htm >
< dima@paragraph.com >

How to notify the property change to the bean from Property Editor

The simplest way to do this is to extend java.bean.PropertyEditorSupport. This class creates a list of propertyChangeListener-s for you and gives you a very handy "firePropertyChange()" member function to notify these listeners.

The main idea of property editor, which PropertyEditorSupport implements, is to store a copy of the property value internally, modify ONLY this copy and notify listeners about such changes. The copy of such property value is sent to property editor via "setValue(Object value)" member func.

Next, if you, for example, support "tagged" names - provide "String[] getTags()" member func. to enumerate all possible values of the property. In this case outside code will use "String getAsText()" to find out the current property value and "String setAsText()" to set new property value. For these functions you have to provide code to convert from text representation of your property value to its actual type and vice versa (like enumeration string tags in C++ to int's :) Now the main point - to let BeanBox know that property has actually changed don't forget to call "firePropertyChange()" in "String setAsText()" method !

In short : property editor is not supposed to modify bean property directly, instead editor maintains internal copy of this property state and notifies listeners about all property changes. BeanBox is an example of such listener. When BeanBox gets notification of the property change from the editor, it first requests new property value calling editor getValue() method and then uses bean "setter" method to set new bean property value.

Speaking about property "setter/getter" methods, an interesting fact is that using PropertyDescriptor constructor with explicit "setter/getter" method names as a parameter, you can bypass the standard JavaBeans convention on patterns for accessor methods. This allows to give property a name that editor will display which is different from the actual property name and patterns that this property "setter/getter" methods use.

How Customizer and Property Editor classes interoperate with BeanBox

To change some bean property, bean Customizer class can use reference to this bean instance that BeanBox passes to Customizer constructor. On the other hand, your bean Property Editor class can't change property directly - instead editor maintains internal copy of this property state and notifies listeners about all property changes.

Nevertheless, to make everything work correctly, your Customizer class, MUST notify property change listeners anyway, like in example below :

public class MyValveCustomizer extends Panel implements Customizer {
...
  public boolean handleEvent(Event evt) {

    if (evt.target instanceof Checkbox) {
      Checkbox checked = cbg.getCurrent();
      dbgOut(checked.getLabel());
        
      if( (checked.getLabel()).equals("on") ) {
        target_.setOpen(true);
      } else {
        target_.setOpen(false);
      }
      // notify listeners !!!
      support.firePropertyChange("", null, null);
    }
    return (super.handleEvent(evt));
  }
...
}

This technique insures that all "visual" property updates occur simultaneously in Customizer and Property Sheet windows opened in BeanBox at the same time. More detailed explanation of this follows :

When loading a bean, BeanBox finds out the name of this bean Property Editor class. If it finds one, BeanBox creates instance of its internal EditedAdaptor class passing a reference to PropertySheet - another internal BeanBox class - to EditedAdaptor constructor. EditedAdaptor implements PropertyChangeListener interface.

Next BeanBox registers newly created instance of EditedAdaptor class as a listener of the PropertyChange event in your bean Property Editor class. The same way BeanBox deals with your bean Customizer class, creating a fresh EditedAdaptor instance for it and registers this adaptor class as a listener of the PropertyChange event in your Customizer class.

Thus, when your Property Editor or Customizer reports some property update to registered listeners with PropertyChangeSupport.firePropertyChange(String propertyName, Object oldValue, Object newValue) method, all BeanBox EditedAdaptor class instances receive these updates in propertyChange(PropertyChangeEvent evt) method that BeanBox calls.

Having reference to BeanBox PropertySheet object, EditedAdaptor notifies it about bean property updates passing PropertyChangeEvent event to it. If bean property change was performed by bean Property Editor, PropertySheet will use your bean "setter" methods to set new property value in your bean.

Next PropertySheet ALWAYS re-reads ALL bean properties and updates the editors for any other properties that have changed, calling your PropertyEditor.setValue(Object value). This insures that your bean Property Editor always "senses" property modifications performed by bean Customizer and these changes are always visible in Property Sheet window.

Back to Beans Unlimited 1