001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.wizards.datatransfer;
011:
012: import java.io.File;
013: import java.io.FileFilter;
014: import java.lang.reflect.InvocationTargetException;
015:
016: import org.eclipse.core.resources.IProject;
017: import org.eclipse.core.resources.IProjectDescription;
018: import org.eclipse.core.resources.IResource;
019: import org.eclipse.core.resources.IResourceStatus;
020: import org.eclipse.core.resources.IWorkspace;
021: import org.eclipse.core.resources.ResourcesPlugin;
022: import org.eclipse.core.runtime.CoreException;
023: import org.eclipse.core.runtime.IPath;
024: import org.eclipse.core.runtime.IProgressMonitor;
025: import org.eclipse.core.runtime.OperationCanceledException;
026: import org.eclipse.core.runtime.Path;
027: import org.eclipse.core.runtime.Platform;
028: import org.eclipse.core.runtime.SubProgressMonitor;
029: import org.eclipse.jface.dialogs.ErrorDialog;
030: import org.eclipse.jface.dialogs.MessageDialog;
031: import org.eclipse.jface.wizard.WizardPage;
032: import org.eclipse.osgi.util.NLS;
033: import org.eclipse.swt.SWT;
034: import org.eclipse.swt.events.SelectionAdapter;
035: import org.eclipse.swt.events.SelectionEvent;
036: import org.eclipse.swt.graphics.Font;
037: import org.eclipse.swt.layout.GridData;
038: import org.eclipse.swt.layout.GridLayout;
039: import org.eclipse.swt.widgets.Button;
040: import org.eclipse.swt.widgets.Composite;
041: import org.eclipse.swt.widgets.DirectoryDialog;
042: import org.eclipse.swt.widgets.Event;
043: import org.eclipse.swt.widgets.Label;
044: import org.eclipse.swt.widgets.Listener;
045: import org.eclipse.swt.widgets.Text;
046: import org.eclipse.ui.PlatformUI;
047: import org.eclipse.ui.actions.WorkspaceModifyOperation;
048: import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
049: import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
050: import org.eclipse.ui.internal.wizards.datatransfer.DataTransferMessages;
051:
052: /**
053: * Standard main page for a wizard that creates a project resource from
054: * whose location already contains a project.
055: * <p>
056: * This page may be used by clients as-is; it may be also be subclassed to suit.
057: * </p>
058: * <p>
059: * Example usage:
060: * <pre>
061: * mainPage = new WizardExternalProjectImportPage("basicNewProjectPage");
062: * mainPage.setTitle("Project");
063: * mainPage.setDescription("Create a new project resource.");
064: * </pre>
065: * </p>
066: */
067: public class WizardExternalProjectImportPage extends WizardPage {
068:
069: private FileFilter projectFilter = new FileFilter() {
070: //Only accept those files that are .project
071: public boolean accept(File pathName) {
072: return pathName.getName().equals(
073: IProjectDescription.DESCRIPTION_FILE_NAME);
074: }
075: };
076:
077: //Keep track of the directory that we browsed to last time
078: //the wizard was invoked.
079: private static String previouslyBrowsedDirectory = ""; //$NON-NLS-1$
080:
081: // widgets
082: private Text projectNameField;
083:
084: private Text locationPathField;
085:
086: private Button browseButton;
087:
088: private IProjectDescription description;
089:
090: private Listener locationModifyListener = new Listener() {
091: public void handleEvent(Event e) {
092: setPageComplete(validatePage());
093: }
094: };
095:
096: // constants
097: private static final int SIZING_TEXT_FIELD_WIDTH = 250;
098:
099: /**
100: * Creates a new project creation wizard page.
101: *
102: */
103: public WizardExternalProjectImportPage() {
104: super ("wizardExternalProjectPage"); //$NON-NLS-1$
105: setPageComplete(false);
106: setTitle(DataTransferMessages.WizardExternalProjectImportPage_title);
107: setDescription(DataTransferMessages.WizardExternalProjectImportPage_description);
108:
109: }
110:
111: /** (non-Javadoc)
112: * Method declared on IDialogPage.
113: */
114: public void createControl(Composite parent) {
115:
116: initializeDialogUnits(parent);
117:
118: Composite composite = new Composite(parent, SWT.NULL);
119:
120: PlatformUI.getWorkbench().getHelpSystem().setHelp(composite,
121: IIDEHelpContextIds.NEW_PROJECT_WIZARD_PAGE);
122:
123: composite.setLayout(new GridLayout());
124: composite.setLayoutData(new GridData(GridData.FILL_BOTH));
125: composite.setFont(parent.getFont());
126:
127: createProjectNameGroup(composite);
128: createProjectLocationGroup(composite);
129: validatePage();
130: // Show description on opening
131: setErrorMessage(null);
132: setMessage(null);
133: setControl(composite);
134: }
135:
136: /**
137: * Creates the project location specification controls.
138: *
139: * @param parent the parent composite
140: */
141: private final void createProjectLocationGroup(Composite parent) {
142:
143: // project specification group
144: Composite projectGroup = new Composite(parent, SWT.NONE);
145: GridLayout layout = new GridLayout();
146: layout.numColumns = 3;
147: projectGroup.setLayout(layout);
148: projectGroup.setLayoutData(new GridData(
149: GridData.FILL_HORIZONTAL));
150: projectGroup.setFont(parent.getFont());
151:
152: // new project label
153: Label projectContentsLabel = new Label(projectGroup, SWT.NONE);
154: projectContentsLabel
155: .setText(DataTransferMessages.WizardExternalProjectImportPage_projectContentsLabel);
156: projectContentsLabel.setFont(parent.getFont());
157:
158: createUserSpecifiedProjectLocationGroup(projectGroup);
159: }
160:
161: /**
162: * Creates the project name specification controls.
163: *
164: * @param parent the parent composite
165: */
166: private final void createProjectNameGroup(Composite parent) {
167:
168: Font dialogFont = parent.getFont();
169:
170: // project specification group
171: Composite projectGroup = new Composite(parent, SWT.NONE);
172: GridLayout layout = new GridLayout();
173: layout.numColumns = 2;
174: projectGroup.setFont(dialogFont);
175: projectGroup.setLayout(layout);
176: projectGroup.setLayoutData(new GridData(
177: GridData.FILL_HORIZONTAL));
178:
179: // new project label
180: Label projectLabel = new Label(projectGroup, SWT.NONE);
181: projectLabel
182: .setText(DataTransferMessages.WizardExternalProjectImportPage_nameLabel);
183: projectLabel.setFont(dialogFont);
184:
185: // new project name entry field
186: projectNameField = new Text(projectGroup, SWT.BORDER
187: | SWT.READ_ONLY);
188: GridData data = new GridData(GridData.FILL_HORIZONTAL);
189: data.widthHint = SIZING_TEXT_FIELD_WIDTH;
190: projectNameField.setLayoutData(data);
191: projectNameField.setFont(dialogFont);
192: projectNameField.setBackground(parent.getDisplay()
193: .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
194: }
195:
196: /**
197: * Creates the project location specification controls.
198: *
199: * @param projectGroup the parent composite
200: */
201: private void createUserSpecifiedProjectLocationGroup(
202: Composite projectGroup) {
203:
204: Font dialogFont = projectGroup.getFont();
205:
206: // project location entry field
207: this .locationPathField = new Text(projectGroup, SWT.BORDER);
208: GridData data = new GridData(GridData.FILL_HORIZONTAL);
209: data.widthHint = SIZING_TEXT_FIELD_WIDTH;
210: this .locationPathField.setLayoutData(data);
211: this .locationPathField.setFont(dialogFont);
212:
213: // browse button
214: this .browseButton = new Button(projectGroup, SWT.PUSH);
215: this .browseButton
216: .setText(DataTransferMessages.DataTransfer_browse);
217: this .browseButton.setFont(dialogFont);
218: setButtonLayoutData(this .browseButton);
219:
220: this .browseButton.addSelectionListener(new SelectionAdapter() {
221: public void widgetSelected(SelectionEvent event) {
222: handleLocationBrowseButtonPressed();
223: }
224: });
225:
226: locationPathField.addListener(SWT.Modify,
227: locationModifyListener);
228: }
229:
230: /**
231: * Returns the current project location path as entered by
232: * the user, or its anticipated initial value.
233: *
234: * @return the project location path, its anticipated initial value, or <code>null</code>
235: * if no project location path is known
236: */
237: public IPath getLocationPath() {
238:
239: return new Path(getProjectLocationFieldValue());
240: }
241:
242: /**
243: * Creates a project resource handle for the current project name field value.
244: * <p>
245: * This method does not create the project resource; this is the responsibility
246: * of <code>IProject::create</code> invoked by the new project resource wizard.
247: * </p>
248: *
249: * @return the new project resource handle
250: */
251: public IProject getProjectHandle() {
252: return ResourcesPlugin.getWorkspace().getRoot().getProject(
253: getProjectName());
254: }
255:
256: /**
257: * Returns the current project name as entered by the user, or its anticipated
258: * initial value.
259: *
260: * @return the project name, its anticipated initial value, or <code>null</code>
261: * if no project name is known
262: */
263: public String getProjectName() {
264: return getProjectNameFieldValue();
265: }
266:
267: /**
268: * Returns the value of the project name field
269: * with leading and trailing spaces removed.
270: *
271: * @return the project name in the field
272: */
273: private String getProjectNameFieldValue() {
274: if (projectNameField == null) {
275: return ""; //$NON-NLS-1$
276: }
277:
278: return projectNameField.getText().trim();
279: }
280:
281: /**
282: * Returns the value of the project location field
283: * with leading and trailing spaces removed.
284: *
285: * @return the project location directory in the field
286: */
287: private String getProjectLocationFieldValue() {
288: return locationPathField.getText().trim();
289: }
290:
291: /**
292: * Open an appropriate directory browser
293: */
294: private void handleLocationBrowseButtonPressed() {
295: DirectoryDialog dialog = new DirectoryDialog(locationPathField
296: .getShell());
297: dialog
298: .setMessage(DataTransferMessages.WizardExternalProjectImportPage_directoryLabel);
299:
300: String dirName = getProjectLocationFieldValue();
301: if (dirName.length() == 0) {
302: dirName = previouslyBrowsedDirectory;
303: }
304:
305: if (dirName.length() == 0) {
306: dialog.setFilterPath(getWorkspace().getRoot().getLocation()
307: .toOSString());
308: } else {
309: File path = new File(dirName);
310: if (path.exists()) {
311: dialog.setFilterPath(new Path(dirName).toOSString());
312: }
313: }
314:
315: String selectedDirectory = dialog.open();
316: if (selectedDirectory != null) {
317: previouslyBrowsedDirectory = selectedDirectory;
318: locationPathField.setText(previouslyBrowsedDirectory);
319: setProjectName(projectFile(previouslyBrowsedDirectory));
320: }
321: }
322:
323: /**
324: * Returns whether this page's controls currently all contain valid
325: * values.
326: *
327: * @return <code>true</code> if all controls are valid, and
328: * <code>false</code> if at least one is invalid
329: */
330: private boolean validatePage() {
331:
332: String locationFieldContents = getProjectLocationFieldValue();
333:
334: if (locationFieldContents.equals("")) { //$NON-NLS-1$
335: setErrorMessage(null);
336: setMessage(DataTransferMessages.WizardExternalProjectImportPage_projectLocationEmpty);
337: return false;
338: }
339:
340: IPath path = new Path(""); //$NON-NLS-1$
341: if (!path.isValidPath(locationFieldContents)) {
342: setErrorMessage(DataTransferMessages.WizardExternalProjectImportPage_locationError);
343: return false;
344: }
345:
346: File projectFile = projectFile(locationFieldContents);
347: if (projectFile == null) {
348: setErrorMessage(NLS
349: .bind(
350: DataTransferMessages.WizardExternalProjectImportPage_notAProject,
351: locationFieldContents));
352: return false;
353: }
354: setProjectName(projectFile);
355:
356: if (getProjectHandle().exists()) {
357: setErrorMessage(DataTransferMessages.WizardExternalProjectImportPage_projectExistsMessage);
358: return false;
359: }
360:
361: setErrorMessage(null);
362: setMessage(null);
363: return true;
364: }
365:
366: private IWorkspace getWorkspace() {
367: IWorkspace workspace = IDEWorkbenchPlugin.getPluginWorkspace();
368: return workspace;
369: }
370:
371: /**
372: * Return whether or not the specifed location is a prefix
373: * of the root.
374: */
375: private boolean isPrefixOfRoot(IPath locationPath) {
376: return Platform.getLocation().isPrefixOf(locationPath);
377: }
378:
379: /**
380: * Set the project name using either the name of the
381: * parent of the file or the name entry in the xml for
382: * the file
383: */
384: private void setProjectName(File projectFile) {
385:
386: //If there is no file or the user has already specified forget it
387: if (projectFile == null) {
388: return;
389: }
390:
391: IPath path = new Path(projectFile.getPath());
392:
393: IProjectDescription newDescription = null;
394:
395: try {
396: newDescription = getWorkspace()
397: .loadProjectDescription(path);
398: } catch (CoreException exception) {
399: //no good couldn't get the name
400: }
401:
402: if (newDescription == null) {
403: this .description = null;
404: this .projectNameField.setText(""); //$NON-NLS-1$
405: } else {
406: this .description = newDescription;
407: this .projectNameField.setText(this .description.getName());
408: }
409: }
410:
411: /**
412: * Return a.project file from the specified location.
413: * If there isn't one return null.
414: */
415: private File projectFile(String locationFieldContents) {
416: File directory = new File(locationFieldContents);
417: if (directory.isFile()) {
418: return null;
419: }
420:
421: File[] files = directory.listFiles(this .projectFilter);
422: if (files != null && files.length == 1) {
423: return files[0];
424: }
425:
426: return null;
427: }
428:
429: /**
430: * Creates a new project resource with the selected name.
431: * <p>
432: * In normal usage, this method is invoked after the user has pressed Finish on
433: * the wizard; the enablement of the Finish button implies that all controls
434: * on the pages currently contain valid values.
435: * </p>
436: *
437: * @return the created project resource, or <code>null</code> if the project
438: * was not created
439: */
440: IProject createExistingProject() {
441:
442: String projectName = projectNameField.getText();
443: final IWorkspace workspace = ResourcesPlugin.getWorkspace();
444: final IProject project = workspace.getRoot().getProject(
445: projectName);
446: if (this .description == null) {
447: this .description = workspace
448: .newProjectDescription(projectName);
449: IPath locationPath = getLocationPath();
450: //If it is under the root use the default location
451: if (isPrefixOfRoot(locationPath)) {
452: this .description.setLocation(null);
453: } else {
454: this .description.setLocation(locationPath);
455: }
456: } else {
457: this .description.setName(projectName);
458: }
459:
460: // create the new project operation
461: WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
462: protected void execute(IProgressMonitor monitor)
463: throws CoreException {
464: monitor.beginTask("", 2000); //$NON-NLS-1$
465: project.create(description, new SubProgressMonitor(
466: monitor, 1000));
467: if (monitor.isCanceled()) {
468: throw new OperationCanceledException();
469: }
470: project.open(IResource.BACKGROUND_REFRESH,
471: new SubProgressMonitor(monitor, 1000));
472:
473: }
474: };
475:
476: // run the new project creation operation
477: try {
478: getContainer().run(true, true, op);
479: } catch (InterruptedException e) {
480: return null;
481: } catch (InvocationTargetException e) {
482: // ie.- one of the steps resulted in a core exception
483: Throwable t = e.getTargetException();
484: if (t instanceof CoreException) {
485: if (((CoreException) t).getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS) {
486: MessageDialog
487: .openError(
488: getShell(),
489: DataTransferMessages.WizardExternalProjectImportPage_errorMessage,
490: NLS
491: .bind(
492: DataTransferMessages.WizardExternalProjectImportPage_caseVariantExistsError,
493: projectName));
494: } else {
495: ErrorDialog
496: .openError(
497: getShell(),
498: DataTransferMessages.WizardExternalProjectImportPage_errorMessage,
499: null, ((CoreException) t)
500: .getStatus());
501: }
502: }
503: return null;
504: }
505:
506: return project;
507: }
508:
509: /*
510: * see @DialogPage.setVisible(boolean)
511: */
512: public void setVisible(boolean visible) {
513: super.setVisible(visible);
514: if (visible) {
515: this.locationPathField.setFocus();
516: }
517: }
518:
519: }
|