Bug 568565 - Editor selection changed on "Link with Editor" activation
diff --git a/org.eclipse.handly.ui/src/org/eclipse/handly/ui/outline/OutlineLinkingHelper.java b/org.eclipse.handly.ui/src/org/eclipse/handly/ui/outline/OutlineLinkingHelper.java
index 53843c4..7bdb7ab 100644
--- a/org.eclipse.handly.ui/src/org/eclipse/handly/ui/outline/OutlineLinkingHelper.java
+++ b/org.eclipse.handly.ui/src/org/eclipse/handly/ui/outline/OutlineLinkingHelper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014, 2018 1C-Soft LLC and others.
+ * Copyright (c) 2014, 2020 1C-Soft LLC and others.
  *
  * This program and the accompanying materials are made available under
  * the terms of the Eclipse Public License 2.0 which is available at
@@ -86,11 +86,10 @@
     @Override
     public void setLinkWithEditor(boolean enabled)
     {
-        super.setLinkWithEditor(enabled);
-        isLinkingEnabled = enabled;
         if (enabled)
             linkToOutline(
                 outlinePage.getEditor().getSite().getSelectionProvider().getSelection());
+        setLinkingEnabled(enabled);
     }
 
     /**
@@ -133,4 +132,17 @@
      *  (may be <code>null</code> or empty)
      */
     protected abstract void linkToOutline(ISelection selection);
+
+    final void setLinkingEnabled(boolean enabled)
+    {
+        if (enabled == isLinkingEnabled)
+            return;
+        super.setLinkWithEditor(enabled);
+        isLinkingEnabled = enabled;
+    }
+
+    final boolean isLinkingEnabled()
+    {
+        return isLinkingEnabled;
+    }
 }
diff --git a/org.eclipse.handly.ui/src/org/eclipse/handly/ui/outline/SourceElementLinkingHelper.java b/org.eclipse.handly.ui/src/org/eclipse/handly/ui/outline/SourceElementLinkingHelper.java
index 39e5988..a1650ad 100644
--- a/org.eclipse.handly.ui/src/org/eclipse/handly/ui/outline/SourceElementLinkingHelper.java
+++ b/org.eclipse.handly.ui/src/org/eclipse/handly/ui/outline/SourceElementLinkingHelper.java
@@ -276,30 +276,43 @@
     private void cancelLinkToOutlineJob()
     {
         linkToOutlineJob.cancel();
-        linkToOutlineJob.setSelection(null);
+        linkToOutlineJob.setArgs(null);
     }
 
     private void scheduleLinkToOutlineJob(ISelection selection)
     {
         linkToOutlineJob.cancel();
-        linkToOutlineJob.setSelection(selection);
+        linkToOutlineJob.setArgs(new LinkToOutlineArgs(selection,
+            isLinkingEnabled()));
         linkToOutlineJob.schedule();
     }
 
+    private static class LinkToOutlineArgs
+    {
+        final ISelection selection;
+        final boolean isLinkingEnabled;
+
+        LinkToOutlineArgs(ISelection selection, boolean isLinkingEnabled)
+        {
+            this.selection = selection;
+            this.isLinkingEnabled = isLinkingEnabled;
+        }
+    }
+
     private class LinkToOutlineJob
         extends Job
     {
-        private volatile ISelection selection;
+        private volatile LinkToOutlineArgs args;
 
         public LinkToOutlineJob()
         {
-            super(""); //$NON-NLS-1$
+            super(LinkToOutlineJob.class.getName());
             setSystem(true);
         }
 
-        public void setSelection(ISelection selection)
+        public void setArgs(LinkToOutlineArgs args)
         {
-            this.selection = selection;
+            this.args = args;
         }
 
         @Override
@@ -311,7 +324,11 @@
         @Override
         protected IStatus run(IProgressMonitor monitor)
         {
-            final ISelection baseSelection = selection;
+            LinkToOutlineArgs args = this.args;
+            if (args == null)
+                return Status.OK_STATUS;
+
+            final ISelection baseSelection = args.selection;
             if (baseSelection == null || baseSelection.isEmpty())
                 return Status.OK_STATUS;
 
@@ -332,11 +349,14 @@
                 @SuppressWarnings("unchecked")
                 public void run()
                 {
+                    LinkToOutlineArgs args = LinkToOutlineJob.this.args;
+                    if (args == null)
+                        return;
                     Control control = getOutlinePage().getControl();
                     TreeViewer treeViewer = getOutlinePage().getTreeViewer();
                     IEditorPart editor = getOutlinePage().getEditor();
                     if (control == null || control.isDisposed()
-                        || !baseSelection.equals(selection)
+                        || !baseSelection.equals(args.selection)
                         || !baseSelection.equals(
                             editor.getSite().getSelectionProvider().getSelection()))
                         return; // the world has changed -> no work needs to be done
@@ -346,7 +366,21 @@
                         || !currentSelection.toList().containsAll(
                             linkedSelection.toList()))
                     {
-                        treeViewer.setSelection(linkedSelection, true);
+                        boolean isLinkingEnabled = isLinkingEnabled();
+                        try
+                        {
+                            // Temporarily restore the linking state as it was
+                            // when the job was scheduled. This will determine
+                            // whether linkToEditor is called in response to
+                            // selection change in treeViewer.
+                            setLinkingEnabled(args.isLinkingEnabled);
+
+                            treeViewer.setSelection(linkedSelection, true);
+                        }
+                        finally
+                        {
+                            setLinkingEnabled(isLinkingEnabled);
+                        }
                     }
                 }
             });