Coverage Report - org.eclipse.swtbot.swt.finder.SWTBotFactory
 
Classes in this File Line Coverage Branch Coverage Complexity
SWTBotFactory
65%
85/130
76%
20/26
1.449
SWTBotFactory$1
100%
3/3
N/A
1.449
SWTBotFactory$2
100%
3/3
N/A
1.449
 
 1  16
 /*******************************************************************************
 2  
  * Copyright (c) 2008 Ketan Padegaonkar and others.
 3  
  * All rights reserved. This program and the accompanying materials
 4  
  * are made available under the terms of the Eclipse Public License v1.0
 5  
  * which accompanies this distribution, and is available at
 6  
  * http://www.eclipse.org/legal/epl-v10.html
 7  
  *
 8  
  * Contributors:
 9  
  *     Ketan Padegaonkar - initial API and implementation
 10  
  *     Vincent Mahe - http://swtbot.org/bugzilla/show_bug.cgi?id=123
 11  
  *     Ketan Padegaonkar - http://swtbot.org/bugzilla/show_bug.cgi?id=136
 12  
  *     Hans Schwaebli - http://swtbot.org/bugzilla/show_bug.cgi?id=135
 13  
  *     Ketan Patel - https://bugs.eclipse.org/bugs/show_bug.cgi?id=259837
 14  
  *     Toby Weston - (Bug 259860)
 15  
  *     Ketan Patel - (Bug 259860)
 16  
  *******************************************************************************/
 17  
 package org.eclipse.swtbot.swt.finder;
 18  
 
 19  
 import static org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable.syncExec;
 20  
 import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.allOf;
 21  
 import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.widgetOfType;
 22  
 import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withId;
 23  
 import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withMnemonic;
 24  
 import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withText;
 25  
 import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withTooltip;
 26  
 import static org.eclipse.swtbot.swt.finder.waits.Conditions.waitForMenu;
 27  
 import static org.eclipse.swtbot.swt.finder.waits.Conditions.waitForShell;
 28  
 import static org.eclipse.swtbot.swt.finder.waits.Conditions.waitForWidget;
 29  
 
 30  
 import java.util.ArrayList;
 31  
 import java.util.List;
 32  
 
 33  
 import org.eclipse.swt.widgets.Control;
 34  
 import org.eclipse.swt.widgets.Display;
 35  
 import org.eclipse.swt.widgets.MenuItem;
 36  
 import org.eclipse.swt.widgets.Shell;
 37  
 import org.eclipse.swt.widgets.Tray;
 38  
 import org.eclipse.swt.widgets.TrayItem;
 39  
 import org.eclipse.swt.widgets.Widget;
 40  
 import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
 41  
 import org.eclipse.swtbot.swt.finder.finders.Finder;
 42  
 import org.eclipse.swtbot.swt.finder.matchers.WithItem;
 43  
 import org.eclipse.swtbot.swt.finder.results.Result;
 44  
 import org.eclipse.swtbot.swt.finder.results.VoidResult;
 45  
 import org.eclipse.swtbot.swt.finder.results.WidgetResult;
 46  
 import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences;
 47  
 import org.eclipse.swtbot.swt.finder.utils.SWTUtils;
 48  
 import org.eclipse.swtbot.swt.finder.utils.internal.Assert;
 49  
 import org.eclipse.swtbot.swt.finder.waits.ICondition;
 50  
 import org.eclipse.swtbot.swt.finder.waits.WaitForObjectCondition;
 51  
 import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
 52  
 import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
 53  
 import org.eclipse.swtbot.swt.finder.widgets.SWTBotTrayItem;
 54  
 import org.eclipse.swtbot.swt.finder.widgets.TimeoutException;
 55  
 import org.hamcrest.Matcher;
 56  
 
 57  
 /**
 58  
  * Instances of this class provide a convenience API to access widgets.
 59  
  * <p>
 60  
  * Note: The SWTEclipeBot should be used if testing an eclipse based product/plug-in.
 61  
  * </p>
 62  
  *
 63  
  * @author Ketan Padegaonkar &lt;KetanPadegaonkar [at] gmail [dot] com&gt;
 64  
  * @author Vincent Mahe &lt;vmahe [at] irisa [dot] fr&gt;
 65  
  * @version $Id$
 66  
  * @since 2.0
 67  
  */
 68  1
 abstract class SWTBotFactory {
 69  
 
 70  
         /** the delay between successive polling while waiting for a condition to be true. Use SWTBotPreferences#DEFAULT_POLL_DELAY */
 71  
         @Deprecated
 72  1
         public static final long        DEFAULT_POLL_DELAY        = SWTBotPreferences.DEFAULT_POLL_DELAY;
 73  
         /** The display on which the bot operates on. */
 74  
         protected final Display                display;
 75  
         /** The finder used by the bot to find controls. */
 76  
         protected final Finder                finder;
 77  
 
 78  
         /**
 79  
          * Constructs a bot with the given finder.
 80  
          *
 81  
          * @param finder the finder.
 82  
          */
 83  3329
         public SWTBotFactory(Finder finder) {
 84  3329
                 display = SWTUtils.display();
 85  3329
                 this.finder = finder;
 86  3329
         }
 87  
 
 88  
         /**
 89  
          * @return a wrapper around a @{link Shell} with the specified text.
 90  
          * @param text the text on the shell.
 91  
          */
 92  
         public SWTBotShell shell(String text) {
 93  39
                 return shell(text, 0);
 94  
         }
 95  
 
 96  
         /**
 97  
          * @return a wrapper around a {@link Shell} with the specified index.
 98  
          * @param text the text on the shell.
 99  
          * @param index the index of the shell, in case there are multiple shells with the same text.
 100  
          */
 101  
         public SWTBotShell shell(String text, int index) {
 102  39
                 return new SWTBotShell(shells(text).get(index));
 103  
         }
 104  
 
 105  
         /**
 106  
          * @return a wrapper around a {@link Shell} with the specified index.
 107  
          * @param text the text on the shell.
 108  
          */
 109  
         public List<Shell> shells(String text) {
 110  39
                 Matcher<Shell> withText = withText(text);
 111  39
                 WaitForObjectCondition<Shell> waitForShell = waitForShell(withText);
 112  39
                 waitUntilWidgetAppears(waitForShell);
 113  37
                 List<Shell> allShells = waitForShell.getAllMatches();
 114  37
                 return allShells;
 115  
         }
 116  
 
 117  
         /**
 118  
          * @return a wrapper around a @{link Shell} with the specified text.
 119  
          * @param text the text on the shell.
 120  
          * @param parent the parent under which a shell will be found.
 121  
          */
 122  
         public SWTBotShell shell(String text, Shell parent) {
 123  0
                 return shell(text, parent, 0);
 124  
         }
 125  
 
 126  
         /**
 127  
          * @return a wrapper around a {@link Shell} with the specified index.
 128  
          * @param text the text on the shell.
 129  
          * @param parent the parent under which a shell will be found.
 130  
          * @param index the index of the shell, in case there are multiple shells with the same text.
 131  
          */
 132  
         public SWTBotShell shell(String text, Shell parent, int index) {
 133  0
                 return new SWTBotShell(shells(text, parent).get(index));
 134  
         }
 135  
 
 136  
         /**
 137  
          * @return a List of {@link Shell} which matched.
 138  
          * @param text the text on the shell.
 139  
          * @param parent the parent under which a shell will be found.
 140  
          */
 141  
         public List<Shell> shells(String text, Shell parent) {
 142  0
                 Matcher<Shell> withText = withText(text);
 143  0
                 WaitForObjectCondition<Shell> waitForShell = waitForShell(withText, parent);
 144  0
                 waitUntilWidgetAppears(waitForShell);
 145  0
                 List<Shell> allShells = waitForShell.getAllMatches();
 146  0
                 return allShells;
 147  
         }
 148  
 
 149  
         /**
 150  
          * @param value the value of the id
 151  
          * @return a wrapper around a @{link Shell} with the specified value pair for its id.
 152  
          * @since 2.0
 153  
          */
 154  
         public SWTBotShell shellWithId(String value) {
 155  0
                 return shellWithId(value, 0);
 156  
         }
 157  
 
 158  
         /**
 159  
          * @param key the key of the id
 160  
          * @param value the value of the id
 161  
          * @return a wrapper around a @{link Shell} with the specified key/value pair for its id.
 162  
          */
 163  
         public SWTBotShell shellWithId(String key, String value) {
 164  1
                 return shellWithId(key, value, 0);
 165  
         }
 166  
 
 167  
         /**
 168  
          * @param value the value of the id
 169  
          * @param index the index of the shell, in case there are multiple shells with the same text.
 170  
          * @return a wrapper around a @{link Shell} with the specified value for its id.
 171  
          * @since 2.0
 172  
          */
 173  
         public SWTBotShell shellWithId(String value, int index) {
 174  0
                 Matcher<Shell> withId = withId(value);
 175  0
                 WaitForObjectCondition<Shell> waitForShell = waitForShell(withId);
 176  0
                 waitUntilWidgetAppears(waitForShell);
 177  0
                 return new SWTBotShell(waitForShell.get(index));
 178  
         }
 179  
 
 180  
         /**
 181  
          * @param key the key of the id
 182  
          * @param value the value of the id
 183  
          * @param index the index of the shell, in case there are multiple shells with the same text.
 184  
          * @return a wrapper around a @{link Shell} with the specified key/value pair for its id.
 185  
          */
 186  
         public SWTBotShell shellWithId(String key, String value, int index) {
 187  1
                 Matcher<Shell> withId = withId(key, value);
 188  1
                 WaitForObjectCondition<Shell> waitForShell = waitForShell(withId);
 189  1
                 waitUntilWidgetAppears(waitForShell);
 190  1
                 return new SWTBotShell(waitForShell.get(index));
 191  
         }
 192  
 
 193  
         /**
 194  
          * @param text the text on the menu.
 195  
          * @return a menu item that matches the specified text.
 196  
          */
 197  
         public SWTBotMenu menu(String text) {
 198  5
                 return menu(text, 0);
 199  
         }
 200  
 
 201  
         /**
 202  
          * @param text the text on the menu.
 203  
          * @param index the index of the menu, in case there are multiple menus with the same text.
 204  
          * @return a menu item that matches the specified text.
 205  
          */
 206  
         public SWTBotMenu menu(String text, int index) {
 207  5
                 Matcher<MenuItem> withMnemonic = withMnemonic(text);
 208  5
                 return menu(activeShell(), withMnemonic, index);
 209  
         }
 210  
 
 211  
         /**
 212  
          * @param value the value of the id.
 213  
          * @return a wrapper around a @{link Menu} with the specified key/value pair for its id.
 214  
          */
 215  
         public SWTBotMenu menuWithId(String value) {
 216  0
                 return menuWithId(value, 0);
 217  
         }
 218  
 
 219  
         /**
 220  
          * @param value the value of the id.
 221  
          * @param index the index of the menu item, in case there are multiple shells with the same text.
 222  
          * @return a wrapper around a @{link Menu} with the specified key/value pair for its id.
 223  
          */
 224  
         public SWTBotMenu menuWithId(String value, int index) {
 225  0
                 Matcher<MenuItem> withId = withId(value);
 226  0
                 return menu(activeShell(), withId, index);
 227  
         }
 228  
 
 229  
         /**
 230  
          * @param key the key of the id.
 231  
          * @param value the value of the id.
 232  
          * @return a wrapper around a @{link Menu} with the specified key/value pair for its id.
 233  
          */
 234  
         public SWTBotMenu menuWithId(String key, String value) {
 235  0
                 return menuWithId(key, value, 0);
 236  
         }
 237  
 
 238  
         /**
 239  
          * @param key the key of the id.
 240  
          * @param value the value of the id.
 241  
          * @param index the index of the menu item, in case there are multiple shells with the same text.
 242  
          * @return a wrapper around a @{link Menu} with the specified key/value pair for its id.
 243  
          */
 244  
         public SWTBotMenu menuWithId(String key, String value, int index) {
 245  0
                 Matcher<MenuItem> withId = withId(key, value);
 246  0
                 return menu(activeShell(), withId, index);
 247  
         }
 248  
 
 249  
         /**
 250  
          * @param shell the shell to search for the menu.
 251  
          * @param matcher the matcher used to find the menu.
 252  
          * @param index the index of the menu, in case there are multiple menus with the same text.
 253  
          * @return a menu item that matches the specified text.
 254  
          */
 255  
         public SWTBotMenu menu(SWTBotShell shell, Matcher<MenuItem> matcher, int index) {
 256  5
                 WaitForObjectCondition<MenuItem> waitForMenu = waitForMenu(shell, matcher);
 257  5
                 waitUntilWidgetAppears(waitForMenu);
 258  3
                 return new SWTBotMenu(waitForMenu.get(index), matcher);
 259  
         }
 260  
 
 261  
         /**
 262  
          * @param matcher the matcher used to match widgets.
 263  
          * @param parentWidget the parent widget to search for a given widget.
 264  
          * @return a list of widgets that match the matcher.
 265  
          */
 266  
         public <T extends Widget> List<? extends T> widgets(Matcher<T> matcher, Widget parentWidget) {
 267  0
                 WaitForObjectCondition<T> waitForWidget = waitForWidget(matcher, parentWidget);
 268  0
                 waitUntilWidgetAppears(waitForWidget);
 269  0
                 return waitForWidget.getAllMatches();
 270  
         }
 271  
 
 272  
         /**
 273  
          * @param matcher the matcher used to match widgets.
 274  
          * @return a list of widgets in the active shell that match the matcher.
 275  
          */
 276  
         public <T extends Widget> List<? extends T> widgets(Matcher<T> matcher) {
 277  0
                 return widgets(matcher, activeShell().widget);
 278  
         }
 279  
 
 280  
         /**
 281  
          * @param matcher the matcher used to match widgets.
 282  
          * @param parentWidget the parent widget to search for a given widget.
 283  
          * @return the first widget that matchs the matcher.
 284  
          */
 285  
         public <T extends Widget> T widget(Matcher<T> matcher, Widget parentWidget) {
 286  0
                 return widget(matcher, parentWidget, 0);
 287  
         }
 288  
 
 289  
         /**
 290  
          * @param matcher the matcher used to match widgets.
 291  
          * @param parentWidget the parent widget to search for a given widget.
 292  
          * @param index the index of the widget, incase the matcher finds multiple widgets
 293  
          * @return the first widget that matchs the matcher.
 294  
          */
 295  
         public <T extends Widget> T widget(Matcher<T> matcher, Widget parentWidget, int index) {
 296  0
                 WaitForObjectCondition<T> waitForWidget = waitForWidget(matcher, parentWidget);
 297  0
                 waitUntilWidgetAppears(waitForWidget);
 298  0
                 return waitForWidget.get(index);
 299  
         }
 300  
 
 301  
         /**
 302  
          * @param matcher the matcher used to match widgets.
 303  
          * @param index the index of the widget in case there are multiple widgets.
 304  
          * @return the index'th widget matching the matcher.
 305  
          */
 306  
         public <T extends Widget> T widget(Matcher<T> matcher, int index) {
 307  1732
                 WaitForObjectCondition<T> waitForWidget = waitForWidget(matcher);
 308  1732
                 waitUntilWidgetAppears(waitForWidget);
 309  1717
                 return waitForWidget.get(index);
 310  
         }
 311  
 
 312  
         /**
 313  
          * @param matcher the matcher used to match widgets.
 314  
          * @return the index'th widget matching the matcher.
 315  
          */
 316  
         public <T extends Widget> T widget(Matcher<T> matcher) {
 317  2
                 return widget(matcher, 0);
 318  
         }
 319  
 
 320  
         /**
 321  
          * Gets the list of shells found in the display.
 322  
          *
 323  
          * @return all the shells in the display.
 324  
          */
 325  
         public SWTBotShell[] shells() {
 326  1
                 Shell[] shells = finder.getShells();
 327  1
                 ArrayList<SWTBotShell> result = new ArrayList<SWTBotShell>();
 328  9
                 for (Shell shell : shells) {
 329  8
                         result.add(new SWTBotShell(shell));
 330  
                 }
 331  1
                 return result.toArray(new SWTBotShell[] {});
 332  
         }
 333  
 
 334  
         /**
 335  
          * Gets the current active shell.
 336  
          *
 337  
          * @return the current active shell
 338  
          * @throws WidgetNotFoundException if the widget is not found.
 339  
          */
 340  
         public SWTBotShell activeShell() throws WidgetNotFoundException {
 341  13
                 return new SWTBotShell(getFinder().activeShell());
 342  
         }
 343  
 
 344  
         public void waitUntilWidgetAppears(ICondition waitForWidget) {
 345  
                 try {
 346  1790
                         waitUntil(waitForWidget);
 347  20
                 } catch (TimeoutException e) {
 348  20
                         throw new WidgetNotFoundException("Could not find widget.", e); //$NON-NLS-1$
 349  
                 }
 350  1770
         }
 351  
 
 352  
         /**
 353  
          * Waits until a specified condition evaluates to true.
 354  
          *
 355  
          * @param condition the {@link ICondition} to be evaluated.
 356  
          * @throws TimeoutException if the condition does not evaluate to true after {@link SWTBotPreferences#TIMEOUT} milliseconds.
 357  
          * @since 1.2
 358  
          */
 359  
         public void waitUntil(ICondition condition) throws TimeoutException {
 360  4772
                 waitUntil(condition, SWTBotPreferences.TIMEOUT);
 361  4751
         }
 362  
 
 363  
         /**
 364  
          * Waits until the timeout is reached or the condition is met.
 365  
          *
 366  
          * @param condition the condition to be evaluated.
 367  
          * @param timeout the timeout.
 368  
          * @throws TimeoutException if the condition does not evaluate to true after timeout milliseconds.
 369  
          * @since 1.2
 370  
          */
 371  
         public void waitUntil(ICondition condition, long timeout) throws TimeoutException {
 372  4773
                 waitUntil(condition, timeout, SWTBotPreferences.DEFAULT_POLL_DELAY);
 373  4751
         }
 374  
 
 375  
         /**
 376  
          * Waits until the condition has been meet, or the timeout is reached. The interval is the delay between evaluating
 377  
          * the condition after it has failed.
 378  
          *
 379  
          * @param condition the condition to be evaluated.
 380  
          * @param timeout the timeout.
 381  
          * @param interval The delay time.
 382  
          * @throws TimeoutException if the condition does not evaluate to true after timeout milliseconds.
 383  
          */
 384  
         public void waitUntil(ICondition condition, long timeout, long interval) throws TimeoutException {
 385  4773
                 Assert.isTrue(interval >= 0, "interval value is negative"); //$NON-NLS-1$
 386  4773
                 Assert.isTrue(timeout >= 0, "timeout value is negative"); //$NON-NLS-1$
 387  4772
                 long limit = System.currentTimeMillis() + timeout;
 388  4772
                 condition.init((SWTBot) this);
 389  
                 while (true) {
 390  
                         try {
 391  4914
                                 if (condition.test())
 392  4751
                                         return;
 393  0
                         } catch (Throwable e) {
 394  
                                 // do nothing
 395  
                         }
 396  163
                         sleep(interval);
 397  163
                         if (System.currentTimeMillis() > limit)
 398  21
                                 throw new TimeoutException("Timeout after: " + timeout + " ms.: " + condition.getFailureMessage()); //$NON-NLS-1$ //$NON-NLS-2$
 399  
                 }
 400  
         }
 401  
 
 402  
         /**
 403  
          * Waits while the condition is true.
 404  
          *
 405  
          * @param condition the {@link ICondition} to be evaluated.
 406  
          * @throws TimeoutException if the condition does not evaluate to false after {@link SWTBotPreferences#TIMEOUT} milliseconds.
 407  
          * @since 2.0
 408  
          */
 409  
         public void waitWhile(ICondition condition) throws TimeoutException {
 410  2
                 waitWhile(condition, SWTBotPreferences.TIMEOUT);
 411  1
         }
 412  
 
 413  
         /**
 414  
          * Waits while the condition is true, until the timeout is reached.
 415  
          *
 416  
          * @param condition the condition to be evaluated.
 417  
          * @param timeout the timeout.
 418  
          * @throws TimeoutException if the condition does not evaluate to false after timeout milliseconds.
 419  
          * @since 2.0
 420  
          */
 421  
         public void waitWhile(ICondition condition, long timeout) throws TimeoutException {
 422  2
                 waitWhile(condition, timeout, SWTBotPreferences.DEFAULT_POLL_DELAY);
 423  1
         }
 424  
 
 425  
         /**
 426  
          * Waits while the condition is true, until the timeout is reached. The interval is the delay between evaluating the
 427  
          * condition after it has succeed.
 428  
          *
 429  
          * @param condition the condition to be evaluated.
 430  
          * @param timeout the timeout.
 431  
          * @param interval The delay time.
 432  
          * @throws TimeoutException if the condition does not evaluate to false after timeout milliseconds.
 433  
          * @since 2.0
 434  
          */
 435  
         public void waitWhile(ICondition condition, long timeout, long interval) throws TimeoutException {
 436  2
                 Assert.isTrue(interval >= 0, "interval value is negative"); //$NON-NLS-1$
 437  2
                 Assert.isTrue(timeout >= 0, "timeout value is negative"); //$NON-NLS-1$
 438  2
                 long limit = System.currentTimeMillis() + timeout;
 439  2
                 condition.init((SWTBot) this);
 440  
                 while (true) {
 441  
                         try {
 442  16
                                 if (!condition.test())
 443  1
                                         return;
 444  0
                         } catch (Throwable e) {
 445  
                                 // do nothing
 446  
                         }
 447  15
                         sleep(interval);
 448  15
                         if (System.currentTimeMillis() > limit)
 449  1
                                 throw new TimeoutException("Timeout after: " + timeout + " ms.: " + condition.getFailureMessage()); //$NON-NLS-1$ //$NON-NLS-2$
 450  
                 }
 451  
         }
 452  
 
 453  
         /**
 454  
          * Sleeps for the given number of milliseconds.
 455  
          *
 456  
          * @param millis the time in milliseconds for which to sleep.
 457  
          */
 458  
         public void sleep(long millis) {
 459  181
                 SWTUtils.sleep(millis);
 460  181
         }
 461  
 
 462  
         /**
 463  
          * Gets the display
 464  
          *
 465  
          * @return the display
 466  
          * @since 1.0
 467  
          */
 468  
         public Display getDisplay() {
 469  0
                 return display;
 470  
         }
 471  
 
 472  
         /**
 473  
          * Captures a screenshot to the given file name.
 474  
          *
 475  
          * @see SWTUtils#captureScreenshot(String)
 476  
          * @param fileName the filename to save screenshot to.
 477  
          * @return <code>true</code> if the screenshot was created and saved, <code>false</code> otherwise.
 478  
          * @since 1.1
 479  
          */
 480  
         public boolean captureScreenshot(String fileName) {
 481  0
                 return SWTUtils.captureScreenshot(fileName);
 482  
         }
 483  
 
 484  
         /**
 485  
          * @return the finder
 486  
          */
 487  
         public Finder getFinder() {
 488  1893
                 return finder;
 489  
         }
 490  
 
 491  
         /**
 492  
          * Returns the control which currently has keyboard focus, or <code>null</code> if keyboard events are not currently
 493  
          * going to any of the controls built by the currently running application.
 494  
          *
 495  
          * @return the control which currently has focus, or <code>null</code>
 496  
          * @see Display#getFocusControl()
 497  
          */
 498  
         public Control getFocusedWidget() {
 499  1
                 return syncExec(new WidgetResult<Control>() {
 500  
                         public Control run() {
 501  1
                                 return display.getFocusControl();
 502  
                         }
 503  
                 });
 504  
         }
 505  
 
 506  
         /**
 507  
          * @return the first {@link SWTBotTrayItem}
 508  
          */
 509  
         public SWTBotTrayItem trayItem() {
 510  1
                 return trayItem(0);
 511  
         }
 512  
 
 513  
         /**
 514  
          * @param index he index of the tray item.
 515  
          * @return a {@link SWTBotTrayItem} at specified <code>index</code>
 516  
          */
 517  
         public SWTBotTrayItem trayItem(int index) {
 518  4
                 return trayItems().get(index);
 519  
         }
 520  
 
 521  
         /**
 522  
          * @param tooltip the tooltip on the tray item.
 523  
          * @return the first {@link SWTBotTrayItem} with the specified <code>tooltip</code>.
 524  
          */
 525  
         public SWTBotTrayItem trayItemWithTooltip(String tooltip) {
 526  3
                 return trayItemWithTooltip(tooltip, 0);
 527  
         }
 528  
 
 529  
         /**
 530  
          * @param tooltip the tooltip on the tray item.
 531  
          * @param index the index of the tray item.
 532  
          * @return a {@link SWTBotTrayItem} with the specified <code>tooltip</code>.
 533  
          */
 534  
         @SuppressWarnings("unchecked")
 535  
         public SWTBotTrayItem trayItemWithTooltip(String tooltip, int index) {
 536  3
                 java.util.List<SWTBotTrayItem> items = trayItems(allOf(widgetOfType(TrayItem.class), withTooltip(tooltip)));
 537  3
                 if (items.isEmpty() || items.size() <= index)
 538  0
                         throw new WidgetNotFoundException("Widget does not contain an item at index " + index);
 539  3
                 return items.get(index);
 540  
         }
 541  
 
 542  
         /**
 543  
          * @return List of all tray items in the system tray.
 544  
          */
 545  
         public java.util.List<SWTBotTrayItem> trayItems() {
 546  5
                 return trayItems(widgetOfType(TrayItem.class));
 547  
         }
 548  
 
 549  
         /**
 550  
          * @param matcher the matcher used to match tray item
 551  
          * @return List of {@link SWTBotTrayItem} matching the matcher.
 552  
          */
 553  
         public List<SWTBotTrayItem> trayItems(Matcher<?> matcher) {
 554  8
                 WithItem<TrayItem> itemMatcher = WithItem.withItem(matcher);
 555  8
                 WaitForObjectCondition<?> waitForWidget = waitForWidget(itemMatcher, systemTray());
 556  8
                 waitUntilWidgetAppears(waitForWidget);
 557  8
                 List<SWTBotTrayItem> items = new ArrayList<SWTBotTrayItem>();
 558  34
                 for (TrayItem item : itemMatcher.getAllMatches())
 559  18
                         items.add(new SWTBotTrayItem(item));
 560  8
                 return items;
 561  
         }
 562  
 
 563  
         /**
 564  
          * @return The single instance of the system tray
 565  
          */
 566  
         protected Tray systemTray() {
 567  8
                 Tray tray = syncExec(SWTUtils.display(), new WidgetResult<Tray>() {
 568  
                         public Tray run() {
 569  8
                                 return SWTUtils.display().getSystemTray();
 570  
                         }
 571  
                 });
 572  8
                 if (tray == null) {
 573  0
                         throw new WidgetNotFoundException("no system tray found");
 574  
                 }
 575  8
                 return tray;
 576  
         }
 577  
 
 578  
         /**
 579  
          * Performs an operation with a timeout and return a result.
 580  
          * <p>
 581  
          * This is a convenience api for performing a particular operation with a different timeout:
 582  
          * </p>
 583  
          *
 584  
          * <pre>
 585  
          * long timeout = ...;
 586  
          * long old = SWTBotPreferences.TIMEOUT;
 587  
          * SWTBotPreferences.TIMEOUT = timeout;
 588  
          * try {
 589  
          *         // do something that takes very long
 590  
          *         return aNumber;
 591  
          * } finally {
 592  
          *         SWTBotPreferences.TIMEOUT = old;
 593  
          * }
 594  
          * </pre>
 595  
          * <p>
 596  
          * The above can now be written as:
 597  
          * </p>
 598  
          *
 599  
          * <pre>
 600  
          * performWithTimeout(new Result<Integer>() {
 601  
          *         public Integer run() {
 602  
          *                // do something that takes very long
 603  
          *         }
 604  
          * }, timeout);
 605  
          *</pre>
 606  
          *
 607  
          * @param runnable the runnable to execute.
 608  
          * @param timeout the timeout for performing the operation.
 609  
          * @return the result of executing the runnable.
 610  
          */
 611  
         public <T> T performWithTimeout(Result<T> runnable, long timeout){
 612  0
                 long old = SWTBotPreferences.TIMEOUT;
 613  0
                 SWTBotPreferences.TIMEOUT = timeout;
 614  
         try {
 615  0
                 return runnable.run();
 616  0
         } finally {
 617  0
                 SWTBotPreferences.TIMEOUT = old;
 618  0
         }
 619  
 
 620  
         }
 621  
 
 622  
         /**
 623  
          * @see #performWithTimeout(Result, long) for more information.
 624  
          * @param runnable the runnable to execute.
 625  
          * @param timeout the timeout for performing the operation.
 626  
          */
 627  
         public void performWithTimeout(VoidResult runnable, long timeout) {
 628  0
                 long old = SWTBotPreferences.TIMEOUT;
 629  0
                 SWTBotPreferences.TIMEOUT = timeout;
 630  
         try {
 631  0
                 runnable.run();
 632  0
         } finally {
 633  0
                 SWTBotPreferences.TIMEOUT = old;
 634  0
         }
 635  0
         }
 636  
 }