/******************************************************************************* * Copyright (c) 2000, 2013 IBM Corporation 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: IBM Corporation - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.wizard.template; import java.io.File; import java.io.IOException; import java.util.Observable; import java.util.Observer; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.jdt.internal.corext.util.Messages; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages; import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField; import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener; import org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter; import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil; import org.eclipse.jdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField; import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonDialogField; import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Shell; import org.springframework.ide.eclipse.wizard.WizardPlugin; /** * The following code is copied from: * * org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageOne * * as these were originally private methods, yet perform general working sets * handling from a structured selection and package explorer part that can be * reused for other project wizards. * * Visibility of the methods has been increased from private to protected or * public. Otherwise, the code remains unchanged. * */ public class ProjectNameLocationArea extends WizardPageArea { private final NameGroup nameGroup; private final LocationGroup locationGroup; private final Validator validator; private final Shell shell; private final NewSpringProjectWizardModel model; public ProjectNameLocationArea(NewSpringProjectWizardModel model, IWizardPageStatusHandler statusHandler, Shell shell) { super(statusHandler); this.shell = shell; this.model = model; validator = new Validator(); nameGroup = new NameGroup(); locationGroup = new LocationGroup(); } @Override public Control createArea(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().applyTo(composite); GridDataFactory.fillDefaults().grab(true, false).applyTo(composite); nameGroup.createControl(composite); locationGroup.createControl(composite); // establish connections nameGroup.addObserver(locationGroup); // initialize all elements nameGroup.notifyObservers(); nameGroup.addObserver(validator); locationGroup.addObserver(validator); // Fire the first event for validation setProjectName(""); //$NON-NLS-1$ return composite; } /** * Gets a project name for the new project. * * @return the new project resource handle */ protected String getProjectName() { return nameGroup.getName(); } /** * Sets the name of the new project * * @param name the new name */ protected void setProjectName(String name) { if (name == null) { throw new IllegalArgumentException(); } nameGroup.setName(name); } /** * Request a project name. Fires an event whenever the text field is * changed, regardless of its content. */ protected final class NameGroup extends Observable implements IDialogFieldListener { protected final StringDialogField fNameField; public NameGroup() { // text field for project name fNameField = new StringDialogField(); fNameField.setLabelText(NewWizardMessages.NewJavaProjectWizardPageOne_NameGroup_label_text); fNameField.setDialogFieldListener(this); } public Control createControl(Composite composite) { Composite nameComposite = new Composite(composite, SWT.NONE); nameComposite.setFont(composite.getFont()); nameComposite.setLayout(new GridLayout(2, false)); fNameField.doFillIntoGrid(nameComposite, 2); LayoutUtil.setHorizontalGrabbing(fNameField.getTextControl(null)); GridDataFactory.fillDefaults().grab(true, false).applyTo(nameComposite); return nameComposite; } protected void fireEvent() { setChanged(); notifyObservers(); } public String getName() { return fNameField.getText().trim(); } public void postSetFocus() { fNameField.postSetFocusOnDialogField(shell.getDisplay()); } public void setName(String name) { fNameField.setText(name); } /* * (non-Javadoc) * * @see * org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener * #dialogFieldChanged(org.eclipse.jdt.internal.ui.wizards.dialogfields. * DialogField) */ public void dialogFieldChanged(DialogField field) { fireEvent(); } } /** * Request a location. Fires an event whenever the checkbox or the location * field is changed, regardless of whether the change originates from the * user or has been invoked programmatically. */ private final class LocationGroup extends Observable implements Observer, IStringButtonAdapter, IDialogFieldListener { protected final SelectionButtonDialogField fUseDefaults; protected final StringButtonDialogField fLocation; private String fPreviousExternalLocation; private static final String DIALOGSTORE_LAST_EXTERNAL_LOC = JavaUI.ID_PLUGIN + ".last.external.project"; //$NON-NLS-1$ public LocationGroup() { fUseDefaults = new SelectionButtonDialogField(SWT.CHECK); fUseDefaults.setDialogFieldListener(this); fUseDefaults.setLabelText(NewWizardMessages.NewJavaProjectWizardPageOne_LocationGroup_location_desc); fLocation = new StringButtonDialogField(this); fLocation.setDialogFieldListener(this); fLocation.setLabelText(NewWizardMessages.NewJavaProjectWizardPageOne_LocationGroup_locationLabel_desc); fLocation.setButtonLabel(NewWizardMessages.NewJavaProjectWizardPageOne_LocationGroup_browseButton_desc); fUseDefaults.setSelection(true); fPreviousExternalLocation = ""; //$NON-NLS-1$ } public Control createControl(Composite composite) { final int numColumns = 4; final Composite locationComposite = new Composite(composite, SWT.NONE); locationComposite.setLayout(new GridLayout(numColumns, false)); fUseDefaults.doFillIntoGrid(locationComposite, numColumns); fLocation.doFillIntoGrid(locationComposite, numColumns); LayoutUtil.setHorizontalGrabbing(fLocation.getTextControl(null)); GridDataFactory.fillDefaults().grab(true, false).applyTo(locationComposite); return locationComposite; } protected void fireEvent() { setChanged(); notifyObservers(); } protected String getDefaultPath(String name) { final IPath path = Platform.getLocation().append(name); return path.toOSString(); } /* * (non-Javadoc) * * @see java.util.Observer#update(java.util.Observable, * java.lang.Object) */ public void update(Observable o, Object arg) { if (isUseDefaultSelected()) { fLocation.setText(getDefaultPath(nameGroup.getName())); } fireEvent(); } public IPath getLocation() { if (isUseDefaultSelected()) { return Platform.getLocation(); } return Path.fromOSString(fLocation.getText().trim()); } public boolean isUseDefaultSelected() { return fUseDefaults.isSelected(); } public void setLocation(IPath path) { fUseDefaults.setSelection(path == null); if (path != null) { fLocation.setText(path.toOSString()); } else { fLocation.setText(getDefaultPath(nameGroup.getName())); } fireEvent(); } /* * (non-Javadoc) * * @see * org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter * # * changeControlPressed(org.eclipse.jdt.internal.ui.wizards.dialogfields * .DialogField) */ public void changeControlPressed(DialogField field) { final DirectoryDialog dialog = new DirectoryDialog(shell); dialog.setMessage(NewWizardMessages.NewJavaProjectWizardPageOne_directory_message); String directoryName = fLocation.getText().trim(); if (directoryName.length() == 0) { String prevLocation = JavaPlugin.getDefault().getDialogSettings().get(DIALOGSTORE_LAST_EXTERNAL_LOC); if (prevLocation != null) { directoryName = prevLocation; } } if (directoryName.length() > 0) { final File path = new File(directoryName); if (path.exists()) { dialog.setFilterPath(directoryName); } } final String selectedDirectory = dialog.open(); if (selectedDirectory != null) { String oldDirectory = new Path(fLocation.getText().trim()).lastSegment(); fLocation.setText(selectedDirectory); String lastSegment = new Path(selectedDirectory).lastSegment(); if (lastSegment != null && (nameGroup.getName().length() == 0 || nameGroup.getName().equals(oldDirectory))) { nameGroup.setName(lastSegment); } JavaPlugin.getDefault().getDialogSettings().put(DIALOGSTORE_LAST_EXTERNAL_LOC, selectedDirectory); } } /* * (non-Javadoc) * * @see * org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener * #dialogFieldChanged(org.eclipse.jdt.internal.ui.wizards.dialogfields. * DialogField) */ public void dialogFieldChanged(DialogField field) { if (field == fUseDefaults) { final boolean checked = fUseDefaults.isSelected(); if (checked) { fPreviousExternalLocation = fLocation.getText(); fLocation.setText(getDefaultPath(nameGroup.getName())); fLocation.setEnabled(false); } else { fLocation.setText(fPreviousExternalLocation); fLocation.setEnabled(true); } } fireEvent(); } } protected final class Validator implements Observer { public void update(Observable o, Object arg) { IStatus status = validateArea(); notifyStatusChange(status); } } @Override protected IStatus validateArea() { // First time the area is validated, treat missing data as OK status as // not to show an error when the UI is first displayed. // Subsequent validations should treat missing data as ERROR. int missingDataStatus = IStatus.INFO; final String name = getProjectName(); final String location = locationGroup.getLocation().toOSString(); model.projectName.setValue(name); // Only set the location if default is not used. Otherwise set null if (locationGroup.isUseDefaultSelected()) { model.projectLocation.setValue(null); } else { model.projectLocation.setValue(location); } final IWorkspace workspace = JavaPlugin.getWorkspace(); // check whether the project name field is empty if (name.length() == 0) { setAreaComplete(false); return createStatus(NewWizardMessages.NewJavaProjectWizardPageOne_Message_enterProjectName, missingDataStatus); } // check whether the project name is valid final IStatus nameStatus = workspace.validateName(name, IResource.PROJECT); if (!nameStatus.isOK()) { setAreaComplete(false); return createStatus(nameStatus.getMessage(), IStatus.ERROR); } // check whether project already exists final IProject handle = workspace.getRoot().getProject(name); if (handle.exists()) { setAreaComplete(false); return createStatus(NewWizardMessages.NewJavaProjectWizardPageOne_Message_projectAlreadyExists, IStatus.ERROR); } IPath projectLocation = ResourcesPlugin.getWorkspace().getRoot().getLocation().append(name); if (projectLocation.toFile().exists()) { try { // correct casing String canonicalPath = projectLocation.toFile().getCanonicalPath(); projectLocation = new Path(canonicalPath); } catch (IOException e) { // Do not set as a wizard status, as it may sill be continue // with further checks WizardPlugin .getDefault() .getLog() .log(new Status(IStatus.ERROR, WizardPlugin.PLUGIN_ID, "I/O Error when correcting project path casing: " + e.getMessage(), e)); } String existingName = projectLocation.lastSegment(); if (!existingName.equals(nameGroup.getName())) { setAreaComplete(false); return createStatus(Messages.format( NewWizardMessages.NewJavaProjectWizardPageOne_Message_invalidProjectNameForWorkspaceRoot, BasicElementLabels.getResourceName(existingName)), IStatus.ERROR); } } // check whether location is empty if (location.length() == 0) { setAreaComplete(false); return createStatus(NewWizardMessages.NewJavaProjectWizardPageOne_Message_enterLocation, missingDataStatus); } // check whether the location is a syntactically correct path if (!Path.EMPTY.isValidPath(location)) { setAreaComplete(false); return createStatus(NewWizardMessages.NewJavaProjectWizardPageOne_Message_invalidDirectory, IStatus.ERROR); } IPath projectPath = null; if (!locationGroup.isUseDefaultSelected()) { projectPath = Path.fromOSString(location); if (!projectPath.toFile().exists()) { // check non-existing external location if (!canCreate(projectPath.toFile())) { setAreaComplete(false); return createStatus( NewWizardMessages.NewJavaProjectWizardPageOne_Message_cannotCreateAtExternalLocation, IStatus.ERROR); } } } // validate the location final IStatus locationStatus = workspace.validateProjectLocation(handle, projectPath); if (!locationStatus.isOK()) { setAreaComplete(false); return createStatus(locationStatus.getMessage(), IStatus.ERROR); } setAreaComplete(true); return Status.OK_STATUS; } private boolean canCreate(File file) { while (!file.exists()) { file = file.getParentFile(); if (file == null) { return false; } } return file.canWrite(); } }