1 package net.mograsim.plugin.launch;
3 import java.util.Arrays;
4 import java.util.HashSet;
6 import java.util.function.Supplier;
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;
37 import net.mograsim.plugin.nature.MograsimNature;
38 import net.mograsim.plugin.util.FileExtensionViewerFilter;
39 import net.mograsim.plugin.util.ImageDescriptorWithMargins;
41 //a big part of this class is stolen from org.eclipse.jdt.debug.ui
42 public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab
44 private Text projSelText;
45 private Text mpmFileSelText;
46 private Text initialRAMFileSelText;
49 public void createControl(Composite parent)
51 parent.setLayout(new FillLayout());
52 Composite innerParent = new Composite(parent, SWT.NONE);
53 setControl(innerParent);
55 innerParent.setLayout(new GridLayout());
57 this.projSelText = createResourceSelectorGroup(innerParent, "&Project:", this::chooseMograsimProject);
59 this.mpmFileSelText = createResourceSelectorGroup(innerParent, "&MPM:", this::chooseMPMFile);
61 this.initialRAMFileSelText = createResourceSelectorGroup(innerParent, "Initial &RAM (optional):", this::chooseInitialRAMFile);
64 private Text createResourceSelectorGroup(Composite innerParent, String groupName, Supplier<String> chooser)
66 Group group = new Group(innerParent, SWT.NONE);
67 group.setLayout(new GridLayout(2, false));
68 group.setText(groupName);
69 group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
71 Text text = new Text(group, SWT.BORDER);
72 text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
73 text.addModifyListener(e -> updateLaunchConfigurationDialog());
75 Button browseButton = new Button(group, SWT.PUSH);
76 GridData projSelButtonData = new GridData();
77 projSelButtonData.widthHint = calculateWidthHint(browseButton);
78 projSelButtonData.horizontalAlignment = SWT.FILL;
79 browseButton.setLayoutData(projSelButtonData);
80 browseButton.setText("&Browse...");
81 browseButton.addListener(SWT.Selection, e ->
83 String chosen = chooser.get();
90 private static int calculateWidthHint(Control c)
92 int wHint = new PixelConverter(c).convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
93 return Math.max(wHint, c.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
96 private String chooseMograsimProject()
98 WorkbenchLabelProvider renderer = new WorkbenchLabelProvider()
101 protected ImageDescriptor decorateImage(ImageDescriptor input, Object element)
103 return new ImageDescriptorWithMargins(input, new Point(22, 16));
106 ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), renderer);
107 dialog.setTitle("Project Selection");
108 dialog.setMessage("Select a Mograsim project");
109 dialog.setElements(filterOpenMograsimProjects(ResourcesPlugin.getWorkspace().getRoot().getProjects()));
110 if (dialog.open() == Window.OK)
111 return ((IProject) dialog.getFirstResult()).getName();
115 private String chooseMPMFile()
117 WorkbenchLabelProvider renderer = new WorkbenchLabelProvider()
120 protected ImageDescriptor decorateImage(ImageDescriptor input, Object element)
122 return new ImageDescriptorWithMargins(input, new Point(22, 16));
125 ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), renderer, new WorkbenchContentProvider());
126 dialog.setTitle("MPM Selection");
127 dialog.setMessage("Select a MPM file");
128 dialog.setInput(getSelectedProject());
129 dialog.addFilter(new FileExtensionViewerFilter("mpm"));
131 if (dialog.open() == Window.OK)
132 return ((IResource) dialog.getResult()[0]).getProjectRelativePath().toPortableString();
136 private String chooseInitialRAMFile()
138 WorkbenchLabelProvider renderer = new WorkbenchLabelProvider()
141 protected ImageDescriptor decorateImage(ImageDescriptor input, Object element)
143 return new ImageDescriptorWithMargins(input, new Point(22, 16));
146 ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), renderer, new WorkbenchContentProvider());
147 dialog.setTitle("Initial RAM Selection");
148 dialog.setMessage("Select a RAM file");
149 dialog.setInput(getSelectedProject());
150 dialog.addFilter(new FileExtensionViewerFilter("mem"));
152 if (dialog.open() == Window.OK)
153 return ((IResource) dialog.getResult()[0]).getProjectRelativePath().toPortableString();
157 private IProject getSelectedProject()
159 String projName = projSelText.getText().trim();
160 IWorkspace workspace = ResourcesPlugin.getWorkspace();
161 if (workspace.validateName(projName, IResource.PROJECT).isOK())
162 return workspace.getRoot().getProject(projName);
166 private static IProject[] filterOpenMograsimProjects(IProject[] projects)
168 return Arrays.stream(projects).filter(p ->
172 return p.isAccessible() && p.hasNature(MograsimNature.NATURE_ID);
174 catch (CoreException e)
176 throw new RuntimeException(e);
178 }).toArray(IProject[]::new);
182 public void setDefaults(ILaunchConfigurationWorkingCopy configuration)
184 // TODO don't let the user have to specify everything
188 public void initializeFrom(ILaunchConfiguration configuration)
190 projSelText.setText(getStringAttribSafe(configuration, MachineLaunchConfigType.PROJECT_ATTR, ""));
191 mpmFileSelText.setText(getStringAttribSafe(configuration, MachineLaunchConfigType.MPM_FILE_ATTR, ""));
192 initialRAMFileSelText.setText(getStringAttribSafe(configuration, MachineLaunchConfigType.INITIAL_RAM_FILE_ATTR, ""));
195 private String getStringAttribSafe(ILaunchConfiguration configuration, String attrib, String defaultValue)
199 return configuration.getAttribute(attrib, defaultValue);
201 catch (CoreException e)
203 setErrorMessage(e.getStatus().getMessage());
209 public void performApply(ILaunchConfigurationWorkingCopy configuration)
211 String projName = projSelText.getText().trim();
212 String mpmFileName = mpmFileSelText.getText().trim();
213 String initialRAMFileName = initialRAMFileSelText.getText().trim();
215 Set<IResource> associatedResources = new HashSet<>();
216 IWorkspace workspace = ResourcesPlugin.getWorkspace();
217 if (workspace.validateName(projName, IResource.PROJECT).isOK())
219 IProject project = workspace.getRoot().getProject(projName);
222 if (project != null && project.isAccessible() && project.hasNature(MograsimNature.NATURE_ID))
224 associatedResources.add(project);
226 IResource mpmFile = project.findMember(mpmFileName);
227 if (mpmFile != null && mpmFile.exists() && mpmFile.getType() == IResource.FILE)
228 associatedResources.add(mpmFile);
230 IResource ramFile = project.findMember(initialRAMFileName);
231 if (ramFile != null && ramFile.exists() && ramFile.getType() == IResource.FILE)
232 associatedResources.add(ramFile);
235 catch (CoreException e)
237 setErrorMessage(e.getStatus().getMessage());
240 configuration.setMappedResources(associatedResources.toArray(IResource[]::new));
241 configuration.setAttribute(MachineLaunchConfigType.PROJECT_ATTR, projName);
242 configuration.setAttribute(MachineLaunchConfigType.MPM_FILE_ATTR, mpmFileName);
243 configuration.setAttribute(MachineLaunchConfigType.INITIAL_RAM_FILE_ATTR, initialRAMFileName);
247 public boolean isValid(ILaunchConfiguration launchConfig)
249 setErrorMessage(null);
251 String projName = projSelText.getText().trim();
252 if (projName.length() == 0)
253 return setErrorAndReturnFalse("No project specified");
255 IWorkspace workspace = ResourcesPlugin.getWorkspace();
256 IStatus status = workspace.validateName(projName, IResource.PROJECT);
258 return setErrorAndReturnFalse("Illegal project name: {0}: {1}", projName, status.getMessage());
260 IProject project = workspace.getRoot().getProject(projName);
261 if (!project.exists())
262 return setErrorAndReturnFalse("Project {0} does not exist", projName);
263 if (!project.isOpen())
264 return setErrorAndReturnFalse("Project {0} is closed", projName);
267 if (!project.hasNature(MograsimNature.NATURE_ID))
268 return setErrorAndReturnFalse("Project {0} is not a Mograsim project", projName);
270 catch (CoreException e)
272 return setErrorAndReturnFalse(e.getStatus().getMessage());
275 String mpmFileName = mpmFileSelText.getText().trim();
276 if (mpmFileName.length() == 0)
277 return setErrorAndReturnFalse("No MPM file specified");
278 IResource mpmResource = project.findMember(mpmFileName);
279 if (mpmResource == null || !mpmResource.exists())
280 return setErrorAndReturnFalse("MPM file {0} does not exist", mpmFileName);
281 if (mpmResource.getType() != IResource.FILE)
282 return setErrorAndReturnFalse("MPM file {0} is not a file", mpmFileName);
284 String initialRAMFileName = initialRAMFileSelText.getText().trim();
285 if (initialRAMFileName.length() > 0)
287 IResource initialRAMResource = project.findMember(initialRAMFileName);
288 if (initialRAMResource == null || !initialRAMResource.exists())
289 return setErrorAndReturnFalse("Initial RAM file {0} does not exist", initialRAMFileName);
290 if (initialRAMResource.getType() != IResource.FILE)
291 return setErrorAndReturnFalse("Initial RAM file {0} is not a file", initialRAMFileName);
297 private boolean setErrorAndReturnFalse(String message, String... params)
299 setErrorMessage(NLS.bind(message, params));
304 public String getName()
306 return "testlaunchconfigtabname";