Shopping List Sync Application



Table of contents

Fine Granularity Updates to Interface

For most Sync applications, using Sync’s doRefresh method is sufficient for updating the user interface. The most basic implementation doRefresh would update the entire interface, regardless of changes to the model. In some cases, however, it is desirable to update only parts of the interface that correspond to changes in the model. The user interface accomplishes this through Java’s property change events fired by the basic Sync Model. In the following code snippets observe the propagation of the MyValueChange property event.

// PointListGui.java
PropertyChangeListener mcl = new PropertyChangeListener(){
public void propertyChange(PropertyChangeEvent event) {
// Update GUI as data changes
if (event.getPropertyName().equals("MyPutItem")){
// Update GUI
} else if (event.getPropertyName().equals("MyValueChange")){
// Update GUI
} else if (event.getPropertyName().equals("MyNameChange")){
// Update GUI
} else
System.out.println("Update from unknown element);

}
};

Following are instructions for one technique of implementing the user interface for tracking changes. The explanation uses code snippets to highlight aspects; see the source code for full details.

Although a Sync model uses Java property change events, they are not sufficient. The usual Sync related property change event, such as in the name property, does not identify which object the property belongs to. The default assumption is that it is a property of the basic Sync model, in this case the PointListModel class.

// ListItem.java
public int getValue() {
return internalValue;
}

public void setValue(int v){
internalValue = v;
propertyChange.firePropertyChange("Value", null, new Integer(internalValue));
}


However if an object stored in the model changes, it is not possible to determine which object changed; ListItems are examples of objects stored in a hash table in the model. Instead, we add an additional property change event that identifies the object.

// ListItem.java
public int getValue() {
return internalValue;
}

public void setValue(int v){
internalValue = v;
propertyChange.firePropertyChange("Value", null, new Integer(internalValue));
// Application specific, used to incrementally update the GUI
propertyChange.firePropertyChange("MyValueChange", null, this);
}


The basic Sync model has to be modified to trap these property change events. This is accomplished by adding a property change listener parameter, called mcl, as shown in the code snippet. The mcl must be transient because the parameter type is not serializable. Sync models require all data members to be serializable so that data can be transmitted between collaborators’ applications. As the mcl is transient, it has to be recreated at every Sync client.

// PointListModel
transient PropertyChangeListener mcl;

public void setupListeners() {
mcl = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
// Catch events from changes in ListItems and any other model
// data
// Pass on to the GUI or View that is listening
System.out.println("[Model property Change] "
+ event.getPropertyName());
propertyChange.firePropertyChange(event.getPropertyName(), // prperty name can be MyValueChange
 null, event.getNewValue());
}
};
}


The mcl has to be added as a listener to all objects stored in the Sync model to trap the change events. Each object can be accessed and appended when it is added to a hash table (or similarly for a vector if applicable) as in this snippet. The putKey event happens when an object is added to a hash table.

// PointListModel, part of HashtableListener interface
public void keyPut(Object arg0, Object arg1, int arg2) {
// Track elements added to hashtable
if( arg1 instanceof ListItem) {
((ListItem)arg1).addPropertyChangeListener(mcl);
}
// Notify gui of put
propertyChange.firePropertyChange("MyPutItem",null, arg1);
}



Dorian Miller Aug 27, 2006