protected void setSelectionToClient(
      VirtualTreeModelViewer virtualViewer, ILabelProvider labelProvider, VirtualItem findItem) {
    virtualViewer.getTree().setSelection(new VirtualItem[] {findItem});
    ModelDelta stateDelta = new ModelDelta(virtualViewer.getInput(), IModelDelta.NO_CHANGE);
    virtualViewer.saveElementState(TreePath.EMPTY, stateDelta, IModelDelta.SELECT);
    // Set the force flag to all select delta in order to override model's selection policy.
    stateDelta.accept(
        new IModelDeltaVisitor() {
          @Override
          public boolean visit(IModelDelta delta, int depth) {
            if ((delta.getFlags() & IModelDelta.SELECT) != 0) {
              ((ModelDelta) delta).setFlags(delta.getFlags() | IModelDelta.FORCE);
            }
            return true;
          }
        });
    fClientViewer.updateViewer(stateDelta);

    ISelection selection = fClientViewer.getSelection();
    if (!selection.isEmpty()
        && selection instanceof IStructuredSelection
        && ((IStructuredSelection) selection).getFirstElement().equals(findItem.getData())) {
    } else {
      DebugUIPlugin.errorDialog(
          fClientViewer.getControl().getShell(),
          ActionMessages.VirtualFindAction_0,
          MessageFormat.format(
              ActionMessages.VirtualFindAction_1, new Object[] {labelProvider.getText(findItem)}),
          new Status(
              IStatus.ERROR,
              DebugUIPlugin.getUniqueIdentifier(),
              ActionMessages.VirtualFindAction_1));
    }
  }
  @Override
  public void run() {
    final VirtualViewerListener listener = new VirtualViewerListener();
    VirtualTreeModelViewer virtualViewer = initVirtualViewer(fClientViewer, listener);

    ProgressMonitorDialog dialog =
        new TimeTriggeredProgressMonitorDialog(fClientViewer.getControl().getShell(), 500);
    final IProgressMonitor monitor = dialog.getProgressMonitor();
    dialog.setCancelable(true);

    try {
      dialog.run(
          true,
          true,
          new IRunnableWithProgress() {
            @Override
            public void run(final IProgressMonitor m)
                throws InvocationTargetException, InterruptedException {
              synchronized (listener) {
                listener.fProgressMonitor = m;
                listener.fProgressMonitor.beginTask(
                    DebugUIPlugin.removeAccelerators(getText()), listener.fRemainingUpdatesCount);
              }

              while ((!listener.fLabelUpdatesComplete || !listener.fViewerUpdatesComplete)
                  && !listener.fProgressMonitor.isCanceled()) {
                Thread.sleep(1);
              }
              synchronized (listener) {
                listener.fProgressMonitor = null;
              }
            }
          });
    } catch (InvocationTargetException e) {
      DebugUIPlugin.log(e);
      return;
    } catch (InterruptedException e) {
      return;
    }

    VirtualItem root = virtualViewer.getTree();
    if (!monitor.isCanceled()) {
      List<VirtualItem> list = new ArrayList<VirtualItem>();
      collectAllChildren(root, list);
      FindLabelProvider labelProvider = new FindLabelProvider(virtualViewer, list);
      VirtualItem result = performFind(list, labelProvider);
      if (result != null) {
        setSelectionToClient(virtualViewer, labelProvider, result);
      }
    }

    virtualViewer.removeLabelUpdateListener(listener);
    virtualViewer.removeViewerUpdateListener(listener);
    virtualViewer.dispose();
  }
 protected VirtualItem performFind(List<VirtualItem> items, FindLabelProvider labelProvider) {
   FindElementDialog dialog =
       new FindElementDialog(
           fClientViewer.getControl().getShell(), labelProvider, items.toArray());
   dialog.setTitle(ActionMessages.FindDialog_3);
   dialog.setMessage(ActionMessages.FindDialog_1);
   if (dialog.open() == Window.OK) {
     Object[] elements = dialog.getResult();
     if (elements.length == 1) {
       return (VirtualItem) elements[0];
     }
   }
   return null;
 }