Java tutorial
/******************************************************************************* * Copyright (c) 2000, 2009 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 net.sf.eclipsefp.haskell.ui.internal.wizards; import java.io.File; import java.io.IOException; import java.net.URI; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.util.Observable; import java.util.Observer; import net.sf.eclipsefp.haskell.buildwrapper.BuildWrapperPlugin; import net.sf.eclipsefp.haskell.ui.HaskellUIPlugin; import net.sf.eclipsefp.haskell.ui.dialog.Validator; import net.sf.eclipsefp.haskell.ui.dialog.ValidatorManager; import net.sf.eclipsefp.haskell.ui.dialog.dialogfields.DialogField; import net.sf.eclipsefp.haskell.ui.dialog.dialogfields.IDialogFieldListener; import net.sf.eclipsefp.haskell.ui.dialog.dialogfields.IStringButtonAdapter; import net.sf.eclipsefp.haskell.ui.dialog.dialogfields.LayoutUtil; import net.sf.eclipsefp.haskell.ui.dialog.dialogfields.SelectionButtonDialogField; import net.sf.eclipsefp.haskell.ui.dialog.dialogfields.StringButtonDialogField; import net.sf.eclipsefp.haskell.ui.dialog.dialogfields.StringDialogField; import net.sf.eclipsefp.haskell.ui.internal.util.UITexts; import org.eclipse.core.filesystem.URIUtil; 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.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; 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.Group; /** * Largely a copy of org.eclipse.jdt.ui.wizards.NewJavaProjectWizardPageOne. * * It would make sense to extend {@link WizardNewProjectCreationPage}. However, * that class does not allow setting the project name, so then we couldn't set * the project name based on the directory name of the existing source. * * @author Thomas ten Cate */ public class NewProjectWizardPage extends WizardPage { /** * Request a project name. Fires an event whenever the text field is * changed, regardless of its content. */ private final class NameGroup extends Observable implements IDialogFieldListener { protected final StringDialogField fNameField; public NameGroup() { // text field for project name fNameField = new StringDialogField(); fNameField.setLabelText(UITexts.newProjectWizardPage_NameGroup_label_text); fNameField.setDialogFieldListener(this); } public Control createControl(final Composite composite) { Composite nameComposite = new Composite(composite, SWT.NONE); nameComposite.setFont(composite.getFont()); nameComposite.setLayout(initGridLayout(new GridLayout(2, false), false)); fNameField.doFillIntoGrid(nameComposite, 2); LayoutUtil.setHorizontalGrabbing(fNameField.getTextControl(null)); return nameComposite; } protected void fireEvent() { setChanged(); notifyObservers(); } public String getName() { return fNameField.getText().trim(); } public void postSetFocus() { fNameField.postSetFocusOnDialogField(getShell().getDisplay()); } public void setName(final 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) */ @Override public void dialogFieldChanged(final 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 fWorkspaceRadio; protected final SelectionButtonDialogField fExternalRadio; protected final StringButtonDialogField fLocation; private String fPreviousExternalLocation; private final String DIALOGSTORE_LAST_EXTERNAL_LOC = HaskellUIPlugin.getPluginId() + ".last.external.project"; //$NON-NLS-1$ public LocationGroup() { fWorkspaceRadio = new SelectionButtonDialogField(SWT.RADIO); fWorkspaceRadio.setDialogFieldListener(this); fWorkspaceRadio.setLabelText(UITexts.newProjectWizardPage_LocationGroup_workspace_desc); fExternalRadio = new SelectionButtonDialogField(SWT.RADIO); fExternalRadio.setLabelText(UITexts.newProjectWizardPage_LocationGroup_external_desc); fLocation = new StringButtonDialogField(this); fLocation.setDialogFieldListener(this); fLocation.setLabelText(UITexts.newProjectWizardPage_LocationGroup_locationLabel_desc); fLocation.setButtonLabel(UITexts.newProjectWizardPage_LocationGroup_browseButton_desc); fExternalRadio.attachDialogField(fLocation); fWorkspaceRadio.setSelection(true); fExternalRadio.setSelection(false); fPreviousExternalLocation = ""; //$NON-NLS-1$ } public Control createControl(final Composite composite) { final int numColumns = 3; final Group group = new Group(composite, SWT.NONE); group.setLayout(initGridLayout(new GridLayout(numColumns, false), true)); group.setText(UITexts.newProjectWizardPage_LocationGroup_title); fWorkspaceRadio.doFillIntoGrid(group, numColumns); fExternalRadio.doFillIntoGrid(group, numColumns); fLocation.doFillIntoGrid(group, numColumns); LayoutUtil.setHorizontalGrabbing(fLocation.getTextControl(null)); return group; } protected void fireEvent() { setChanged(); notifyObservers(); } protected String getDefaultPath(final 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) */ @Override public void update(final Observable o, final Object arg) { if (isWorkspaceRadioSelected()) { fLocation.setText(getDefaultPath(getProjectName())); } fireEvent(); } public IPath getLocation() { if (isWorkspaceRadioSelected()) { return Platform.getLocation(); } return Path.fromOSString(fLocation.getText().trim()); } public boolean isWorkspaceRadioSelected() { return fWorkspaceRadio.isSelected(); } /** * Returns <code>true</code> if the location is in the workspace * * @return <code>true</code> if the location is in the workspace */ public boolean isLocationInWorkspace() { final String location = fLocationGroup.getLocation().toOSString(); IPath projectPath = Path.fromOSString(location); return Platform.getLocation().isPrefixOf(projectPath); } public void setLocation(final IPath path) { fWorkspaceRadio.setSelection(path == null); if (path != null) { fLocation.setText(path.toOSString()); } else { fLocation.setText(getDefaultPath(getProjectName())); } fireEvent(); } /* (non-Javadoc) * @see org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter#changeControlPressed(org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField) */ @Override public void changeControlPressed(final DialogField field) { final DirectoryDialog dialog = new DirectoryDialog(getShell()); dialog.setMessage(UITexts.newProjectWizardPage_directory_message); String directoryName = fLocation.getText().trim(); if (directoryName.length() == 0) { String prevLocation = HaskellUIPlugin.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 && (getProjectName().length() == 0 || getProjectName().equals(oldDirectory))) { setProjectName(lastSegment); } HaskellUIPlugin.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) */ @Override public void dialogFieldChanged(final DialogField field) { if (field == fWorkspaceRadio) { final boolean checked = fWorkspaceRadio.isSelected(); if (checked) { fPreviousExternalLocation = fLocation.getText(); fLocation.setText(getDefaultPath(fNameGroup.getName())); } else { fLocation.setText(fPreviousExternalLocation); } } fireEvent(); } } private final class ComponentGroup extends Observable implements IDialogFieldListener { protected final SelectionButtonDialogField fExecutable; protected final SelectionButtonDialogField fLibrary; public ComponentGroup() { fExecutable = new SelectionButtonDialogField(SWT.CHECK); fExecutable.setDialogFieldListener(this); fExecutable.setLabelText(UITexts.newProjectWizardPage_ComponentGroup_executable); fExecutable.setSelection(true); fLibrary = new SelectionButtonDialogField(SWT.CHECK); fLibrary.setDialogFieldListener(this); fLibrary.setLabelText(UITexts.newProjectWizardPage_ComponentGroup_library); } public Composite createControl(final Composite composite) { final int numColumns = 1; final Group group = new Group(composite, SWT.NONE); group.setLayout(initGridLayout(new GridLayout(numColumns, false), true)); group.setText(UITexts.newProjectWizardPage_ComponentGroup_title); fExecutable.doFillIntoGrid(group, numColumns); fLibrary.doFillIntoGrid(group, numColumns); return group; } protected void fireEvent() { setChanged(); notifyObservers(); } @Override public void dialogFieldChanged(final DialogField field) { fireEvent(); } public boolean isLibrary() { return fLibrary.isSelected(); } public boolean isExecutable() { return fExecutable.isSelected(); } } /** * Validate this page and show appropriate warnings and error NewWizardMessages. */ private final class PageValidator extends Validator { public PageValidator(final ValidatorManager manager) { super(manager); } @Override protected void doUpdate() { final IWorkspace workspace = ResourcesPlugin.getWorkspace(); final String name = fNameGroup.getName(); // check whether the project name field is empty if (name.length() == 0) { setIncomplete(UITexts.newProjectWizardPage_Message_enterProjectName, IMessageProvider.INFORMATION); return; } // check whether the project name is valid final IStatus nameStatus = workspace.validateName(name, IResource.PROJECT); if (!nameStatus.isOK()) { setErrorMessage(nameStatus.getMessage()); setPageComplete(false); return; } for (int a = 0; a < name.length(); a++) { char c = name.charAt(a); if (!(Character.isDigit(c) || Character.isLetter(c) || c == '-')) { setIncomplete(UITexts.newProjectWizardPage_Message_projectInvalidName); return; } } CharsetEncoder asciiEncoder = Charset.forName("US-ASCII").newEncoder(); if (!asciiEncoder.canEncode(name)) { setIncomplete(UITexts.newProjectWizardPage_Message_projectNonAsciiName); return; } // check whether project already exists final IProject handle = workspace.getRoot().getProject(name); if (handle.exists()) { setIncomplete(UITexts.newProjectWizardPage_Message_projectAlreadyExists); return; } if (fLocationGroup.isWorkspaceRadioSelected()) { 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) { HaskellUIPlugin.log(e); } String existingName = projectLocation.lastSegment(); if (!existingName.equals(fNameGroup.getName())) { setIncomplete( NLS.bind(UITexts.newProjectWizardPageMessage_invalidProjectNameForWorkspaceRoot, existingName)); return; } } } final String location = fLocationGroup.getLocation().toOSString(); // check whether location is empty if (location.length() == 0) { setErrorMessage(null); setIncomplete(UITexts.newProjectWizardPage_Message_enterLocation); return; } // check whether the location is a syntactically correct path if (!Path.EMPTY.isValidPath(location)) { setIncomplete(UITexts.newProjectWizardPage_Message_invalidDirectory); return; } IPath projectPath = Path.fromOSString(location); if (fLocationGroup.isWorkspaceRadioSelected()) { projectPath = projectPath.append(fNameGroup.getName()); } if (projectPath.toFile().exists()) {//create from existing source if (Platform.getLocation().isPrefixOf(projectPath)) { //create from existing source in workspace // why? // if (!Platform.getLocation().equals(projectPath.removeLastSegments(1))) { // setErrorMessage(UITexts.newProjectWizardPage_Message_notOnWorkspaceRoot); // setPageComplete(false); // return; // } if (!projectPath.toFile().exists()) { setIncomplete(UITexts.newProjectWizardPage_Message_notExistingProjectOnWorkspaceRoot); return; } } IPath cabalFile = BuildWrapperPlugin.getCabalFile(projectPath, name); //projectPath.append(name).addFileExtension( FileUtil.EXTENSION_CABAL ); // cabal file exists: disable component choice enableComponentControl(cabalFile == null); setWarningMessage(UITexts.newProjectWizardPage_Message_alreadyExists); setPageComplete(true); return; } else if (!fLocationGroup.isWorkspaceRadioSelected()) {//create at non existing external location if (!canCreate(projectPath.toFile())) { setIncomplete(UITexts.newProjectWizardPage_Message_cannotCreateAtExternalLocation); return; } // If we do not place the contents in the workspace validate the // location. final IStatus locationStatus = workspace.validateProjectLocation(handle, projectPath); if (!locationStatus.isOK()) { setIncomplete(locationStatus.getMessage()); return; } } enableComponentControl(true); setPageComplete(true); setMessage(null); } private boolean canCreate(final File file) { File parent = file; while (!parent.exists()) { parent = parent.getParentFile(); if (parent == null) { return false; } } return parent.canWrite(); } } private static final String PAGE_NAME = "NewProjectWizardPage"; //$NON-NLS-1$ private final ValidatorManager fValidatorManager; private PageValidator fValidator; private final NameGroup fNameGroup; private final LocationGroup fLocationGroup; private final ComponentGroup fComponentGroup; private Composite componentControl; public NewProjectWizardPage() { this(PAGE_NAME); } public NewProjectWizardPage(final String pageName) { super(pageName); fNameGroup = new NameGroup(); fLocationGroup = new LocationGroup(); fComponentGroup = new ComponentGroup(); // establish connections fNameGroup.addObserver(fLocationGroup); // initialize all elements fNameGroup.notifyObservers(); // create and connect validator fValidatorManager = new ValidatorManager(this); createValidators(fValidatorManager); fNameGroup.addObserver(fValidator); fLocationGroup.addObserver(fValidator); // initialize defaults setProjectName(""); //$NON-NLS-1$ setProjectLocationURI(null); } /** * Subclasses may override to add additional validators, * but must call the superclass method. */ protected void createValidators(final ValidatorManager manager) { fValidator = new PageValidator(manager); } protected ValidatorManager getValidatorManager() { return fValidatorManager; } /** * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) * * Subclasses should not override; rather, override {@link #createControls}. */ @Override public void createControl(final Composite parent) { initializeDialogUnits(parent); final Composite composite = new Composite(parent, SWT.NULL); composite.setFont(parent.getFont()); composite.setLayout(initGridLayout(new GridLayout(1, false), true)); composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); createControls(composite); setControl(composite); fValidatorManager.fullUpdate(); } /** * Creates the controls within this page. * Subclasses may override. */ protected void createControls(final Composite composite) { createNameControl(composite); createLocationControl(composite); componentControl = createComponentControl(composite); } /** * Creates the controls for the name field. * * @param composite the parent composite * @return the created control */ protected Control createNameControl(final Composite composite) { Control nameControl = fNameGroup.createControl(composite); nameControl.setLayoutData(horizontalFillGridData()); return nameControl; } /** * Creates the controls for the location field. * * @param composite the parent composite * @return the created control */ protected Control createLocationControl(final Composite composite) { Control locationControl = fLocationGroup.createControl(composite); locationControl.setLayoutData(horizontalFillGridData()); return locationControl; } /** * Creates the controls for the name field. * * @param composite the parent composite * @return the created control */ protected Composite createComponentControl(final Composite composite) { Composite componentControl = fComponentGroup.createControl(composite); componentControl.setLayoutData(horizontalFillGridData()); return componentControl; } /** * enable or disable the component group * @param enabled */ protected void enableComponentControl(final boolean enabled) { if (componentControl != null) { componentControl.setEnabled(enabled); fComponentGroup.fExecutable.setEnabled(enabled); fComponentGroup.fLibrary.setEnabled(enabled); if (!enabled) { fComponentGroup.fExecutable.setSelection(false); fComponentGroup.fLibrary.setSelection(false); } } } public boolean isLibrary() { return fComponentGroup.isLibrary(); } public boolean isExecutable() { return fComponentGroup.isExecutable(); } /** * Gets a project name for the new project. * * @return the new project resource handle */ public String getProjectName() { return fNameGroup.getName(); } /** * Sets the name of the new project * * @param name the new name */ public void setProjectName(final String name) { if (name == null) { throw new IllegalArgumentException(); } fNameGroup.setName(name); } /** * Returns the current project location path as entered by the user, or <code>null</code> * if the project should be created in the workspace. * @return the project location path or its anticipated initial value. */ public URI getProjectLocationURI() { if (fLocationGroup.isLocationInWorkspace()) { return null; } return URIUtil.toURI(fLocationGroup.getLocation()); } /** * Sets the project location of the new project or <code>null</code> if the project * should be created in the workspace * * @param uri the new project location */ public void setProjectLocationURI(final URI uri) { IPath path = uri != null ? URIUtil.toPath(uri) : null; fLocationGroup.setLocation(path); } /** * Creates a project resource handle for the current project name field * value. The project handle is created relative to the workspace root. * <p> * This method does not create the project resource; this is the * responsibility of <code>IProject::create</code> invoked by the new * project resource wizard. * </p> * * @return the new project resource handle */ public IProject getProjectHandle() { return ResourcesPlugin.getWorkspace().getRoot().getProject(getProjectName()); } /** * Returns the current project location path as entered by * the user, or its anticipated initial value. * Note that if the default has been returned the path * in a project description used to create a project * should not be set. * * @return the project location path or its anticipated initial value. */ public IPath getProjectLocationPath() { return fLocationGroup.getLocation(); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.DialogPage#setVisible(boolean) */ @Override public void setVisible(final boolean visible) { super.setVisible(visible); if (visible) { fNameGroup.postSetFocus(); } } protected GridLayout initGridLayout(final GridLayout layout, final boolean margins) { layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); if (margins) { layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); } else { layout.marginWidth = 0; layout.marginHeight = 0; } return layout; } protected GridData horizontalFillGridData() { return new GridData(GridData.FILL_HORIZONTAL); } }