001 package org.springframework.richclient.form.binding.swing;
002
003 import java.awt.event.ActionEvent;
004 import java.awt.event.ActionListener;
005 import java.util.ArrayList;
006 import java.util.LinkedHashMap;
007 import java.util.List;
008 import java.util.Map;
009
010 import javax.swing.ButtonGroup;
011 import javax.swing.JComponent;
012 import javax.swing.JPanel;
013 import javax.swing.JRadioButton;
014
015 import org.springframework.binding.form.FormModel;
016 import org.springframework.context.support.MessageSourceAccessor;
017 import org.springframework.richclient.form.binding.support.CustomBinding;
018 import org.springframework.util.Assert;
019
020 import com.jgoodies.forms.factories.FormFactory;
021 import com.jgoodies.forms.layout.CellConstraints;
022 import com.jgoodies.forms.layout.ColumnSpec;
023 import com.jgoodies.forms.layout.FormLayout;
024 import com.jgoodies.forms.layout.RowSpec;
025
026 /**
027 * Radiobutton binding for Enum values.
028 *
029 * Labels for the radio buttons can be configured in the messages:
030 *
031 * <pre>
032 * my.package.MyClass.MY_ENUM = My Enum Label
033 * my.package.MyClass.null = None
034 * </pre>
035 *
036 * @author Lieven Doclo
037 *
038 */
039 public class EnumRadioButtonBinding extends CustomBinding {
040
041 private JPanel contentPanel;
042
043 private List<Enum> selectableEnumsList;
044
045 private Map<String, ContainerJRadioButton<Enum>> radioButtons;
046
047 private Class propertyType;
048
049 private ButtonGroup group;
050
051 private MessageSourceAccessor messageSourceAccessor;
052
053 public EnumRadioButtonBinding(JPanel contentPanel, FormModel formModel, String formPropertyPath,
054 Class<?> propertyType, List<Enum> selectableEnumsList) {
055 super(formModel, formPropertyPath, propertyType);
056 this.contentPanel = contentPanel;
057 this.propertyType = propertyType;
058 radioButtons = new LinkedHashMap<String, ContainerJRadioButton<Enum>>();
059 messageSourceAccessor = getMessages();
060 this.selectableEnumsList = selectableEnumsList;
061 createRadioButtons();
062 }
063
064 @Override
065 protected void valueModelChanged(Object newValue) {
066 deselectAll();
067 Enum enumValue = (Enum) newValue;
068 ContainerJRadioButton<Enum> button;
069 if (enumValue == null) {
070 button = radioButtons.get(null);
071 }
072 else {
073 button = radioButtons.get(enumValue.name());
074 }
075 if (button != null) {
076 button.setSelected(true);
077 }
078 }
079
080 private void deselectAll() {
081 if (group != null)
082 group.clearSelection();
083 }
084
085 @Override
086 protected JComponent doBindControl() {
087 Assert.notNull(selectableEnumsList);
088 return createBindingControl();
089 }
090
091 private JPanel createBindingControl() {
092 group = new ButtonGroup();
093 FormLayout layout = new FormLayout(new ColumnSpec[] { FormFactory.DEFAULT_COLSPEC },
094 getDefaultRowsWithGap(radioButtons.keySet().size()));
095 int count = 1;
096 contentPanel.setLayout(layout);
097 for (ContainerJRadioButton<Enum> button : radioButtons.values()) {
098 group.add(button);
099 contentPanel.add(button, new CellConstraints(1, count));
100 count += 2;
101 }
102 valueModelChanged(getValue());
103 return contentPanel;
104 }
105
106 private static RowSpec[] getDefaultRowsWithGap(int rowCount) {
107 List<RowSpec> rows = new ArrayList<RowSpec>();
108 for (int i = 0; i < rowCount; i++) {
109 rows.add(new RowSpec("fill:pref:nogrow"));
110 rows.add(FormFactory.LINE_GAP_ROWSPEC);
111 }
112 rows.remove(rows.size() - 1);
113 return rows.toArray(new RowSpec[] {});
114 }
115
116 @Override
117 protected void enabledChanged() {
118 for (ContainerJRadioButton<Enum> button : radioButtons.values()) {
119 button.setEnabled(isEnabled());
120 }
121
122 }
123
124 @Override
125 protected void readOnlyChanged() {
126 for (ContainerJRadioButton<Enum> button : radioButtons.values()) {
127 button.setEnabled(isReadOnly());
128 }
129 }
130
131 private void createRadioButtons() {
132 for (Enum enumValue : selectableEnumsList) {
133 ContainerJRadioButton<Enum> button = new ContainerJRadioButton<Enum>();
134 String text;
135 if (enumValue == null) {
136 text = messageSourceAccessor.getMessage(propertyType.getName() + ".null", "null");
137 button.setText(text == null ? propertyType.getName() + ".null" : text);
138 }
139 else {
140 text = messageSourceAccessor.getMessage(propertyType.getName() + "." + enumValue.name(), enumValue
141 .name());
142 button.setText(text == null ? propertyType.getName() + "." + enumValue.name() : text);
143 }
144 button.setContainedObject(enumValue);
145 button.addActionListener(new ActionListener() {
146
147 public void actionPerformed(ActionEvent e) {
148 ContainerJRadioButton<Enum> button = (ContainerJRadioButton<Enum>) e.getSource();
149 controlValueChanged(button.getContainedObject());
150 }
151
152 });
153 if (enumValue == null)
154 radioButtons.put(null, button);
155 else
156 radioButtons.put(enumValue.name(), button);
157
158 }
159 }
160
161 private class ContainerJRadioButton<T> extends JRadioButton {
162
163 private T containedObject;
164
165 public T getContainedObject() {
166 return containedObject;
167 }
168
169 public void setContainedObject(T containedObject) {
170 this.containedObject = containedObject;
171 }
172
173 }
174
175 }