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 }