| /******************************************************************************* |
| * Copyright (c) 2000, 2009 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 |
| * Philippe Ombredanne - bug 84808 |
| *******************************************************************************/ |
| package org.eclipse.team.internal.ccvs.ui.wizards; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.*; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.*; |
| import org.eclipse.team.internal.ccvs.core.ICVSRemoteFolder; |
| import org.eclipse.team.internal.ccvs.ui.CVSUIMessages; |
| import org.eclipse.team.internal.ccvs.ui.IHelpContextIds; |
| import org.eclipse.ui.PlatformUI; |
| |
| /** |
| * @author Administrator |
| * |
| * To change the template for this generated type comment go to |
| * Window>Preferences>Java>Code Generation>Code and Comments |
| */ |
| public class CheckoutAsLocationSelectionPage extends CVSWizardPage { |
| |
| public static final String NAME = "CheckoutAsLocationSelectionPage"; //$NON-NLS-1$ |
| |
| private Button browseButton; |
| private Combo locationPathField; |
| private Label locationLabel; |
| private boolean useDefaults = true; |
| private ICVSRemoteFolder[] remoteFolders; |
| private String targetLocation; |
| private IProject singleProject; |
| |
| // constants |
| private static final int SIZING_TEXT_FIELD_WIDTH = 250; |
| private static final int COMBO_HISTORY_LENGTH = 5; |
| |
| // store id constants |
| private static final String STORE_PREVIOUS_LOCATIONS = |
| "CheckoutAsLocationSelectionPage.STORE_PREVIOUS_LOCATIONS";//$NON-NLS-1$ |
| |
| /** |
| * @param pageName |
| * @param title |
| * @param titleImage |
| * @param description |
| */ |
| public CheckoutAsLocationSelectionPage(ImageDescriptor titleImage, ICVSRemoteFolder[] remoteFolders) { |
| super(NAME, CVSUIMessages.CheckoutAsLocationSelectionPage_title, titleImage, CVSUIMessages.CheckoutAsLocationSelectionPage_description); // |
| this.remoteFolders = remoteFolders; |
| } |
| |
| /** |
| * @return |
| */ |
| private boolean isSingleFolder() { |
| return remoteFolders.length == 1; |
| } |
| |
| /** |
| * @param string |
| */ |
| public void setProject(IProject project) { |
| singleProject = project; |
| setLocationForSelection(true); |
| } |
| |
| /** |
| * @param string |
| */ |
| public void setProjectName(String string) { |
| if (string == null || string.equals(".")) return; //$NON-NLS-1$ |
| if (singleProject != null && singleProject.getName().equals(string)) return; |
| setProject(ResourcesPlugin.getWorkspace().getRoot().getProject(string)); |
| } |
| |
| private IProject getSingleProject() { |
| if (singleProject == null) { |
| setProjectName(getPreferredFolderName(remoteFolders[0])); |
| } |
| return singleProject; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) |
| */ |
| @Override |
| public void createControl(Composite parent) { |
| Composite composite= createComposite(parent, 1, false); |
| setControl(composite); |
| // required in order to use setButtonLayoutData |
| initializeDialogUnits(composite); |
| |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IHelpContextIds.CHECKOUT_LOCATION_SELECTION_PAGE); |
| |
| final Button useDefaultsButton = |
| new Button(composite, SWT.CHECK | SWT.RIGHT); |
| useDefaultsButton.setText(CVSUIMessages.CheckoutAsLocationSelectionPage_useDefaultLabel); |
| useDefaultsButton.setSelection(this.useDefaults); |
| |
| createUserSpecifiedProjectLocationGroup(composite, !this.useDefaults); |
| initializeValues(); |
| |
| SelectionListener listener = new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| useDefaults = useDefaultsButton.getSelection(); |
| browseButton.setEnabled(!useDefaults); |
| locationPathField.setEnabled(!useDefaults); |
| locationLabel.setEnabled(!useDefaults); |
| setLocationForSelection(true); |
| setErrorMessage(useDefaults ? null : checkValidLocation()); |
| } |
| }; |
| useDefaultsButton.addSelectionListener(listener); |
| Dialog.applyDialogFont(parent); |
| } |
| |
| /** |
| * Creates the project location specification controls. |
| * |
| * @return the parent of the widgets created |
| * @param projectGroup the parent composite |
| * @param enabled - sets the initial enabled state of the widgets |
| */ |
| private Composite createUserSpecifiedProjectLocationGroup(Composite parent, boolean enabled) { |
| |
| // This group needs 3 columns |
| Composite projectGroup = createComposite(parent, 3, true); |
| |
| // location label |
| locationLabel = new Label(projectGroup, SWT.NONE); |
| if (isSingleFolder()) { |
| locationLabel.setText(CVSUIMessages.CheckoutAsLocationSelectionPage_locationLabel); |
| } else { |
| locationLabel.setText(CVSUIMessages.CheckoutAsLocationSelectionPage_parentDirectoryLabel); |
| } |
| locationLabel.setEnabled(enabled); |
| |
| // project location entry field |
| locationPathField = new Combo(projectGroup, SWT.DROP_DOWN); |
| GridData data = new GridData(GridData.FILL_HORIZONTAL); |
| data.widthHint = SIZING_TEXT_FIELD_WIDTH; |
| locationPathField.setLayoutData(data); |
| locationPathField.setEnabled(enabled); |
| |
| // browse button |
| this.browseButton = new Button(projectGroup, SWT.PUSH); |
| this.browseButton.setText(CVSUIMessages.CheckoutAsLocationSelectionPage_browseLabel); |
| this.browseButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent event) { |
| handleLocationBrowseButtonPressed(); |
| } |
| }); |
| this.browseButton.setEnabled(enabled); |
| setButtonLayoutData(this.browseButton); |
| |
| // Set the initial value first before listener |
| // to avoid handling an event during the creation. |
| setLocationForSelection(true); |
| locationPathField.addModifyListener(e -> setErrorMessage(checkValidLocation())); |
| return projectGroup; |
| } |
| |
| /** |
| * Initializes states of the controls. |
| */ |
| private void initializeValues() { |
| // Set remembered values |
| IDialogSettings settings = getDialogSettings(); |
| if (settings != null) { |
| String[] previouseLocations = settings.getArray(STORE_PREVIOUS_LOCATIONS); |
| if (previouseLocations != null) { |
| for (int i = 0; i < previouseLocations.length; i++) { |
| if(isSingleFolder()) |
| locationPathField.add(new Path(previouseLocations[i]).append(getSingleProject().getName()).toOSString()); |
| else |
| locationPathField.add(previouseLocations[i]); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Saves the widget values |
| */ |
| private void saveWidgetValues() { |
| // Update history |
| IDialogSettings settings = getDialogSettings(); |
| if (settings != null) { |
| String[] previouseLocations = settings.getArray(STORE_PREVIOUS_LOCATIONS); |
| if (previouseLocations == null) previouseLocations = new String[0]; |
| if(isSingleFolder()) |
| previouseLocations = addToHistory(previouseLocations, new Path(locationPathField.getText()).removeLastSegments(1).toOSString()); |
| else |
| previouseLocations = addToHistory(previouseLocations, locationPathField.getText()); |
| settings.put(STORE_PREVIOUS_LOCATIONS, previouseLocations); |
| } |
| } |
| |
| /** |
| * Adds an entry to a history, while taking care of duplicate history items |
| * and excessively long histories. The assumption is made that all histories |
| * should be of length <code>CheckoutAsLocationSelectionPage.COMBO_HISTORY_LENGTH</code>. |
| * |
| * @param history the current history |
| * @param newEntry the entry to add to the history |
| * @return the history with the new entry appended |
| */ |
| private String[] addToHistory(String[] history, String newEntry) { |
| ArrayList<String> l = new ArrayList<>(Arrays.asList(history)); |
| addToHistory(l, newEntry); |
| String[] r = new String[l.size()]; |
| l.toArray(r); |
| return r; |
| } |
| |
| /** |
| * Adds an entry to a history, while taking care of duplicate history items |
| * and excessively long histories. The assumption is made that all histories |
| * should be of length <code>CheckoutAsLocationSelectionPage.COMBO_HISTORY_LENGTH</code>. |
| * |
| * @param history the current history |
| * @param newEntry the entry to add to the history |
| */ |
| private void addToHistory(List<String> history, String newEntry) { |
| history.remove(newEntry); |
| history.add(0,newEntry); |
| |
| // since only one new item was added, we can be over the limit |
| // by at most one item |
| if (history.size() > COMBO_HISTORY_LENGTH) |
| history.remove(COMBO_HISTORY_LENGTH); |
| } |
| |
| /** |
| * Check if the entry in the widget location is valid. If it is valid return null. Otherwise |
| * return a string that indicates the problem. |
| */ |
| private String checkValidLocation() { |
| |
| if (useDefaults) { |
| targetLocation = null; |
| return null; |
| } else { |
| targetLocation = locationPathField.getText(); |
| if (targetLocation.equals("")) {//$NON-NLS-1$ |
| return(CVSUIMessages.CheckoutAsLocationSelectionPage_locationEmpty); |
| } |
| else{ |
| IPath path = new Path("");//$NON-NLS-1$ |
| if (!path.isValidPath(targetLocation)) { |
| return CVSUIMessages.CheckoutAsLocationSelectionPage_invalidLocation; |
| } |
| } |
| |
| if (isSingleFolder()) { |
| IStatus locationStatus = |
| ResourcesPlugin.getWorkspace().validateProjectLocation( |
| getSingleProject(), |
| new Path(targetLocation)); |
| |
| if (!locationStatus.isOK()) |
| return locationStatus.getMessage(); |
| } else { |
| for (int i = 0; i < remoteFolders.length; i++) { |
| String projectName = getPreferredFolderName(remoteFolders[i]); |
| IStatus locationStatus = ResourcesPlugin.getWorkspace().validateProjectLocation( |
| ResourcesPlugin.getWorkspace().getRoot().getProject(projectName), |
| new Path(targetLocation).append(projectName)); |
| if (!locationStatus.isOK()) |
| return locationStatus.getMessage(); |
| } |
| } |
| |
| return null; |
| } |
| } |
| |
| /** |
| * Set the location to the default location if we are set to useDefaults. |
| */ |
| private void setLocationForSelection(boolean changed) { |
| if (useDefaults) { |
| IPath defaultPath = null; |
| if (isSingleFolder()) { |
| IProject singleProject = getSingleProject(); |
| if (singleProject != null) { |
| try { |
| defaultPath = singleProject.getDescription().getLocation(); |
| } catch (CoreException e) { |
| // ignore |
| } |
| if (defaultPath == null) { |
| defaultPath = Platform.getLocation().append(singleProject.getName()); |
| } |
| } |
| } else { |
| defaultPath = Platform.getLocation(); |
| } |
| if (defaultPath != null) { |
| locationPathField.setText(defaultPath.toOSString()); |
| } |
| targetLocation = null; |
| } else if (changed) { |
| IPath location = null; |
| IProject project = getSingleProject(); |
| if (project != null) { |
| try { |
| location = project.getDescription().getLocation(); |
| } catch (CoreException e) { |
| // ignore the exception |
| } |
| } |
| if (location == null) { |
| targetLocation = null; |
| locationPathField.setText(""); //$NON-NLS-1$ |
| } else { |
| if (isSingleFolder()) { |
| targetLocation = location.toOSString(); |
| } else { |
| targetLocation = location.removeLastSegments(1).toOSString(); |
| } |
| locationPathField.setText(targetLocation); |
| } |
| } |
| } |
| |
| /** |
| * Open an appropriate directory browser |
| */ |
| private void handleLocationBrowseButtonPressed() { |
| DirectoryDialog dialog = new DirectoryDialog(locationPathField.getShell()); |
| if (isSingleFolder()) { |
| dialog.setMessage(NLS.bind(CVSUIMessages.CheckoutAsLocationSelectionPage_messageForSingle, new String[] { getSingleProject().getName() })); |
| } else { |
| dialog.setMessage(NLS.bind(CVSUIMessages.CheckoutAsLocationSelectionPage_messageForMulti, new String[] { Integer.valueOf(remoteFolders.length).toString() })); |
| } |
| |
| String dirName = locationPathField.getText(); |
| if (!dirName.equals("")) {//$NON-NLS-1$ |
| File path = new File(dirName); |
| if (path.exists()) |
| dialog.setFilterPath(dirName); |
| } |
| |
| String selectedDirectory = dialog.open(); |
| if (selectedDirectory != null) { |
| if (isSingleFolder()) { |
| locationPathField.setText(new Path(selectedDirectory).append(getSingleProject().getName()).toOSString()); |
| } else { |
| locationPathField.setText(new Path(selectedDirectory).toOSString()); |
| } |
| } |
| targetLocation = locationPathField.getText(); |
| } |
| |
| /** |
| * Return the custom location for a single project. In this case, the specified |
| * location is used as the location of the project. |
| * |
| * @param project |
| * @return |
| */ |
| public String getTargetLocation() { |
| if (isCustomLocationSpecified()) { |
| saveWidgetValues(); |
| return targetLocation; |
| } |
| return null; |
| } |
| |
| /** |
| * @return |
| */ |
| private boolean isCustomLocationSpecified() { |
| return !useDefaults; |
| } |
| |
| } |