Added a test launch config
authorDaniel Kirschten <daniel.kirschten@gmx.de>
Sat, 28 Sep 2019 14:31:45 +0000 (16:31 +0200)
committerDaniel Kirschten <daniel.kirschten@gmx.de>
Sat, 28 Sep 2019 14:31:45 +0000 (16:31 +0200)
plugins/net.mograsim.plugin.core/META-INF/MANIFEST.MF
plugins/net.mograsim.plugin.core/plugin.xml
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/MograsimActivator.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/EmptyLaunchConfigTabGroup.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MachineLaunchConfigType.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/launch/MainMachineLaunchConfigTab.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/util/ImageDescriptorWithMargins.java [new file with mode: 0644]

index 3fae54f..2ce9f38 100644 (file)
@@ -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
index c48d9c4..0c1efa6 100644 (file)
                        <selection class="org.eclipse.core.resources.IResource"/>
                </wizard>
        </extension>
+ <extension
+       point="org.eclipse.debug.core.launchConfigurationTypes">
+    <launchConfigurationType
+          delegate="net.mograsim.plugin.launch.MachineLaunchConfigType"
+          id="net.mograsim.plugin.core.launchmachine.type"
+          modes="run, debug"
+          name="Mograsim machine">
+    </launchConfigurationType>
+ </extension>
+ <extension
+       point="org.eclipse.debug.ui.launchConfigurationTabGroups">
+    <launchConfigurationTabGroup
+          class="net.mograsim.plugin.launch.EmptyLaunchConfigTabGroup"
+          id="net.mograsim.plugin.core.launchmachine.tabgroup"
+          type="net.mograsim.plugin.core.launchmachine.type">
+    </launchConfigurationTabGroup>
+ </extension>
+ <extension
+       point="org.eclipse.debug.ui.launchConfigurationTabs">
+    <tab
+          class="net.mograsim.plugin.launch.MainMachineLaunchConfigTab"
+          group="net.mograsim.plugin.core.launchmachine.tabgroup"
+          id="net.mograsim.plugin.core.launchmachine.maintab"
+          name="Common">
+    </tab>
+ </extension>
+ <extension
+       point="org.eclipse.debug.ui.launchConfigurationTypeImages">
+    <launchConfigurationTypeImage
+          configTypeID="net.mograsim.plugin.core.launchmachine.type"
+          icon="icons/mograsim/orange/icon_orange_16.png"
+          id="net.mograsim.plugin.core.launchmachine.image">
+    </launchConfigurationTypeImage>
+ </extension>
 </plugin>
index 9311ddd..765a63a 100644 (file)
@@ -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 (file)
index 0000000..6f4844e
--- /dev/null
@@ -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 <code>org.eclipse.debug.ui.launchConfigurationTabs</code>.
+ * 
+ * @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 (file)
index 0000000..03c481a
--- /dev/null
@@ -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 = "<unknown: " + type + ">";
+               }
+               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 (file)
index 0000000..6579efc
--- /dev/null
@@ -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<IResource> 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 (file)
index 0000000..a664b09
--- /dev/null
@@ -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