001 /*
002 * Copyright 2002-2004 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.springframework.richclient.form.binding.swing;
017
018 import java.util.Arrays;
019 import java.util.Collections;
020 import java.util.HashMap;
021 import java.util.List;
022 import java.util.Map;
023 import java.util.Observable;
024
025 import javax.swing.ComboBoxModel;
026 import javax.swing.DefaultComboBoxModel;
027 import javax.swing.DefaultListModel;
028 import javax.swing.JComboBox;
029 import javax.swing.ListModel;
030 import javax.swing.event.ListDataEvent;
031 import javax.swing.event.ListDataListener;
032
033 import org.springframework.binding.value.ValueModel;
034 import org.springframework.binding.value.support.ValueHolder;
035 import org.springframework.rules.constraint.Constraint;
036 import org.springframework.richclient.form.binding.Binding;
037 import org.springframework.util.comparator.ComparableComparator;
038
039 public class ComboBoxBindingTests extends BindingAbstractTests {
040
041 private static final String[] SELECTABLEITEMS = new String[] { "0", "1", "2", "3", "4" };
042
043 private ValueModel sih;
044
045 private ComboBoxBinding cbb;
046
047 private JComboBox cb;
048
049 private TestDataListener testListener;
050
051 protected String setUpBinding() {
052 cbb = new ComboBoxBinding(fm, "simpleProperty");
053 cb = (JComboBox) cbb.getControl();
054 sih = new ValueHolder(SELECTABLEITEMS);
055 cbb.setSelectableItems(sih);
056 testListener = new TestDataListener();
057 cb.getModel().addListDataListener(testListener);
058 return "simpleProperty";
059 }
060
061 public void testWithListModel() throws Exception {
062 DefaultListModel model = new DefaultListModel();
063 model.addElement("1");
064 model.addElement("2");
065 model.addElement("3");
066 model.addElement("4");
067 cbb.setSelectableItems(model);
068 cbb.doBindControl();
069 ComboBoxModel cbmodel = cb.getModel();
070 assertEquals(model.getSize(), cbmodel.getSize());
071 for (int i = 0, size = model.size(); i < size; i++) {
072 assertEquals(model.getElementAt(i), cbmodel.getElementAt(i));
073 }
074 }
075
076 public void testWithList() throws Exception {
077 List model = Arrays.asList(SELECTABLEITEMS);
078 cbb.setSelectableItems(model);
079 cbb.doBindControl();
080 ComboBoxModel cbmodel = cb.getModel();
081 assertEquals(model.size(), cbmodel.getSize());
082 for (int i = 0, size = model.size(); i < size; i++) {
083 assertEquals(model.get(i), cbmodel.getElementAt(i));
084 }
085 }
086
087 public void testWithArray() throws Exception {
088 Object[] model = SELECTABLEITEMS;
089 cbb.setSelectableItems(model);
090 cbb.doBindControl();
091 ComboBoxModel cbmodel = cb.getModel();
092 assertEquals(model.length, cbmodel.getSize());
093 for (int i = 0, size = model.length; i < size; i++) {
094 assertEquals(model[i], cbmodel.getElementAt(i));
095 }
096 }
097
098 public void testValueModelUpdatesComponent() {
099 TestListDataListener tldl = new TestListDataListener();
100 cb.getModel().addListDataListener(tldl);
101
102 assertEquals(null, cb.getSelectedItem());
103 assertEquals(-1, cb.getSelectedIndex());
104 tldl.assertCalls(0);
105
106 vm.setValue("1");
107 assertEquals("1", cb.getSelectedItem());
108 assertEquals(1, cb.getSelectedIndex());
109 tldl.assertEvent(1, ListDataEvent.CONTENTS_CHANGED, -1, -1);
110
111 vm.setValue("2");
112 assertEquals("2", cb.getSelectedItem());
113 assertEquals(2, cb.getSelectedIndex());
114 tldl.assertEvent(2, ListDataEvent.CONTENTS_CHANGED, -1, -1);
115
116 vm.setValue(null);
117 assertEquals(null, cb.getSelectedItem());
118 assertEquals(-1, cb.getSelectedIndex());
119 tldl.assertEvent(3, ListDataEvent.CONTENTS_CHANGED, -1, -1);
120
121 vm.setValue(null);
122 tldl.assertCalls(3);
123 }
124
125 public void testComponentUpdatesValueModel() {
126 cb.setSelectedIndex(1);
127 assertEquals("1", vm.getValue());
128
129 cb.setSelectedItem("2");
130 assertEquals("2", vm.getValue());
131
132 cb.setSelectedIndex(-1);
133 assertEquals(null, vm.getValue());
134
135 cb.setSelectedItem(null);
136 assertEquals(null, vm.getValue());
137 }
138
139 public void testSelectableValueChangeUpdatesComboBoxModel() {
140 assertEquals("0", cb.getModel().getElementAt(0));
141
142 sih.setValue(new Object[] { "1" });
143 assertEquals("1", cb.getModel().getElementAt(0));
144 }
145
146 public void testComponentTracksEnabledChanges() {
147 assertTrue(cb.isEnabled());
148
149 fm.getFieldMetadata("simpleProperty").setEnabled(false);
150 assertFalse(cb.isEnabled());
151
152 fm.getFieldMetadata("simpleProperty").setEnabled(true);
153 assertTrue(cb.isEnabled());
154 }
155
156 public void testComponentTracksReadOnlyChanges() {
157 assertTrue(cb.isEnabled());
158
159 fm.getFieldMetadata("simpleProperty").setReadOnly(true);
160 assertFalse(cb.isEnabled());
161
162 fm.getFieldMetadata("simpleProperty").setReadOnly(false);
163 assertTrue(cb.isEnabled());
164 }
165
166 public void testSelectableItemHolderNullValue() {
167 ComboBoxBinding binding = new ComboBoxBinding(fm, "simpleProperty");
168 binding.getControl();
169 ValueHolder valueHolder = new ValueHolder();
170 try {
171 binding.setSelectableItems(valueHolder);
172 fail();
173 } catch (IllegalArgumentException e) {
174 // expected
175 }
176 }
177
178 public void testExistingModel() {
179 JComboBox cb = new JComboBox(new DefaultComboBoxModel(new Object[] { "1", "2", "3" }));
180 ComboBoxBinder binder = new ComboBoxBinder();
181 Binding binding = binder.bind(cb, fm, "simpleProperty", Collections.EMPTY_MAP);
182 assertEquals(3, ((JComboBox) binding.getControl()).getModel().getSize());
183 }
184
185 public void testFilter() {
186 setUpBinding();
187 ListModel model = cb.getModel();
188 cbb.setFilter(new Constraint() {
189 public boolean test(Object argument) {
190 return "1".equals(argument) || "4".equals(argument);
191 }
192 });
193 assertEquals(2, model.getSize());
194 assertEquals("1", model.getElementAt(0));
195 assertEquals("4", model.getElementAt(1));
196 }
197
198 public void testUpdatingFilter() {
199 setUpBinding();
200 ListModel model = cb.getModel();
201 TestConstraint testConstraint = new TestConstraint();
202 cbb.setFilter(testConstraint);
203 assertEquals(2, model.getSize());
204 assertEquals("1", model.getElementAt(0));
205 assertEquals("4", model.getElementAt(1));
206
207 testConstraint.testCalled = 0;
208 testConstraint.setFilterValues(new Object[] { "2" });
209 // assertEquals(SELECTABLEITEMS.length, testConstraint.testCalled);
210 assertEquals(testConstraint.filterValues.length, model.getSize());
211 assertEquals("2", model.getElementAt(0));
212 }
213
214 public void testFilterWithContext() {
215 ComboBoxBinder binder = new ComboBoxBinder();
216 binder.setSelectableItems(SELECTABLEITEMS);
217 Map context = new HashMap();
218 Constraint filter = new Constraint() {
219 public boolean test(Object argument) {
220 return "1".equals(argument) || "4".equals(argument);
221 }
222 };
223 context.put(ComboBoxBinder.FILTER_KEY, filter);
224 ComboBoxBinding binding = (ComboBoxBinding) binder.bind(fm, "simpleProperty", context);
225 ListModel bindingModel = binding.getBindingModel();
226 assertEquals(filter, binding.getFilter());
227 assertEquals(2, bindingModel.getSize());
228 assertEquals("1", bindingModel.getElementAt(0));
229 assertEquals("4", bindingModel.getElementAt(1));
230 }
231
232 public void testComparator() {
233 ComboBoxBinder binder = new ComboBoxBinder();
234 binder.setSelectableItems(new Object[] { "2", "4", "1", "2", "3" });
235 binder.setComparator(new ComparableComparator());
236 ComboBoxBinding binding = (ComboBoxBinding) binder.bind(fm, "simpleProperty", Collections.EMPTY_MAP);
237 ListModel bindingModel = binding.getBindingModel();
238 assertEquals(5, bindingModel.getSize());
239 assertEquals("1", bindingModel.getElementAt(0));
240 assertEquals("2", bindingModel.getElementAt(1));
241 assertEquals("2", bindingModel.getElementAt(2));
242 assertEquals("3", bindingModel.getElementAt(3));
243 assertEquals("4", bindingModel.getElementAt(4));
244 }
245
246 public void testEmptySelectionValue() throws Exception {
247 ComboBoxModel model = cb.getModel();
248 int modelSize = model.getSize();
249 testListener.contentsChanged = null;
250 testListener.intervalAdded = null;
251 testListener.intervalRemoved = null;
252 String emptyValue = "select a Value";
253 cbb.setEmptySelectionValue(emptyValue);
254 assertEquals(modelSize + 1, model.getSize());
255 assertEquals(emptyValue, model.getElementAt(0));
256 assertNotNull(testListener.contentsChanged);
257 assertNull(testListener.intervalAdded);
258 assertNull(testListener.intervalRemoved);
259 cb.setSelectedItem(SELECTABLEITEMS[0]);
260 assertEquals(SELECTABLEITEMS[0], model.getSelectedItem());
261 assertEquals(SELECTABLEITEMS[0], vm.getValue());
262 cb.setSelectedItem(emptyValue);
263 assertEquals(emptyValue, model.getSelectedItem());
264 assertEquals(null, vm.getValue());
265 cb.setSelectedItem(null);
266 assertEquals(emptyValue, model.getSelectedItem());
267 assertEquals(null, vm.getValue());
268
269 cb.setSelectedItem(emptyValue);
270 testListener.contentsChanged = null;
271 testListener.intervalAdded = null;
272 testListener.intervalRemoved = null;
273 cbb.setEmptySelectionValue(null);
274 assertNotNull(testListener.contentsChanged);
275 assertNull(testListener.intervalAdded);
276 assertNull(testListener.intervalRemoved);
277 assertEquals(modelSize, model.getSize());
278 assertEquals(SELECTABLEITEMS[0], model.getElementAt(0));
279 assertNull(vm.getValue());
280 }
281
282 private static class TestConstraint extends Observable implements Constraint {
283 Object[] filterValues = new Object[] { "1", "4" };
284
285 int testCalled = 0;
286
287 public boolean test(Object argument) {
288 testCalled++;
289 for (int i = 0; i < filterValues.length; i++) {
290 if (filterValues[i].equals(argument))
291 return true;
292 }
293 return false;
294 }
295
296 public void setFilterValues(Object[] objects) {
297 filterValues = objects;
298 setChanged();
299 notifyObservers();
300 }
301 }
302
303 private class TestDataListener implements ListDataListener {
304
305 private ListDataEvent contentsChanged;
306
307 private ListDataEvent intervalAdded;
308
309 private ListDataEvent intervalRemoved;
310
311 public void contentsChanged(ListDataEvent e) {
312 contentsChanged = e;
313 }
314
315 public void intervalAdded(ListDataEvent e) {
316 intervalAdded = e;
317 }
318
319 public void intervalRemoved(ListDataEvent e) {
320 intervalRemoved = e;
321 }
322
323 }
324 }