public void runViewUpdate(final Runnable runnable, final boolean preserveExpansion) {
   if (Utils.canUpdateViewer(getViewer()) || isPerformingBackgroundUpdate()) {
     internalRunViewUpdate(runnable, preserveExpansion);
   } else {
     if (Thread.currentThread() != getEventHandlerJob().getThread()) {
       // Run view update should only be called from the UI thread or
       // the update handler thread.
       // We will log the problem for now and make it an assert later
       TeamUIPlugin.log(
           IStatus.WARNING,
           "View update invoked from invalid thread",
           new TeamException(
               "View update invoked from invalid thread")); //$NON-NLS-1$ //$NON-NLS-2$
     }
     final Control ctrl = getViewer().getControl();
     if (ctrl != null && !ctrl.isDisposed()) {
       ctrl.getDisplay()
           .syncExec(
               new Runnable() {
                 public void run() {
                   if (!ctrl.isDisposed()) {
                     BusyIndicator.showWhile(
                         ctrl.getDisplay(),
                         new Runnable() {
                           public void run() {
                             internalRunViewUpdate(runnable, preserveExpansion);
                           }
                         });
                   }
                 }
               });
     }
   }
 }
 /**
  * Forces the viewer to update the labels for queued elemens whose label has changed during this
  * round of changes. This method should only be invoked in the UI thread.
  */
 protected void firePendingLabelUpdates() {
   if (!Utils.canUpdateViewer(getViewer())) return;
   try {
     Object[] updates = pendingLabelUpdates.toArray(new Object[pendingLabelUpdates.size()]);
     updateLabels(updates);
   } finally {
     pendingLabelUpdates.clear();
   }
 }
  /*
   * Method that can be called from the UI thread to update the view model.
   */
  private void internalRunViewUpdate(final Runnable runnable, boolean preserveExpansion) {
    StructuredViewer viewer = getViewer();
    IResource[] expanded = null;
    IResource[] selected = null;
    try {
      if (Utils.canUpdateViewer(viewer)) {
        viewer.getControl().setRedraw(false);
        if (preserveExpansion) {
          expanded = provider.getExpandedResources();
          selected = provider.getSelectedResources();
        }
        if (viewer instanceof AbstractTreeViewer && additionsMap == null)
          additionsMap = new HashMap();
      }
      runnable.run();
    } finally {
      if (Utils.canUpdateViewer(viewer)) {
        try {
          if (additionsMap != null && !additionsMap.isEmpty() && Utils.canUpdateViewer(viewer)) {
            for (Iterator iter = additionsMap.keySet().iterator(); iter.hasNext(); ) {
              ISynchronizeModelElement parent = (ISynchronizeModelElement) iter.next();
              if (Policy.DEBUG_SYNC_MODELS) {
                System.out.println("Adding child view items of " + parent.getName()); // $NON-NLS-1$
              }
              Set toAdd = (Set) additionsMap.get(parent);
              ((AbstractTreeViewer) viewer).add(parent, toAdd.toArray(new Object[toAdd.size()]));
            }
            additionsMap = null;
          }
          if (expanded != null) {
            provider.expandResources(expanded);
          }
          if (selected != null) {
            provider.selectResources(selected);
          }
        } finally {
          viewer.getControl().setRedraw(true);
        }
      }
    }

    ISynchronizeModelElement root = provider.getModelRoot();
    if (root instanceof SynchronizeModelElement) ((SynchronizeModelElement) root).fireChanges();
  }
 /*
  * Forces the viewer to update the labels for the given elements
  */
 private void updateLabels(Object[] elements) {
   StructuredViewer tree = getViewer();
   if (Utils.canUpdateViewer(tree)) {
     tree.update(elements, null);
   }
 }