From 350f07ad55e5be633a85910d4634a7b16008412e Mon Sep 17 00:00:00 2001 From: Daniel Kirschten Date: Sat, 28 Sep 2019 16:31:45 +0200 Subject: [PATCH] Added a test launch config --- .../META-INF/MANIFEST.MF | 5 +- plugins/net.mograsim.plugin.core/plugin.xml | 34 +++ .../mograsim/plugin/MograsimActivator.java | 2 + .../launch/EmptyLaunchConfigTabGroup.java | 19 ++ .../launch/MachineLaunchConfigType.java | 77 +++++++ .../launch/MainMachineLaunchConfigTab.java | 208 ++++++++++++++++++ .../util/ImageDescriptorWithMargins.java | 37 ++++ 7 files changed, 381 insertions(+), 1 deletion(-) create mode 100644 plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/EmptyLaunchConfigTabGroup.java create mode 100644 plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineLaunchConfigType.java create mode 100644 plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MainMachineLaunchConfigTab.java create mode 100644 plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/util/ImageDescriptorWithMargins.java diff --git a/plugins/net.mograsim.plugin.core/META-INF/MANIFEST.MF b/plugins/net.mograsim.plugin.core/META-INF/MANIFEST.MF index 3fae54f2..2ce9f389 100644 --- a/plugins/net.mograsim.plugin.core/META-INF/MANIFEST.MF +++ b/plugins/net.mograsim.plugin.core/META-INF/MANIFEST.MF @@ -8,6 +8,7 @@ Export-Package: net.mograsim.plugin;uses:="org.eclipse.ui.themes,org.eclipse.swt net.mograsim.plugin.asm.editor, net.mograsim.plugin.asm.editor.rules, net.mograsim.plugin.editors, + net.mograsim.plugin.launch, net.mograsim.plugin.nature, net.mograsim.plugin.nature.properties, net.mograsim.plugin.tables, @@ -32,7 +33,9 @@ Require-Bundle: org.eclipse.core.runtime, net.mograsim.preferences;bundle-version="0.1.0", net.mograsim.machine, org.eclipse.core.expressions, - SWTInput + SWTInput, + org.eclipse.debug.core;bundle-version="3.14.0", + org.eclipse.debug.ui;bundle-version="3.14.200" Bundle-RequiredExecutionEnvironment: JavaSE-11 Automatic-Module-Name: net.mograsim.plugin.core Bundle-Vendor: %Bundle-Vendor.0 diff --git a/plugins/net.mograsim.plugin.core/plugin.xml b/plugins/net.mograsim.plugin.core/plugin.xml index c48d9c43..0c1efa6a 100644 --- a/plugins/net.mograsim.plugin.core/plugin.xml +++ b/plugins/net.mograsim.plugin.core/plugin.xml @@ -357,4 +357,38 @@ + + + + + + + + + + + + + + + + diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/MograsimActivator.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/MograsimActivator.java index 9311ddd5..765a63a5 100644 --- a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/MograsimActivator.java +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/MograsimActivator.java @@ -8,6 +8,8 @@ import net.mograsim.preferences.Preferences; public final class MograsimActivator extends AbstractUIPlugin { + public static final String PLUGIN_ID = "net.mograsim.plugin.core"; + private static MograsimActivator instance; public MograsimActivator() diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/EmptyLaunchConfigTabGroup.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/EmptyLaunchConfigTabGroup.java new file mode 100644 index 00000000..6f4844e3 --- /dev/null +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/EmptyLaunchConfigTabGroup.java @@ -0,0 +1,19 @@ +package net.mograsim.plugin.launch; + +import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup; +import org.eclipse.debug.ui.ILaunchConfigurationDialog; +import org.eclipse.debug.ui.ILaunchConfigurationTab; + +/** + * Useful for specifying launch config tabs via the extension point org.eclipse.debug.ui.launchConfigurationTabs. + * + * @author Daniel Kirschten + */ +public class EmptyLaunchConfigTabGroup extends AbstractLaunchConfigurationTabGroup +{ + @Override + public void createTabs(ILaunchConfigurationDialog dialog, String mode) + { + setTabs(new ILaunchConfigurationTab[0]); + } +} \ No newline at end of file diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineLaunchConfigType.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineLaunchConfigType.java new file mode 100644 index 00000000..03c481a5 --- /dev/null +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineLaunchConfigType.java @@ -0,0 +1,77 @@ +package net.mograsim.plugin.launch; + +import java.io.IOException; + +import org.eclipse.core.resources.IResourceChangeEvent; +import org.eclipse.core.resources.IResourceChangeListener; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.model.LaunchConfigurationDelegate; + +import net.mograsim.plugin.MograsimActivator; + +public class MachineLaunchConfigType extends LaunchConfigurationDelegate +{ + public static final String PROJECT_ATTR = MograsimActivator.PLUGIN_ID + "project"; + + private final IResourceChangeListener resChangedListener; + + public MachineLaunchConfigType() + { + this.resChangedListener = this::resourceChanged; + } + + @Override + public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException + { + ResourcesPlugin.getWorkspace().addResourceChangeListener(resChangedListener, + IResourceChangeEvent.POST_BUILD | IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_BUILD + | IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.PRE_REFRESH); + System.out.println("launch"); + // TODO start a machine + ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "\"echo Press Enter... &&pause>NUL && echo finished\""); + try + { + launch.addProcess(DebugPlugin.newProcess(launch, pb.start(), "")); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + private void resourceChanged(IResourceChangeEvent event) + { + // TODO react to MPM changes + int type = event.getType(); + String typeStr; + switch (type) + { + case IResourceChangeEvent.POST_BUILD: + typeStr = "POST_BUILD"; + break; + case IResourceChangeEvent.POST_CHANGE: + typeStr = "POST_CHANGE"; + break; + case IResourceChangeEvent.PRE_BUILD: + typeStr = "PRE_BUILD"; + break; + case IResourceChangeEvent.PRE_CLOSE: + typeStr = "PRE_CLOSE"; + break; + case IResourceChangeEvent.PRE_DELETE: + typeStr = "PRE_DELETE"; + break; + case IResourceChangeEvent.PRE_REFRESH: + typeStr = "PRE_REFRESH"; + break; + default: + typeStr = ""; + } + System.out.println(typeStr + ": " + event); + } +} \ No newline at end of file diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MainMachineLaunchConfigTab.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MainMachineLaunchConfigTab.java new file mode 100644 index 00000000..6579efc9 --- /dev/null +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MainMachineLaunchConfigTab.java @@ -0,0 +1,208 @@ +package net.mograsim.plugin.launch; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.layout.PixelConverter; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.dialogs.ElementListSelectionDialog; +import org.eclipse.ui.model.WorkbenchLabelProvider; + +import net.mograsim.plugin.nature.MograsimNature; +import net.mograsim.plugin.util.ImageDescriptorWithMargins; + +//a big part of this class is stolen from org.eclipse.jdt.debug.ui +public class MainMachineLaunchConfigTab extends AbstractLaunchConfigurationTab +{ + private Text projSelText; + + @Override + public void createControl(Composite parent) + { + parent.setLayout(new FillLayout()); + Composite innerParent = new Composite(parent, SWT.NONE); + setControl(innerParent); + + innerParent.setLayout(new GridLayout()); + + Group projSelGroup = new Group(innerParent, SWT.NONE); + projSelGroup.setLayout(new GridLayout(2, false)); + projSelGroup.setText("&Project:"); + projSelGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + projSelText = new Text(projSelGroup, SWT.BORDER); + projSelText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + projSelText.addModifyListener(e -> updateLaunchConfigurationDialog()); + Button projSelButton = new Button(projSelGroup, SWT.PUSH); + GridData projSelButtonData = new GridData(); + projSelButtonData.widthHint = calculateWidthHint(projSelButton); + projSelButtonData.horizontalAlignment = SWT.FILL; + projSelButton.setLayoutData(projSelButtonData); + projSelButton.setText("&Browse..."); + projSelButton.addListener(SWT.Selection, e -> + { + IProject choosedProject = chooseMograsimProject(); + if (choosedProject != null) + projSelText.setText(choosedProject.getName()); + }); + + // TODO MPM / RAM selectors + } + + private static int calculateWidthHint(Control c) + { + int wHint = new PixelConverter(c).convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); + return Math.max(wHint, c.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x); + } + + private IProject chooseMograsimProject() + { + WorkbenchLabelProvider renderer = new WorkbenchLabelProvider() + { + @Override + protected ImageDescriptor decorateImage(ImageDescriptor input, Object element) + { + return new ImageDescriptorWithMargins(input, new Point(22, 16)); + } + }; + ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), renderer); + dialog.setTitle("title"); + dialog.setMessage("message"); + dialog.setElements(filterOpenMograsimProjects(ResourcesPlugin.getWorkspace().getRoot().getProjects())); + if (dialog.open() == Window.OK) + return (IProject) dialog.getFirstResult(); + return null; + } + + private static IProject[] filterOpenMograsimProjects(IProject[] projects) + { + return Arrays.stream(projects).filter(p -> + { + try + { + return p.isAccessible() && p.hasNature(MograsimNature.NATURE_ID); + } + catch (CoreException e) + { + throw new RuntimeException(e); + } + }).toArray(IProject[]::new); + } + + @Override + public void setDefaults(ILaunchConfigurationWorkingCopy configuration) + { + // TODO don't let the user have to specify everything + } + + @Override + public void initializeFrom(ILaunchConfiguration configuration) + { + String projName = ""; + try + { + projName = configuration.getAttribute(MachineLaunchConfigType.PROJECT_ATTR, ""); + } + catch (CoreException e) + { + setErrorMessage(e.getStatus().getMessage()); + } + projSelText.setText(projName); + } + + @Override + public void performApply(ILaunchConfigurationWorkingCopy configuration) + { + Set associatedResources = new HashSet<>(); + String projName = projSelText.getText().trim(); + if (projName.length() != 0) + { + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IProject project = workspace.getRoot().getProject(projName); + try + { + if (project != null && project.isAccessible() && project.hasNature(MograsimNature.NATURE_ID)) + associatedResources.add(project); + } + catch (CoreException e) + { + setErrorMessage(e.getStatus().getMessage()); + } + } + configuration.setMappedResources(associatedResources.toArray(IResource[]::new)); + configuration.setAttribute(MachineLaunchConfigType.PROJECT_ATTR, projName); + } + + @Override + public boolean isValid(ILaunchConfiguration launchConfig) + { + setErrorMessage(null); + setMessage(null); + String projName = projSelText.getText().trim(); + if (projName.length() == 0) + { + setErrorMessage("No project specified"); + return false; + } + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IStatus status = workspace.validateName(projName, IResource.PROJECT); + if (!status.isOK()) + { + setErrorMessage(NLS.bind("Illegal project name: {0}", new String[] { status.getMessage() })); + return false; + } + IProject project = workspace.getRoot().getProject(projName); + if (!project.exists()) + { + setErrorMessage(NLS.bind("Project {0} does not exist", new String[] { projName })); + return false; + } + if (!project.isOpen()) + { + setErrorMessage(NLS.bind("Project {0} is closed", new String[] { projName })); + return false; + } + try + { + if (!project.hasNature(MograsimNature.NATURE_ID)) + { + setErrorMessage(NLS.bind("Project {0} is not a Mograsim project", new String[] { projName })); + return false; + } + } + catch (CoreException e) + { + setErrorMessage(e.getStatus().getMessage()); + return false; + } + return true; + } + + @Override + public String getName() + { + return "testlaunchconfigtabname"; + } +} \ No newline at end of file diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/util/ImageDescriptorWithMargins.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/util/ImageDescriptorWithMargins.java new file mode 100644 index 00000000..a664b09d --- /dev/null +++ b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/util/ImageDescriptorWithMargins.java @@ -0,0 +1,37 @@ +package net.mograsim.plugin.util; + +import org.eclipse.jface.resource.CompositeImageDescriptor; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Point; + +public class ImageDescriptorWithMargins extends CompositeImageDescriptor +{ + private final ImageDescriptor input; + private final Point size; + private final int ox, oy; + + public ImageDescriptorWithMargins(ImageDescriptor input, Point size) + { + this(input, 0, 0, size); + } + + public ImageDescriptorWithMargins(ImageDescriptor input, int offX, int offY, Point size) + { + this.input = input; + this.size = size; + this.ox = offX; + this.oy = offY; + } + + @Override + protected Point getSize() + { + return size; + } + + @Override + protected void drawCompositeImage(int width, int height) + { + drawImage(input::getImageData, ox, oy); + } +} \ No newline at end of file -- 2.17.1