Bug 355049: "Export" should not show linked resources by default

A follow up change which allows to hide/show linked resource entries in
the export wizard resources tree if the "Resolve and export linked
resources" checkbox is toggled.

Change-Id: Ie4ef8cb004313f2091ee976f303f479ecb499d80
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
diff --git a/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/dialogs/WizardExportResourcesPage.java b/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/dialogs/WizardExportResourcesPage.java
index 9fccd7b..df1889b 100644
--- a/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/dialogs/WizardExportResourcesPage.java
+++ b/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/dialogs/WizardExportResourcesPage.java
@@ -80,6 +80,8 @@
     // widgets
     private ResourceTreeAndListGroup resourceGroup;
 
+    private boolean showLinkedResources;
+
     private final static String SELECT_TYPES_TITLE = IDEWorkbenchMessages.WizardTransferPage_selectTypes;
 
     private final static String SELECT_ALL_TITLE = IDEWorkbenchMessages.WizardTransferPage_selectAll;
@@ -282,11 +284,12 @@
 			}
         }
 
+        showLinkedResources = getShowLinkedResources();
         this.resourceGroup = new ResourceTreeAndListGroup(parent, input,
-                getResourceProvider(IResource.FOLDER | IResource.PROJECT),
+                getResourceProvider(IResource.FOLDER | IResource.PROJECT, showLinkedResources),
                 WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider(),
-                getResourceProvider(IResource.FILE), WorkbenchLabelProvider
-                        .getDecoratingWorkbenchLabelProvider(), SWT.NONE,
+                getResourceProvider(IResource.FILE, showLinkedResources),
+                WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider(), SWT.NONE,
                 DialogUtil.inRegularFontMode(parent));
 
         ICheckStateListener listener = event -> updateWidgetEnablements();
@@ -336,40 +339,89 @@
         return result;
     }
 
+    private static class ResourceProvider extends WorkbenchContentProvider {
+        private static final Object[] EMPTY = new Object[0];
+        private int resourceType;
+        private boolean showLinkedResources;
+
+        public ResourceProvider(int resourceType, boolean showLinkedResources) {
+            super();
+            this.resourceType = resourceType;
+            this.showLinkedResources = showLinkedResources;
+        }
+
+        @Override
+		public Object[] getChildren(Object o) {
+            if (o instanceof IContainer) {
+                IContainer container = (IContainer) o;
+                if (!showLinkedResources && container.isLinked(IResource.CHECK_ANCESTORS)) {
+                    // just return an empty set of children
+                    return EMPTY;
+                }
+                IResource[] members = null;
+                try {
+                    members = container.members();
+                } catch (CoreException e) {
+                    // just return an empty set of children
+                    return EMPTY;
+                }
+
+                // filter out the desired resource types
+                List<IResource> results = new ArrayList<>();
+                for (int i = 0; i < members.length; i++) {
+                    // And the test bits with the resource types to see if they
+                    // are what we want
+                    IResource resource = members[i];
+                    if (!showLinkedResources && resource.isLinked()) {
+                        continue;
+                    }
+                    if ((resource.getType() & resourceType) > 0) {
+                        results.add(resource);
+                    }
+                }
+                return results.toArray();
+            }
+            // input element case
+            if (o instanceof ArrayList) {
+                return ((List<?>) o).toArray();
+            }
+            return EMPTY;
+        }
+    }
+
     /**
      * Returns a content provider for <code>IResource</code>s that returns
      * only children of the given resource type.
      */
