private void expand(final SWTBotTreeItem entry, boolean wait, final String nextNode) {
    UIThreadRunnable.asyncExec(
        bot.getDisplay(),
        new VoidResult() {
          public void run() {
            entry.expand();
          }
        });

    if (wait) {
      bot.waitUntil(
          new DefaultCondition() {
            public boolean test() throws Exception {
              //                    if ( nextNode != null )
              //                    {
              //                        String adjustedNodeName = nextNode != null ? adjustNodeName(
              // entry, nextNode ) : null;
              //                        SWTBotTreeItem node = entry.getNode( adjustedNodeName );
              //                        if ( node == null )
              //                        {
              //                            return false;
              //                        }
              //                    }
              return !entry.getNodes().contains("Fetching Entries...")
                  && !entry.getNodes().contains("Opening Connection...");
            }

            public String getFailureMessage() {
              return "Could not find entry " + entry.getText() + " -> " + nextNode;
            }
          });
    }
  }
  /**
   * Clicks a button asynchronously and waits till the given condition is fulfilled.
   *
   * @param bot the SWT bot
   * @param button the button to click
   * @param waitCondition the condition to wait for, may be null
   * @throws TimeoutException
   */
  public static void asyncClick(
      final SWTWorkbenchBot bot, final SWTBotButton button, final ICondition waitCondition)
      throws TimeoutException {
    bot.waitUntil(
        new DefaultCondition() {
          public boolean test() throws Exception {
            return button.isEnabled();
          }

          public String getFailureMessage() {
            return "Button isn't enabled.";
          }
        });

    UIThreadRunnable.asyncExec(
        bot.getDisplay(),
        new VoidResult() {
          public void run() {
            button.click();
          }
        });

    if (waitCondition != null) {
      bot.waitUntil(waitCondition);
    }
  }
  /**
   * Expands the entry. Takes care that all attributes and child entries are initialized so that
   * there are no pending background actions and event notifications. This is necessary to avoid
   * race conditions.
   *
   * @param bot the bot
   * @param entry the entry to expand
   * @param nextName the name of the entry that must become visible, may be null
   * @throws Exception the exception
   */
  public static void expandEntry(
      final SWTWorkbenchBot bot, final SWTBotTreeItem entry, final String nextName) {
    UIThreadRunnable.asyncExec(
        bot.getDisplay(),
        new VoidResult() {
          public void run() {
            entry.expand();
          }
        });

    bot.waitUntil(
        new DefaultCondition() {
          public boolean test() throws Exception {
            if (nextName != null) {
              String adjustedNodeName = nextName != null ? adjustNodeName(entry, nextName) : null;
              SWTBotTreeItem node = entry.getNode(adjustedNodeName);
              if (node == null) {
                return false;
              }
            }
            return !entry.getNodes().contains("Fetching Entries...");
          }

          public String getFailureMessage() {
            return "Could not find entry " + entry.getText() + " -> " + nextName;
          }
        });
  }
 /** click on the edit part at the specified location */
 public SWTBotGefEditPart click(final Point location) {
   UIThreadRunnable.asyncExec(
       new VoidResult() {
         public void run() {
           graphicalEditor.getCanvas().mouseEnterLeftClickAndExit(location.x, location.y);
         }
       });
   return this;
 }
 /** double click on the edit part. */
 public SWTBotGefEditPart doubleClick() {
   final Rectangle bounds = getBounds();
   UIThreadRunnable.asyncExec(
       new VoidResult() {
         public void run() {
           graphicalEditor.getCanvas().mouseMoveDoubleClick(bounds.x, bounds.y);
         }
       });
   return this;
 }
 public SWTBotGefEditPart activateDirectEdit(final Object feature) {
   UIThreadRunnable.asyncExec(
       new VoidResult() {
         public void run() {
           DirectEditRequest request = new DirectEditRequest();
           if (feature != null) request.setDirectEditFeature(feature);
           part().performRequest(request);
         }
       });
   return this;
 }
 public void addSDK(final File home) throws IOException {
   final SDKInfo info = SDKInfo.loadSDK(home);
   UIThreadRunnable.asyncExec(
       SWTUtils.display(),
       new VoidResult() {
         @Override
         public void run() {
           SDKTableWidget w =
               (SDKTableWidget) sdks.widget.getData("org.eclipse.swtbot.widget.owner");
           CheckboxTableViewer v = w.getViewer();
           v.add(info);
         }
       });
 }
  @Override
  public void synchronizeOnActivityQueue(JID jid, long timeout) throws RemoteException {

    ISarosSession session = this.session;
    IActivityListener listener = this.listener;

    // this is too lazy, but ok for testing purposes

    if (session == null) throw new IllegalStateException("no session running");

    if (listener == null) throw new IllegalStateException("no session running");

    final CountDownLatch swtThreadSync = new CountDownLatch(1);

    UIThreadRunnable.asyncExec(
        new VoidResult() {
          @Override
          public void run() {
            swtThreadSync.countDown();
          }
        });

    try {
      if (!swtThreadSync.await(
          SarosSWTBotPreferences.SAROS_DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)) {
        LOG.warn("could not synchronize on the SWT EDT");
      }
    } catch (InterruptedException e1) {
      Thread.currentThread().interrupt();
    }

    int id = RANDOM.nextInt();

    NOPActivity activity = new NOPActivity(session.getLocalUser(), session.getUser(jid), id);

    CountDownLatch latch = new CountDownLatch(1);

    synchronizeRequests.put(id, latch);
    listener.created(activity);

    try {
      if (!latch.await(timeout, TimeUnit.MILLISECONDS))
        throw new TimeoutException("no reply from " + jid);
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
    } finally {
      synchronizeRequests.remove(id);
    }
  }
  private static void click(final MenuItem menuItem) {
    final Event event = new Event();
    event.time = (int) System.currentTimeMillis();
    event.widget = menuItem;
    event.display = menuItem.getDisplay();
    event.type = SWT.Selection;

    UIThreadRunnable.asyncExec(
        menuItem.getDisplay(),
        new VoidResult() {
          public void run() {
            menuItem.notifyListeners(SWT.Selection, event);
          }
        });
  }
  /**
   * Clicks a tree item asynchronously and waits till the given condition is fulfilled.
   *
   * @param bot the SWT bot
   * @param item the tree item to click
   * @param waitCondition the condition to wait for, may be null
   * @throws TimeoutException the timeout exception
   */
  public static void asyncClick(
      final SWTWorkbenchBot bot, final SWTBotTreeItem item, final ICondition waitCondition)
      throws TimeoutException {
    UIThreadRunnable.asyncExec(
        bot.getDisplay(),
        new VoidResult() {
          public void run() {
            item.click();
          }
        });

    if (waitCondition != null) {
      bot.waitUntil(waitCondition);
    }
  }
  private void revertAndCommit(final ESPrimaryVersionSpec baseVersion) throws ESException {

    final int localProjectsSize =
        ESWorkspaceProvider.INSTANCE.getWorkspace().getLocalProjects().size();

    UIThreadRunnable.asyncExec(
        new VoidResult() {
          public void run() {
            final UIRevertCommitController revertCommitController =
                new UIRevertCommitController(
                    getBot().getDisplay().getActiveShell(), baseVersion, getLocalProject());
            revertCommitController.execute();
          }
        });

    final SWTBotShell shell = getBot().shell("Confirmation");
    shell.bot().button("OK").click();

    getBot()
        .waitUntil(
            new DefaultCondition() {
              // BEGIN SUPRESS CATCH EXCEPTION

              public boolean test() throws Exception {
                return localProjectsSize + 1
                    == ESWorkspaceProvider.INSTANCE.getWorkspace().getLocalProjects().size();
              }

              // END SUPRESS CATCH EXCEPTION

              public String getFailureMessage() {
                return "Revert did not succeed.";
              }
            },
            timeout());

    final List<ESLocalProject> localProjects =
        ESWorkspaceProvider.INSTANCE.getWorkspace().getLocalProjects();
    final ESLocalProject localProject = localProjects.get(localProjects.size() - 1);
    localProject.commit(new NullProgressMonitor());
  }
  private void openImportWizard() {
    fWizard = new ImportTraceWizard();

    UIThreadRunnable.asyncExec(
        new VoidResult() {
          @Override
          public void run() {
            final IWorkbench workbench = PlatformUI.getWorkbench();
            // Fire the Import Trace Wizard
            if (workbench != null) {
              final IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow();
              Shell shell = activeWorkbenchWindow.getShell();
              assertNotNull(shell);
              ((ImportTraceWizard) fWizard)
                  .init(PlatformUI.getWorkbench(), StructuredSelection.EMPTY);
              WizardDialog dialog = new WizardDialog(shell, fWizard);
              dialog.open();
            }
          }
        });

    fBot.waitUntil(ConditionHelpers.isWizardReady(fWizard));
  }