package gve.calc.formula;
/* MVC stuff.
* Controllers and Views always come in pairs. They can
* communicate directly to each other. They can also communicate
* directly with the model.
* A single model can be connected to a number of Controller/View pairs.
* The model is unaware of its controllers.
*/
import java.util.Hashtable;
import java.util.Vector;
public class MVC {
This class cannot be instantiated.
It is a repository of functions. |
private MVC() {}
/* Keys are models; values are (Vectors of) views */
private static Hashtable registrations = new Hashtable();
/* A view wants to be notified whenever a model changes.
* This is similar to having Listeners, but avoids the overhead
* of adding a "listeners" field in each model */
public static void registerView(Object model,View view) {
Object views = registrations.get(model);
if (views == null) {
// For efficiency, don't create a Vector
// when there's only a single listener
registrations.put(model,view);
} else if (views instanceof Vector) {
((Vector)views).addElement(view);
} else {
// there was one view registered
Vector v = new Vector(4);
v.addElement(views);
v.addElement(view);
registrations.put(model,v);
}
}
public static void unregisterView(Object model,View view) {
Object views = registrations.get(model);
if (views == null)
throw new Error("unregisterView: view was not registered");
else if (views instanceof Vector) {
Vector v = (Vector)views;
if (v.removeElement(view)) {
if (v.size() == 1) {
// only one registered view left
view = (View)v.elementAt(0);
v.setSize(0);
registrations.put(model,view);
}
} else
throw new Error("unregisterView: view was not registered");
} else {
if (views != view)
throw new Error("unregisterView: view was not registered");
// All views are unregistered now
registrations.remove(model);
}
}
public static View [] getViews(Object model) {
Object views = registrations.get(model);
if (views == null) return new View[0];
if (views instanceof Vector) {
Vector v = (Vector)views;
View [] result = new View[v.size()];
v.copyInto(result);
return result;
}
View [] result = new View[1];
result[0] = (View)views;
return result;
}
/* Model has changed. This function notifies
* all the dependent views of the change by calling their
* updateView() method. */
public static void changed(Object model) {
changed(model,null);
}
/* Same as above, but allow us to pass extra parameter. */
public static void changed(Object model,Object with) {
Object views = registrations.get(model);
if (views == null) return;
if (views instanceof Vector) {
Vector v = (Vector)views;
for (int count = v.size()-1; count>-0; count--) {
View view = (View)v.elementAt(count);
view.updateView(with);
}
return;
}
((View)views).updateView(with);
}
}