001: package abbot.tester;
002:
003: import java.awt.*;
004: import javax.swing.*;
005: import javax.swing.text.*;
006:
007: import abbot.Log;
008: import abbot.Platform;
009: import abbot.i18n.Strings;
010: import javax.swing.text.DefaultEditorKit;
011:
012: /** Provides actions and assertions {@link JTextComponent}-based
013: * components.
014: */
015: public class JTextComponentTester extends JComponentTester {
016:
017: /**
018: * Type the given text into the given component, replacing any existing
019: * text already there. If the empty string or <code>null</code> is given,
020: * simply removes all existing text.
021: */
022: public void actionEnterText(Component c, String text) {
023: scrollToVisible(c, 0);
024: actionActionMap(c, DefaultEditorKit.selectAllAction);
025: if (text == null || "".equals(text)) {
026: if (!"".equals(((JTextComponent) c).getText())) {
027: actionActionMap(c,
028: DefaultEditorKit.deletePrevCharAction);
029: }
030: } else {
031: actionKeyString(c, text);
032: }
033: }
034:
035: /** Click at the given index position. */
036: public void actionClick(Component tc, int index) {
037: Point where = scrollToVisible(tc, index);
038: actionClick(tc, where.x, where.y);
039: }
040:
041: public void actionSetCaretPosition(Component tc, int index) {
042: actionClick(tc, index);
043: }
044:
045: /** Move the pointer to the given index location. Takes care of
046: * auto-scrolling through text.
047: */
048: // TODO move this to a JTextComponentLocation and rely on existing
049: // mechanisms to do the scrolling.
050: protected Point scrollToVisible(Component c, int index) {
051: JTextComponent tc = (JTextComponent) c;
052: try {
053: Rectangle visible = tc.getVisibleRect();
054: Rectangle rect = tc.modelToView(index);
055: Log.debug("visible=" + visible + ", index=" + index
056: + " is at " + rect);
057: if (rect == null) {
058: String msg = Strings.get("tester.zero_size");
059: throw new ActionFailedException(msg);
060: }
061: // Autoscroll on JTextComponent is a bit flakey
062: if (!visible.contains(rect.x, rect.y)) {
063: scrollRectToVisible(tc, rect);
064: visible = tc.getVisibleRect();
065: rect = tc.modelToView(index);
066: Log.debug("visible=" + visible + " caret=" + rect);
067: if (!visible.contains(rect.x, rect.y)) {
068: String msg = Strings.get(
069: "tester.JComponent.not_visible",
070: new Object[] { new Integer(rect.x),
071: new Integer(rect.y), tc, });
072: throw new ActionFailedException(msg);
073: }
074: }
075: return new Point(rect.x + rect.width / 2, rect.y
076: + rect.height / 2);
077: } catch (BadLocationException ble) {
078: String msg = Strings.get(
079: "tester.JTextComponent.bad_location", new Object[] {
080: ble.getMessage(), new Integer(index),
081: tc.getText() });
082: throw new ActionFailedException(msg);
083: }
084: }
085:
086: /** Account for differences in scrolling {@link javax.swing.JTextField}.
087: @see JComponentTester#scrollRectToVisible
088: @see JComponent#scrollRectToVisible
089: */
090: protected void scrollRectToVisible(JComponent c, Rectangle rect) {
091: super .scrollRectToVisible(c, rect);
092: // Taken from JComponent
093: if (!isVisible(c, rect) && c instanceof JTextField) {
094: int dx = c.getX();
095: int dy = c.getY();
096: Container parent;
097: for (parent = c.getParent(); !(parent == null)
098: && !(parent instanceof JComponent)
099: && !(parent instanceof CellRendererPane); parent = parent
100: .getParent()) {
101: Rectangle bounds = parent.getBounds();
102: dx += bounds.x;
103: dy += bounds.y;
104: }
105: if (!(parent == null)
106: && !(parent instanceof CellRendererPane)) {
107: rect.x += dx;
108: rect.y += dy;
109: super .scrollRectToVisible((JComponent) parent, rect);
110: rect.x -= dx;
111: rect.y -= dy;
112: }
113: }
114: }
115:
116: /** Equivalent to JTextComponent.setCaretPosition(int), but operates
117: * through the UI.
118: */
119: protected void startSelection(Component comp, int index) {
120: final JTextComponent tc = (JTextComponent) comp;
121: // Avoid automatic drag/drop if the selection start is already
122: // part of a selection (OSX has setDragEnabled true by default).
123: if (tc.getSelectionStart() != tc.getSelectionEnd()) {
124: invokeAndWait(new Runnable() {
125: public void run() {
126: tc.setCaretPosition(0);
127: tc.moveCaretPosition(0);
128: }
129: });
130: }
131: Point where = scrollToVisible(comp, index);
132: mousePress(comp, where.x, where.y);
133: }
134:
135: /** Equivalent to JTextComponent.moveCaretPosition(int), but operates
136: * through the UI.
137: */
138: protected void endSelection(Component comp, int index) {
139: Point where = scrollToVisible(comp, index);
140: mouseMove(comp, where.x, where.y);
141: if (Platform.isOSX())
142: delay(75);
143: mouseRelease();
144: }
145:
146: /** Start a selection at the given index. */
147: public void actionStartSelection(Component comp, int index) {
148: startSelection(comp, index);
149: waitForIdle();
150: }
151:
152: /** Terminate a selection on the given index. */
153: public void actionEndSelection(Component comp, int index) {
154: endSelection(comp, index);
155: waitForIdle();
156: }
157:
158: /** Select the given text range.
159: @deprecated Use actionSelectText instead.
160: */
161: public void actionSelect(Component comp, int start, int end) {
162: actionSelectText(comp, start, end);
163: }
164:
165: /** Select the given text range. */
166: public void actionSelectText(Component comp, int start, int end) {
167: // An idle wait is sometimes required, otherwise the mouse press is
168: // never registered (w32, 1.4)
169: actionStartSelection(comp, start);
170: actionEndSelection(comp, end);
171:
172: // Verify the selection was properly made
173: JTextComponent tc = (JTextComponent) comp;
174: if (!(tc.getSelectionStart() == Math.min(start, end) && tc
175: .getSelectionEnd() == Math.max(start, end))) {
176: String msg = Strings.get(
177: "tester.JTextComponent.selection_failed",
178: new Object[] { new Integer(start),
179: new Integer(end),
180: new Integer(tc.getSelectionStart()),
181: new Integer(tc.getSelectionEnd()), });
182: throw new ActionFailedException(msg);
183: }
184: }
185: }
|