001    /*
002     * Created on May 21, 2007
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 @2007-2010 the original author or authors.
015     */
016    package org.fest.swing.fixture;
017    
018    import java.awt.Point;
019    import java.util.regex.Pattern;
020    
021    import javax.swing.*;
022    import javax.swing.tree.TreePath;
023    
024    import org.fest.swing.cell.JTreeCellReader;
025    import org.fest.swing.core.*;
026    import org.fest.swing.driver.BasicJTreeCellReader;
027    import org.fest.swing.driver.JTreeDriver;
028    import org.fest.swing.exception.*;
029    import org.fest.swing.timing.Timeout;
030    
031    /**
032     * Understands functional testing of <code>{@link JTree}</code>s:
033     * <ul>
034     * <li>user input simulation</li>
035     * <li>state verification</li>
036     * <li>property value query</li>
037     * </ul>
038     * <p>
039     * <code>{@link TreePath}</code>s can be specified using <code>String</code>s. For example, for the following
040     * tree:
041     *
042     * <pre><code>
043     * root
044     *   |
045     *   -- node1
046     *      |
047     *      -- node1.1
048     * </code></pre>
049     *
050     * we can identify the node "node1.1" as follows:
051     *
052     * <pre><code>
053     *   root/node1/node1.1
054     * </code></pre>
055     *
056     * </p>
057     * <p>
058     * The default path separator is "/". It can be changed by calling <code>{@link #separator(String)}</code>.
059     * </p>
060     * <p>
061     * The conversion between the values given in tests and the values being displayed by a <code>{@link JTree}</code>
062     * renderer is performed by a <code>{@link JTreeCellReader}</code>. This fixture uses a
063     * <code>{@link BasicJTreeCellReader}</code> by default.
064     * </p>
065     *
066     * @author Keith Coughtrey
067     * @author Alex Ruiz
068     * @author Yvonne Wang
069     * @author Fabien Barbero
070     */
071    public class JTreeFixture extends ComponentFixture<JTree> implements CommonComponentFixture,
072        JComponentFixture, JPopupMenuInvokerFixture {
073    
074      private JTreeDriver driver;
075    
076      /**
077       * Creates a new <code>{@link JTreeFixture}</code>.
078       * @param robot performs simulation of user events on the given <code>JTree</code>.
079       * @param target the <code>JTree</code> to be managed by this fixture.
080       * @throws NullPointerException if <code>robot</code> is <code>null</code>.
081       * @throws NullPointerException if <code>target</code> is <code>null</code>.
082       */
083      public JTreeFixture(Robot robot, JTree target) {
084        super(robot, target);
085        createDriver();
086      }
087    
088      /**
089       * Creates a new <code>{@link JTreeFixture}</code>.
090       * @param robot performs simulation of user events on a <code>JTree</code>.
091       * @param treeName the name of the <code>JTree</code> to find using the given <code>Robot</code>.
092       * @throws NullPointerException if <code>robot</code> is <code>null</code>.
093       * @throws ComponentLookupException if a matching <code>JTree</code> could not be found.
094       * @throws ComponentLookupException if more than one matching <code>JTree</code> is found.
095       */
096      public JTreeFixture(Robot robot, String treeName) {
097        super(robot, treeName, JTree.class);
098        createDriver();
099      }
100    
101      private void createDriver() {
102        driver(new JTreeDriver(robot));
103      }
104    
105      /**
106       * Sets the <code>{@link JTreeDriver}</code> to be used by this fixture.
107       * @param newDriver the new <code>JTreeDriver</code>.
108       * @throws NullPointerException if the given driver is <code>null</code>.
109       */
110      protected final void driver(JTreeDriver newDriver) {
111        validateNotNull(newDriver);
112        driver = newDriver;
113      }
114    
115      /**
116       * Clicks the given row.
117       * @param row the given row.
118       * @return this fixture.
119       * @throws IllegalStateException if the <code>JTree</code> is disabled.
120       * @throws IllegalStateException if the <code>JTree</code> is not showing on the screen.
121       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
122       * visible rows in the <code>JTree</code>.
123       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
124       * @since 1.2
125       */
126      public JTreeFixture clickRow(int row) {
127        driver.clickRow(target, row);
128        return this;
129      }
130    
131    
132      /**
133       * Clicks the given row.
134       * @param row the given row.
135       * @param button the mouse button to use.
136       * @return this fixture.
137       * @throws NullPointerException if the button is <code>null</code>.
138       * @throws IllegalStateException if the <code>JTree</code> is disabled.
139       * @throws IllegalStateException if the <code>JTree</code> is not showing on the screen.
140       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
141       * visible rows in the <code>JTree</code>.
142       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
143       * @since 1.2
144       */
145      public JTreeFixture clickRow(int row, MouseButton button) {
146        driver.clickRow(target, row, button);
147        return this;
148      }
149    
150    
151      /**
152       * Clicks the given row.
153       * @param row the given row.
154       * @param mouseClickInfo specifies the mouse button to use and how many times to click.
155       * @return this fixture.
156       * @throws NullPointerException if the given <code>MouseClickInfo</code> is <code>null</code>.
157       * @throws IllegalStateException if the <code>JTree</code> is disabled.
158       * @throws IllegalStateException if the <code>JTree</code> is not showing on the screen.
159       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
160       * visible rows in the <code>JTree</code>.
161       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
162       * @since 1.2
163       */
164      public JTreeFixture clickRow(int row, MouseClickInfo mouseClickInfo) {
165        driver.clickRow(target, row, mouseClickInfo);
166        return this;
167      }
168    
169      /**
170       * Clicks the given path, expanding parent nodes if necessary.
171       * @param path the given path.
172       * @return this fixture.
173       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
174       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
175       * @throws LocationUnavailableException if the given path cannot be found.
176       */
177      public JTreeFixture clickPath(String path) {
178        driver.clickPath(target, path);
179        return this;
180      }
181    
182      /**
183       * Clicks the given path, expanding parent nodes if necessary.
184       * @param path the given path.
185       * @param button the mouse button to use.
186       * @return this fixture.
187       * @throws NullPointerException if the button is <code>null</code>.
188       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
189       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
190       * @throws LocationUnavailableException if the given path cannot be found.
191       * @since 1.2
192       */
193      public JTreeFixture clickPath(String path, MouseButton button) {
194        driver.clickPath(target, path, button);
195        return this;
196      }
197    
198      /**
199       * Clicks the given path, expanding parent nodes if necessary.
200       * @param path the given path.
201       * @param mouseClickInfo specifies the mouse button to use and how many times to click.
202       * @return this fixture.
203       * @throws NullPointerException if the given <code>MouseClickInfo</code> is <code>null</code>.
204       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
205       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
206       * @throws LocationUnavailableException if the given path cannot be found.
207       * @since 1.2
208       */
209      public JTreeFixture clickPath(String path, MouseClickInfo mouseClickInfo) {
210        driver.clickPath(target, path, mouseClickInfo);
211        return this;
212      }
213    
214      /**
215       * Double-clicks the given row.
216       * @param row the given row.
217       * @return this fixture.
218       * @throws IllegalStateException if the <code>JTree</code> is disabled.
219       * @throws IllegalStateException if the <code>JTree</code> is not showing on the screen.
220       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
221       * visible rows in the <code>JTree</code>.
222       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
223       * @since 1.2
224       */
225      public JTreeFixture doubleClickRow(int row) {
226        driver.doubleClickRow(target, row);
227        return this;
228      }
229    
230      /**
231       * Double-clicks the given path.
232       * @param path the given path.
233       * @return this fixture.
234       * @throws IllegalStateException if the <code>JTree</code> is disabled.
235       * @throws IllegalStateException if the <code>JTree</code> is not showing on the screen.
236       * @throws LocationUnavailableException if the given path cannot be found.
237       * @since 1.2
238       */
239      public JTreeFixture doubleClickPath(String path) {
240        driver.doubleClickPath(target, path);
241        return this;
242      }
243    
244      /**
245       * Right-clicks the given row.
246       * @param row the given row.
247       * @return this fixture.
248       * @throws IllegalStateException if the <code>JTree</code> is disabled.
249       * @throws IllegalStateException if the <code>JTree</code> is not showing on the screen.
250       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
251       * visible rows in the <code>JTree</code>.
252       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
253       * @since 1.2
254       */
255      public JTreeFixture rightClickRow(int row) {
256        driver.rightClickRow(target, row);
257        return this;
258      }
259    
260      /**
261       * Right-clicks the given path, expanding parent nodes if necessary.
262       * @param path the given path.
263       * @return this fixture.
264       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
265       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
266       * @throws LocationUnavailableException if the given path cannot be found.
267       * @since 1.2
268       */
269      public JTreeFixture rightClickPath(String path) {
270        driver.rightClickPath(target, path);
271        return this;
272      }
273    
274      /**
275       * Simulates a user clicking this fixture's <code>{@link JTree}</code>.
276       * @return this fixture.
277       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
278       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
279       */
280      public JTreeFixture click() {
281        driver.click(target);
282        return this;
283      }
284    
285      /**
286       * Simulates a user clicking this fixture's <code>{@link JTree}</code>.
287       * @param button the button to click.
288       * @return this fixture.
289       * @throws NullPointerException if the given <code>MouseButton</code> is <code>null</code>.
290       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
291       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
292       */
293      public JTreeFixture click(MouseButton button) {
294        driver.click(target, button);
295        return this;
296      }
297    
298      /**
299       * Simulates a user clicking this fixture's <code>{@link JTree}</code>.
300       * @param mouseClickInfo specifies the button to click and the times the button should be clicked.
301       * @return this fixture.
302       * @throws NullPointerException if the given <code>MouseClickInfo</code> is <code>null</code>.
303       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
304       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
305       */
306      public JTreeFixture click(MouseClickInfo mouseClickInfo) {
307        driver.click(target, mouseClickInfo);
308        return this;
309      }
310    
311      /**
312       * Simulates a user double-clicking this fixture's <code>{@link JTree}</code>.
313       * @return this fixture.
314       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
315       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
316       */
317      public JTreeFixture doubleClick() {
318        driver.doubleClick(target);
319        return this;
320      }
321    
322      /**
323       * Simulates a user right-clicking this fixture's <code>{@link JTree}</code>.
324       * @return this fixture.
325       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
326       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
327       */
328      public JTreeFixture rightClick() {
329        driver.rightClick(target);
330        return this;
331      }
332    
333      /**
334       * Simulates a user dragging a row from this fixture's <code>{@link JTree}</code>.
335       * @param row the index of the row to drag.
336       * @return this fixture.
337       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
338       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
339       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
340       * visible rows in the <code>JTree</code>.
341       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
342       */
343      public JTreeFixture drag(int row) {
344        driver.drag(target, row);
345        return this;
346      }
347    
348      /**
349       * Simulates a user dragging an item from this fixture's <code>{@link JTree}</code>.
350       * @param path the path corresponding to the item to drag.
351       * @return this fixture.
352       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
353       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
354       * @throws LocationUnavailableException if the given path cannot be found.
355       */
356      public JTreeFixture drag(String path) {
357        driver.drag(target, path);
358        return this;
359      }
360    
361      /**
362       * Simulates a user dropping an item into this fixture's <code>{@link JTree}</code>.
363       * @param row the row to drop the item to.
364       * @return this fixture.
365       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
366       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
367       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
368       * visible rows in the <code>JTree</code>.
369       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
370       * @throws ActionFailedException if there is no drag action in effect.
371       */
372      public JTreeFixture drop(int row) {
373        driver.drop(target, row);
374        return this;
375      }
376    
377      /**
378       * Simulates a user dropping an item into this fixture's <code>{@link JTree}</code>.
379       * @param path the path corresponding to the item relative to the drop point.
380       * @return this fixture.
381       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
382       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
383       * @throws LocationUnavailableException if the given path cannot be found.
384       * @throws ActionFailedException if there is no drag action in effect.
385       */
386      public JTreeFixture drop(String path) {
387        driver.drop(target, path);
388        return this;
389      }
390    
391      /**
392       * Selects the given path, expanding parent nodes if necessary. Unlike <code>{@link #clickPath(String)}</code>,
393       * this method will not click the path if it is already selected.
394       * @param path the path to select.
395       * @return this fixture.
396       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
397       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
398       * @throws LocationUnavailableException if the given path cannot be found.
399       */
400      public JTreeFixture selectPath(String path) {
401        driver.selectPath(target, path);
402        return this;
403      }
404    
405      /**
406       * Select the given paths, expanding parent nodes if necessary.
407       * @param paths the paths to select.
408       * @return this fixture.
409       * @throws NullPointerException if the array of rows is <code>null</code>.
410       * @throws IllegalArgumentException if the array of rows is empty.
411       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
412       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
413       * @throws LocationUnavailableException if the any of the given paths cannot be found.
414       */
415      public JTreeFixture selectPaths(String... paths) {
416        driver.selectPaths(target, paths);
417        return this;
418      }
419    
420      /**
421       * Simulates a user selecting the tree node at the given row.
422       * @param row the index of the row to select.
423       * @return this fixture.
424       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
425       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
426       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
427       * visible rows in the <code>JTree</code>.
428       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
429       */
430      public JTreeFixture selectRow(int row) {
431        driver.selectRow(target, row);
432        return this;
433      }
434    
435      /**
436       * Simulates a user selecting the tree nodes at the given rows.
437       * @param rows the indices of the rows to select.
438       * @return this fixture.
439       * @throws NullPointerException if the array of rows is <code>null</code>.
440       * @throws IllegalArgumentException if the array of rows is empty.
441       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
442       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
443       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
444       * visible rows in the <code>JTree</code>.
445       * @throws LocationUnavailableException if a tree path for any of the given rows cannot be found.
446       */
447      public JTreeFixture selectRows(int... rows) {
448        driver.selectRows(target, rows);
449        return this;
450      }
451    
452      /**
453       * Simulates a user toggling the open/closed state of the tree node at the given row.
454       * @param row the index of the row to toggle.
455       * @return this fixture.
456       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
457       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
458       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
459       * visible rows in the <code>JTree</code>.
460       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
461       * @throws ActionFailedException if this method fails to toggle the row.
462       */
463      public JTreeFixture toggleRow(int row) {
464        driver.toggleRow(target, row);
465        return this;
466      }
467    
468      /**
469       * Simulates a user expanding the tree node at the given row.
470       * @param row the index of the row to expand.
471       * @return this fixture.
472       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
473       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
474       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
475       * visible rows in the <code>JTree</code>.
476       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
477       * @throws ActionFailedException if this method fails to expand the row.
478       * @since 1.2
479       */
480      public JTreeFixture expandRow(int row) {
481        driver.expandRow(target, row);
482        return this;
483      }
484    
485      /**
486       * Simulates a user collapsing the tree node at the given row.
487       * @param row the index of the row to collapse.
488       * @return this fixture.
489       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
490       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
491       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
492       * visible rows in the <code>JTree</code>.
493       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
494       * @throws ActionFailedException if this method fails to collapse the row.
495       * @since 1.2
496       */
497      public JTreeFixture collapseRow(int row) {
498        driver.collapseRow(target, row);
499        return this;
500      }
501    
502      /**
503       * Simulates a user expanding the tree node at the given path.
504       * @param path the path of the row to expand.
505       * @return this fixture.
506       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
507       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
508       * @throws LocationUnavailableException if the given path cannot be found.
509       * @throws ActionFailedException if this method fails to expand the path.
510       * @since 1.2
511       */
512      public JTreeFixture expandPath(String path) {
513        driver.expandPath(target, path);
514        return this;
515      }
516    
517      /**
518       * Simulates a user collapsing the tree node at the given path.
519       * @param path the path of the row to collapse.
520       * @return this fixture.
521       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
522       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
523       * @throws LocationUnavailableException if the given path cannot be found.
524       * @throws ActionFailedException if this method fails to collapse the path.
525       * @since 1.2
526       */
527      public JTreeFixture collapsePath(String path) {
528        driver.collapsePath(target, path);
529        return this;
530      }
531    
532      /**
533       * Shows a pop-up menu at the position of the node in the given row.
534       * @param row the index of the row invoking the pop-up menu.
535       * @return a fixture that manages the displayed pop-up menu.
536       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
537       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
538       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
539       * visible rows in the <code>JTree</code>.
540       * @throws ComponentLookupException if a pop-up menu cannot be found.
541       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
542       */
543      public JPopupMenuFixture showPopupMenuAt(int row) {
544        JPopupMenu popupMenu = driver.showPopupMenu(target, row);
545        return new JPopupMenuFixture(robot, popupMenu);
546      }
547    
548      /**
549       * Shows a pop-up menu at the position of the last node in the given path. The last node in the given path will be
550       * made visible (by expanding the parent node(s)) if it is not visible.
551       * @param path the path of the node invoking the pop-up menu.
552       * @return a fixture that manages the displayed pop-up menu.
553       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
554       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
555       * @throws ComponentLookupException if a pop-up menu cannot be found.
556       * @throws LocationUnavailableException if the given path cannot be found.
557       */
558      public JPopupMenuFixture showPopupMenuAt(String path) {
559        JPopupMenu popupMenu = driver.showPopupMenu(target, path);
560        return new JPopupMenuFixture(robot, popupMenu);
561      }
562    
563      /**
564       * Gives input focus to this fixture's <code>{@link JTree}</code>.
565       * @return this fixture.
566       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
567       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
568       */
569      public JTreeFixture focus() {
570        driver.focus(target);
571        return this;
572      }
573    
574      /**
575       * Simulates a user pressing given key with the given modifiers on this fixture's <code>{@link JTree}</code>.
576       * Modifiers is a mask from the available <code>{@link java.awt.event.InputEvent}</code> masks.
577       * @param keyPressInfo specifies the key and modifiers to press.
578       * @return this fixture.
579       * @throws NullPointerException if the given <code>KeyPressInfo</code> is <code>null</code>.
580       * @throws IllegalArgumentException if the given code is not a valid key code.
581       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
582       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
583       * @see KeyPressInfo
584       */
585      public JTreeFixture pressAndReleaseKey(KeyPressInfo keyPressInfo) {
586        driver.pressAndReleaseKey(target, keyPressInfo);
587        return this;
588      }
589    
590      /**
591       * Simulates a user pressing and releasing the given keys in this fixture's <code>{@link JTree}</code>.
592       * @param keyCodes the codes of the keys to press.
593       * @return this fixture.
594       * @throws NullPointerException if the given array of codes is <code>null</code>.
595       * @throws IllegalArgumentException if any of the given code is not a valid key code.
596       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
597       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
598       * @see java.awt.event.KeyEvent
599       */
600      public JTreeFixture pressAndReleaseKeys(int...keyCodes) {
601        driver.pressAndReleaseKeys(target, keyCodes);
602        return this;
603      }
604    
605      /**
606       * Simulates a user pressing the given key on this fixture's <code>{@link JTree}</code>.
607       * @param keyCode the code of the key to press.
608       * @return this fixture.
609       * @throws IllegalArgumentException if any of the given code is not a valid key code.
610       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
611       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
612       * @see java.awt.event.KeyEvent
613       */
614      public JTreeFixture pressKey(int keyCode) {
615        driver.pressKey(target, keyCode);
616        return this;
617      }
618    
619      /**
620       * Simulates a user releasing the given key on this fixture's <code>{@link JTree}</code>.
621       * @param keyCode the code of the key to release.
622       * @return this fixture.
623       * @see java.awt.event.KeyEvent
624       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
625       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
626       * @throws IllegalArgumentException if any of the given code is not a valid key code.
627       */
628      public JTreeFixture releaseKey(int keyCode) {
629        driver.releaseKey(target, keyCode);
630        return this;
631      }
632    
633      /**
634       * Asserts that this fixture's <code>{@link JTree}</code> has input focus.
635       * @return this fixture.
636       * @throws AssertionError if this fixture's <code>JTree</code> does not have input focus.
637       */
638      public JTreeFixture requireFocused() {
639        driver.requireFocused(target);
640        return this;
641      }
642    
643      /**
644       * Asserts that this fixture's <code>{@link JTree}</code> is enabled.
645       * @return this fixture.
646       * @throws AssertionError if this fixture's <code>JTree</code> is disabled.
647       */
648      public JTreeFixture requireEnabled() {
649        driver.requireEnabled(target);
650        return this;
651      }
652    
653      /**
654       * Asserts that this fixture's <code>{@link JTree}</code> is enabled.
655       * @param timeout the time this fixture will wait for the component to be enabled.
656       * @return this fixture.
657       * @throws org.fest.swing.exception.WaitTimedOutError if this fixture's <code>JTree</code> is never enabled.
658       */
659      public JTreeFixture requireEnabled(Timeout timeout) {
660        driver.requireEnabled(target, timeout);
661        return this;
662      }
663    
664      /**
665       * Asserts that this fixture's <code>{@link JTree}</code> is disabled.
666       * @return this fixture.
667       * @throws AssertionError if this fixture's <code>JTree</code> is enabled.
668       */
669      public JTreeFixture requireDisabled() {
670        driver.requireDisabled(target);
671        return this;
672      }
673    
674      /**
675       * Asserts that this fixture's <code>{@link JTree}</code> is visible.
676       * @return this fixture.
677       * @throws AssertionError if this fixture's <code>JTree</code> is not visible.
678       */
679      public JTreeFixture requireVisible() {
680        driver.requireVisible(target);
681        return this;
682      }
683    
684      /**
685       * Asserts that this fixture's <code>{@link JTree}</code> is not visible.
686       * @return this fixture.
687       * @throws AssertionError if this fixture's <code>JTree</code> is visible.
688       */
689      public JTreeFixture requireNotVisible() {
690        driver.requireNotVisible(target);
691        return this;
692      }
693    
694      /**
695       * Asserts that this fixture's <code>{@link JTree}</code> is editable.
696       * @throws AssertionError if this fixture's <code>JTree</code> is not editable.
697       * @return this fixture.
698       * @throws AssertionError if this fixture's <code>JTree</code> is not editable.
699       */
700      public JTreeFixture requireEditable() {
701        driver.requireEditable(target);
702        return this;
703      }
704    
705      /**
706       * Asserts that this fixture's <code>{@link JTree}</code> is not editable.
707       * @throws AssertionError if this fixture's <code>JTree</code> is editable.
708       * @return this fixture.
709       * @throws AssertionError if this fixture's <code>JTree</code> is editable.
710       */
711      public JTreeFixture requireNotEditable() {
712        driver.requireNotEditable(target);
713        return this;
714      }
715    
716      /**
717       * Asserts that this fixture's <code>{@link JTree}</code> selection is equal to the given paths.
718       * @param paths the given paths, expected to be selected.
719       * @return this fixture.
720       * @throws NullPointerException if the array of paths is <code>null</code>.
721       * @throws LocationUnavailableException if any of the given path cannot be found.
722       * @throws AssertionError if this fixture's <code>JTree</code> selection is not equal to the given paths.
723       */
724      public JTreeFixture requireSelection(String... paths) {
725        driver.requireSelection(target, paths);
726        return this;
727      }
728    
729      /**
730       * Asserts that this fixture's <code>{@link JTree}</code>'s selected rows are equal to the given one.
731       * @param rows the indices of the rows, expected to be selected.
732       * @throws NullPointerException if the array of row indices is <code>null</code>.
733       * @throws AssertionError if this fixture's <code>JTree</code> selection is not equal to the given rows.
734       * @return this fixture.
735       */
736      public JTreeFixture requireSelection(int... rows) {
737        driver.requireSelection(target, rows);
738        return this;
739      }
740    
741      /**
742       * Asserts that this fixture's <code>{@link JTree}</code>'s does not have any selection.
743       * @return this fixture.
744       * @throws AssertionError if this fixture's <code>JTree</code> has a selection.
745       */
746      public JTreeFixture requireNoSelection() {
747        driver.requireNoSelection(target);
748        return this;
749      }
750    
751      /**
752       * Asserts that the toolTip in this fixture's <code>{@link JTree}</code> matches the given value.
753       * @param expected the given value. It can be a regular expression.
754       * @return this fixture.
755       * @throws AssertionError if the toolTip in this fixture's <code>JTree</code> does not match the given value.
756       * @since 1.2
757       */
758      public JTreeFixture requireToolTip(String expected) {
759        driver.requireToolTip(target, expected);
760        return this;
761      }
762    
763      /**
764       * Asserts that the toolTip in this fixture's <code>{@link JTree}</code> matches the given regular expression
765       * pattern.
766       * @param pattern the regular expression pattern to match.
767       * @return this fixture.
768       * @throws NullPointerException if the given regular expression pattern is <code>null</code>.
769       * @throws AssertionError if the toolTip in this fixture's <code>JTree</code> does not match the given regular
770       * expression.
771       * @since 1.2
772       */
773      public JTreeFixture requireToolTip(Pattern pattern) {
774        driver.requireToolTip(target, pattern);
775        return this;
776      }
777    
778    
779      /**
780       * Returns the client property stored in this fixture's <code>{@link JButton}</code>, under the given key.
781       * @param key the key to use to retrieve the client property.
782       * @return the value of the client property stored under the given key, or <code>null</code> if the property was
783       * not found.
784       * @throws NullPointerException if the given key is <code>null</code>.
785       * @since 1.2
786       */
787      public Object clientProperty(Object key) {
788        return driver.clientProperty(target, key);
789      }
790    
791      /**
792       * Shows a pop-up menu using this fixture's <code>{@link JTree}</code> as the invoker of the pop-up menu.
793       * @return a fixture that manages the displayed pop-up menu.
794       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
795       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
796       * @throws ComponentLookupException if a pop-up menu cannot be found.
797       */
798      public JPopupMenuFixture showPopupMenu() {
799        return new JPopupMenuFixture(robot, driver.invokePopupMenu(target));
800      }
801    
802      /**
803       * Shows a pop-up menu at the given point using this fixture's <code>{@link JTree}</code> as the invoker of the
804       * pop-up menu.
805       * @param p the given point where to show the pop-up menu.
806       * @return a fixture that manages the displayed pop-up menu.
807       * @throws IllegalStateException if this fixture's <code>JTree</code> is disabled.
808       * @throws IllegalStateException if this fixture's <code>JTree</code> is not showing on the screen.
809       * @throws ComponentLookupException if a pop-up menu cannot be found.
810       */
811      public JPopupMenuFixture showPopupMenuAt(Point p) {
812        return new JPopupMenuFixture(robot, driver.invokePopupMenu(target, p));
813      }
814    
815      /**
816       * Returns the separator to use when converting <code>{@link TreePath}</code>s to <code>String</code>s.
817       * @return the separator to use when converting <code>{@link TreePath}</code>s to <code>String</code>s.
818       */
819      public String separator() {
820        return driver.separator();
821      }
822    
823      /**
824       * Updates the separator to use when converting <code>{@link TreePath}</code>s to <code>String</code>s. The default
825       * value is "/".
826       * @param separator the new separator.
827       * @return this fixture.
828       * @throws NullPointerException if the given separator is <code>null</code>.
829       */
830      public JTreeFixture separator(String separator) {
831        driver.separator(separator);
832        return this;
833      }
834    
835      /**
836       * Updates the implementation of <code>{@link JTreeCellReader}</code> to use when comparing internal values of a
837       * <code>{@link JTree}</code> and the values expected in a test. The default implementation to use
838       * is <code>{@link BasicJTreeCellReader}</code>.
839       * @param cellReader the new <code>JTreeCellValueReader</code> to use.
840       * @throws NullPointerException if <code>cellReader</code> is <code>null</code>.
841       * @return this fixture.
842       */
843      public JTreeFixture cellReader(JTreeCellReader cellReader) {
844        driver.cellReader(cellReader);
845        return this;
846      }
847    
848      /**
849       * Returns a fixture that manages the node specified by the given row.
850       * @param row the given row.
851       * @return a fixture that manages the node specified by the given row.
852       * @throws IndexOutOfBoundsException if the given index is less than zero or equal than or greater than the number of
853       * visible rows in the <code>JTree</code>.
854       * @since 1.2
855       */
856      public JTreeNodeFixture node(int row) {
857        driver.validateRow(target, row);
858        return new JTreeRowFixture(this, row);
859      }
860    
861      /**
862       * Returns a fixture that manages the node specified by the given path.
863       * @param path the given path.
864       * @return a fixture that manages the node specified by the given path.
865       * @throws LocationUnavailableException if the given path cannot be found.
866       * @since 1.2
867       */
868      public JTreeNodeFixture node(String path) {
869        driver.validatePath(target, path);
870        return new JTreePathFixture(this, path);
871      }
872    
873      /**
874       * Returns the <code>String</code> representation of the node at the given path.
875       * @param path the given path.
876       * @return the <code>String</code> representation of the node at the given path.
877       * @throws LocationUnavailableException if the given path cannot be found.
878       * @since 1.2
879       */
880      public String valueAt(String path) {
881        return driver.nodeValue(target, path);
882      }
883    
884      /**
885       * Returns the <code>String</code> representation of the given row.
886       * @param row the given row.
887       * @return the <code>String</code> representation of the node at the given path.
888       * @throws IndexOutOfBoundsException if the given row is less than zero or equal than or greater than the number of
889       * visible rows in the <code>JTree</code>.
890       * @throws LocationUnavailableException if a tree path for the given row cannot be found.
891       * @since 1.2
892       */
893      public String valueAt(int row) {
894        return driver.nodeValue(target, row);
895      }
896    }