/*
* This software is Copyright 2005,2006,2007,2008 Langdale Consultants.
* Langdale Consultants can be contacted at: http://www.langdale.com.au
*/
package au.com.langdale.ui.plumbing;
/**
* Implements the heart of the form plumbing logic.
*
* Controller methods trigger Binding and Observer methods
* in a prescribed sequence that depends on the synchronous parameter.
*
* Loops are prevented for calls representing widget events.
*/
public class Controller implements ICanRefresh {
private Binding binding;
private Observer observer;
private boolean synchronous;
private int preventer = 0;
/**
* Construct with Binding and Observer delegates and the given widget
* synchronisation mode.
*/
public Controller(Binding binding, Observer observer, boolean synchronous) {
this.binding = binding;
this.observer = observer;
this.synchronous = synchronous;
}
/**
* Indicates that the underlying model (data) will be kept synchronised
* with the widgets by widget events. The value is set by the ctor parameter.
*
* If true update() is called after widget events. Otherwise update() must
* be explicitly called to transfer widget values to the underlying model.
*/
public boolean isSynchronous() {
return synchronous;
}
/**
* Trigger processing of a user action or entry.
*
* This method is normally hooked to widget events by the
* various widget templates.
*
* Unit tests might explicitly call this if widget events
* are not sufficient to monitor widget state.
*
* This triggers validate(). If synchronous mode,
* update() and refresh() are also triggered.
*/
public void fireWidgetEvent() {
if( preventer > 0)
return;
if(synchronous)
fireUpdate();
else
fireValidate();
}
/**
* The method should be called to initialise the widget values
* and again whenever the underlying data (the model) changes.
*
* This triggers refresh() and validate() while suppressing events that
* would trigger update().
*/
public void doRefresh() {
preventer++;
try {
binding.refresh();
}
finally {
preventer--;
}
fireValidate();
}
/**
* Initialise the widgets with default values.
* This triggers reset() and validate().
*
* If synchronous mode, update() and refresh() are also triggered.
*/
public void doReset() {
preventer++;
try {
binding.reset();
}
finally {
preventer--;
}
fireWidgetEvent();
}
/**
* Commit user entries from the widgets to the underlying data (the model).
* This triggers update(), refresh() and validate().
*/
public void fireUpdate() {
binding.update();
observer.markDirty();
doRefresh();
}
/**
* Trigger validation.
*/
public String fireValidate() {
String message = binding.validate();
if( message != null)
observer.markInvalid(message);
else
observer.markValid();
return message;
}
}