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 MyValueChangeproperty
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.
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); }