001: package abbot.tester;
002:
003: import java.awt.Component;
004: import java.awt.Container;
005: import java.util.ArrayList;
006:
007: import javax.swing.*;
008:
009: import abbot.Log;
010: import abbot.i18n.Strings;
011: import abbot.util.ExtendedComparator;
012: import abbot.util.AWT;
013: import abbot.finder.*;
014: import abbot.finder.matchers.*;
015:
016: public class JComboBoxTester extends JComponentTester {
017:
018: private class ListNotFoundException extends ActionFailedException {
019: public ListNotFoundException(String m) {
020: super (m);
021: }
022: }
023:
024: private JListTester listTester = new JListTester();
025:
026: /** Return an array of strings that represent the combo box list.
027: * Note that the current selection might not be included, since it's
028: * possible to have a custom (edited) entry there that is not included in
029: * the default contents.
030: */
031: public String[] getContents(JComboBox cb) {
032: ArrayList list = new ArrayList();
033: for (int i = 0; i < cb.getItemCount(); i++) {
034: list.add(cb.getItemAt(i).toString());
035: }
036: return (String[]) list.toArray(new String[list.size()]);
037: }
038:
039: public void actionSelectIndex(Component comp, final int index) {
040: final JComboBox cb = (JComboBox) comp;
041:
042: // activate it, if not already showing
043: if (!cb.getUI().isPopupVisible(cb)) {
044: // NOTE: if the index is out of range, the selected item will be
045: // one end or the other of the list.
046: if (cb.isEditable()) {
047: // Location of popup button activator is LAF-dependent
048: invokeAndWait(new Runnable() {
049: public void run() {
050: cb.getUI().setPopupVisible(cb, true);
051: }
052: });
053: } else {
054: actionClick(cb);
055: }
056: }
057: try {
058: // Not all LAFs use a JList for the popup
059: JList list = findComboList(cb);
060: listTester.actionSelectIndex(list, index);
061: } catch (ListNotFoundException e) {
062: invokeAndWait(new Runnable() {
063: public void run() {
064: cb.setSelectedIndex(index);
065: if (cb.getUI().isPopupVisible(cb))
066: cb.getUI().setPopupVisible(cb, false);
067: }
068: });
069: }
070: }
071:
072: /** Find the JList in the popup raised by this combo box, if
073: the LAF actually uses one.
074: */
075: public JList findComboList(JComboBox cb) {
076: Component popup = AWT.findActivePopupMenu();
077: if (popup == null) {
078: long now = System.currentTimeMillis();
079: while ((popup = AWT.findActivePopupMenu()) == null) {
080: if (System.currentTimeMillis() - now > popupDelay)
081: throw new ListNotFoundException(Strings
082: .get("tester.JComboBox.popup_not_found"));
083: sleep();
084: }
085: }
086:
087: Component comp = findJList((Container) popup);
088: if (comp == null)
089: throw new ListNotFoundException(Strings
090: .get("tester.JComboBox.popup_not_found"));
091: return (JList) comp;
092: }
093:
094: private JList findJList(Container parent) {
095: try {
096: ComponentFinder finder = BasicFinder.getDefault();
097: return (JList) finder.find(parent, new ClassMatcher(
098: JList.class));
099: } catch (ComponentSearchException e) {
100: return null;
101: }
102: }
103:
104: /** If the value looks meaningful, return it, otherwise return null. */
105: public String getValueAsString(JComboBox combo, JList list,
106: Object item, int index) {
107: String value = item.toString();
108: // If the value is the default Object.toString method (which
109: // returns <class>@<pointer value>), try to find something better.
110: if (value.startsWith(item.getClass().getName() + "@")) {
111: Component c = combo.getRenderer()
112: .getListCellRendererComponent(list, item, index,
113: true, true);
114: if (c instanceof javax.swing.JLabel)
115: return ((javax.swing.JLabel) c).getText();
116: return null;
117: }
118: return value;
119: }
120:
121: public void actionSelectItem(Component comp, String item) {
122: JComboBox cb = (JComboBox) comp;
123: Object obj = cb.getSelectedItem();
124: if ((obj == null && item == null)
125: || (obj != null && ExtendedComparator.stringsMatch(
126: item, obj.toString())))
127: return;
128:
129: for (int i = 0; i < cb.getItemCount(); i++) {
130: obj = cb.getItemAt(i);
131: Log.debug("Comparing against '" + obj + "'");
132: if ((obj == null && item == null)
133: || (obj != null && ExtendedComparator.stringsMatch(
134: item, obj.toString()))) {
135: actionSelectIndex(comp, i);
136: return;
137: }
138: }
139: // While actions are supposed to represent real user actions, it's
140: // possible that the current environment does not match sufficiently,
141: // so we need to throw an appropriate exception that can be used to
142: // diagnose the problem.
143: String mid = "[";
144: StringBuffer contents = new StringBuffer();
145: for (int i = 0; i < cb.getItemCount(); i++) {
146: contents.append(mid);
147: contents.append(cb.getItemAt(i).toString());
148: mid = ", ";
149: }
150: contents.append("]");
151: throw new ActionFailedException(Strings.get(
152: "tester.JComboBox.item_not_found", new Object[] { item,
153: contents.toString() }));
154: }
155: }
|