-    private ITreeContentProvider getResourceProvider(final int resourceType) {
-        return new WorkbenchContentProvider() {
-            @Override
-			public Object[] getChildren(Object o) {
-                if (o instanceof IContainer) {
-                    IResource[] members = null;
-                    try {
-                        members = ((IContainer) o).members();
-                    } catch (CoreException e) {
-                        //just return an empty set of children
-                        return new Object[0];
-                    }
+    private ITreeContentProvider getResourceProvider(int resourceType, boolean showLinkedResources) {
+        return new ResourceProvider(resourceType, showLinkedResources);
+    }
 
-                    //filter out the desired resource types
-                    ArrayList results = new ArrayList();
-                    for (int i = 0; i < members.length; i++) {
-                        //And the test bits with the resource types to see if they are what we want
-                        if ((members[i].getType() & resourceType) > 0) {
-                            results.add(members[i]);
-                        }
-                    }
-                    return results.toArray();
-                }
-                //input element case
-                if (o instanceof ArrayList) {
-                    return ((ArrayList) o).toArray();
-                }
-                return new Object[0];
-            }
-        };
+    /**
+     * Returns {<code>true</code> if the page tree and list providers should
+     * show linked resources. Default is false.
+     *
+     * @since 3.12
+     */
+    protected boolean getShowLinkedResources() {
+        return showLinkedResources;
+    }
+
+    /**
+     * Updates the resources tree to show or hide linked resources
+     *
+     * @param showLinked
+     *            {<code>true</code> if the page should show linked resources
+     * @since 3.12
+     */
+    protected void updateContentProviders(boolean showLinked) {
+        showLinkedResources = showLinked;
+        resourceGroup.setTreeProviders(
+                getResourceProvider(IResource.FOLDER | IResource.PROJECT, showLinkedResources),
+                WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider());
+
+        resourceGroup.setListProviders(getResourceProvider(IResource.FILE, showLinkedResources),
+                WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider());
     }
 
     /**
diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/ide/dialogs/ResourceTreeAndListGroup.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/ide/dialogs/ResourceTreeAndListGroup.java
index f79e1974..a74b272 100644
--- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/ide/dialogs/ResourceTreeAndListGroup.java
+++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/ide/dialogs/ResourceTreeAndListGroup.java
@@ -991,10 +991,27 @@
      *	@param labelProvider ILabelProvider
      */
     public void setTreeProviders(ITreeContentProvider contentProvider, ILabelProvider labelProvider) {
+        List<?> items;
+        if (root == null) {
+            items = Collections.emptyList();
+        } else {
+            // remember checked elements
+            items = getAllWhiteCheckedItems();
+            // reset all caches
+            for (Object object : items) {
+                setTreeChecked(object, false);
+            }
+        }
+
         treeViewer.setContentProvider(contentProvider);
         treeViewer.setLabelProvider(labelProvider);
-		treeContentProvider = contentProvider;
-		treeLabelProvider = labelProvider;
+        treeContentProvider = contentProvider;
+        treeLabelProvider = labelProvider;
+
+        // select (if any) previously checked elements again in the new model
+        for (Object object : items) {
+            setTreeChecked(object, true);
+        }
     }
 
     /**
diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/WizardFileSystemResourceExportPage1.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/WizardFileSystemResourceExportPage1.java
index 1faab2a..fccf9a1 100644
--- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/WizardFileSystemResourceExportPage1.java
+++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/wizards/datatransfer/WizardFileSystemResourceExportPage1.java
@@ -221,6 +221,8 @@
 		resolveLinkedResourcesCheckbox = new Button(parent, SWT.CHECK | SWT.LEFT);
 		resolveLinkedResourcesCheckbox.setText(DataTransferMessages.ExportFile_resolveLinkedResources);
 		resolveLinkedResourcesCheckbox.setFont(font);
+		resolveLinkedResourcesCheckbox.setSelection(getShowLinkedResources());
+		resolveLinkedResourcesCheckbox.addListener(SWT.Selection, this);
 	}
 
     /**
@@ -362,6 +364,13 @@
     }
 
     /**
+	 * Updates the content providers to show/hide linked resurces
+	 */
+	protected void handleResolveLinkedResourcesCheckboxSelected() {
+		updateContentProviders(resolveLinkedResourcesCheckbox.getSelection());
+	}
+
+    /**
      * Handle all events and enablements for widgets in this page
      * @param e Event
      */
@@ -371,6 +380,8 @@
 
         if (source == destinationBrowseButton) {
 			handleDestinationBrowseButtonPressed();
+		} else if (source == resolveLinkedResourcesCheckbox) {
+			handleResolveLinkedResourcesCheckboxSelected();
 		}
 
         updatePageCompletion();
@@ -433,7 +444,10 @@
                     .getBoolean(STORE_CREATE_STRUCTURE_ID);
             createDirectoryStructureButton.setSelection(createDirectories);
             createSelectionOnlyButton.setSelection(!createDirectories);
-			resolveLinkedResourcesCheckbox.setSelection(settings.getBoolean(STORE_RESOLVE_LINKED_RESOURCES_ID));
+			boolean showLinked = settings.getBoolean(STORE_RESOLVE_LINKED_RESOURCES_ID);
+			if (resolveLinkedResourcesCheckbox.getSelection() != showLinked) {
+				resolveLinkedResourcesCheckbox.setSelection(showLinked);
+			}
         }
     }