h1. Value Container
Lets assume we have a Java class which holds some parameters we want to be able to edit later, e.g. in a GUI for some image analysis tool:
{code:java}
public static class ClusterAlgoParams {
int clusterCount;
double threshold;
// ...
}
{code}
This class shall serve as the data model in the [MVC architecture|http://en.wikipedia.org/wiki/Model-view-controller] of our GUI. Since our model is a [POJO|http://en.wikipedia.org/wiki/Plain_Old_Java_Object], it does not automatically have the ability to inform the controller (= the binding) if values change. The Ceres binding framework allows to "wrap" instances of such plain Java classes in a {{ValueContainer}}. A value container is basically a bucket of ({{name:String}}/{{value:Object}}) pairs associated with some meta data (represented by the {{ValueDescriptor}} class). A value containers also can fire the desired change event, if a a contained value changes.
{code:java}
ClusterAlgoParams params = new ClusterAlgoParams();
// ...
ValueContainer vc = ValueContainer.createObjectBacked(params);
{code}
Now that the parameters are wrapped by the value container, we can add meta data to each value in order to specify the units, a description, a {{Validator}}, a {{Converter}} or properties used to configure the bound GUI components:
{code:java}
ClusterAlgoParams params = new ClusterAlgoParams();
// ...
ValueDescriptor vd = vc.getValueDescriptor("clusterCount");
vd.setDisplayName("Number of clusters");
vd.setValueRange(new ValueRange(2, 256));
// ...
{code}
h1. Swing Binding
Once we have the configured value container (model), we can create the bindings (controllers) for the Java Swing GUI components (views):
{code:java}
JTextField textField;
JSpinner spinner;
// ...
BindingContext ctx = new BindingContext(vc);
ctx.bind("clusterCount", textField);
ctx.bind("threshold", spinner);
{code}
h1. Value Model
The values in the value container are represented by the {{ValueModel}} class. In the example above, all value models in the container are linked to the fields of the wrapped objects. Additionally, values can also be linked to entries in a {{[Map<String, Object>|http://java.sun.com/javase/6/docs/api/java/util/Map.html]}} or linked to nothing at all:
{code:java}
ValueContainer vc;
Map<String, Object> map;
// ...
vc.addModel(ValueModel.createMapEntryModel(map, "auxDataFile", File.class));
vc.addModel(ValueModel.createValueModel("debug", Boolean.TYPE));
//...
{code}
If neither a POJO nor a {{Map}} fits your needs, you can implement your own {{ValueAccessor}} and create a custom value model by using the {{ValueModel}} constructor directly:
{code:java}
ValueContainer vc;
Map<String, Object> map;
ValueDescriptor vd = new ValueDescriptor();
ValueAccessor va = new MyCustomValueAccessor(/*...*/);
// ...
vc.addModel(new ValueModel(vd, va));
//...
{code}
Lets assume we have a Java class which holds some parameters we want to be able to edit later, e.g. in a GUI for some image analysis tool:
{code:java}
public static class ClusterAlgoParams {
int clusterCount;
double threshold;
// ...
}
{code}
This class shall serve as the data model in the [MVC architecture|http://en.wikipedia.org/wiki/Model-view-controller] of our GUI. Since our model is a [POJO|http://en.wikipedia.org/wiki/Plain_Old_Java_Object], it does not automatically have the ability to inform the controller (= the binding) if values change. The Ceres binding framework allows to "wrap" instances of such plain Java classes in a {{ValueContainer}}. A value container is basically a bucket of ({{name:String}}/{{value:Object}}) pairs associated with some meta data (represented by the {{ValueDescriptor}} class). A value containers also can fire the desired change event, if a a contained value changes.
{code:java}
ClusterAlgoParams params = new ClusterAlgoParams();
// ...
ValueContainer vc = ValueContainer.createObjectBacked(params);
{code}
Now that the parameters are wrapped by the value container, we can add meta data to each value in order to specify the units, a description, a {{Validator}}, a {{Converter}} or properties used to configure the bound GUI components:
{code:java}
ClusterAlgoParams params = new ClusterAlgoParams();
// ...
ValueDescriptor vd = vc.getValueDescriptor("clusterCount");
vd.setDisplayName("Number of clusters");
vd.setValueRange(new ValueRange(2, 256));
// ...
{code}
h1. Swing Binding
Once we have the configured value container (model), we can create the bindings (controllers) for the Java Swing GUI components (views):
{code:java}
JTextField textField;
JSpinner spinner;
// ...
BindingContext ctx = new BindingContext(vc);
ctx.bind("clusterCount", textField);
ctx.bind("threshold", spinner);
{code}
h1. Value Model
The values in the value container are represented by the {{ValueModel}} class. In the example above, all value models in the container are linked to the fields of the wrapped objects. Additionally, values can also be linked to entries in a {{[Map<String, Object>|http://java.sun.com/javase/6/docs/api/java/util/Map.html]}} or linked to nothing at all:
{code:java}
ValueContainer vc;
Map<String, Object> map;
// ...
vc.addModel(ValueModel.createMapEntryModel(map, "auxDataFile", File.class));
vc.addModel(ValueModel.createValueModel("debug", Boolean.TYPE));
//...
{code}
If neither a POJO nor a {{Map}} fits your needs, you can implement your own {{ValueAccessor}} and create a custom value model by using the {{ValueModel}} constructor directly:
{code:java}
ValueContainer vc;
Map<String, Object> map;
ValueDescriptor vd = new ValueDescriptor();
ValueAccessor va = new MyCustomValueAccessor(/*...*/);
// ...
vc.addModel(new ValueModel(vd, va));
//...
{code}