blob: c47c70e9ef36edb47163ca4684d8f200338c2306 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2017 Red Hat Inc., and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Mickael Istria (Red Hat Inc.) - initial API and implementation
* Snjezana Peco (Red Hat Inc.)
* Lars Vogel <Lars.Vogel@vogella.com>
* RĂ¼diger Herrmann <ruediger.herrmann@gmx.de>
* Patrik Suzzi <psuzzi@gmail.com> - Bug 500836
* Lucas Bullen (Red Hat Inc.) - Bug 526490
******************************************************************************/
package org.eclipse.ui.internal.wizards.datatransfer;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ICheckStateProvider;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerColumn;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.jface.wizard.ProgressMonitorPart;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.dialogs.WorkingSetGroup;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.dialogs.ImportExportWizard;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.progress.ProgressManager;
import org.eclipse.ui.internal.progress.ProgressManager.JobMonitor;
import org.eclipse.ui.internal.registry.WorkingSetDescriptor;
import org.eclipse.ui.internal.registry.WorkingSetRegistry;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.wizards.datatransfer.ProjectConfigurator;
/**
* This page of {@link SmartImportWizard} simply asks for what to import, and asks
* user a basic choice of how to import (import raw, infer sub- projects...)
*
* @since 3.12
*
*/
public class SmartImportRootWizardPage extends WizardPage {
static final String IMPORTED_SOURCES = SmartImportRootWizardPage.class.getName() + ".knownSources"; //$NON-NLS-1$
// Root
private File selection;
private Combo rootDirectoryText;
private ControlDecoration rootDirectoryTextDecorator;
// Proposal part
private CheckboxTreeViewer tree;
private ControlDecoration proposalSelectionDecorator;
private Set<File> directoriesToImport;
private Label selectionSummary;
protected Map<File, List<ProjectConfigurator>> potentialProjects = Collections.emptyMap();
// Configuration part
private boolean closeProjectsAfterImport = false;
private boolean detectNestedProjects = true;
private boolean configureProjects = true;
// Working sets
private Set<IWorkingSet> workingSets;
private WorkingSetGroup workingSetsGroup;
// Progress monitor
protected Supplier<ProgressMonitorPart> wizardProgressMonitor = new Supplier<ProgressMonitorPart>() {
private ProgressMonitorPart progressMonitorPart;
@Override
public ProgressMonitorPart get() {
if (progressMonitorPart == null) {
try {
getWizard().getContainer().run(false, true, monitor -> {
if (monitor instanceof ProgressMonitorPart) {
progressMonitorPart = (ProgressMonitorPart) monitor;
}
});
} catch (InvocationTargetException ite) {
IStatus status = new Status(IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH,
DataTransferMessages.SmartImportWizardPage_scanProjectsFailed, ite.getCause());
StatusManager.getManager().handle(status, StatusManager.LOG | StatusManager.SHOW);
} catch (InterruptedException operationCanceled) {
Thread.interrupted();
}
}
return progressMonitorPart;
}
};
private Job refreshProposalsJob;
private JobMonitor jobMonitor;
private DelegateProgressMonitorInUIThreadAndPreservingFocus delegateMonitor;
private SelectionListener cancelWorkListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
stopAndDisconnectCurrentWork();
}
};
private Button selectAllButton;
private Button deselectAllButton;
private class FolderForProjectsLabelProvider extends CellLabelProvider implements IColorProvider {
public String getText(Object o) {
File file = (File) o;
Path filePath = file.toPath();
Path rootPath = getWizard().getImportJob().getRoot().toPath();
if (filePath.startsWith(rootPath)) {
if (rootPath.getParent() != null) {
Path relative = rootPath.getParent().relativize(filePath);
if (relative.getNameCount() > 0) {
return relative.toString();
}
}
}
return filePath.toString();
}
@Override
public Color getBackground(Object o) {
return null;
}
@Override
public Color getForeground(Object o) {
if (isExistingProject((File) o) || isExistingProjectName((File) o)) {
return Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
}
return null;
}
@Override
public void update(ViewerCell cell) {
cell.setText(getText(cell.getElement()));
Color color = getForeground(cell.getElement());
if (color != null) {
cell.setForeground(color);
}
}
}
private class ProjectConfiguratorLabelProvider extends CellLabelProvider implements IColorProvider {
public String getText(Object o) {
File file = (File) o;
if (isExistingProject(file)) {
return DataTransferMessages.SmartImportProposals_alreadyImportedAsProject_title;
} else if (isExistingProjectName(file)) {
return DataTransferMessages.SmartImportProposals_anotherProjectWithSameNameExists_title;
}
List<ProjectConfigurator> configurators = SmartImportRootWizardPage.this.potentialProjects.get(file);
if (configurators.isEmpty()) {
return ""; //$NON-NLS-1$
}
return ProjectConfiguratorExtensionManager.getLabel(configurators.get(0));
}
@Override
public Color getBackground(Object o) {
return null;
}
@Override
public Color getForeground(Object o) {
if (isExistingProject((File) o) || isExistingProjectName((File) o)) {
return Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
}
return null;
}
@Override
public void update(ViewerCell cell) {
cell.setText(getText(cell.getElement()));
Color color = getForeground(cell.getElement());
if (color != null) {
cell.setForeground(color);
}
}
}
/**
* Constructs a new instance of that page
*
* @param wizard
* the container wizard (most likely an {@link SmartImportWizard}
* @param initialSelection
* initial selection (directory or archive)
* @param initialWorkingSets
* initial working sets
*/
public SmartImportRootWizardPage(SmartImportWizard wizard, File initialSelection,
Set<IWorkingSet> initialWorkingSets) {
super(SmartImportRootWizardPage.class.getName());
this.selection = initialSelection;
this.workingSets = initialWorkingSets;
if (this.workingSets == null) {
this.workingSets = new HashSet<>();
}
setWizard(wizard);
}
@Override
public void setWizard(IWizard easymportWizard) {
Assert.isTrue(easymportWizard instanceof SmartImportWizard);
super.setWizard(easymportWizard);
}
@Override
public SmartImportWizard getWizard() {
return (SmartImportWizard) super.getWizard();
}
@Override
public void createControl(Composite parent) {
setTitle(DataTransferMessages.SmartImportWizardPage_importProjectsInFolderTitle);
setDescription(DataTransferMessages.SmartImportWizardPage_importProjectsInFolderDescription);
initializeDialogUnits(parent);
Composite res = new Composite(parent, SWT.NONE);
GridLayoutFactory.swtDefaults().margins(10, 10).numColumns(4).equalWidth(false).applyTo(res);
createInputSelectionOptions(res);
GridData proposalsGroupLayoutData = new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1);
proposalsGroupLayoutData.verticalIndent = 12;
createProposalsGroup(res).setLayoutData(proposalsGroupLayoutData);
createConfigurationOptions(res);
createWorkingSetsGroup(res);
createLink(res);
if (this.selection != null) {
rootDirectoryText.setText(this.selection.getAbsolutePath());
validatePage();
}
setControl(res);
}
private void createLink(Composite res) {
Link showOtherImportWizards = new Link(res, SWT.NONE);
showOtherImportWizards
.setText("<A>" + DataTransferMessages.SmartImportWizardPage_showOtherSpecializedImportWizard + "</A>"); //$NON-NLS-1$ //$NON-NLS-2$
showOtherImportWizards.setLayoutData(new GridData(SWT.END, SWT.END, true, false, 4, 1));
showOtherImportWizards.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
ImportExportWizard importWizard = new ImportExportWizard(ImportExportWizard.IMPORT);
IStructuredSelection sel = null;
if (selection != null) {
sel = new StructuredSelection(selection);
} else {
sel = new StructuredSelection();
}
importWizard.init(PlatformUI.getWorkbench(), sel);
IDialogSettings workbenchSettings = WorkbenchPlugin.getDefault().getDialogSettings();
IDialogSettings wizardSettings = workbenchSettings.getSection("ImportExportAction"); //$NON-NLS-1$
if (wizardSettings == null) {
wizardSettings = workbenchSettings.addNewSection("ImportExportAction"); //$NON-NLS-1$
}
importWizard.setDialogSettings(wizardSettings);
importWizard.addPages();
getWizard().getContainer().showPage(importWizard.getPages()[0]);
}
});
}
private void createWorkingSetsGroup(Composite parent) {
Composite workingSetComposite = new Composite(parent, SWT.NONE);
GridData layoutData = new GridData(SWT.FILL, SWT.TOP, true, false, 4, 1);
layoutData.verticalIndent = 10;
workingSetComposite.setLayoutData(layoutData);
GridLayoutFactory.fillDefaults().applyTo(workingSetComposite);
WorkingSetRegistry registry = WorkbenchPlugin.getDefault().getWorkingSetRegistry();
String[] workingSetIds = Arrays.stream(registry.getNewPageWorkingSetDescriptors())
.map(WorkingSetDescriptor::getId).toArray(String[]::new);
IStructuredSelection wsSel = null;
if (this.workingSets != null) {
wsSel = new StructuredSelection(this.workingSets.toArray());
}
this.workingSetsGroup = new WorkingSetGroup(workingSetComposite, wsSel, workingSetIds);
}
/**
* @param parent
*/
private void createInputSelectionOptions(Composite parent) {
Label rootDirectoryLabel = new Label(parent, SWT.NONE);
rootDirectoryLabel.setText(DataTransferMessages.SmartImportWizardPage_selectRootDirectory);
rootDirectoryText = new Combo(parent, SWT.BORDER);
String[] knownSources = getWizard().getDialogSettings().getArray(IMPORTED_SOURCES);
if (knownSources != null) {
rootDirectoryText.setItems(knownSources);
}
GridData rootDirectoryTextLayoutData = new GridData(SWT.FILL, SWT.CENTER, true, false);
rootDirectoryText.setLayoutData(rootDirectoryTextLayoutData);
rootDirectoryText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
SmartImportRootWizardPage.this.selection = new File(((Combo) e.widget).getText());
if (SmartImportWizard.isValidArchive(selection)) {
if (SmartImportWizard.getExpandDirectory(selection).isDirectory()) {
if (MessageDialog.openConfirm(getShell(),
DataTransferMessages.SmartImportWizardPage_overwriteArchiveDirectory_title,
NLS.bind(DataTransferMessages.SmartImportWizardPage_overwriteArchiveDirectory_message,
SmartImportWizard.getExpandDirectory(selection)))) {
expandSelectedArchive();
}
} else {
expandSelectedArchive();
}
}
validatePage();
refreshProposals();
}
private void expandSelectedArchive() {
try {
getContainer().run(true, true, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
getWizard().expandArchive(selection, monitor);
if (monitor.isCanceled()) {
throw new InterruptedException();
}
}
});
} catch (Exception ex) {
MessageDialog.openWarning(getShell(),
DataTransferMessages.SmartImportWizardPage_incompleteExpand_title,
NLS.bind(DataTransferMessages.SmartImportWizardPage_incompleteExpand_title,
SmartImportWizard.getExpandDirectory(selection)));
}
}
});
this.rootDirectoryTextDecorator = new ControlDecoration(rootDirectoryText, SWT.TOP | SWT.LEFT);
Image errorImage = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_ERROR).getImage();
rootDirectoryTextLayoutData.horizontalIndent += errorImage.getBounds().width;
this.rootDirectoryTextDecorator.setImage(errorImage);
this.rootDirectoryTextDecorator
.setDescriptionText(DataTransferMessages.SmartImportWizardPage_incorrectRootDirectory);
this.rootDirectoryTextDecorator.hide();
Button directoryButton = new Button(parent, SWT.PUSH);
directoryButton.setText(DataTransferMessages.SmartImportWizardPage_browse);
setButtonLayoutData(directoryButton);
directoryButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.SHEET);
dialog.setText(DataTransferMessages.SmartImportWizardPage_browseForFolder);
dialog.setMessage(DataTransferMessages.SmartImportWizardPage_selectFolderOrArchiveToImport);
if (rootDirectoryText.getText() != null) {
File current = new File(rootDirectoryText.getText());
if (current.isDirectory()) {
dialog.setFilterPath(current.getAbsolutePath());
} else if (current.isFile()) {
dialog.setFilterPath(current.getParentFile().getAbsolutePath());
}
}
if (dialog.getFilterPath() == null) {
dialog.setFilterPath(ResourcesPlugin.getWorkspace().getRoot().getLocation().toFile().toString());
}
String directory = dialog.open();
if (directory != null) {
rootDirectoryText.setText(directory);
}
}
});
Button browseArchiveButton = new Button(parent, SWT.PUSH);
browseArchiveButton.setText(DataTransferMessages.SmartImportWizardPage_selectArchiveButton);
setButtonLayoutData(browseArchiveButton);
browseArchiveButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
FileDialog dialog = new FileDialog(getShell(), SWT.SHEET);
dialog.setText(DataTransferMessages.SmartImportWizardPage_selectArchiveTitle);
dialog.setFilterExtensions(new String[] { "*.zip;*.tar;*.tar.gz" }); //$NON-NLS-1$
dialog.setFilterNames(new String[] { DataTransferMessages.SmartImportWizardPage_allSupportedArchives });
if (rootDirectoryText.getText() != null) {
File current = new File(rootDirectoryText.getText());
if (current.isDirectory()) {
dialog.setFilterPath(current.getAbsolutePath());
} else if (current.isFile()) {
dialog.setFilterPath(current.getParentFile().getAbsolutePath());
dialog.setFileName(current.getName());
}
}
if (dialog.getFilterPath() == null) {
dialog.setFilterPath(ResourcesPlugin.getWorkspace().getRoot().getLocation().toFile().toString());
}
String archive = dialog.open();
if (archive != null) {
rootDirectoryText.setText(archive);
}
}
});
}
/**
* Creates the UI elements for the import options
*/
private void createConfigurationOptions(Composite parent) {
Button closeProjectsCheckbox = new Button(parent, SWT.CHECK);
closeProjectsCheckbox.setText(DataTransferMessages.SmartImportWizardPage_closeProjectsAfterImport);
closeProjectsCheckbox.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1));
closeProjectsCheckbox.setSelection(closeProjectsAfterImport);
closeProjectsCheckbox.addSelectionListener(SelectionListener
.widgetSelectedAdapter(e -> closeProjectsAfterImport = closeProjectsCheckbox.getSelection()));
Link showDetectorsLink = new Link(parent, SWT.NONE);
showDetectorsLink.setText(DataTransferMessages.SmartImportWizardPage_showAvailableDetectors);
GridData layoutData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 4, 1);
showDetectorsLink.setLayoutData(layoutData);
showDetectorsLink.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
StringBuilder message = new StringBuilder();
message.append(DataTransferMessages.SmartImportWizardPage_availableDetectors_description);
message.append('\n');
message.append('\n');
List<String> extensionsLabels = new ArrayList<>(
ProjectConfiguratorExtensionManager.getAllExtensionLabels());
Collections.sort(extensionsLabels);
for (String extensionLabel : extensionsLabels) {
message.append("* "); //$NON-NLS-1$
message.append(extensionLabel);
message.append('\n');
}
MessageDialog.openInformation(getShell(),
DataTransferMessages.SmartImportWizardPage_availableDetectors_title, message.toString());
}
});
final Button detectNestedProjectsCheckbox = new Button(parent, SWT.CHECK);
detectNestedProjectsCheckbox.setText(DataTransferMessages.SmartImportWizardPage_detectNestedProjects);
detectNestedProjectsCheckbox.setLayoutData(layoutData);
detectNestedProjectsCheckbox.setSelection(this.detectNestedProjects);
detectNestedProjectsCheckbox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
SmartImportRootWizardPage.this.detectNestedProjects = detectNestedProjectsCheckbox.getSelection();
refreshProposals();
}
});
final Button configureProjectsCheckbox = new Button(parent, SWT.CHECK);
configureProjectsCheckbox.setText(DataTransferMessages.SmartImportWizardPage_configureProjects);
configureProjectsCheckbox.setLayoutData(layoutData);
configureProjectsCheckbox.setSelection(this.configureProjects);
configureProjectsCheckbox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
SmartImportRootWizardPage.this.configureProjects = configureProjectsCheckbox.getSelection();
refreshProposals();
}
});
}
/**
* @param res
*/
private Composite createProposalsGroup(Composite parent) {
Composite res = new Composite(parent, SWT.NONE);
GridLayoutFactory.fillDefaults().numColumns(2).applyTo(res);
PatternFilter patternFilter = new PatternFilter();
patternFilter.setIncludeLeadingWildcard(true);
FilteredTree filterTree = new FilteredTree(res, SWT.BORDER | SWT.CHECK, patternFilter, true) {
@Override
public CheckboxTreeViewer doCreateTreeViewer(Composite treeParent, int style) {
return new CheckboxTreeViewer(treeParent, style);
}
};
tree = (CheckboxTreeViewer) filterTree.getViewer();
GridData treeGridData = new GridData(SWT.FILL, SWT.FILL, true, true);
treeGridData.heightHint = 90;
tree.getControl().setLayoutData(treeGridData);
tree.setContentProvider(new ITreeContentProvider() {
@Override
public Object[] getElements(Object inputElement) {
Map<File, ?> potentialProjects = (Map<File, ?>) inputElement;
return potentialProjects.keySet().toArray(new File[potentialProjects.size()]);
}
@Override
public Object[] getChildren(Object parentElement) {
return null;
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public boolean hasChildren(Object element) {
return false;
}
});
tree.setComparator(new ViewerComparator() {
@Override
public int compare(Viewer v, Object o1, Object o2) {
return ((File) o1).getAbsolutePath().compareTo(((File) o2).getAbsolutePath());
}
});
tree.setCheckStateProvider(new ICheckStateProvider() {
@Override
public boolean isGrayed(Object element) {
return false;
}
@Override
public boolean isChecked(Object element) {
return SmartImportRootWizardPage.this.directoriesToImport.contains(element);
}
});
tree.addCheckStateListener(new ICheckStateListener() {
@Override
public void checkStateChanged(CheckStateChangedEvent event) {
if (isExistingProject((File) event.getElement())
|| isExistingProjectName((File) event.getElement())) {
tree.setChecked(event.getElement(), false);
return;
}
if (event.getChecked()) {
SmartImportRootWizardPage.this.directoriesToImport.add((File) event.getElement());
} else {
SmartImportRootWizardPage.this.directoriesToImport.remove(event.getElement());
}
proposalsSelectionChanged();
}
});
tree.getTree().setHeaderVisible(true);
ViewerColumn pathColumn = new TreeViewerColumn(tree, SWT.NONE);
pathColumn.setLabelProvider(new FolderForProjectsLabelProvider());
tree.getTree().getColumn(0).setText(DataTransferMessages.SmartImportProposals_folder);
tree.getTree().getColumn(0).setWidth(500);
ViewerColumn projectTypeColumn = new TreeViewerColumn(tree, SWT.NONE);
projectTypeColumn.setLabelProvider(new ProjectConfiguratorLabelProvider());
tree.getTree().getColumn(1).setText(DataTransferMessages.SmartImportProposals_importAs);
tree.getTree().getColumn(1).setWidth(150);
this.proposalSelectionDecorator = new ControlDecoration(tree.getTree(), SWT.TOP | SWT.LEFT);
Image errorImage = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_ERROR)
.getImage();
this.proposalSelectionDecorator.setImage(errorImage);
this.proposalSelectionDecorator
.setDescriptionText(DataTransferMessages.SmartImportWizardPage_selectAtLeastOneFolderToOpenAsProject);
this.proposalSelectionDecorator.hide();
Composite selectionButtonsGroup = new Composite(res, SWT.NONE);
GridLayoutFactory.fillDefaults().applyTo(selectionButtonsGroup);
selectionButtonsGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
selectAllButton = new Button(selectionButtonsGroup, SWT.PUSH);
setButtonLayoutData(selectAllButton);
selectAllButton.setText(DataTransferMessages.DataTransfer_selectAll);
selectAllButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
for (TreeItem item : tree.getTree().getItems()) {
File dir = (File) item.getData();
if (isExistingProject(dir) || isExistingProjectName(dir)) {
tree.setChecked(dir, false);
} else {
tree.setChecked(dir, true);
SmartImportRootWizardPage.this.directoriesToImport.add(dir);
}
}
proposalsSelectionChanged();
}
});
deselectAllButton = new Button(selectionButtonsGroup, SWT.PUSH);
setButtonLayoutData(deselectAllButton);
deselectAllButton.setText(DataTransferMessages.DataTransfer_deselectAll);
deselectAllButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
for (Object item : tree.getCheckedElements()) {
tree.setChecked(item, false);
SmartImportRootWizardPage.this.directoriesToImport.remove(item);
}
proposalsSelectionChanged();
}
});
selectionSummary = new Label(selectionButtonsGroup, SWT.NONE);
selectionSummary.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, true, 1, 1));
selectionSummary.setText(NLS.bind(DataTransferMessages.SmartImportProposals_selectionSummary, 0, 0));
Button hideProjectsAlreadyInWorkspace = new Button(selectionButtonsGroup, SWT.CHECK);
hideProjectsAlreadyInWorkspace.setText(DataTransferMessages.SmartImportProposals_hideExistingProjects);
hideProjectsAlreadyInWorkspace.addSelectionListener(new SelectionAdapter() {
final ViewerFilter existingProjectsFilter = new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
return !isExistingProject((File) element);
}
};
@Override
public void widgetSelected(SelectionEvent e) {
ViewerFilter[] currentFilters = tree.getFilters();
ViewerFilter[] newFilters = null;
if (((Button) e.widget).getSelection()) {
newFilters = new ViewerFilter[currentFilters.length + 1];
System.arraycopy(currentFilters, 0, newFilters, 0, currentFilters.length);
newFilters[newFilters.length - 1] = existingProjectsFilter;
} else {
List<ViewerFilter> filters = new ArrayList<>(
currentFilters.length > 0 ? currentFilters.length - 1 : 0);
for (ViewerFilter filter : currentFilters) {
if (filter != existingProjectsFilter) {
filters.add(filter);
}
}
newFilters = filters.toArray(new ViewerFilter[filters.size()]);
}
tree.setFilters(newFilters);
}
});
tree.setInput(Collections.emptyMap());
return res;
}
/**
* @param element
* @return
*/
protected boolean isExistingProject(File element) {
for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
IPath location = project.getLocation();
if (location != null && element.equals(location.toFile())) {
return true;
}
}
return false;
}
protected boolean isExistingProjectName(File element) {
return ResourcesPlugin.getWorkspace().getRoot().getProject(element.getName()).exists();
}
protected void validatePage() {
// reset error message
setErrorMessage(null);
// order of invocation of setErrorMessage == reverse order of priority
// ie: most important one must call setErrorMessage last
if (tree.getCheckedElements().length == 0) {
this.proposalSelectionDecorator.show();
setErrorMessage(this.proposalSelectionDecorator.getDescriptionText());
} else {
this.proposalSelectionDecorator.hide();
}
if (!sourceIsValid()) {
this.rootDirectoryTextDecorator.show();
setErrorMessage(this.rootDirectoryTextDecorator.getDescriptionText());
} else {
this.rootDirectoryTextDecorator.hide();
}
setPageComplete(isPageComplete());
}
@Override
public boolean isPageComplete() {
return sourceIsValid() && getWizard().getImportJob() != null
&& (getWizard().getImportJob().getDirectoriesToImport() == null
|| !getWizard().getImportJob().getDirectoriesToImport().isEmpty());
}
private boolean sourceIsValid() {
return this.selection != null
&& (this.selection.isDirectory() || SmartImportWizard.isValidArchive(this.selection));
}
/**
*
* @return The selected source of import (can be a directory or an archive)
*/
public File getSelectedRoot() {
return this.selection;
}
/**
* Sets the initial source to import.
*
* @param directoryOrArchive
*/
public void setInitialImportRoot(File directoryOrArchive) {
this.selection = directoryOrArchive;
this.rootDirectoryText.setText(directoryOrArchive.getAbsolutePath());
refreshProposals();
}
/**
*
* @return The user selected working sets to assign to imported projects.
*/
public Set<IWorkingSet> getSelectedWorkingSets() {
this.workingSets = new HashSet<>();
// workingSetsGroup doesn't support listeners...
Runnable workingSetsRetriever = new Runnable() {
@Override
public void run() {
for (IWorkingSet workingSet : SmartImportRootWizardPage.this.workingSetsGroup
.getSelectedWorkingSets()) {
SmartImportRootWizardPage.this.workingSets.add(workingSet);
}
}
};
if (Display.getCurrent() == null) {
getContainer().getShell().getDisplay().syncExec(workingSetsRetriever);
} else {
workingSetsRetriever.run();
}
return this.workingSets;
}
private void proposalsSelectionChanged() {
if (getWizard().getImportJob() != null) {
if (potentialProjects.size() == 1 && potentialProjects.values().iterator().next().isEmpty()) {
getWizard().getImportJob().setDirectoriesToImport(null);
getWizard().getImportJob().setExcludedDirectories(null);
selectionSummary.setText(NLS.bind(DataTransferMessages.SmartImportProposals_selectionSummary,
directoriesToImport.size(), 1));
} else {
Set<File> excludedDirectories = new HashSet(((Map<File, ?>) this.tree.getInput()).keySet());
for (Object item : this.directoriesToImport) {
File directory = (File) item;
excludedDirectories.remove(directory);
}
getWizard().getImportJob().setDirectoriesToImport(directoriesToImport);
getWizard().getImportJob().setExcludedDirectories(excludedDirectories);
selectionSummary.setText(NLS.bind(DataTransferMessages.SmartImportProposals_selectionSummary,
directoriesToImport.size(),
potentialProjects.size()));
}
}
setPageComplete(isPageComplete());
}
/**
* @return whether the job should recurse to find nested projects
*/
public boolean isDetectNestedProject() {
return this.detectNestedProjects;
}
/**
* @return whether the job should configure projects (add natures etc...)
*/
public boolean isConfigureProjects() {
return this.configureProjects;
}
boolean isCloseProjectsAfterImport() {
return closeProjectsAfterImport;
}
private void refreshProposals() {
stopAndDisconnectCurrentWork();
this.potentialProjects = Collections.emptyMap();
proposalsUpdated();
// compute new state
if (sourceIsValid()) {
tree.getControl().setEnabled(false);
selectAllButton.setEnabled(false);
deselectAllButton.setEnabled(false);
TreeItem computingItem = new TreeItem(tree.getTree(), SWT.DEFAULT);
computingItem
.setText(NLS.bind(DataTransferMessages.SmartImportJob_inspecting, selection.getAbsolutePath()));
final SmartImportJob importJob = getWizard().getImportJob();
refreshProposalsJob = new Job(
NLS.bind(DataTransferMessages.SmartImportJob_inspecting, selection.getAbsolutePath())) {
@Override
public IStatus run(IProgressMonitor monitor) {
SmartImportRootWizardPage.this.potentialProjects = importJob.getImportProposals(monitor);
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
if (!potentialProjects.containsKey(importJob.getRoot())) {
potentialProjects.put(importJob.getRoot(), Collections.emptyList());
}
return Status.OK_STATUS;
}
};
Control previousFocusControl = tree.getControl().getDisplay().getFocusControl();
if (previousFocusControl == null) {
previousFocusControl = rootDirectoryText;
}
Point initialSelection = rootDirectoryText.getSelection();
wizardProgressMonitor.get().attachToCancelComponent(null);
wizardProgressMonitor.get().setVisible(true);
// restore focus and selection because IWizardDialog.run(...) and
// attachToCancelComponent take them
previousFocusControl.setFocus();
rootDirectoryText.setSelection(initialSelection);
ToolItem stopButton = getStopButton(wizardProgressMonitor.get());
stopButton.addSelectionListener(this.cancelWorkListener);
jobMonitor = ProgressManager.getInstance().progressFor(refreshProposalsJob);
delegateMonitor = new DelegateProgressMonitorInUIThreadAndPreservingFocus(wizardProgressMonitor.get());
jobMonitor.addProgressListener(delegateMonitor);
refreshProposalsJob.setPriority(Job.INTERACTIVE);
refreshProposalsJob.setUser(true);
refreshProposalsJob.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
Control control = tree.getControl();
if (!control.isDisposed()) {
control.getDisplay().asyncExec(() -> {
IStatus result = event.getResult();
if (!control.isDisposed() && result.isOK()) {
computingItem.dispose();
if (sourceIsValid() && getWizard().getImportJob() == importJob) {
proposalsUpdated();
}
tree.getTree().setEnabled(potentialProjects.size() > 1);
selectAllButton.setEnabled(potentialProjects.size() > 1);
deselectAllButton.setEnabled(potentialProjects.size() > 1);
} else if (result.getCode() == IStatus.CANCEL) {
computingItem.setText(DataTransferMessages.SmartImportProposals_inspecitionCanceled);
} else if (result.getCode() == IStatus.ERROR) {
computingItem.setText(
NLS.bind(DataTransferMessages.SmartImportProposals_errorWhileInspecting,
result.getMessage()));
}
if (!wizardProgressMonitor.get().isDisposed()
&& refreshProposalsJob.getState() == Job.NONE) {
wizardProgressMonitor.get().setVisible(false);
}
});
}
}
});
refreshProposalsJob.schedule(0);
}
}
private static ToolItem getStopButton(ProgressMonitorPart part) {
for (Control control : part.getChildren()) {
if (control instanceof ToolBar) {
for (ToolItem item : ((ToolBar) control).getItems()) {
if (item.getToolTipText().equals(JFaceResources.getString("ProgressMonitorPart.cancelToolTip"))) { //$NON-NLS-1$ ))
return item;
}
}
}
}
return null;
}
private void stopAndDisconnectCurrentWork() {
if (refreshProposalsJob != null) {
refreshProposalsJob.cancel();
}
}
private void proposalsUpdated() {
tree.setInput(potentialProjects);
this.directoriesToImport = new HashSet<>();
for (File dir : potentialProjects.keySet()) {
if (!(isExistingProject(dir) || isExistingProjectName(dir))) {
directoriesToImport.add(dir);
}
}
tree.setCheckedElements(directoriesToImport.toArray(new Object[directoriesToImport.size()]));
proposalsSelectionChanged();
validatePage();
}
@Override
public void dispose() {
stopAndDisconnectCurrentWork();
getStopButton(wizardProgressMonitor.get()).removeSelectionListener(this.cancelWorkListener);
super.dispose();
}
/**
* Only made public for testing purpose
*
* @return the Wizard progress monitor
* @noreference This method is not intended to be referenced by clients.
*/
public ProgressMonitorPart getWizardProgressMonitor() {
return this.wizardProgressMonitor.get();
}
}