TreeItem getItemForDifference(TreeDifference difference) {
   for (int i = difference.getPath().getSegmentCount() - 1; i >= 0; i--) {
     Object segment = difference.getPath().getSegment(i);
     TreeItem item = (TreeItem) findItem(ComparableProvider.getComparableTreeObject(segment));
     // if item is null, check for a matching difference with
     // element type of EmptyElement
     if (item == null) {
       if (difference.getMatchingDifference().getElement() instanceof EmptyElement) {
         // if not found then locate the item for the empty element
         item = (TreeItem) findItem(difference.getMatchingDifference().getElement());
       }
     }
     if (item != null && !item.isDisposed()) {
       TreeItem[] topItems = getTree().getItems();
       for (TreeItem top : topItems) {
         if (top == item) {
           return item;
         }
       }
       // else check for expanded state
       if (item.getParentItem().getExpanded() && !item.getBounds().isEmpty()) {
         return item;
       }
     }
   }
   return null;
 }
 public static boolean differenceIsGraphical(TreeDifference difference) {
   Object diffElement = difference.getElement();
   if (diffElement instanceof EmptyElement) {
     diffElement = ((EmptyElement) diffElement).getParent();
     diffElement = ComparableProvider.getComparableTreeObject(diffElement);
   }
   if (diffElement == null) {
     diffElement = difference.getMatchingDifference().getElement();
   }
   if (diffElement != null) {
     return differenceElementIsGraphical(diffElement);
   }
   return false;
 }
  protected Object handleOpen() {
    if (mergeViewer.getAncestorTree() == this) {
      return null;
    }
    IStructuredSelection sel = (IStructuredSelection) getSelection();
    if (sel.isEmpty()) {
      return null;
    }
    Object current = sel.iterator().next();
    // if the current selection has an Action_Semantics field
    // the grab the necessary object element to open that, failing
    // that look for a description attribute
    if (current instanceof NonRootModelElementComparable) {
      NonRootModelElement nrme =
          (NonRootModelElement) ((NonRootModelElementComparable) current).getRealElement();
      if (nrme instanceof StateMachineState_c || nrme instanceof Transition_c) {
        // we need to navigate to the Action element
        // for the activity and description attributes
        Object[] children = ((ITreeContentProvider) getContentProvider()).getChildren(current);
        for (Object child : children) {
          if (child instanceof NonRootModelElementComparable) {
            current = child;
            break;
          }
        }
      }
      ObjectElement actionObjEle = null;
      ObjectElement descripObjEle = null;
      Object[] children = ((ITreeContentProvider) getContentProvider()).getChildren(current);
      for (Object child : children) {
        if (child instanceof ObjectElementComparable) {
          ObjectElementComparable comparable = (ObjectElementComparable) child;
          ObjectElement objElement = (ObjectElement) comparable.getRealElement();
          if (objElement.getName().equals("Action_Semantics")) {
            actionObjEle = objElement;
          } else {
            if (objElement.getName().equals("Descrip")) {
              descripObjEle = objElement;
            }
          }
        }
      }
      if (actionObjEle != null) {
        current = ComparableProvider.getComparableTreeObject(actionObjEle);
      } else {
        if (descripObjEle != null) {
          current = ComparableProvider.getComparableTreeObject(descripObjEle);
        }
      }
    }
    if (current instanceof ObjectElementComparable) {
      ObjectElementComparable comparable = (ObjectElementComparable) current;
      ObjectElement objElement = (ObjectElement) comparable.getRealElement();
      if (objElement.getName().equals("Descrip")
          || objElement.getName().equals("Action_Semantics")) {
        Object leftInput = getMergeViewer().getLeftViewer().getInput();
        Object rightInput = getMergeViewer().getRightViewer().getInput();
        TreeItem rightMatch = getMatchingItem(comparable, synchronizedViewers.get(0));
        TreeItem ancestorMatch = null;
        if (synchronizedViewers.size() == 2) {
          ancestorMatch = getMatchingItem(comparable, synchronizedViewers.get(1));
        }
        Object leftElement = comparable.getRealElement();
        Object rightElement = null;
        Object ancestor = null;
        if (ancestorMatch != null) {
          ancestor = ((ComparableTreeObject) ancestorMatch.getData()).getRealElement();
        }
        if (rightMatch != null) {
          rightElement = ((ComparableTreeObject) rightMatch.getData()).getRealElement();
        }
        if (mergeViewer.getLeftViewer() != this) {
          if (rightMatch == null) {
            leftElement = null;
          } else {
            leftElement = rightMatch.getData();
            leftElement = ((ComparableTreeObject) leftElement).getRealElement();
          }
          rightElement = comparable.getRealElement();
        }
        // create a compare dialog, using the text compare
        final CompareConfiguration compareConfiguration = new CompareConfiguration();
        boolean leftEditable =
            leftInput instanceof IEditableContent && ((IEditableContent) leftInput).isEditable();
        boolean rightEditable =
            rightInput instanceof IEditableContent && ((IEditableContent) rightInput).isEditable();
        // if this is a single file compare, do not allow editing
        // at this time as there is no easy way to place the content
        // changes back into the file
        if (ComparePlugin.getDefault()
            .getModelCacheManager()
            .isInputReadonly(ModelCacheManager.getLeftKey(mergeViewer.getInput()))) {
          compareConfiguration.setLeftEditable(false);
          compareConfiguration.setRightEditable(false);
        } else {
          compareConfiguration.setLeftEditable(leftEditable);
          compareConfiguration.setRightEditable(rightEditable);
        }
        final TextualAttributeCompareEditorInput compareInput =
            new TextualAttributeCompareEditorInput(
                compareConfiguration,
                (ObjectElement) leftElement,
                (ObjectElement) rightElement,
                (ObjectElement) ancestor,
                SynchronizedTreeViewer.this);
        if (CompareUIPlugin.getDefault().compareResultOK(compareInput, null)) {
          Runnable runnable =
              new Runnable() {
                public void run() {
                  CompareDialog dialog =
                      new CompareDialog(
                          PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
                          compareInput) {

                        @Override
                        protected Button createButton(
                            Composite parent, int id, String label, boolean defaultButton) {
                          if (id == IDialogConstants.CANCEL_ID) {
                            return null;
                          } else {
                            return super.createButton(parent, id, label, defaultButton);
                          }
                        }
                      };
                  dialog.open();
                }
              };
          if (Display.getCurrent() == null) {
            Display.getDefault().syncExec(runnable);
          } else {
            runnable.run();
          }
        }
        return null;
      }
    }

    return null;
  }