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    }