001    /*
002     * Created on Mar 1, 2008
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005     * in compliance with the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License
010     * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011     * or implied. See the License for the specific language governing permissions and limitations under
012     * the License.
013     *
014     * Copyright @2008-2010 the original author or authors.
015     */
016    package org.fest.swing.core;
017    
018    import java.awt.*;
019    import java.awt.event.InputEvent;
020    
021    import javax.swing.JPopupMenu;
022    
023    import org.fest.swing.exception.ActionFailedException;
024    import org.fest.swing.exception.ComponentLookupException;
025    import org.fest.swing.hierarchy.ComponentHierarchy;
026    import org.fest.swing.lock.ScreenLock;
027    
028    /**
029     * Understands simulation of user events on a GUI <code>{@link Component}</code>.
030     *
031     * @author Alex Ruiz
032     * @author Yvonne Wang
033     */
034    public interface Robot {
035    
036      /**
037       * Returns the <code>{@link ComponentHierarchy}</code> being used by this robot.
038       * @return the <code>ComponentHierarchy</code> being used by this robot.
039       */
040      ComponentHierarchy hierarchy();
041    
042      /**
043       * Returns the <code>{@link ComponentFinder}</code> being used by this robot.
044       * @return the <code>ComponentFinder</code> being used by this robot.
045       */
046      ComponentFinder finder();
047    
048      /**
049       * Returns the <code>{@link BasicComponentPrinter}</code> being used by this robot.
050       * @return the <code>ComponentPrinter</code> being used by this robot.
051       */
052      ComponentPrinter printer();
053    
054      /**
055       * Safely display a window with proper EDT synchronization. This method blocks until the <code>{@link Window}</code>
056       * is showing and ready for input.
057       * @param w the window to display.
058       */
059      void showWindow(Window w);
060    
061      /**
062       * Safely display a window with proper EDT synchronization. This method blocks until the <code>{@link Window}</code>
063       * is showing and ready for input.
064       * @param w the window to display.
065       * @param size the size of the window to display.
066       */
067      void showWindow(Window w, Dimension size);
068    
069      /**
070       * <p>
071       * Safely display a window with proper EDT synchronization. This method blocks until the window is showing. This
072       * method will return even when the window is a modal dialog, since the show method is called on the event dispatch
073       * thread. The window will be packed if the pack flag is set, and set to the given size if it is non-<code>null</code>.
074       * </p>
075       * Modal dialogs may be shown with this method without blocking.
076       * @param w the window to display.
077       * @param size the size of the window to display.
078       * @param pack flag that indicates if the window should be packed or not. By packed we mean calling
079       * <code>w.pack()</code>.
080       */
081      void showWindow(final Window w, final Dimension size, final boolean pack);
082    
083      /**
084       * Simulates a user closing the given window.
085       * @param w the window to close.
086       */
087      void close(Window w);
088    
089      /**
090       * Gives input focus to the given <code>{@link Component}</code>. Note that the component may not yet have focus when
091       * this method returns.
092       * @param c the component to give focus to.
093       */
094      void focus(Component c);
095    
096      /**
097       * Gives input focus to the given <code>{@link Component}</code> and waits until the <code>{@link Component}</code>
098       * has focus.
099       * @param c the component to give focus to.
100       */
101      void focusAndWaitForFocusGain(Component c);
102    
103      /**
104       * Cleans up any used resources (keyboard, mouse, open windows and <code>{@link ScreenLock}</code>) used by this
105       * robot.
106       */
107      void cleanUp();
108    
109      /**
110       * Cleans up any used resources (keyboard, mouse and <code>{@link ScreenLock}</code>) used by this robot. This method
111       * <strong>does not</strong> dispose any open windows.
112       * <p>
113       * <strong>Note:</strong> The preferred method to use to clean up resources is <code>{@link #cleanUp()}</code>. Using
114       * <code>{@link #cleanUpWithoutDisposingWindows()}</code> may leave many windows open after each test. Use it on very
115       * special cases. Please read <a href="http://code.google.com/p/fest/issues/detail?id=138" target="_blank">bug 138</a>
116       * for more details.
117       * </p>
118       */
119      void cleanUpWithoutDisposingWindows();
120    
121      /**
122       * Simulates a user clicking once the given <code>{@link Component}</code> using the left mouse button.
123       * @param c the <code>Component</code> to click on.
124       * @throws ActionFailedException if the component to click is out of the boundaries of the screen.
125       */
126      void click(Component c);
127    
128      /**
129       * Simulates a user right-clicking the given <code>{@link Component}</code>.
130       * @param c the <code>Component</code> to click on.
131       * @throws ActionFailedException if the component to click is out of the boundaries of the screen.
132       */
133      void rightClick(Component c);
134    
135      /**
136       * Simulates a user clicking once the given <code>{@link Component}</code> using the given mouse button.
137       * @param c the <code>Component</code> to click on.
138       * @param button the mouse button to use.
139       * @throws ActionFailedException if the component to click is out of the boundaries of the screen.
140       */
141      void click(Component c, MouseButton button);
142    
143      /**
144       * Simulates a user double-clicking the given <code>{@link Component}</code>.
145       * @param c the <code>Component</code> to click on.
146       * @throws ActionFailedException if the component to click is out of the boundaries of the screen.
147       */
148      void doubleClick(Component c);
149    
150      /**
151       * Simulates a user clicking the given mouse button, the given times on the given <code>{@link Component}</code>.
152       * @param c the <code>Component</code> to click on.
153       * @param button the mouse button to click.
154       * @param times the number of times to click the given mouse button.
155       * @throws ActionFailedException if the component to click is out of the boundaries of the screen.
156       */
157      void click(Component c, MouseButton button, int times);
158    
159      /**
160       * Simulates a user clicking at the given position on the given <code>{@link Component}</code>.
161       * @param c the <code>Component</code> to click on.
162       * @param where the given coordinates, relative to the given <code>Component</code>.
163       * @throws ActionFailedException if the component to click is out of the boundaries of the screen.
164       */
165      void click(Component c, Point where);
166    
167      /**
168       * Simulates a user clicking the given mouse button, the given times at the given position on the given
169       * <code>{@link Component}</code>.
170       * @param c the <code>Component</code> to click on.
171       * @param where the given coordinates, relative to the given <code>Component</code>.
172       * @param button the mouse button to click.
173       * @param times the number of times to click the given mouse button.
174       * @throws ActionFailedException if the component to click is out of the boundaries of the screen.
175       */
176      void click(Component c, Point where, MouseButton button, int times);
177    
178      /**
179       * Simulates a user clicking the given mouse button, the given times at the given absolute coordinates.
180       * @param where the coordinates where to click.
181       * @param button the mouse button to click.
182       * @param times the number of times to click the given mouse button.
183       */
184      void click(Point where, MouseButton button, int times);
185    
186      /**
187       * Simulates a user pressing a mouse button.
188       * @param button the mouse button to press.
189       */
190      void pressMouse(MouseButton button);
191    
192      /**
193       * Simulates a user pressing the left mouse button on the given <code>{@link Component}</code>.
194       * @param c the <code>Component</code> to click on.
195       * @param where the given coordinates, relative to the given <code>Component</code>.
196       */
197      void pressMouse(Component c, Point where);
198    
199      /**
200       * Simulates a user pressing the given mouse button on the given <code>{@link Component}</code>.
201       * @param c the <code>Component</code> to click on.
202       * @param where the given coordinates, relative to the given <code>Component</code>.
203       * @param button the mouse button to press.
204       */
205      void pressMouse(Component c, Point where, MouseButton button);
206    
207      /**
208       * Simulates a user pressing the given mouse button on the given coordinates.
209       * @param where the position where to press the given mouse button.
210       * @param button the mouse button to press.
211       * @since 1.1
212       */
213      void pressMouse(Point where, MouseButton button);
214    
215      /**
216       * Simulates a user moving the mouse pointer to the center of the given <code>{@link Component}</code>.
217       * @param c the given <code>Component</code>.
218       */
219      void moveMouse(Component c);
220    
221      /**
222       * Simulates a user moving the mouse pointer to the given coordinates relative to the given
223       * <code>{@link Component}</code>.
224       * @param c the given <code>Component</code>.
225       * @param p the given coordinates, relative to the given <code>Component</code>.
226       * @throws ActionFailedException if the given component is not showing and ready for input.
227       */
228      void moveMouse(Component c, Point p);
229    
230      /**
231       * Simulates a user moving the mouse pointer to the given coordinates relative to the given
232       * <code>{@link Component}</code>.
233       * @param c the given <code>Component</code>.
234       * @param x X coordinate, relative to the given <code>Component</code>.
235       * @param y Y coordinate, relative to the given <code>Component</code>.
236       * @throws ActionFailedException if the given component is not showing and ready for input.
237       */
238      void moveMouse(Component c, int x, int y);
239    
240      /**
241       * Simulates a user moving the mouse pointer to the given coordinates.
242       * @param p the given coordinates.
243       * @since 1.1
244       */
245      void moveMouse(Point p);
246    
247      /**
248       * Simulates a user moving the mouse pointer to the given coordinates.
249       * @param x X coordinate.
250       * @param y Y coordinate.
251       * @since 1.1
252       */
253      void moveMouse(int x, int y);
254    
255      /**
256       * Releases the given mouse button.
257       * @param button the mouse button to release.
258       */
259      void releaseMouse(MouseButton button);
260    
261      /**
262       * Releases any mouse button(s) used by the robot.
263       */
264      void releaseMouseButtons();
265    
266      /**
267       * Moves the mouse pointer over to the given <code>{@link Component}</code> and rotates the scroll wheel on
268       * wheel-equipped mice.
269       * @param c the given <code>Component</code>.
270       * @param amount number of "notches" to move the mouse wheel. Negative values indicate movement up/away from the user,
271       * while positive values indicate movement down/towards the user.
272       */
273      void rotateMouseWheel(Component c, int amount);
274    
275      /**
276       * Rotates the scroll wheel on wheel-equipped mice.
277       * @param amount number of "notches" to move the mouse wheel. Negative values indicate movement up/away from the user,
278       * while positive values indicate movement down/towards the user.
279       */
280      void rotateMouseWheel(int amount);
281    
282      /**
283       * Makes the mouse pointer show small quick jumpy movements on the given <code>{@link Component}</code>.
284       * @param c the given <code>Component</code>.
285       */
286      void jitter(Component c);
287    
288      /**
289       * Makes the mouse pointer show small quick jumpy movements on the given <code>{@link Component}</code> at the given
290       * point.
291       * @param c the given <code>Component</code>.
292       * @param where the given point.
293       */
294      void jitter(Component c, Point where);
295    
296      /**
297       * Simulates a user entering the given text. Note that this method the key strokes to the component that has input
298       * focus.
299       * @param text the text to enter.
300       */
301      void enterText(String text);
302    
303      /**
304       * Types the given character. Note that this method sends the key strokes to the component that has input focus.
305       * @param character the character to type.
306       */
307      void type(char character);
308    
309      /**
310       * Type the given key code with the given modifiers. Modifiers is a mask from the available
311       * <code>{@link java.awt.event.InputEvent}</code> masks.
312       * @param keyCode the code of the key to press.
313       * @param modifiers the given modifiers.
314       * @throws IllegalArgumentException if the given code is not a valid key code.
315       */
316      void pressAndReleaseKey(int keyCode, int... modifiers);
317    
318      /**
319       * Simulates a user pressing and releasing the given keys. This method does not affect the current focus.
320       * @param keyCodes one or more codes of the keys to press.
321       * @see java.awt.event.KeyEvent
322       * @throws IllegalArgumentException if any of the given codes is not a valid key code.
323       */
324      void pressAndReleaseKeys(int... keyCodes);
325    
326      /**
327       * Simulates a user pressing given key. This method does not affect the current focus.
328       * @param keyCode the code of the key to press.
329       * @see java.awt.event.KeyEvent
330       * @throws IllegalArgumentException if the given code is not a valid key code.
331       */
332      void pressKey(int keyCode);
333    
334      /**
335       * Simulates a user releasing the given key. This method does not affect the current focus.
336       * @param keyCode the code of the key to release.
337       * @see java.awt.event.KeyEvent
338       * @throws IllegalArgumentException if the given code is not a valid key code.
339       */
340      void releaseKey(int keyCode);
341    
342      /**
343       * Presses the appropriate modifiers corresponding to the given mask. Use mask values from
344       * <code>{@link InputEvent}</code>.
345       * @param modifierMask the given mask.
346       * @see InputEvent
347       */
348      void pressModifiers(int modifierMask);
349    
350      /**
351       * Releases the appropriate modifiers corresponding to the given mask. Use mask values from
352       * <code>{@link InputEvent}</code>.
353       * @param modifierMask the given mask.
354       * @see InputEvent
355       */
356      void releaseModifiers(int modifierMask);
357    
358      /**
359       * Wait for an idle AWT event queue. Note that this is different from the implementation of
360       * <code>java.awt.Robot.waitForIdle()</code>, which may have events on the queue when it returns. Do <strong>NOT</strong>
361       * use this method if there are animations or other continual refreshes happening, since in that case it may never
362       * return.
363       * @throws IllegalThreadStateException if this method is called from the event dispatch thread.
364       */
365      void waitForIdle();
366    
367      /**
368       * Indicates whether the robot is currently in a dragging operation.
369       * @return <code>true</code> if the robot is currently in a dragging operation, <code>false</code> otherwise.
370       */
371      boolean isDragging();
372    
373      /**
374       * Indicates whether the given <code>{@link Component}</code> is ready for input.
375       * @param c the given <code>Component</code>.
376       * @return <code>true</code> if the given <code>Component</code> is ready for input, <code>false</code> otherwise.
377       * @throws ActionFailedException if the given <code>Component</code> does not have a <code>Window</code> ancestor.
378       */
379      boolean isReadyForInput(Component c);
380    
381      /**
382       * Shows a pop-up menu.
383       * @param invoker the component to invoke the pop-up menu from.
384       * @return the displayed pop-up menu.
385       * @throws org.fest.swing.exception.ComponentLookupException if a pop-up menu cannot be found.
386       */
387      JPopupMenu showPopupMenu(Component invoker);
388    
389      /**
390       * Shows a pop-up menu at the given coordinates.
391       * @param invoker the component to invoke the pop-up menu from.
392       * @param location the given coordinates for the pop-up menu.
393       * @return the displayed pop-up menu.
394       * @throws ComponentLookupException if a pop-up menu cannot be found.
395       */
396      JPopupMenu showPopupMenu(Component invoker, Point location);
397    
398      /**
399       * Returns the currently active pop-up menu, if any. If no pop-up is currently showing, returns <code>null</code>.
400       * @return the currently active pop-up menu or <code>null</code>, if no pop-up is currently showing.
401       */
402      JPopupMenu findActivePopupMenu();
403    
404      /**
405       * Ensures that there is no <code>{@link javax.swing.JOptionPane}</code> showing, and potentially blocking GUI tests.
406       * @throws AssertionError if there is one or more <code>JOptionPane</code>s showing on the screen.
407       */
408      void requireNoJOptionPaneIsShowing();
409    
410      /**
411       * Returns the configuration settings for this <code>{@link Robot}</code>.
412       * @return the configuration settings for this <code>Robot</code>.
413       */
414      Settings settings();
415    
416      /**
417       * Indicates whether this <code>Robot</code> is active. Being "active" means that <code>{@link #cleanUp()}</code> has
418       * not been called yet.
419       * @return <code>true</code> if this <code>Robot</code> is active, <code>false</code> otherwise.
420       */
421      boolean isActive();
422    }