001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 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.newresource;
011:
012: import java.lang.reflect.InvocationTargetException;
013: import java.net.URI;
014: import java.util.ArrayList;
015: import java.util.HashSet;
016: import java.util.List;
017: import java.util.Set;
018: import java.util.StringTokenizer;
019:
020: import org.eclipse.core.commands.ExecutionException;
021: import org.eclipse.core.resources.IProject;
022: import org.eclipse.core.resources.IProjectDescription;
023: import org.eclipse.core.resources.IResourceStatus;
024: import org.eclipse.core.resources.IWorkspace;
025: import org.eclipse.core.resources.ResourcesPlugin;
026: import org.eclipse.core.runtime.CoreException;
027: import org.eclipse.core.runtime.IConfigurationElement;
028: import org.eclipse.core.runtime.IExecutableExtension;
029: import org.eclipse.core.runtime.IProgressMonitor;
030: import org.eclipse.core.runtime.IStatus;
031: import org.eclipse.core.runtime.Status;
032: import org.eclipse.jface.dialogs.ErrorDialog;
033: import org.eclipse.jface.dialogs.IDialogConstants;
034: import org.eclipse.jface.dialogs.IDialogSettings;
035: import org.eclipse.jface.dialogs.MessageDialogWithToggle;
036: import org.eclipse.jface.operation.IRunnableWithProgress;
037: import org.eclipse.jface.preference.IPreferenceStore;
038: import org.eclipse.jface.resource.ImageDescriptor;
039: import org.eclipse.jface.viewers.IStructuredSelection;
040: import org.eclipse.osgi.util.NLS;
041: import org.eclipse.swt.widgets.Composite;
042: import org.eclipse.ui.IPerspectiveDescriptor;
043: import org.eclipse.ui.IPerspectiveRegistry;
044: import org.eclipse.ui.IPluginContribution;
045: import org.eclipse.ui.IWorkbench;
046: import org.eclipse.ui.IWorkbenchPage;
047: import org.eclipse.ui.IWorkbenchPreferenceConstants;
048: import org.eclipse.ui.IWorkbenchWindow;
049: import org.eclipse.ui.IWorkingSet;
050: import org.eclipse.ui.PlatformUI;
051: import org.eclipse.ui.WorkbenchException;
052: import org.eclipse.ui.activities.IActivityManager;
053: import org.eclipse.ui.activities.IIdentifier;
054: import org.eclipse.ui.activities.IWorkbenchActivitySupport;
055: import org.eclipse.ui.activities.WorkbenchActivityHelper;
056: import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
057: import org.eclipse.ui.dialogs.WizardNewProjectReferencePage;
058: import org.eclipse.ui.ide.IDE;
059: import org.eclipse.ui.ide.undo.CreateProjectOperation;
060: import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
061: import org.eclipse.ui.internal.IPreferenceConstants;
062: import org.eclipse.ui.internal.WorkbenchPlugin;
063: import org.eclipse.ui.internal.ide.IDEInternalPreferences;
064: import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
065: import org.eclipse.ui.internal.ide.StatusUtil;
066: import org.eclipse.ui.internal.registry.PerspectiveDescriptor;
067: import org.eclipse.ui.internal.util.PrefUtil;
068: import org.eclipse.ui.internal.wizards.newresource.ResourceMessages;
069: import org.eclipse.ui.statushandlers.StatusAdapter;
070: import org.eclipse.ui.statushandlers.StatusManager;
071:
072: /**
073: * Standard workbench wizard that creates a new project resource in the
074: * workspace.
075: * <p>
076: * This class may be instantiated and used without further configuration; this
077: * class is not intended to be subclassed.
078: * </p>
079: * <p>
080: * Example:
081: *
082: * <pre>
083: * IWorkbenchWizard wizard = new BasicNewProjectResourceWizard();
084: * wizard.init(workbench, selection);
085: * WizardDialog dialog = new WizardDialog(shell, wizard);
086: * dialog.open();
087: * </pre>
088: *
089: * During the call to <code>open</code>, the wizard dialog is presented to
090: * the user. When the user hits Finish, a project resource with the
091: * user-specified name is created, the dialog closes, and the call to
092: * <code>open</code> returns.
093: * </p>
094: */
095: public class BasicNewProjectResourceWizard extends
096: BasicNewResourceWizard implements IExecutableExtension {
097: private WizardNewProjectCreationPage mainPage;
098:
099: private WizardNewProjectReferencePage referencePage;
100:
101: // cache of newly-created project
102: private IProject newProject;
103:
104: /**
105: * The config element which declares this wizard.
106: */
107: private IConfigurationElement configElement;
108:
109: private static String WINDOW_PROBLEMS_TITLE = ResourceMessages.NewProject_errorOpeningWindow;
110:
111: /**
112: * Extension attribute name for final perspective.
113: */
114: private static final String FINAL_PERSPECTIVE = "finalPerspective"; //$NON-NLS-1$
115:
116: /**
117: * Extension attribute name for preferred perspectives.
118: */
119: private static final String PREFERRED_PERSPECTIVES = "preferredPerspectives"; //$NON-NLS-1$
120:
121: /**
122: * Creates a wizard for creating a new project resource in the workspace.
123: */
124: public BasicNewProjectResourceWizard() {
125: IDialogSettings workbenchSettings = IDEWorkbenchPlugin
126: .getDefault().getDialogSettings();
127: IDialogSettings section = workbenchSettings
128: .getSection("BasicNewProjectResourceWizard");//$NON-NLS-1$
129: if (section == null) {
130: section = workbenchSettings
131: .addNewSection("BasicNewProjectResourceWizard");//$NON-NLS-1$
132: }
133: setDialogSettings(section);
134: }
135:
136: /*
137: * (non-Javadoc) Method declared on IWizard.
138: */
139: public void addPages() {
140: super .addPages();
141:
142: mainPage = new WizardNewProjectCreationPage(
143: "basicNewProjectPage") { //$NON-NLS-1$
144: /*
145: * (non-Javadoc)
146: *
147: * @see org.eclipse.ui.dialogs.WizardNewProjectCreationPage#createControl(org.eclipse.swt.widgets.Composite)
148: */
149: public void createControl(Composite parent) {
150: super .createControl(parent);
151: createWorkingSetGroup(
152: (Composite) getControl(),
153: getSelection(),
154: new String[] { "org.eclipse.ui.resourceWorkingSetPage" }); //$NON-NLS-1$
155: }
156: };
157: mainPage.setTitle(ResourceMessages.NewProject_title);
158: mainPage
159: .setDescription(ResourceMessages.NewProject_description);
160: this .addPage(mainPage);
161:
162: // only add page if there are already projects in the workspace
163: if (ResourcesPlugin.getWorkspace().getRoot().getProjects().length > 0) {
164: referencePage = new WizardNewProjectReferencePage(
165: "basicReferenceProjectPage");//$NON-NLS-1$
166: referencePage
167: .setTitle(ResourceMessages.NewProject_referenceTitle);
168: referencePage
169: .setDescription(ResourceMessages.NewProject_referenceDescription);
170: this .addPage(referencePage);
171: }
172: }
173:
174: /**
175: * Creates a new project resource with the selected name.
176: * <p>
177: * In normal usage, this method is invoked after the user has pressed Finish
178: * on the wizard; the enablement of the Finish button implies that all
179: * controls on the pages currently contain valid values.
180: * </p>
181: * <p>
182: * Note that this wizard caches the new project once it has been
183: * successfully created; subsequent invocations of this method will answer
184: * the same project resource without attempting to create it again.
185: * </p>
186: *
187: * @return the created project resource, or <code>null</code> if the
188: * project was not created
189: */
190: private IProject createNewProject() {
191: if (newProject != null) {
192: return newProject;
193: }
194:
195: // get a project handle
196: final IProject newProjectHandle = mainPage.getProjectHandle();
197:
198: // get a project descriptor
199: URI location = null;
200: if (!mainPage.useDefaults()) {
201: location = mainPage.getLocationURI();
202: }
203:
204: IWorkspace workspace = ResourcesPlugin.getWorkspace();
205: final IProjectDescription description = workspace
206: .newProjectDescription(newProjectHandle.getName());
207: description.setLocationURI(location);
208:
209: // update the referenced project if provided
210: if (referencePage != null) {
211: IProject[] refProjects = referencePage
212: .getReferencedProjects();
213: if (refProjects.length > 0) {
214: description.setReferencedProjects(refProjects);
215: }
216: }
217:
218: // create the new project operation
219: IRunnableWithProgress op = new IRunnableWithProgress() {
220: public void run(IProgressMonitor monitor)
221: throws InvocationTargetException {
222: CreateProjectOperation op = new CreateProjectOperation(
223: description,
224: ResourceMessages.NewProject_windowTitle);
225: try {
226: PlatformUI
227: .getWorkbench()
228: .getOperationSupport()
229: .getOperationHistory()
230: .execute(
231: op,
232: monitor,
233: WorkspaceUndoUtil
234: .getUIInfoAdapter(getShell()));
235: } catch (ExecutionException e) {
236: throw new InvocationTargetException(e);
237: }
238: }
239: };
240:
241: // run the new project creation operation
242: try {
243: getContainer().run(true, true, op);
244: } catch (InterruptedException e) {
245: return null;
246: } catch (InvocationTargetException e) {
247: Throwable t = e.getTargetException();
248: if (t instanceof ExecutionException
249: && t.getCause() instanceof CoreException) {
250: CoreException cause = (CoreException) t.getCause();
251: StatusAdapter status;
252: if (cause.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS) {
253: status = new StatusAdapter(
254: StatusUtil
255: .newStatus(
256: IStatus.WARNING,
257: NLS
258: .bind(
259: ResourceMessages.NewProject_caseVariantExistsError,
260: newProjectHandle
261: .getName()),
262: cause));
263: } else {
264: status = new StatusAdapter(StatusUtil.newStatus(
265: cause.getStatus().getSeverity(),
266: ResourceMessages.NewProject_errorMessage,
267: cause));
268: }
269: status.setProperty(StatusAdapter.TITLE_PROPERTY,
270: ResourceMessages.NewProject_errorMessage);
271: StatusManager.getManager().handle(status,
272: StatusManager.BLOCK);
273: } else {
274: StatusAdapter status = new StatusAdapter(
275: new Status(
276: IStatus.WARNING,
277: IDEWorkbenchPlugin.IDE_WORKBENCH,
278: 0,
279: NLS
280: .bind(
281: ResourceMessages.NewProject_internalError,
282: t.getMessage()), t));
283: status.setProperty(StatusAdapter.TITLE_PROPERTY,
284: ResourceMessages.NewProject_errorMessage);
285: StatusManager.getManager().handle(status,
286: StatusManager.LOG | StatusManager.BLOCK);
287: }
288: return null;
289: }
290:
291: newProject = newProjectHandle;
292:
293: return newProject;
294: }
295:
296: /**
297: * Returns the newly created project.
298: *
299: * @return the created project, or <code>null</code> if project not
300: * created
301: */
302: public IProject getNewProject() {
303: return newProject;
304: }
305:
306: /*
307: * (non-Javadoc) Method declared on IWorkbenchWizard.
308: */
309: public void init(IWorkbench workbench,
310: IStructuredSelection currentSelection) {
311: super .init(workbench, currentSelection);
312: setNeedsProgressMonitor(true);
313: setWindowTitle(ResourceMessages.NewProject_windowTitle);
314: }
315:
316: /*
317: * (non-Javadoc) Method declared on BasicNewResourceWizard.
318: */
319: protected void initializeDefaultPageImageDescriptor() {
320: ImageDescriptor desc = IDEWorkbenchPlugin
321: .getIDEImageDescriptor("wizban/newprj_wiz.png");//$NON-NLS-1$
322: setDefaultPageImageDescriptor(desc);
323: }
324:
325: /*
326: * (non-Javadoc) Opens a new window with a particular perspective and input.
327: */
328: private static void openInNewWindow(IPerspectiveDescriptor desc) {
329:
330: // Open the page.
331: try {
332: PlatformUI.getWorkbench().openWorkbenchWindow(desc.getId(),
333: ResourcesPlugin.getWorkspace().getRoot());
334: } catch (WorkbenchException e) {
335: IWorkbenchWindow window = PlatformUI.getWorkbench()
336: .getActiveWorkbenchWindow();
337: if (window != null) {
338: ErrorDialog.openError(window.getShell(),
339: WINDOW_PROBLEMS_TITLE, e.getMessage(), e
340: .getStatus());
341: }
342: }
343: }
344:
345: /*
346: * (non-Javadoc) Method declared on IWizard.
347: */
348: public boolean performFinish() {
349: createNewProject();
350:
351: if (newProject == null) {
352: return false;
353: }
354:
355: IWorkingSet[] workingSets = mainPage.getSelectedWorkingSets();
356: getWorkbench().getWorkingSetManager().addToWorkingSets(
357: newProject, workingSets);
358:
359: updatePerspective();
360: selectAndReveal(newProject);
361:
362: return true;
363: }
364:
365: /*
366: * (non-Javadoc) Replaces the current perspective with the new one.
367: */
368: private static void replaceCurrentPerspective(
369: IPerspectiveDescriptor persp) {
370:
371: // Get the active page.
372: IWorkbenchWindow window = PlatformUI.getWorkbench()
373: .getActiveWorkbenchWindow();
374: if (window == null) {
375: return;
376: }
377: IWorkbenchPage page = window.getActivePage();
378: if (page == null) {
379: return;
380: }
381:
382: // Set the perspective.
383: page.setPerspective(persp);
384: }
385:
386: /**
387: * Stores the configuration element for the wizard. The config element will
388: * be used in <code>performFinish</code> to set the result perspective.
389: */
390: public void setInitializationData(IConfigurationElement cfig,
391: String propertyName, Object data) {
392: configElement = cfig;
393: }
394:
395: /**
396: * Updates the perspective for the active page within the window.
397: */
398: protected void updatePerspective() {
399: updatePerspective(configElement);
400: }
401:
402: /**
403: * Updates the perspective based on the current settings in the
404: * Workbench/Perspectives preference page.
405: *
406: * Use the setting for the new perspective opening if we are set to open in
407: * a new perspective.
408: * <p>
409: * A new project wizard class will need to implement the
410: * <code>IExecutableExtension</code> interface so as to gain access to the
411: * wizard's <code>IConfigurationElement</code>. That is the configuration
412: * element to pass into this method.
413: * </p>
414: *
415: * @param configElement -
416: * the element we are updating with
417: *
418: * @see IPreferenceConstants#OPM_NEW_WINDOW
419: * @see IPreferenceConstants#OPM_ACTIVE_PAGE
420: * @see IWorkbenchPreferenceConstants#NO_NEW_PERSPECTIVE
421: */
422: public static void updatePerspective(
423: IConfigurationElement configElement) {
424: // Do not change perspective if the configuration element is
425: // not specified.
426: if (configElement == null) {
427: return;
428: }
429:
430: // Retrieve the new project open perspective preference setting
431: String perspSetting = PrefUtil
432: .getAPIPreferenceStore()
433: .getString(IDE.Preferences.PROJECT_OPEN_NEW_PERSPECTIVE);
434:
435: String promptSetting = IDEWorkbenchPlugin
436: .getDefault()
437: .getPreferenceStore()
438: .getString(
439: IDEInternalPreferences.PROJECT_SWITCH_PERSP_MODE);
440:
441: // Return if do not switch perspective setting and are not prompting
442: if (!(promptSetting.equals(MessageDialogWithToggle.PROMPT))
443: && perspSetting
444: .equals(IWorkbenchPreferenceConstants.NO_NEW_PERSPECTIVE)) {
445: return;
446: }
447:
448: // Read the requested perspective id to be opened.
449: String finalPerspId = configElement
450: .getAttribute(FINAL_PERSPECTIVE);
451: if (finalPerspId == null) {
452: return;
453: }
454:
455: // Map perspective id to descriptor.
456: IPerspectiveRegistry reg = PlatformUI.getWorkbench()
457: .getPerspectiveRegistry();
458:
459: // leave this code in - the perspective of a given project may map to
460: // activities other than those that the wizard itself maps to.
461: IPerspectiveDescriptor finalPersp = reg
462: .findPerspectiveWithId(finalPerspId);
463: if (finalPersp != null
464: && finalPersp instanceof IPluginContribution) {
465: IPluginContribution contribution = (IPluginContribution) finalPersp;
466: if (contribution.getPluginId() != null) {
467: IWorkbenchActivitySupport workbenchActivitySupport = PlatformUI
468: .getWorkbench().getActivitySupport();
469: IActivityManager activityManager = workbenchActivitySupport
470: .getActivityManager();
471: IIdentifier identifier = activityManager
472: .getIdentifier(WorkbenchActivityHelper
473: .createUnifiedId(contribution));
474: Set idActivities = identifier.getActivityIds();
475:
476: if (!idActivities.isEmpty()) {
477: Set enabledIds = new HashSet(activityManager
478: .getEnabledActivityIds());
479:
480: if (enabledIds.addAll(idActivities)) {
481: workbenchActivitySupport
482: .setEnabledActivityIds(enabledIds);
483: }
484: }
485: }
486: } else {
487: IDEWorkbenchPlugin
488: .log("Unable to find persective " //$NON-NLS-1$
489: + finalPerspId
490: + " in BasicNewProjectResourceWizard.updatePerspective"); //$NON-NLS-1$
491: return;
492: }
493:
494: // gather the preferred perspectives
495: // always consider the final perspective (and those derived from it)
496: // to be preferred
497: ArrayList preferredPerspIds = new ArrayList();
498: addPerspectiveAndDescendants(preferredPerspIds, finalPerspId);
499: String preferred = configElement
500: .getAttribute(PREFERRED_PERSPECTIVES);
501: if (preferred != null) {
502: StringTokenizer tok = new StringTokenizer(preferred,
503: " \t\n\r\f,"); //$NON-NLS-1$
504: while (tok.hasMoreTokens()) {
505: addPerspectiveAndDescendants(preferredPerspIds, tok
506: .nextToken());
507: }
508: }
509:
510: IWorkbenchWindow window = PlatformUI.getWorkbench()
511: .getActiveWorkbenchWindow();
512: if (window != null) {
513: IWorkbenchPage page = window.getActivePage();
514: if (page != null) {
515: IPerspectiveDescriptor currentPersp = page
516: .getPerspective();
517:
518: // don't switch if the current perspective is a preferred
519: // perspective
520: if (currentPersp != null
521: && preferredPerspIds.contains(currentPersp
522: .getId())) {
523: return;
524: }
525: }
526:
527: // prompt the user to switch
528: if (!confirmPerspectiveSwitch(window, finalPersp)) {
529: return;
530: }
531: }
532:
533: int workbenchPerspectiveSetting = WorkbenchPlugin.getDefault()
534: .getPreferenceStore().getInt(
535: IPreferenceConstants.OPEN_PERSP_MODE);
536:
537: // open perspective in new window setting
538: if (workbenchPerspectiveSetting == IPreferenceConstants.OPM_NEW_WINDOW) {
539: openInNewWindow(finalPersp);
540: return;
541: }
542:
543: // replace active perspective setting otherwise
544: replaceCurrentPerspective(finalPersp);
545: }
546:
547: /**
548: * Adds to the list all perspective IDs in the Workbench who's original ID
549: * matches the given ID.
550: *
551: * @param perspectiveIds
552: * the list of perspective IDs to supplement.
553: * @param id
554: * the id to query.
555: * @since 3.0
556: */
557: private static void addPerspectiveAndDescendants(
558: List perspectiveIds, String id) {
559: IPerspectiveRegistry registry = PlatformUI.getWorkbench()
560: .getPerspectiveRegistry();
561: IPerspectiveDescriptor[] perspectives = registry
562: .getPerspectives();
563: for (int i = 0; i < perspectives.length; i++) {
564: // @issue illegal ref to workbench internal class;
565: // consider adding getOriginalId() as API on IPerspectiveDescriptor
566: PerspectiveDescriptor descriptor = ((PerspectiveDescriptor) perspectives[i]);
567: if (descriptor.getOriginalId().equals(id)) {
568: perspectiveIds.add(descriptor.getId());
569: }
570: }
571: }
572:
573: /**
574: * Prompts the user for whether to switch perspectives.
575: *
576: * @param window
577: * The workbench window in which to switch perspectives; must not
578: * be <code>null</code>
579: * @param finalPersp
580: * The perspective to switch to; must not be <code>null</code>.
581: *
582: * @return <code>true</code> if it's OK to switch, <code>false</code>
583: * otherwise
584: */
585: private static boolean confirmPerspectiveSwitch(
586: IWorkbenchWindow window, IPerspectiveDescriptor finalPersp) {
587: IPreferenceStore store = IDEWorkbenchPlugin.getDefault()
588: .getPreferenceStore();
589: String pspm = store
590: .getString(IDEInternalPreferences.PROJECT_SWITCH_PERSP_MODE);
591: if (!IDEInternalPreferences.PSPM_PROMPT.equals(pspm)) {
592: // Return whether or not we should always switch
593: return IDEInternalPreferences.PSPM_ALWAYS.equals(pspm);
594: }
595: String desc = finalPersp.getDescription();
596: String message;
597: if (desc == null || desc.length() == 0)
598: message = NLS.bind(
599: ResourceMessages.NewProject_perspSwitchMessage,
600: finalPersp.getLabel());
601: else
602: message = NLS
603: .bind(
604: ResourceMessages.NewProject_perspSwitchMessageWithDesc,
605: new String[] { finalPersp.getLabel(), desc });
606:
607: MessageDialogWithToggle dialog = MessageDialogWithToggle
608: .openYesNoQuestion(
609: window.getShell(),
610: ResourceMessages.NewProject_perspSwitchTitle,
611: message,
612: null /* use the default message for the toggle */,
613: false /* toggle is initially unchecked */,
614: store,
615: IDEInternalPreferences.PROJECT_SWITCH_PERSP_MODE);
616: int result = dialog.getReturnCode();
617:
618: // If we are not going to prompt anymore propogate the choice.
619: if (dialog.getToggleState()) {
620: String preferenceValue;
621: if (result == IDialogConstants.YES_ID) {
622: // Doesn't matter if it is replace or new window
623: // as we are going to use the open perspective setting
624: preferenceValue = IWorkbenchPreferenceConstants.OPEN_PERSPECTIVE_REPLACE;
625: } else {
626: preferenceValue = IWorkbenchPreferenceConstants.NO_NEW_PERSPECTIVE;
627: }
628:
629: // update PROJECT_OPEN_NEW_PERSPECTIVE to correspond
630: PrefUtil.getAPIPreferenceStore().setValue(
631: IDE.Preferences.PROJECT_OPEN_NEW_PERSPECTIVE,
632: preferenceValue);
633: }
634: return result == IDialogConstants.YES_ID;
635: }
636: }
|