blob: e69fa9c044a48ae3c9b3c8430d8890bf13a02309 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2008 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.team.internal.ccvs.ui.wizards;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
import org.eclipse.team.internal.ccvs.ui.CVSUIMessages;
import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
import org.eclipse.team.internal.ccvs.ui.model.RemoteContentProvider;
import org.eclipse.team.internal.ccvs.ui.repo.RepositoryComparator;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.WorkbenchLabelProvider;
public class ModuleSelectionPage extends CVSWizardPage {
Button useProjectNameButton;
Button useSpecifiedNameButton;
private Button selectModuleButton;
private Button useModuleAndProjectNameButton;
Text text;
TreeViewer moduleList;
String moduleName;
// The project being associated with the remote module (or null)
private IProject project;
private ICVSRepositoryLocation location;
private boolean badLocation = false;
private String helpContextId;
private boolean supportsMultiSelection;
private boolean isFetchingModules = false;
private Object fetchingModulesLock = new Object();
private String SEPARATOR = "/"; //$NON-NLS-1$
public ModuleSelectionPage(String pageName, String title, ImageDescriptor titleImage) {
super(pageName, title, titleImage);
}
public void setHelpContxtId(String helpContextId) {
this.helpContextId = helpContextId;
}
@Override
public void createControl(Composite parent) {
Composite composite = createComposite(parent, 2, false);
if (helpContextId != null)
PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, helpContextId);
Listener listener = event -> updateEnablements(false);
if (project != null) {
useProjectNameButton = createRadioButton(composite, CVSUIMessages.ModuleSelectionPage_moduleIsProject, 2);
useProjectNameButton.addListener(SWT.Selection, listener);
}
useSpecifiedNameButton = createRadioButton(composite, CVSUIMessages.ModuleSelectionPage_specifyModule, 1);
useSpecifiedNameButton.addListener(SWT.Selection, listener);
text = createTextField(composite);
text.addListener(SWT.Modify, listener);
selectModuleButton = createRadioButton(composite, CVSUIMessages.ModuleSelectionPage_2, 2);
selectModuleButton.addListener(SWT.Selection, listener);
if (project != null) {
useModuleAndProjectNameButton = new Button(composite, SWT.CHECK);
useModuleAndProjectNameButton.setText(CVSUIMessages.ModuleSelectionPage_3);
GridData data = new GridData();
data.horizontalSpan = 2;
data.horizontalIndent = 10;
useModuleAndProjectNameButton.setLayoutData(data);
useModuleAndProjectNameButton.addListener(SWT.Selection, event -> updateText());
}
moduleList = createModuleTree(composite, 2);
// Set the initial enablement
if (useProjectNameButton != null) {
useProjectNameButton.setSelection(true);
useSpecifiedNameButton.setSelection(false);
} else {
useSpecifiedNameButton.setSelection(true);
}
selectModuleButton.setSelection(false);
if (useModuleAndProjectNameButton != null)
useModuleAndProjectNameButton.setSelection(false);
updateEnablements(false);
setControl(composite);
Dialog.applyDialogFont(parent);
}
private void updateText() {
updateEnablements(false);
ICVSRemoteFolder[] modules = internalGetSelectedModules();
if (modules.length == 1) {
// There is at 1 module selected
ICVSRemoteFolder selectedModule = modules[0];
String repositoryRelativePath = selectedModule.getRepositoryRelativePath();
if (!repositoryRelativePath.equals(FolderSyncInfo.VIRTUAL_DIRECTORY)) {
text.setText(repositoryRelativePath);
}
} else {
text.setText(useModuleAndProjectName() ? project.getName() : ""); //$NON-NLS-1$
}
}
private boolean useModuleAndProjectName() {
return useModuleAndProjectNameButton != null
&& useModuleAndProjectNameButton.getSelection();
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible) {
IWizard w = getWizard();
if (w instanceof CheckoutWizard) {
((CheckoutWizard)w).resetSubwizard();
}
if (useProjectNameButton != null && useProjectNameButton.getSelection()) {
useProjectNameButton.setFocus();
} else if (useSpecifiedNameButton.getSelection()) {
text.setFocus();
} else {
moduleList.getControl().setFocus();
}
}
}
protected void updateEnablements(boolean updateModulesList) {
if (useProjectNameButton != null && useProjectNameButton.getSelection()) {
text.setEnabled(false);
moduleList.getControl().setEnabled(false);
if (useModuleAndProjectNameButton != null)
useModuleAndProjectNameButton.setEnabled(false);
moduleName = null;
setPageComplete(true);
} else if (useSpecifiedNameButton.getSelection()) {
text.setEnabled(true);
moduleList.getControl().setEnabled(false);
if (useModuleAndProjectNameButton != null)
useModuleAndProjectNameButton.setEnabled(false);
moduleName = text.getText();
if (moduleName.length() == 0) {
moduleName = null;
setPageComplete(false);
} else {
setPageComplete(true);
}
} else if (!badLocation){
text.setEnabled(false);
if (useModuleAndProjectNameButton != null)
useModuleAndProjectNameButton.setEnabled(true);
moduleList.getControl().setEnabled(true);
moduleName = null;
if (moduleList.getInput() == null || updateModulesList) {
boolean fetchModules = false;
// The input is set after the page is shown to avoid
// fetching if the user wants to specify the name manually
try {
// This can be called from different events in the event loop.
// Ensure that we only fetch the input once
synchronized (fetchingModulesLock) {
if (!isFetchingModules) {
// This the first thread in so fetch the modules
fetchModules = true;
isFetchingModules = true;
}
}
if (fetchModules) {
// Validate the location first since the module fecthing is
// done in a deferred fashion
getContainer().run(true, true, monitor -> {
try {
validateLocation(monitor);
} catch (CVSException e) {
throw new InvocationTargetException(e);
}
});
setModuleListInput();
}
} catch (InvocationTargetException e) {
if (!badLocation) {
badLocation = true;
CVSUIPlugin.openError(getShell(), null, null, e);
// This will null the module list input
setModuleListInput();
}
} catch (InterruptedException e) {
// Canceled by the user
} finally {
synchronized (fetchingModulesLock) {
if (fetchModules) {
isFetchingModules = false;
}
}
}
}
setPageComplete(internalGetSelectedModules().length > 0);
}
}
/* package */ ICVSRemoteFolder[] internalGetSelectedModules() {
if (moduleList != null && moduleList.getControl().isEnabled()) {
ISelection selection = moduleList.getSelection();
if (!selection.isEmpty() && selection instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection)selection;
ArrayList<ICVSRemoteFolder> result = new ArrayList<>();
for (Iterator iter = ss.iterator(); iter.hasNext();) {
Object element = iter.next();
if (element instanceof ICVSRemoteFolder) {
if (useModuleAndProjectName()) {
String relativePath = ((ICVSRemoteFolder)element).getRepositoryRelativePath();
ICVSRemoteFolder remoteFolder = internalCreateModuleHandle(relativePath + SEPARATOR + project.getName())[0];
result.add(remoteFolder);
} else {
result.add((ICVSRemoteFolder) element);
}
}
}
return result.toArray(new ICVSRemoteFolder[result.size()]);
}
} else {
if (moduleName != null) {
return internalCreateModuleHandle(moduleName);
} else if (project != null) {
return internalCreateModuleHandle(project.getName());
}
}
return new ICVSRemoteFolder[0];
}
private ICVSRemoteFolder[] internalCreateModuleHandle(String name) {
ICVSRepositoryLocation location = getLocation();
if (location == null) return new ICVSRemoteFolder[0];
String[] names = name.split(","); //$NON-NLS-1$
int length = names.length;
java.util.List<ICVSRemoteFolder> folders = new ArrayList<>();
for (int i = 0; i < length; i++) {
// call trim() in case the user has added spaces after the commas
String trimmedName = names[i].trim();
if (trimmedName.length() > 0)
folders.add(location.getRemoteFolder(trimmedName, CVSTag.DEFAULT));
}
return folders.toArray(new ICVSRemoteFolder[folders.size()]);
}
/**
* Return the selected existing remote folder. If this
* method returns <code>null</code>, then <code>getModuleName()</code>
* can be used to get the name entered manually by the use.
* @return the selected existing remote module
*/
public ICVSRemoteFolder getSelectedModule() {
ICVSRemoteFolder[] selectedModules = getSelectedModules();
if (selectedModules.length > 0) {
return selectedModules[0];
} else {
return null;
}
}
public ICVSRemoteFolder[] getSelectedModules() {
final ICVSRemoteFolder[][] folder = new ICVSRemoteFolder[][] { null };
Display.getDefault().syncExec(() -> folder[0] = internalGetSelectedModules());
return folder[0];
}
private TreeViewer createModuleTree(Composite composite, int horizontalSpan) {
Tree tree = new Tree(composite, (supportsMultiSelection ? SWT.MULTI : SWT.SINGLE) | SWT.BORDER);
GridData data = new GridData(GridData.FILL_BOTH);
// see bug 158380
data.heightHint = Math.max(composite.getParent().getSize().y, 100);
data.horizontalSpan = horizontalSpan;
tree.setLayoutData(data);
TreeViewer result = new TreeViewer(tree) {
/*
* Fix to allow filtering to be used without triggering fetching
* of the contents of all children (see bug 62268)
*/
@Override
public boolean isExpandable(Object element) {
ITreeContentProvider cp = (ITreeContentProvider) getContentProvider();
if(cp == null)
return false;
return cp.hasChildren(element);
}
};
result.setContentProvider(new RemoteContentProvider());
result.setLabelProvider(new WorkbenchLabelProvider());
result.addFilter(new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
return !(element instanceof ICVSRemoteFile);
}
});
result.addSelectionChangedListener(event -> updateText());
result.getTree().addMouseListener(new MouseAdapter() {
@Override
public void mouseDoubleClick(MouseEvent e) {
if (getSelectedModule() != null) {
gotoNextPage();
}
}
});
result.setComparator(new RepositoryComparator());
return result;
}
private void setModuleListInput() {
ICVSRepositoryLocation location = getLocation();
if (location == null || badLocation) return;
moduleList.setInput(location.getRemoteFolder(ICVSRemoteFolder.REPOSITORY_ROOT_FOLDER_NAME, CVSTag.DEFAULT));
}
private ICVSRepositoryLocation getLocation() {
return location;
}
public void setLocation(ICVSRepositoryLocation location) {
boolean refresh = location != null && !location.equals(this.location);
this.location = location;
badLocation = false;
if (moduleList != null) {
updateEnablements(refresh);
}
}
public void setProject(IProject project) {
this.project = project;
}
public void setSupportsMultiSelection(boolean supportsMultiSelection) {
this.supportsMultiSelection = supportsMultiSelection;
}
/* package */ void gotoNextPage() {
getContainer().showPage(getNextPage());
}
/* package */ void validateLocation(IProgressMonitor monitor) throws CVSException {
location.validateConnection(monitor);
}
}