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 }