Just looked into this for myself today. Yes, it is possible...damn Spring Rich rocks. For my test I created a form object with a map, to make it quick and easy I just overrode Rectangle.
Code:
public class MyRect extends Rectangle {
private Map<String, Color> colors;
public Map<String, Color> getColors() {
return colors;
}
public void setColors(Map<String, Color> colors) {
this.colors = colors;
}
public MyRect() {
super(0, 0, 50, 100);
colors = new HashMap<String, Color>();
colors.put("red", Color.RED);
colors.put("blue", Color.BLUE);
colors.put("cyan", Color.CYAN);
}
}
I then created a view to display my test form. To create the form model I just called FormModelHelper.createFormModel(r). The other methods seem to work as well. In my form's #createFormControl() method I bound my map to the controls like this.
Code:
@Override
protected JComponent createFormControl() {
SwingBindingFactory bf = (SwingBindingFactory)getBindingFactory();
FormLayout layout = new FormLayout("pref, $lcgap, pref",
"pref, $pgap, default:grow");
MyFormBuilder builder = new MyFormBuilder(bf, layout);
builder.setLabelAttributes(FormLayoutFormBuilder.ALIGN_RIGHT_CENTER);
builder.addTextAreaAndLabel("colors[red]", 1, 1);
builder.nextRow();
builder.addComponent(createButtonBar());
return builder.getPanel();
}
Of course for this example to work I needed to create a pair of converters to convert ColorToString and StringToColor.
Code:
public class ColorToString extends AbstractFormattingConverter {
private final boolean allowEmpty;
/**
* Creates a new instance of <code>ColorToString</code>.
*/
public ColorToString() {
this(new SimpleFormatterFactory(), true);
}
/**
* Creates a new instance of <code>ColorToString</code>.
*/
public ColorToString(FormatterFactory formatterFactory, boolean allowEmpty) {
super(formatterFactory);
this.allowEmpty = allowEmpty;
}
@Override
protected Object doConvert(Object source, Class type, ConversionContext cc) throws Exception {
Color color = (Color)source;
return (!allowEmpty || source != null)
? color.getRed() + "," + color.getGreen() + "," + color.getBlue() : null;
}
@Override
public Class[] getSourceClasses() {
return new Class[] {Color.class};
}
@Override
public Class[] getTargetClasses() {
return new Class[] {String.class};
}
}
public class StringToColor extends AbstractFormattingConverter {
private final boolean allowEmpty;
/**
* Creates a new instance of <code>StringToColor</code>.
*/
public StringToColor() {
this(new SimpleFormatterFactory(), true);
}
/**
* Creates a new instance of <code>StringToColor</code>.
*/
public StringToColor(FormatterFactory formatterFactory, boolean allowEmpty) {
super(formatterFactory);
this.allowEmpty = allowEmpty;
}
@Override
protected Color doConvert(Object source, Class type, ConversionContext cc) throws Exception {
String[] parts = ((String)source).split(",");
return (!allowEmpty || source != null) ? new Color(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2])) : null;
}
@Override
public Class[] getSourceClasses() {
return new Class[] {String.class};
}
@Override
public Class[] getTargetClasses() {
return new Class[] {Color.class};
}
}
and configure my conversion service to use the new converters in the application context.
Code:
<bean id="conversionService" class="org.springframework.richclient.application.DefaultConversionServiceFactoryBean" />
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" >
<property name="targetObject" ref="conversionService" />
<property name="targetMethod" value="addConverters" />
<property name="arguments">
<list>
<list>
<bean class="org.my.app.converter.ColorToString" />
<bean class="org.my.app.converter.StringToColor" />
</list>
</list>
</property>
</bean>
This should allow you to bind controls to a map, although I have not yet tested what happens if the property does not exist in the map.