Made MPM configurable; changed startup exec speed from 10 to 1
[Mograsim.git] / plugins / net.mograsim.plugin.core / src / net / mograsim / plugin / launch / MainMachineLaunchConfigTab.java
1 package net.mograsim.plugin.launch;
2
3 import java.util.Arrays;
4 import java.util.HashSet;
5 import java.util.Set;
6 import java.util.function.Supplier;
7
8 import org.eclipse.core.resources.IProject;
9 import org.eclipse.core.resources.IResource;
10 import org.eclipse.core.resources.IWorkspace;
11 import org.eclipse.core.resources.ResourcesPlugin;
12 import org.eclipse.core.runtime.CoreException;
13 import org.eclipse.core.runtime.IStatus;
14 import org.eclipse.debug.core.ILaunchConfiguration;
15 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
16 import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
17 import org.eclipse.jface.dialogs.IDialogConstants;
18 import org.eclipse.jface.layout.PixelConverter;
19 import org.eclipse.jface.resource.ImageDescriptor;
20 import org.eclipse.jface.window.Window;
21 import org.eclipse.osgi.util.NLS;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.graphics.Point;
24 import org.eclipse.swt.layout.FillLayout;
25 import org.eclipse.swt.layout.GridData;
26 import org.eclipse.swt.layout.GridLayout;
27 import org.eclipse.swt.widgets.Button;
28 import org.eclipse.swt.widgets.Composite;
29 import org.eclipse.swt.widgets.Control;
30 import org.eclipse.swt.widgets.Group;
31 import org.eclipse.swt.widgets.Text;
32 import org.eclipse.ui.dialogs.ElementListSelectionDialog;
33 import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
34 import org.eclipse.ui.model.WorkbenchContentProvider;
35 import org.eclipse.ui.model.WorkbenchLabelProvider;
36
37 import net.mograsim.plugin.nature.MograsimNature;
38 import net.mograsim.plugin.util.FileExtensionViewerFilter;
39 import net.mograsim.plugin.util.ImageDescriptorWithMargins;
40
41 //a big part of this class is stolen from org.eclipse.jdt.debug.ui
42 public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab
43 {
44         private Text projSelText;
45         private Text mpmFileSelText;
46
47         @Override
48         public void createControl(Composite parent)
49         {
50                 parent.setLayout(new FillLayout());
51                 Composite innerParent = new Composite(parent, SWT.NONE);
52                 setControl(innerParent);
53
54                 innerParent.setLayout(new GridLayout());
55
56                 this.projSelText = createResourceSelectorGroup(innerParent, this::chooseMograsimProject);
57
58                 this.mpmFileSelText = createResourceSelectorGroup(innerParent, this::chooseMPMFile);
59
60                 // TODO RAM selector
61         }
62
63         private Text createResourceSelectorGroup(Composite innerParent, Supplier<String> chooser)
64         {
65                 Group projSelGroup = new Group(innerParent, SWT.NONE);
66                 projSelGroup.setLayout(new GridLayout(2, false));
67                 projSelGroup.setText("&Project:");
68                 projSelGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
69                 Text projSelText = new Text(projSelGroup, SWT.BORDER);
70                 projSelText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
71                 projSelText.addModifyListener(e -> updateLaunchConfigurationDialog());
72                 Button projSelButton = new Button(projSelGroup, SWT.PUSH);
73                 GridData projSelButtonData = new GridData();
74                 projSelButtonData.widthHint = calculateWidthHint(projSelButton);
75                 projSelButtonData.horizontalAlignment = SWT.FILL;
76                 projSelButton.setLayoutData(projSelButtonData);
77                 projSelButton.setText("&Browse...");
78                 projSelButton.addListener(SWT.Selection, e ->
79                 {
80                         String chosen = chooser.get();
81                         if (chosen != null)
82                                 projSelText.setText(chosen);
83                 });
84                 return projSelText;
85         }
86
87         private static int calculateWidthHint(Control c)
88         {
89                 int wHint = new PixelConverter(c).convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
90                 return Math.max(wHint, c.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
91         }
92
93         private String chooseMograsimProject()
94         {
95                 WorkbenchLabelProvider renderer = new WorkbenchLabelProvider()
96                 {
97                         @Override
98                         protected ImageDescriptor decorateImage(ImageDescriptor input, Object element)
99                         {
100                                 return new ImageDescriptorWithMargins(input, new Point(22, 16));
101                         }
102                 };
103                 ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), renderer);
104                 dialog.setTitle("Project Selection");
105                 dialog.setMessage("Select a Mograsim project");
106                 dialog.setElements(filterOpenMograsimProjects(ResourcesPlugin.getWorkspace().getRoot().getProjects()));
107                 if (dialog.open() == Window.OK)
108                         return ((IProject) dialog.getFirstResult()).getName();
109                 return null;
110         }
111
112         private String chooseMPMFile()
113         {
114                 WorkbenchLabelProvider renderer = new WorkbenchLabelProvider()
115                 {
116                         @Override
117                         protected ImageDescriptor decorateImage(ImageDescriptor input, Object element)
118                         {
119                                 return new ImageDescriptorWithMargins(input, new Point(22, 16));
120                         }
121                 };
122                 ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), renderer, new WorkbenchContentProvider());
123                 dialog.setInput(getSelectedProject());
124                 dialog.addFilter(new FileExtensionViewerFilter("mpm"));
125
126                 if (dialog.open() == Window.OK)
127                         return ((IResource) dialog.getResult()[0]).getProjectRelativePath().toPortableString();
128                 return null;
129         }
130
131         private IProject getSelectedProject()
132         {
133                 String projName = projSelText.getText().trim();
134                 IWorkspace workspace = ResourcesPlugin.getWorkspace();
135                 if (workspace.validateName(projName, IResource.PROJECT).isOK())
136                         return workspace.getRoot().getProject(projName);
137                 return null;
138         }
139
140         private static IProject[] filterOpenMograsimProjects(IProject[] projects)
141         {
142                 return Arrays.stream(projects).filter(p ->
143                 {
144                         try
145                         {
146                                 return p.isAccessible() && p.hasNature(MograsimNature.NATURE_ID);
147                         }
148                         catch (CoreException e)
149                         {
150                                 throw new RuntimeException(e);
151                         }
152                 }).toArray(IProject[]::new);
153         }
154
155         @Override
156         public void setDefaults(ILaunchConfigurationWorkingCopy configuration)
157         {
158                 // TODO don't let the user have to specify everything
159         }
160
161         @Override
162         public void initializeFrom(ILaunchConfiguration configuration)
163         {
164                 String projName = "";
165                 try
166                 {
167                         projName = configuration.getAttribute(MachineLaunchConfigType.PROJECT_ATTR, "");
168                 }
169                 catch (CoreException e)
170                 {
171                         setErrorMessage(e.getStatus().getMessage());
172                 }
173                 projSelText.setText(projName);
174         }
175
176         @Override
177         public void performApply(ILaunchConfigurationWorkingCopy configuration)
178         {
179                 String projName = projSelText.getText().trim();
180                 String mpmFileName = mpmFileSelText.getText().trim();
181
182                 Set<IResource> associatedResources = new HashSet<>();
183                 IWorkspace workspace = ResourcesPlugin.getWorkspace();
184                 if (workspace.validateName(projName, IResource.PROJECT).isOK())
185                 {
186                         IProject project = workspace.getRoot().getProject(projName);
187                         try
188                         {
189                                 if (project != null && project.isAccessible() && project.hasNature(MograsimNature.NATURE_ID))
190                                 {
191                                         IResource mpmFile = project.findMember(mpmFileName);
192                                         if (mpmFile != null && mpmFile.exists() && mpmFile.getType() == IResource.FILE)
193                                                 associatedResources.add(mpmFile);
194                                         else
195                                                 associatedResources.add(project);
196                                 }
197                         }
198                         catch (CoreException e)
199                         {
200                                 setErrorMessage(e.getStatus().getMessage());
201                         }
202                 }
203                 configuration.setMappedResources(associatedResources.toArray(IResource[]::new));
204                 configuration.setAttribute(MachineLaunchConfigType.PROJECT_ATTR, projName);
205                 configuration.setAttribute(MachineLaunchConfigType.MPM_FILE_ATTR, mpmFileName);
206         }
207
208         @Override
209         public boolean isValid(ILaunchConfiguration launchConfig)
210         {
211                 setErrorMessage(null);
212                 setMessage(null);
213                 String projName = projSelText.getText().trim();
214                 if (projName.length() == 0)
215                         return setErrorAndReturnFalse("No project specified");
216
217                 IWorkspace workspace = ResourcesPlugin.getWorkspace();
218                 IStatus status = workspace.validateName(projName, IResource.PROJECT);
219                 if (!status.isOK())
220                         return setErrorAndReturnFalse("Illegal project name: {0}: {1}", projName, status.getMessage());
221
222                 IProject project = workspace.getRoot().getProject(projName);
223                 if (!project.exists())
224                         return setErrorAndReturnFalse("Project {0} does not exist", projName);
225                 if (!project.isOpen())
226                         return setErrorAndReturnFalse("Project {0} is closed", projName);
227                 try
228                 {
229                         if (!project.hasNature(MograsimNature.NATURE_ID))
230                                 return setErrorAndReturnFalse("Project {0} is not a Mograsim project", projName);
231                 }
232                 catch (CoreException e)
233                 {
234                         return setErrorAndReturnFalse(e.getStatus().getMessage());
235                 }
236
237                 String mpmFileName = mpmFileSelText.getText().trim();
238                 if (mpmFileName.length() == 0)
239                         return setErrorAndReturnFalse("No MPM file specified");
240                 IResource mpmResource = project.findMember(mpmFileName);
241                 if (mpmResource == null || !mpmResource.exists())
242                         return setErrorAndReturnFalse("MPM file {0} does not exist", mpmFileName);
243                 if (mpmResource.getType() != IResource.FILE)
244                         return setErrorAndReturnFalse("MPM file {0} is not a file", mpmFileName);
245
246                 return true;
247         }
248
249         private boolean setErrorAndReturnFalse(String message, String... params)
250         {
251                 setErrorMessage(NLS.bind(message, params));
252                 return false;
253         }
254
255         @Override
256         public String getName()
257         {
258                 return "testlaunchconfigtabname";
259         }
260 }