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.Label;
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;
40 import net.mograsim.plugin.util.ProjectViewerFilter;
42 //a big part of this class is stolen from org.eclipse.jdt.debug.ui
43 public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab
45 private Text projSelText;
46 private Text mpmFileSelText;
47 private Text mpromFileSelText;
48 private Text initialRAMFileSelText;
51 public void createControl(Composite parent)
53 parent.setLayout(new FillLayout());
54 Composite innerParent = new Composite(parent, SWT.NONE);
55 setControl(innerParent);
57 innerParent.setLayout(new GridLayout(3, false));
59 this.projSelText = addResourceSelector(innerParent, "P&roject:", this::chooseMograsimProject);
61 this.mpmFileSelText = addResourceSelector(innerParent, "&MPM:", this::chooseMPMFile);
63 this.mpromFileSelText = addResourceSelector(innerParent, "M&PROM (optional):", this::chooseMPROMFile);
65 this.initialRAMFileSelText = addResourceSelector(innerParent, "Initial &RAM (optional):", this::chooseInitialRAMFile);
68 private Text addResourceSelector(Composite innerParent, String label, Supplier<String> chooser)
70 Label swtLabel = new Label(innerParent, SWT.NONE);
71 swtLabel.setText(label);
72 swtLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
74 Text text = new Text(innerParent, SWT.BORDER);
75 text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
76 text.addModifyListener(e -> updateLaunchConfigurationDialog());
78 swtLabel.addListener(SWT.FocusIn, e -> text.setFocus());
80 Button browseButton = new Button(innerParent, SWT.PUSH);
81 GridData projSelButtonData = new GridData();
82 projSelButtonData.widthHint = calculateWidthHint(browseButton);
83 projSelButtonData.horizontalAlignment = SWT.FILL;
84 browseButton.setLayoutData(projSelButtonData);
85 browseButton.setText("&Browse...");
86 browseButton.addListener(SWT.Selection, e ->
88 String chosen = chooser.get();
95 private static int calculateWidthHint(Control c)
97 int wHint = new PixelConverter(c).convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
98 return Math.max(wHint, c.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
101 private String chooseMograsimProject()
103 // TODO this seems very ugly, especially hardcoded width/height
104 WorkbenchLabelProvider renderer = new WorkbenchLabelProvider()
107 protected ImageDescriptor decorateImage(ImageDescriptor input, Object element)
109 return new ImageDescriptorWithMargins(input, new Point(20, 16));
112 ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), renderer);
113 dialog.setTitle("Project Selection");
114 dialog.setMessage("Select a Mograsim project");
115 dialog.setElements(filterOpenMograsimProjects(ResourcesPlugin.getWorkspace().getRoot().getProjects()));
116 if (dialog.open() == Window.OK)
117 return ((IProject) dialog.getFirstResult()).getName();
121 private String chooseMPMFile()
123 return chooseFile("MPM", "mpm");
126 private String chooseMPROMFile()
128 return chooseFile("MPROM", "mprom");
131 private String chooseInitialRAMFile()
133 return chooseFile("Initial RAM", "mem");
136 private String chooseFile(String type, String fileext)
138 ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(getShell(), new WorkbenchLabelProvider(),
139 new WorkbenchContentProvider());
140 dialog.setTitle(type + " Selection");
141 dialog.setMessage("Select a ." + fileext + " file");
142 dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());
143 dialog.addFilter(new FileExtensionViewerFilter(fileext));
144 dialog.addFilter(new ProjectViewerFilter(getSelectedProject()));
146 if (dialog.open() == Window.OK)
147 return ((IResource) dialog.getResult()[0]).getProjectRelativePath().toPortableString();
151 private IProject getSelectedProject()
153 String projName = projSelText.getText().trim();
154 IWorkspace workspace = ResourcesPlugin.getWorkspace();
155 if (workspace.validateName(projName, IResource.PROJECT).isOK())
156 return workspace.getRoot().getProject(projName);
160 private static IProject[] filterOpenMograsimProjects(IProject[] projects)
162 return Arrays.stream(projects).filter(p ->
166 return p.isAccessible() && p.hasNature(MograsimNature.NATURE_ID);
168 catch (CoreException e)
170 throw new RuntimeException(e);
172 }).toArray(IProject[]::new);
176 public void setDefaults(ILaunchConfigurationWorkingCopy configuration)
178 // TODO don't let the user have to specify everything
182 public void initializeFrom(ILaunchConfiguration configuration)
184 projSelText.setText(getStringAttribSafe(configuration, MachineLaunchConfigType.PROJECT_ATTR, ""));
185 mpmFileSelText.setText(getStringAttribSafe(configuration, MachineLaunchConfigType.MPM_FILE_ATTR, ""));
186 mpromFileSelText.setText(getStringAttribSafe(configuration, MachineLaunchConfigType.MPROM_FILE_ATTR, ""));
187 initialRAMFileSelText.setText(getStringAttribSafe(configuration, MachineLaunchConfigType.INITIAL_RAM_FILE_ATTR, ""));
190 private String getStringAttribSafe(ILaunchConfiguration configuration, String attrib, String defaultValue)
194 return configuration.getAttribute(attrib, defaultValue);
196 catch (CoreException e)
198 setErrorMessage(e.getStatus().getMessage());
204 public void performApply(ILaunchConfigurationWorkingCopy configuration)
206 String projName = projSelText.getText().trim();
207 String mpmFileName = mpmFileSelText.getText().trim();
208 String mpromFileName = mpromFileSelText.getText().trim();
209 String initialRAMFileName = initialRAMFileSelText.getText().trim();
211 Set<IResource> associatedResources = new HashSet<>();
212 IWorkspace workspace = ResourcesPlugin.getWorkspace();
213 if (workspace.validateName(projName, IResource.PROJECT).isOK())
215 IProject project = workspace.getRoot().getProject(projName);
218 if (project != null && project.isAccessible() && project.hasNature(MograsimNature.NATURE_ID))
220 associatedResources.add(project);
222 IResource mpmFile = project.findMember(mpmFileName);
223 if (mpmFile != null && mpmFile.exists() && mpmFile.getType() == IResource.FILE)
224 associatedResources.add(mpmFile);
226 IResource mpromFile = project.findMember(mpromFileName);
227 if (mpromFile != null && mpromFile.exists() && mpromFile.getType() == IResource.FILE)
228 associatedResources.add(mpromFile);
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.MPROM_FILE_ATTR, mpromFileName);
244 configuration.setAttribute(MachineLaunchConfigType.INITIAL_RAM_FILE_ATTR, initialRAMFileName);
248 public boolean isValid(ILaunchConfiguration launchConfig)
250 setErrorMessage(null);
252 String projName = projSelText.getText().trim();
253 if (projName.length() == 0)
254 return setErrorAndReturnFalse("No project specified");
256 IWorkspace workspace = ResourcesPlugin.getWorkspace();
257 IStatus status = workspace.validateName(projName, IResource.PROJECT);
259 return setErrorAndReturnFalse("Illegal project name: {0}: {1}", projName, status.getMessage());
261 IProject project = workspace.getRoot().getProject(projName);
262 if (!project.exists())
263 return setErrorAndReturnFalse("Project {0} does not exist", projName);
264 if (!project.isOpen())
265 return setErrorAndReturnFalse("Project {0} is closed", projName);
268 if (!project.hasNature(MograsimNature.NATURE_ID))
269 return setErrorAndReturnFalse("Project {0} is not a Mograsim project", projName);
271 catch (CoreException e)
273 return setErrorAndReturnFalse(e.getStatus().getMessage());
276 String mpmFileName = mpmFileSelText.getText().trim();
277 if (mpmFileName.length() == 0)
278 return setErrorAndReturnFalse("No MPM file specified");
279 IResource mpmResource = project.findMember(mpmFileName);
280 if (mpmResource == null || !mpmResource.exists())
281 return setErrorAndReturnFalse("MPM file {0} does not exist", mpmFileName);
282 if (mpmResource.getType() != IResource.FILE)
283 return setErrorAndReturnFalse("MPM file {0} is not a file", mpmFileName);
285 String mpromFileName = mpromFileSelText.getText().trim();
286 if (mpromFileName.length() > 0)
288 IResource mpromResource = project.findMember(mpromFileName);
289 if (mpromResource == null || !mpromResource.exists())
290 return setErrorAndReturnFalse("MPROM file {0} does not exist", mpromFileName);
291 if (mpromResource.getType() != IResource.FILE)
292 return setErrorAndReturnFalse("MPROM file {0} is not a file", mpromFileName);
295 String initialRAMFileName = initialRAMFileSelText.getText().trim();
296 if (initialRAMFileName.length() > 0)
298 IResource initialRAMResource = project.findMember(initialRAMFileName);
299 if (initialRAMResource == null || !initialRAMResource.exists())
300 return setErrorAndReturnFalse("Initial RAM file {0} does not exist", initialRAMFileName);
301 if (initialRAMResource.getType() != IResource.FILE)
302 return setErrorAndReturnFalse("Initial RAM file {0} is not a file", initialRAMFileName);
308 private boolean setErrorAndReturnFalse(String message, String... params)
310 setErrorMessage(NLS.bind(message, params));
315 public String getName()