Showing posts with label WritableValue. Show all posts
Showing posts with label WritableValue. Show all posts

Wednesday, January 10, 2007

Master Detail - Distilling the Pattern

Yesterday I went over master detail in the context of list selection. In the list selection post there were 3 steps that were required to setup the list selection master detail. But the guts of master detail were really just the first two, the third was to setup the viewing of the detail.

  1. Observe changes of the viewer's selection.

  2. Observe the name property of the selection.

  3. Bind the text of the Text widget to the name detail (selected person's name).


In the 2 steps we're concerned with we have 3 players:

  1. viewer - maintains a reference to the selection and provides change events when it changes

  2. selection (person)- maintains a reference to the name and provides change events when it changes

  3. name - value to display


If using dot notation we'd be able to access the value of the detail with something like the following (assuming the selection is not null)...
viewer.selection.name

If we genericize the roles a bit we get...
container.master.detail

The Pattern


The master detail APIs will satisfy your use case if...

  1. you need to observe container.master.detail

  2. AND the master instance can be replaced over time



Non Selection Use Case


A use case that arose recently on the newsgroup was how to setup the binding to a Person model that can be replaced over time. This was in the context of implementing presentation model. The following code was being used as the presentation model.
class ViewModel {
private Person person;

public void getPerson() {
return person;
}

public void setPerson(Person person) {
this.person = person;
}
}

Over time a new person would be set and the UI had to update. Expressed in dot notation this was viewModel.person.name. The only change that needed to occur to the code was that ViewModel needed to fire change events for Person and then the binding was wired up like normal.

class ViewModel {
private Person person;
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);

public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
changeSupport.addPropertyChangeListener(propertyName, listener);
}

public Person getPerson() {
return person;
}

public void setPerson(Person person) {
changeSupport.firePropertyChange("person", this.person, this.person = person);
}
}

// Create an observable to observe changes in the view model
IObservableValue personValue = BeansObservables.observeValue(
viewModel, "person");

//Bind to the name detail of the current person
dbc.bindValue(SWTObservables.observeText(form.getTextName(),
SWT.Modify), BeansObservables.observeDetailValue(Realm
.getDefault(), personValue, "name",
String.class), null);


WritableValue, for those looking for a shortcut


If you're in a position where it doesn't matter if your model is a java bean, look into one of my favorite classes WritableValue. Your code then becomes...

class ViewModel {
/**
* observable value to maintain the person instance
*/
private IObservableValue personObservable = new WritableValue(Person.class);

public IObservableValue getPersonObservable() {
return personObservable;
}
}

//Observe the detail.
IObservableValue detailObservable = BeansObservables
.observeDetailValue(Realm.getDefault(), viewModel.getPersonObservable(), "name",
String.class);

Code to set the person would be...

viewModel.getPersonObservable().setValue(person);