001: package org.uispec4j;
002:
003: import junit.framework.Assert;
004: import junit.framework.AssertionFailedError;
005: import org.uispec4j.assertion.Assertion;
006: import org.uispec4j.assertion.UISpecAssert;
007: import org.uispec4j.finder.FinderUtils;
008: import org.uispec4j.finder.StringMatcher;
009: import org.uispec4j.utils.ArrayUtils;
010: import org.uispec4j.xml.XmlWriter;
011:
012: import javax.swing.ComboBoxModel;
013: import javax.swing.JComboBox;
014: import javax.swing.JList;
015: import javax.swing.ListModel;
016: import java.awt.Component;
017: import java.awt.Container;
018: import java.util.ArrayList;
019: import java.util.List;
020: import java.util.Arrays;
021:
022: /**
023: * Wrapper for JComboBox components.
024: * This class provides means for checking the contents and selection of the comboBox,
025: * changing the selection, etc. For all these methods, when using String values,
026: * the means of retrieving a String representation of the displayed values can be customized
027: * using the {@link #setCellValueConverter(ListBoxCellValueConverter)} method and providing
028: * a new {@link ListBoxCellValueConverter} implementation.
029: * A {@link DefaultListBoxCellValueConverter} is set up by default.
030: */
031: public class ComboBox extends AbstractUIComponent {
032:
033: public static final String TYPE_NAME = "comboBox";
034: public static final Class[] SWING_CLASSES = { JComboBox.class };
035: private static final JList REFERENCE_JLIST = new JList();
036:
037: private JComboBox jComboBox;
038: private ListBoxCellValueConverter cellValueConverter = new DefaultListBoxCellValueConverter();
039:
040: public ComboBox(JComboBox combo) {
041: this .jComboBox = combo;
042: }
043:
044: public Component getAwtComponent() {
045: return jComboBox;
046: }
047:
048: public String getDescriptionTypeName() {
049: return TYPE_NAME;
050: }
051:
052: public void setCellValueConverter(
053: ListBoxCellValueConverter cellValueConverter) {
054: this .cellValueConverter = cellValueConverter;
055: }
056:
057: protected void getSubDescription(Container container,
058: XmlWriter.Tag tag) {
059: // ignore the combo inner button
060: }
061:
062: /**
063: * Selects the first item in the list, if not empty
064: */
065: public void click() {
066: if (jComboBox.getModel().getSize() > 0) {
067: jComboBox.setSelectedIndex(0);
068: }
069: }
070:
071: public void select(String value) {
072: ListModel model = jComboBox.getModel();
073: StringMatcher[] stringMatchers = FinderUtils.getMatchers(value);
074: for (int i = 0; i < stringMatchers.length; i++) {
075: StringMatcher stringMatcher = stringMatchers[i];
076: List indexes = new ArrayList();
077: for (int j = 0, max = model.getSize(); j < max; j++) {
078: if (stringMatcher.matches(getRenderedValue(j))) {
079: indexes.add(new Integer(j));
080: }
081: }
082: if (indexes.size() == 1) {
083: jComboBox.setSelectedIndex(((Integer) indexes.get(0))
084: .intValue());
085: return;
086: }
087: if (indexes.size() > 1) {
088: String[] items = new String[indexes.size()];
089: for (int j = 0; j < items.length; j++) {
090: items[j] = getRenderedValue(j);
091: }
092: throw new ItemAmbiguityException(value, items);
093: }
094: }
095: Assert.fail(value + " not found in ComboBox");
096: }
097:
098: /**
099: * Changes the displayed text, in case of an editable combo box. <p/>
100: * This method will throw an exception if the component is not editable.<p/>
101: */
102: public void setText(String text) {
103: UISpecAssert.assertTrue(isEditable());
104: jComboBox.setSelectedItem(text);
105: }
106:
107: public Assertion contentEquals(final String[] expected) {
108: return new Assertion() {
109: public void check() {
110: ArrayUtils.assertEquals(expected, getContent());
111: }
112: };
113: }
114:
115: public Assertion contains(final String item) {
116: return contains(new String[] { item });
117: }
118:
119: public Assertion contains(final String[] items) {
120: return new Assertion() {
121: public void check() throws Exception {
122: List content = Arrays.asList(getContent());
123: for (int i = 0; i < items.length; i++) {
124: String item = items[i];
125: if (!content.contains(item)) {
126: throw new AssertionFailedError("Item '" + item
127: + "' not found - actual content:"
128: + content);
129: }
130: }
131: }
132: };
133: }
134:
135: /**
136: * Checks that the combo box displays the given value and that it shows no elements when expanded.
137: */
138: public Assertion isEmpty(final String displayedValue) {
139: return new Assertion() {
140: public void check() {
141: if (jComboBox.getItemCount() != 0) {
142: Assert.fail("Unexpected content: "
143: + ArrayUtils.toString(getContent()));
144: }
145: Assert.assertEquals(displayedValue,
146: getRenderedValue(-1));
147: }
148: };
149: }
150:
151: public Assertion selectionEquals(final String selection) {
152: return new Assertion() {
153: public void check() {
154: if (jComboBox.getSelectedItem() == null) {
155: Assert.assertNull(selection);
156: } else {
157: Assert.assertEquals(selection, getRenderedValue(
158: jComboBox.getSelectedItem(), -1));
159: }
160: }
161: };
162: }
163:
164: public Assertion isEditable() {
165: return new Assertion() {
166: public void check() {
167: if (!jComboBox.isEditable()) {
168: throw new AssertionFailedError(
169: "The combo box is not editable");
170: }
171: }
172: };
173: }
174:
175: private String[] getContent() {
176: ComboBoxModel model = jComboBox.getModel();
177: String[] comboContents = new String[model.getSize()];
178: for (int i = 0; i < comboContents.length; i++) {
179: comboContents[i] = getRenderedValue(i);
180: }
181: return comboContents;
182: }
183:
184: private String getRenderedValue(int index) {
185: return getRenderedValue(jComboBox.getModel()
186: .getElementAt(index), index);
187: }
188:
189: private String getRenderedValue(Object value, int index) {
190: Component component = jComboBox.getRenderer()
191: .getListCellRendererComponent(REFERENCE_JLIST, value,
192: index, false, false);
193: Object modelObject = (index == -1) ? null : jComboBox
194: .getModel().getElementAt(index);
195: return cellValueConverter.getValue(index, component,
196: modelObject);
197: }
198: }
|