Added new Mograsim project wizard and updated getting started.
[Mograsim.git] / plugins / net.mograsim.plugin.core / src / net / mograsim / plugin / wizards / newWizards / NewMograsimProject.java
1 package net.mograsim.plugin.wizards.newWizards;
2
3 import java.lang.reflect.InvocationTargetException;
4 import java.net.URI;
5 import java.util.ArrayList;
6 import java.util.HashSet;
7 import java.util.LinkedHashMap;
8 import java.util.List;
9 import java.util.Set;
10 import java.util.StringTokenizer;
11
12 import org.eclipse.core.commands.ExecutionException;
13 import org.eclipse.core.resources.IProject;
14 import org.eclipse.core.resources.IProjectDescription;
15 import org.eclipse.core.resources.IResourceStatus;
16 import org.eclipse.core.resources.IWorkspace;
17 import org.eclipse.core.resources.ResourcesPlugin;
18 import org.eclipse.core.runtime.CoreException;
19 import org.eclipse.core.runtime.IConfigurationElement;
20 import org.eclipse.core.runtime.IExecutableExtension;
21 import org.eclipse.core.runtime.IStatus;
22 import org.eclipse.core.runtime.Status;
23 import org.eclipse.jface.dialogs.Dialog;
24 import org.eclipse.jface.dialogs.ErrorDialog;
25 import org.eclipse.jface.dialogs.IDialogConstants;
26 import org.eclipse.jface.dialogs.IDialogSettings;
27 import org.eclipse.jface.dialogs.MessageDialog;
28 import org.eclipse.jface.dialogs.MessageDialogWithToggle;
29 import org.eclipse.jface.operation.IRunnableWithProgress;
30 import org.eclipse.jface.preference.IPreferenceStore;
31 import org.eclipse.jface.resource.ImageDescriptor;
32 import org.eclipse.jface.viewers.IStructuredSelection;
33 import org.eclipse.osgi.util.NLS;
34 import org.eclipse.swt.SWT;
35 import org.eclipse.swt.widgets.Composite;
36 import org.eclipse.ui.IPerspectiveDescriptor;
37 import org.eclipse.ui.IPerspectiveRegistry;
38 import org.eclipse.ui.IPluginContribution;
39 import org.eclipse.ui.IWorkbench;
40 import org.eclipse.ui.IWorkbenchPage;
41 import org.eclipse.ui.IWorkbenchPreferenceConstants;
42 import org.eclipse.ui.IWorkbenchWindow;
43 import org.eclipse.ui.IWorkingSet;
44 import org.eclipse.ui.PlatformUI;
45 import org.eclipse.ui.WorkbenchException;
46 import org.eclipse.ui.activities.IActivityManager;
47 import org.eclipse.ui.activities.IIdentifier;
48 import org.eclipse.ui.activities.IWorkbenchActivitySupport;
49 import org.eclipse.ui.activities.WorkbenchActivityHelper;
50 import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
51 import org.eclipse.ui.ide.IDE;
52 import org.eclipse.ui.ide.undo.CreateProjectOperation;
53 import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
54 import org.eclipse.ui.internal.IPreferenceConstants;
55 import org.eclipse.ui.internal.WorkbenchPlugin;
56 import org.eclipse.ui.internal.ide.IDEInternalPreferences;
57 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
58 import org.eclipse.ui.internal.ide.StatusUtil;
59 import org.eclipse.ui.internal.registry.PerspectiveDescriptor;
60 import org.eclipse.ui.internal.util.PrefUtil;
61 import org.eclipse.ui.internal.wizards.newresource.ResourceMessages;
62 import org.eclipse.ui.statushandlers.StatusAdapter;
63 import org.eclipse.ui.statushandlers.StatusManager;
64 import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
65 import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
66
67 import net.mograsim.plugin.nature.AddMograsimNatureHandler;
68
69 /**
70  * This is a copy of {@link BasicNewProjectResourceWizard} for Mograsim. (This is done to remove the reference tab)
71  *
72  *
73  * @author Christian Femers
74  *
75  */
76 public class NewMograsimProject extends BasicNewResourceWizard implements IExecutableExtension
77 {
78
79         private WizardNewProjectCreationPage mainPage;
80         private MograsimSettingsPage mograsimPage;
81
82 // cache of newly-created project
83         private IProject newProject;
84
85         /**
86          * The config element which declares this wizard.
87          */
88         private IConfigurationElement configElement;
89
90         private static String WINDOW_PROBLEMS_TITLE = ResourceMessages.NewProject_errorOpeningWindow;
91
92         /**
93          * Extension attribute name for final perspective.
94          */
95         private static final String FINAL_PERSPECTIVE = "finalPerspective"; //$NON-NLS-1$
96
97         /**
98          * Extension attribute name for preferred perspectives.
99          */
100         private static final String PREFERRED_PERSPECTIVES = "preferredPerspectives"; //$NON-NLS-1$
101
102         /**
103          * Creates a wizard for creating a new project resource in the workspace.
104          */
105         public NewMograsimProject()
106         {
107                 IDialogSettings workbenchSettings = IDEWorkbenchPlugin.getDefault().getDialogSettings();
108                 IDialogSettings section = workbenchSettings.getSection("BasicNewProjectResourceWizard");//$NON-NLS-1$
109                 if (section == null)
110                 {
111                         section = workbenchSettings.addNewSection("BasicNewProjectResourceWizard");//$NON-NLS-1$
112                 }
113                 setDialogSettings(section);
114
115         }
116
117         @Override
118         public void addPages()
119         {
120                 super.addPages();
121
122                 mainPage = new WizardNewProjectCreationPage("basicNewProjectPage") //$NON-NLS-1$
123                 {
124                         @Override
125                         public void createControl(Composite parent)
126                         {
127                                 super.createControl(parent);
128                                 createWorkingSetGroup((Composite) getControl(), getSelection(), new String[] { "org.eclipse.ui.resourceWorkingSetPage" }); //$NON-NLS-1$
129                                 Dialog.applyDialogFont(getControl());
130                         }
131                 };
132                 mainPage.setTitle("New Mograsim Project");
133                 mainPage.setDescription(ResourceMessages.NewProject_description);
134                 this.addPage(mainPage);
135
136                 mograsimPage = new MograsimSettingsPage()
137                 {
138                         @Override
139                         public void createControl(Composite parent)
140                         {
141                                 super.createControl(parent);
142                                 Dialog.applyDialogFont(getControl());
143                         }
144                 };
145                 mograsimPage.setDescription("Configure the Mograsim Project and its Machine");
146                 this.addPage(mograsimPage);
147         }
148
149         /**
150          * Creates a new project resource with the selected name.
151          * <p>
152          * In normal usage, this method is invoked after the user has pressed Finish on the wizard; the enablement of the Finish button implies
153          * that all controls on the pages currently contain valid values.
154          * </p>
155          * <p>
156          * Note that this wizard caches the new project once it has been successfully created; subsequent invocations of this method will answer
157          * the same project resource without attempting to create it again.
158          * </p>
159          *
160          * @return the created project resource, or <code>null</code> if the project was not created
161          */
162         private IProject createNewProject()
163         {
164                 if (newProject != null)
165                 {
166                         return newProject;
167                 }
168
169 // get a project handle
170                 final IProject newProjectHandle = mainPage.getProjectHandle();
171
172 // get a project descriptor
173                 URI location = null;
174                 if (!mainPage.useDefaults())
175                 {
176                         location = mainPage.getLocationURI();
177                 }
178
179                 IWorkspace workspace = ResourcesPlugin.getWorkspace();
180                 final IProjectDescription description = workspace.newProjectDescription(newProjectHandle.getName());
181                 description.setLocationURI(location);
182
183 // create the new project operation
184                 IRunnableWithProgress op = monitor ->
185                 {
186                         CreateProjectOperation op1 = new CreateProjectOperation(description, ResourceMessages.NewProject_windowTitle);
187                         try
188                         {
189 // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=219901
190 // directly execute the operation so that the undo state is
191 // not preserved.  Making this undoable resulted in too many
192 // accidental file deletions.
193                                 op1.execute(monitor, WorkspaceUndoUtil.getUIInfoAdapter(getShell()));
194                         }
195                         catch (ExecutionException e)
196                         {
197                                 throw new InvocationTargetException(e);
198                         }
199                 };
200
201 // run the new project creation operation
202                 try
203                 {
204                         getContainer().run(true, true, op);
205                 }
206                 catch (InterruptedException e)
207                 {
208                         return null;
209                 }
210                 catch (InvocationTargetException e)
211                 {
212                         Throwable t = e.getTargetException();
213                         if (t instanceof ExecutionException && t.getCause() instanceof CoreException)
214                         {
215                                 CoreException cause = (CoreException) t.getCause();
216                                 StatusAdapter status;
217                                 if (cause.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS)
218                                 {
219                                         status = new StatusAdapter(StatusUtil.newStatus(IStatus.WARNING,
220                                                         NLS.bind(ResourceMessages.NewProject_caseVariantExistsError, newProjectHandle.getName()), cause));
221                                 } else
222                                 {
223                                         status = new StatusAdapter(
224                                                         StatusUtil.newStatus(cause.getStatus().getSeverity(), ResourceMessages.NewProject_errorMessage, cause));
225                                 }
226                                 status.setProperty(StatusAdapter.TITLE_PROPERTY, ResourceMessages.NewProject_errorMessage);
227                                 StatusManager.getManager().handle(status, StatusManager.BLOCK);
228                         } else
229                         {
230                                 StatusAdapter status = new StatusAdapter(new Status(IStatus.WARNING, IDEWorkbenchPlugin.IDE_WORKBENCH, 0,
231                                                 NLS.bind(ResourceMessages.NewProject_internalError, t.getMessage()), t));
232                                 status.setProperty(StatusAdapter.TITLE_PROPERTY, ResourceMessages.NewProject_errorMessage);
233                                 StatusManager.getManager().handle(status, StatusManager.LOG | StatusManager.BLOCK);
234                         }
235                         return null;
236                 }
237
238                 newProject = newProjectHandle;
239
240                 return newProject;
241         }
242
243         /**
244          * Returns the newly created project.
245          *
246          * @return the created project, or <code>null</code> if project not created
247          */
248         public IProject getNewProject()
249         {
250                 return newProject;
251         }
252
253         @Override
254         public void init(IWorkbench workbench, IStructuredSelection currentSelection)
255         {
256                 super.init(workbench, currentSelection);
257                 setNeedsProgressMonitor(true);
258                 setWindowTitle("New Mograsim Project");
259         }
260
261         @Override
262         protected void initializeDefaultPageImageDescriptor()
263         {
264                 ImageDescriptor desc = IDEWorkbenchPlugin.getIDEImageDescriptor("wizban/newprj_wiz.png");//$NON-NLS-1$
265                 setDefaultPageImageDescriptor(desc);
266         }
267
268         private static void openInNewWindow(IPerspectiveDescriptor desc)
269         {
270
271 // Open the page.
272                 try
273                 {
274                         PlatformUI.getWorkbench().openWorkbenchWindow(desc.getId(), ResourcesPlugin.getWorkspace().getRoot());
275                 }
276                 catch (WorkbenchException e)
277                 {
278                         IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
279                         if (window != null)
280                         {
281                                 ErrorDialog.openError(window.getShell(), WINDOW_PROBLEMS_TITLE, e.getMessage(), e.getStatus());
282                         }
283                 }
284         }
285
286         @Override
287         public boolean performFinish()
288         {
289                 createNewProject();
290
291                 if (newProject == null)
292                 {
293                         return false;
294                 }
295
296                 IWorkingSet[] workingSets = mainPage.getSelectedWorkingSets();
297                 getWorkbench().getWorkingSetManager().addToWorkingSets(newProject, workingSets);
298
299                 try
300                 {
301                         AddMograsimNatureHandler.addNatureAndConfigure(getNewProject(), mograsimPage.getMograsimProjectConfig().getMachineId());
302                 }
303                 catch (CoreException e)
304                 {
305                         e.printStackTrace();
306                 }
307
308                 updatePerspective();
309                 selectAndReveal(newProject);
310
311                 return true;
312         }
313
314         private static void replaceCurrentPerspective(IPerspectiveDescriptor persp)
315         {
316
317 // Get the active page.
318                 IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
319                 if (window == null)
320                 {
321                         return;
322                 }
323                 IWorkbenchPage page = window.getActivePage();
324                 if (page == null)
325                 {
326                         return;
327                 }
328
329 // Set the perspective.
330                 page.setPerspective(persp);
331         }
332
333         /**
334          * Stores the configuration element for the wizard. The config element will be used in <code>performFinish</code> to set the result
335          * perspective.
336          */
337         @Override
338         public void setInitializationData(IConfigurationElement cfig, String propertyName, Object data)
339         {
340                 configElement = cfig;
341         }
342
343         /**
344          * Updates the perspective for the active page within the window.
345          */
346         protected void updatePerspective()
347         {
348                 updatePerspective(configElement);
349         }
350
351         /**
352          * Updates the perspective based on the current settings in the Workbench/Perspectives preference page.
353          *
354          * Use the setting for the new perspective opening if we are set to open in a new perspective.
355          * <p>
356          * A new project wizard class will need to implement the <code>IExecutableExtension</code> interface so as to gain access to the
357          * wizard's <code>IConfigurationElement</code>. That is the configuration element to pass into this method.
358          * </p>
359          *
360          * @param configElement - the element we are updating with
361          *
362          * @see IPreferenceConstants#OPM_NEW_WINDOW
363          * @see IPreferenceConstants#OPM_ACTIVE_PAGE
364          * @see IWorkbenchPreferenceConstants#NO_NEW_PERSPECTIVE
365          */
366         public static void updatePerspective(IConfigurationElement configElement)
367         {
368 // Do not change perspective if the configuration element is
369 // not specified.
370                 if (configElement == null)
371                 {
372                         return;
373                 }
374
375 // Retrieve the new project open perspective preference setting
376                 String perspSetting = PrefUtil.getAPIPreferenceStore().getString(IDE.Preferences.PROJECT_OPEN_NEW_PERSPECTIVE);
377
378                 String promptSetting = IDEWorkbenchPlugin.getDefault().getPreferenceStore()
379                                 .getString(IDEInternalPreferences.PROJECT_SWITCH_PERSP_MODE);
380
381 // Return if do not switch perspective setting and are not prompting
382                 if (!(promptSetting.equals(MessageDialogWithToggle.PROMPT))
383                                 && perspSetting.equals(IWorkbenchPreferenceConstants.NO_NEW_PERSPECTIVE))
384                 {
385                         return;
386                 }
387
388 // Read the requested perspective id to be opened.
389                 String finalPerspId = configElement.getAttribute(FINAL_PERSPECTIVE);
390                 if (finalPerspId == null)
391                 {
392                         return;
393                 }
394
395 // Map perspective id to descriptor.
396                 IPerspectiveRegistry reg = PlatformUI.getWorkbench().getPerspectiveRegistry();
397
398 // leave this code in - the perspective of a given project may map to
399 // activities other than those that the wizard itself maps to.
400                 IPerspectiveDescriptor finalPersp = reg.findPerspectiveWithId(finalPerspId);
401                 if (finalPersp != null && finalPersp instanceof IPluginContribution)
402                 {
403                         IPluginContribution contribution = (IPluginContribution) finalPersp;
404                         if (contribution.getPluginId() != null)
405                         {
406                                 IWorkbenchActivitySupport workbenchActivitySupport = PlatformUI.getWorkbench().getActivitySupport();
407                                 IActivityManager activityManager = workbenchActivitySupport.getActivityManager();
408                                 IIdentifier identifier = activityManager.getIdentifier(WorkbenchActivityHelper.createUnifiedId(contribution));
409                                 Set<String> idActivities = identifier.getActivityIds();
410
411                                 if (!idActivities.isEmpty())
412                                 {
413                                         Set<String> enabledIds = new HashSet<>(activityManager.getEnabledActivityIds());
414
415                                         if (enabledIds.addAll(idActivities))
416                                         {
417                                                 workbenchActivitySupport.setEnabledActivityIds(enabledIds);
418                                         }
419                                 }
420                         }
421                 } else
422                 {
423                         IDEWorkbenchPlugin.log("Unable to find persective " //$NON-NLS-1$
424                                         + finalPerspId + " in BasicNewProjectResourceWizard.updatePerspective"); //$NON-NLS-1$
425                         return;
426                 }
427
428 // gather the preferred perspectives
429 // always consider the final perspective (and those derived from it)
430 // to be preferred
431                 ArrayList<String> preferredPerspIds = new ArrayList<>();
432                 addPerspectiveAndDescendants(preferredPerspIds, finalPerspId);
433                 String preferred = configElement.getAttribute(PREFERRED_PERSPECTIVES);
434                 if (preferred != null)
435                 {
436                         StringTokenizer tok = new StringTokenizer(preferred, " \t\n\r\f,"); //$NON-NLS-1$
437                         while (tok.hasMoreTokens())
438                         {
439                                 addPerspectiveAndDescendants(preferredPerspIds, tok.nextToken());
440                         }
441                 }
442
443                 IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
444                 if (window != null)
445                 {
446                         IWorkbenchPage page = window.getActivePage();
447                         if (page != null)
448                         {
449                                 IPerspectiveDescriptor currentPersp = page.getPerspective();
450
451                                 // don't switch if the current perspective is a preferred
452                                 // perspective
453                                 if (currentPersp != null && preferredPerspIds.contains(currentPersp.getId()))
454                                 {
455                                         return;
456                                 }
457                         }
458
459                         // prompt the user to switch
460                         if (!confirmPerspectiveSwitch(window, finalPersp))
461                         {
462                                 return;
463                         }
464                 }
465
466                 int workbenchPerspectiveSetting = WorkbenchPlugin.getDefault().getPreferenceStore().getInt(IPreferenceConstants.OPEN_PERSP_MODE);
467
468 // open perspective in new window setting
469                 if (workbenchPerspectiveSetting == IPreferenceConstants.OPM_NEW_WINDOW)
470                 {
471                         openInNewWindow(finalPersp);
472                         return;
473                 }
474
475 // replace active perspective setting otherwise
476                 replaceCurrentPerspective(finalPersp);
477         }
478
479         /**
480          * Adds to the list all perspective IDs in the Workbench who's original ID matches the given ID.
481          *
482          * @param perspectiveIds the list of perspective IDs to supplement.
483          * @param id             the id to query.
484          * @since 3.0
485          */
486         private static void addPerspectiveAndDescendants(List<String> perspectiveIds, String id)
487         {
488                 IPerspectiveRegistry registry = PlatformUI.getWorkbench().getPerspectiveRegistry();
489                 for (IPerspectiveDescriptor perspective : registry.getPerspectives())
490                 {
491                         // @issue illegal ref to workbench internal class;
492                         // consider adding getOriginalId() as API on IPerspectiveDescriptor
493                         PerspectiveDescriptor descriptor = ((PerspectiveDescriptor) perspective);
494                         if (descriptor.getOriginalId().equals(id))
495                         {
496                                 perspectiveIds.add(descriptor.getId());
497                         }
498                 }
499         }
500
501         /**
502          * Prompts the user for whether to switch perspectives.
503          *
504          * @param window     The workbench window in which to switch perspectives; must not be <code>null</code>
505          * @param finalPersp The perspective to switch to; must not be <code>null</code>.
506          *
507          * @return <code>true</code> if it's OK to switch, <code>false</code> otherwise
508          */
509         private static boolean confirmPerspectiveSwitch(IWorkbenchWindow window, IPerspectiveDescriptor finalPersp)
510         {
511                 IPreferenceStore store = IDEWorkbenchPlugin.getDefault().getPreferenceStore();
512                 String pspm = store.getString(IDEInternalPreferences.PROJECT_SWITCH_PERSP_MODE);
513                 if (!IDEInternalPreferences.PSPM_PROMPT.equals(pspm))
514                 {
515                         // Return whether or not we should always switch
516                         return IDEInternalPreferences.PSPM_ALWAYS.equals(pspm);
517                 }
518                 String desc = finalPersp.getDescription();
519                 String message;
520                 if (desc == null || desc.length() == 0)
521                         message = NLS.bind(ResourceMessages.NewProject_perspSwitchMessage, finalPersp.getLabel());
522                 else
523                         message = NLS.bind(ResourceMessages.NewProject_perspSwitchMessageWithDesc, new String[] { finalPersp.getLabel(), desc });
524
525                 LinkedHashMap<String, Integer> buttonLabelToId = new LinkedHashMap<>();
526                 buttonLabelToId.put(ResourceMessages.NewProject_perspSwitchButtonLabel, IDialogConstants.YES_ID);
527                 buttonLabelToId.put(IDialogConstants.NO_LABEL, IDialogConstants.NO_ID);
528                 MessageDialogWithToggle dialog = MessageDialogWithToggle.open(MessageDialog.QUESTION, window.getShell(),
529                                 ResourceMessages.NewProject_perspSwitchTitle, message, null, false, store, IDEInternalPreferences.PROJECT_SWITCH_PERSP_MODE,
530                                 SWT.NONE, buttonLabelToId);
531                 int result = dialog.getReturnCode();
532
533 // If we are not going to prompt anymore propogate the choice.
534                 if (dialog.getToggleState())
535                 {
536                         String preferenceValue;
537                         if (result == IDialogConstants.YES_ID)
538                         {
539                                 // Doesn't matter if it is replace or new window
540                                 // as we are going to use the open perspective setting
541                                 preferenceValue = IWorkbenchPreferenceConstants.OPEN_PERSPECTIVE_REPLACE;
542                         } else
543                         {
544                                 preferenceValue = IWorkbenchPreferenceConstants.NO_NEW_PERSPECTIVE;
545                         }
546
547                         // update PROJECT_OPEN_NEW_PERSPECTIVE to correspond
548                         PrefUtil.getAPIPreferenceStore().setValue(IDE.Preferences.PROJECT_OPEN_NEW_PERSPECTIVE, preferenceValue);
549                 }
550                 return result == IDialogConstants.YES_ID;
551         }
552 }