Restructured Mograsim project nature and introduced project context
authorChristian Femers <femers@in.tum.de>
Thu, 19 Sep 2019 14:56:37 +0000 (16:56 +0200)
committerChristian Femers <femers@in.tum.de>
Thu, 19 Sep 2019 14:56:37 +0000 (16:56 +0200)
14 files changed:
features/net.mograsim.feature/feature.xml
plugins/net.mograsim.machine/src/net/mograsim/machine/MachineRegistry.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionMemoryParser.java
plugins/net.mograsim.plugin.core/META-INF/MANIFEST.MF
plugins/net.mograsim.plugin.core/OSGI-INF/l10n/bundle.properties
plugins/net.mograsim.plugin.core/plugin.xml
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/MachineContext.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/MograsimActivator.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/AddMograsimNatureHandler.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/AddRemoveMograsimNatureHandler.java [deleted file]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/MachineContext.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/MograsimNature.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/ProjectMachineContext.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/properties/MograsimNaturePropertyPage.java [new file with mode: 0644]

index 7e12101..2aeb3dc 100644 (file)
@@ -690,11 +690,10 @@ exception as provided by Oracle in the LICENSE file that accompanied this code.&
       <import plugin="org.eclipse.e4.ui.model.workbench"/>
       <import plugin="javax.annotation" version="1.0.0" match="greaterOrEqual"/>
       <import plugin="org.eclipse.help"/>
-      <import plugin="org.eclipse.swt" version="3.110.0" match="greaterOrEqual"/>
       <import plugin="com.google.gson" version="2.8.2" match="greaterOrEqual"/>
-      <import plugin="org.eclipse.ui.themes" version="1.2.0" match="greaterOrEqual"/>
-      <import plugin="org.eclipse.ui.intro" version="3.5.0" match="greaterOrEqual"/>
-      <import plugin="org.eclipse.ui.intro.universal" version="3.3.0" match="greaterOrEqual"/>
+      <import plugin="org.eclipse.swt" version="3.110.0" match="greaterOrEqual"/>
+      <import plugin="org.eclipse.core.expressions"/>
+      <import plugin="org.eclipse.ui.ide"/>
    </requires>
 
    <plugin
index a270646..28e7921 100644 (file)
@@ -4,20 +4,23 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
 import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IRegistryEventListener;
 import org.eclipse.core.runtime.Platform;
 
 public class MachineRegistry
 {
        private static final String MACHINE_EXT_ID = "net.mograsim.machine.machine_definition";
 
-       private static Map<String, MachineDefinition> installedMachines = new HashMap<>();
+       private static final Map<String, MachineDefinition> installedMachines = new HashMap<>();
 
-       public static void reload()
+       private static void reload()
        {
+               installedMachines.clear();
                IExtensionRegistry registry = Platform.getExtensionRegistry();
                System.out.println(Arrays.toString(registry.getExtensionPoints("net.mograsim.machine")));
                IConfigurationElement[] config = registry.getConfigurationElementsFor(MACHINE_EXT_ID);
@@ -45,8 +48,45 @@ public class MachineRegistry
                }
        }
 
-       public static Map<String, MachineDefinition> getinstalledMachines()
+       public static void initialize()
+       {
+               reload();
+               Platform.getExtensionRegistry().addListener(new IRegistryEventListener()
+               {
+
+                       @Override
+                       public void removed(IExtensionPoint[] extensionPoints)
+                       {
+                               // nothing?
+                       }
+
+                       @Override
+                       public void removed(IExtension[] extensions)
+                       {
+                               reload();
+                       }
+
+                       @Override
+                       public void added(IExtensionPoint[] extensionPoints)
+                       {
+                               // nothing?
+                       }
+
+                       @Override
+                       public void added(IExtension[] extensions)
+                       {
+                               reload();
+                       }
+               }, MACHINE_EXT_ID);
+       }
+
+       public static Map<String, MachineDefinition> getInstalledMachines()
        {
                return Collections.unmodifiableMap(installedMachines);
        }
+
+       public static MachineDefinition getMachine(String id)
+       {
+               return installedMachines.get(id);
+       }
 }
index 3c13f67..cea4326 100644 (file)
@@ -56,7 +56,7 @@ public class MicroInstructionMemoryParser
                try
                {
                        MicroInstructionMemoryDefinition def = Objects
-                                       .requireNonNull(MachineRegistry.getinstalledMachines().get(machineName), "Unknown machine: " + machineName)
+                                       .requireNonNull(MachineRegistry.getMachine(machineName), "Unknown machine: " + machineName)
                                        .getMicroInstructionMemoryDefinition();
                        MicroInstructionMemory memory = new StandardMicroInstructionMemory(def);
                        parseMemory(memory, input);
index 6dfa954..c3d17e9 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.nature,
+ net.mograsim.plugin.nature.properties,
  net.mograsim.plugin.tables,
  net.mograsim.plugin.tables.memory,
  net.mograsim.plugin.tables.mi,
@@ -28,7 +29,9 @@ Require-Bundle: org.eclipse.core.runtime,
  javax.annotation;bundle-version="1.0.0",
  net.mograsim.preferences;bundle-version="0.1.0",
  net.mograsim.machine,
- net.mograsim.plugin.core
+ net.mograsim.plugin.core,
+ org.eclipse.core.expressions,
+ org.eclipse.ui.ide
 Bundle-RequiredExecutionEnvironment: JavaSE-11
 Automatic-Module-Name: net.mograsim.plugin.core
 Bundle-Vendor: %Bundle-Vendor.0
index 26d588f..04c03e1 100644 (file)
@@ -9,10 +9,9 @@ view.name = Sample AsmOpsEdit
 e4view.name = Simulation und Visualisierung
 extension.name = Mograsim Project Builder
 extension.name.0 = Mograsim Project Nature
-category.name.0 = Mograsim Project Nature commands
-command.name = Add/RemoveMograsim Project Nature
-command.label = Disable Sample builder
-command.label.0 = Enable Sample builder
+category.name.0 = Mograsim
+command.name = Convert to Mograsim Project
+command.label = Convert to Mograsim Project
 extension.name.1 = XML Problem
 decorator.label = Resource Decorator
 themeElementCategory.label = Mograsim
index 03348a3..38f64cb 100644 (file)
@@ -1,6 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?eclipse version="3.4"?>
 <plugin>
+   <extension
+         point="org.eclipse.core.expressions.definitions">
+      <definition
+            id="net.mograsim.plugin.core.hasNature">
+         <adapt
+               type="org.eclipse.core.resources.IProject">
+            <test
+                  property="org.eclipse.core.resources.projectNature"
+                  value="net.mograsim.plugin.core.mograsimNature">
+            </test>
+         </adapt>
+      </definition>
+   </extension>
 
    <extension
          point="org.eclipse.core.contenttype.contentTypes">
             priority="high">
       </content-type>
    </extension>
+   <extension
+         point="org.eclipse.ui.menus">
+      <menuContribution
+            locationURI="popup:org.eclipse.ui.projectConfigure">
+         <command
+               commandId="net.mograsim.plugin.core.addMograsimNature"
+               label="%command.label"
+               style="push">
+            <visibleWhen
+                  checkEnabled="false">
+               <not>
+                  <reference
+                        definitionId="net.mograsim.plugin.core.hasNature">
+                  </reference>
+               </not>
+            </visibleWhen>
+         </command>
+      </menuContribution>
+   </extension>
+   <extension
+         id="mograsimNature"
+         name="%extension.name.0"
+         point="org.eclipse.core.resources.natures">
+      <runtime>
+         <run
+               class="net.mograsim.plugin.nature.MograsimNature">
+         </run>
+      </runtime>
+      <builder
+            id="net.mograsim.plugin.nature.mograsimBuilder">
+      </builder>
+   </extension>
    <extension
          point="org.eclipse.ui.editors">
       <editorContentTypeBinding
@@ -33,7 +78,7 @@
       </editorContentTypeBinding>
       <editor
                name="%editor.name.0"
-               icon="icons/mograsim/blue-orange/icon_blue-orange_7x8.png"
+               icon="icons/mograsim/blue-orange/icon_blue-orange_16.png"
                class="net.mograsim.plugin.tables.mi.InstructionView"
                id="net.mograsim.plugin.tables.mi.InstructionView">
       </editor>
       </builder>
    </extension>
    <extension
-         id="mograsimNature"
-         name="%extension.name.0"
-         point="org.eclipse.core.resources.natures">
-      <runtime>
-         <run
-               class="net.mograsim.plugin.nature.MograsimNature">
-         </run>
-      </runtime>
-      <builder
-            id="net.mograsim.plugin.nature.mograsimBuilder">
-      </builder>
-   </extension>
-   <extension
-         point="org.eclipse.ui.commands">
-      <category
-            id="net.mograsim.plugin.mograsimNature.category"
-            name="%category.name.0">
-      </category>
-      <command
-            categoryId="net.mograsim.plugin.mograsimNature.category"
-            defaultHandler="net.mograsim.plugin.nature.AddRemoveMograsimNatureHandler"
-            id="net.mograsim.plugin.addRemoveMograsimNature"
-            name="%command.name">
-      </command>
-   </extension>
-   <extension
-         point="org.eclipse.ui.menus">
-      <menuContribution
-            locationURI="popup:org.eclipse.ui.projectConfigure?after=additions">
-         <command
-               commandId="net.mograsim.plugin.addRemoveMograsimNature"
-               label="%command.label"
-               style="push">
-            <visibleWhen
-                  checkEnabled="false">
-               <with
-                     variable="selection">
-                  <count
-                        value="1">
-                  </count>
-                  <iterate>
-                     <adapt
-                           type="org.eclipse.core.resources.IProject">
-                        <test
-                              property="org.eclipse.core.resources.projectNature"
-                              value="net.mograsim.plugin.mograsimNature">
-                        </test>
-                     </adapt>
-                  </iterate>
-               </with>
-            </visibleWhen>
-         </command>
-         <command
-               commandId="net.mograsim.plugin.addRemoveMograsimNature"
-               label="%command.label.0"
-               style="push">
-            <visibleWhen
-                  checkEnabled="false">
-               <with
-                     variable="selection">
-                  <count
-                        value="1">
-                  </count>
-                  <iterate>
-                     <adapt
-                           type="org.eclipse.core.resources.IProject">
-                        <not>
-                           <test
-                                 property="org.eclipse.core.resources.projectNature"
-                                 value="net.mograsim.plugin.mograsimNature">
-                           </test>
-                        </not>
-                     </adapt>
-                  </iterate>
-               </with>
-            </visibleWhen>
-         </command>
-      </menuContribution>
-   </extension>
-   <extension
-         id="xmlProblem"
+         id="asmProblem"
          name="%extension.name.1"
          point="org.eclipse.core.resources.markers">
       <super
             value="true">
       </persistent>
    </extension>
-   <extension
-         point="org.eclipse.ui.decorators">
-      <decorator
-            adaptable="true"
-            icon="icons/mograsim/blue-orange/icon_blue-orange_7x8.png"
-            id="net.mograsim.plugin.decorator"
-            label="%decorator.label"
-            lightweight="true"
-            location="BOTTOM_RIGHT"
-            state="true">
-         <enablement>
-            <and>
-               <objectClass
-                     name="org.eclipse.core.resources.IResource">
-               </objectClass>
-               <or>
-                  <objectClass
-                        name="org.eclipse.core.resources.IProject">
-                  </objectClass>
-                  <objectClass
-                        name="org.eclipse.core.resources.IFile">
-                  </objectClass>
-               </or>
-            </and>
-         </enablement>
-      </decorator>
-   </extension>
    <extension
          point="org.eclipse.ui.themes">
       <themeElementCategory
       <page
             class="net.mograsim.plugin.MainPreferencePage"
             id="net.mograsim.plugin.core.mainprefpage"
-            name="Mograsim preferences">
+            name="Mograsim">
       </page>
    </extension>
+   <extension
+         point="org.eclipse.ui.propertyPages">
+      <page
+            class="net.mograsim.plugin.nature.properties.MograsimNaturePropertyPage"
+            id="net.mograsim.plugin.nature.properties.samplePropertyPage"
+            name="Mograsim">
+         <enabledWhen>
+            <reference
+                  definitionId="net.mograsim.plugin.core.hasNature">
+            </reference>
+         </enabledWhen>
+      </page>
+   </extension>
+   <extension
+         point="org.eclipse.ui.ide.projectNatureImages">
+      <image
+            icon="icons/mograsim/blue-orange/icon_blue-orange_7x8.png"
+            id="net.mograsim.plugin.core.nature.icon"
+            natureId="net.mograsim.plugin.core.mograsimNature">
+      </image>
+   </extension>
+   <extension
+         point="org.eclipse.ui.commands">
+      <category
+            id="net.mograsim.plugin.mograsimNature.category"
+            name="%category.name.0">
+      </category>
+      <command
+            categoryId="net.mograsim.plugin.mograsimNature.category"
+            defaultHandler="net.mograsim.plugin.nature.AddMograsimNatureHandler"
+            id="net.mograsim.plugin.core.addMograsimNature"
+            name="%command.name">
+      </command>
+   </extension>
 
 </plugin>
index 2e7a9c1..9da121a 100644 (file)
@@ -24,7 +24,7 @@ public class MachineContext
                {
                        instance = new MachineContext();
                        // TODO don't hardcode the Am2900
-                       instance.setMachine(MachineRegistry.getinstalledMachines().get("Am2900").createNew());
+                       instance.setMachine(MachineRegistry.getMachine("Am2900").createNew());
                }
                return instance;
        }
index 2d8e8e6..b3340da 100644 (file)
@@ -13,7 +13,7 @@ public final class MograsimActivator extends AbstractUIPlugin
                if (instance != null)
                        throw new IllegalStateException("MograsimActivator already created!");
                instance = this;
-               MachineRegistry.reload();
+               MachineRegistry.initialize();
        }
 
        public static MograsimActivator instance()
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/AddMograsimNatureHandler.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/AddMograsimNatureHandler.java
new file mode 100644 (file)
index 0000000..3941b1d
--- /dev/null
@@ -0,0 +1,89 @@
+package net.mograsim.plugin.nature;
+
+import java.util.Iterator;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+public class AddMograsimNatureHandler extends AbstractHandler
+{
+       @Override
+       public Object execute(ExecutionEvent event) throws ExecutionException
+       {
+               ISelection selection = HandlerUtil.getCurrentSelection(event);
+               //
+
+               MultiStatus ms = new MultiStatus("net.mograsim.plugin.core", 42, "MograsimNature Conversion", null);
+
+               if (selection instanceof IStructuredSelection)
+               {
+                       for (Iterator<?> it = ((IStructuredSelection) selection).iterator(); it.hasNext();)
+                       {
+                               Object element = it.next();
+                               IProject project = null;
+                               if (element instanceof IProject)
+                               {
+                                       project = (IProject) element;
+                               } else if (element instanceof IAdaptable)
+                               {
+                                       project = ((IAdaptable) element).getAdapter(IProject.class);
+                               }
+                               if (project != null)
+                               {
+                                       try
+                                       {
+                                               ms.add(toggleNature(project));
+                                       }
+                                       catch (CoreException e)
+                                       {
+                                               // TODO log something
+                                               throw new ExecutionException("Failed to toggle nature", e);
+                                       }
+                               }
+                       }
+               }
+
+               return ms.getSeverity();
+       }
+
+       /**
+        * Adds Mograsim nature on a project
+        *
+        * @param project to have Mograsim nature
+        * @return
+        */
+       private IStatus toggleNature(IProject project) throws CoreException
+       {
+               IProjectDescription description = project.getDescription();
+               String[] natures = description.getNatureIds();
+
+               // Add the nature
+               String[] newNatures = new String[natures.length + 1];
+               System.arraycopy(natures, 0, newNatures, 0, natures.length);
+               newNatures[natures.length] = MograsimNature.NATURE_ID;
+
+               IWorkspace workspace = ResourcesPlugin.getWorkspace();
+               IStatus status = workspace.validateNatureSet(newNatures);
+
+               // only apply new nature, if the status is ok
+               if (status.getCode() == IStatus.OK)
+               {
+                       description.setNatureIds(newNatures);
+                       project.setDescription(description, null);
+               }
+
+               return status;
+       }
+}
\ No newline at end of file
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/AddRemoveMograsimNatureHandler.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/AddRemoveMograsimNatureHandler.java
deleted file mode 100644 (file)
index e8b38e9..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-package net.mograsim.plugin.nature;
-
-import java.util.Iterator;
-
-import org.eclipse.core.commands.AbstractHandler;
-import org.eclipse.core.commands.ExecutionEvent;
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IProjectDescription;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.handlers.HandlerUtil;
-
-public class AddRemoveMograsimNatureHandler extends AbstractHandler
-{
-       @Override
-       public Object execute(ExecutionEvent event) throws ExecutionException
-       {
-               ISelection selection = HandlerUtil.getCurrentSelection(event);
-               //
-               if (selection instanceof IStructuredSelection)
-               {
-                       for (Iterator<?> it = ((IStructuredSelection) selection).iterator(); it.hasNext();)
-                       {
-                               Object element = it.next();
-                               IProject project = null;
-                               if (element instanceof IProject)
-                               {
-                                       project = (IProject) element;
-                               } else if (element instanceof IAdaptable)
-                               {
-                                       project = ((IAdaptable) element).getAdapter(IProject.class);
-                               }
-                               if (project != null)
-                               {
-                                       try
-                                       {
-                                               toggleNature(project);
-                                       }
-                                       catch (CoreException e)
-                                       {
-                                               // TODO log something
-                                               throw new ExecutionException("Failed to toggle nature", e);
-                                       }
-                               }
-                       }
-               }
-
-               return null;
-       }
-
-       /**
-        * Toggles sample nature on a project
-        *
-        * @param project to have sample nature added or removed
-        */
-       private void toggleNature(IProject project) throws CoreException
-       {
-               IProjectDescription description = project.getDescription();
-               String[] natures = description.getNatureIds();
-
-               for (int i = 0; i < natures.length; ++i)
-               {
-                       if (MograsimNature.NATURE_ID.equals(natures[i]))
-                       {
-                               // Remove the nature
-                               String[] newNatures = new String[natures.length - 1];
-                               System.arraycopy(natures, 0, newNatures, 0, i);
-                               System.arraycopy(natures, i + 1, newNatures, i, natures.length - i - 1);
-                               description.setNatureIds(newNatures);
-                               project.setDescription(description, null);
-                               return;
-                       }
-               }
-
-               // Add the nature
-               String[] newNatures = new String[natures.length + 1];
-               System.arraycopy(natures, 0, newNatures, 0, natures.length);
-               newNatures[natures.length] = MograsimNature.NATURE_ID;
-               description.setNatureIds(newNatures);
-               project.setDescription(description, null);
-       }
-}
\ No newline at end of file
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/MachineContext.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/MachineContext.java
new file mode 100644 (file)
index 0000000..b434ec9
--- /dev/null
@@ -0,0 +1,120 @@
+package net.mograsim.plugin.nature;
+
+import java.io.IOException;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.ui.preferences.ScopedPreferenceStore;
+
+import net.mograsim.machine.Machine;
+import net.mograsim.machine.MachineDefinition;
+import net.mograsim.machine.MachineRegistry;
+
+public class MachineContext
+{
+       IProject owner;
+       ScopedPreferenceStore prefs;
+       Optional<String> machineId;
+       Optional<MachineDefinition> machineDefinition;
+       Optional<Machine> activeMachine;
+
+       public MachineContext(IProject owner)
+       {
+               this.owner = Objects.requireNonNull(owner);
+               prefs = ProjectMachineContext.getProjectPrefs(owner);
+               prefs.addPropertyChangeListener(this::preferenceListener);
+               machineId = ProjectMachineContext.getMachineIdFrom(prefs);
+               updateDefinition();
+       }
+
+       public final IProject getProject()
+       {
+               return owner;
+       }
+
+       public final ScopedPreferenceStore getPreferences()
+       {
+               return prefs;
+       }
+
+       /**
+        * Returns true if the project configuration is valid in the current environment
+        */
+       public final boolean isCurrentyValid()
+       {
+               return machineDefinition.isPresent();
+       }
+
+       /**
+        * Returns true if the persisted project configuration itself is intact
+        */
+       public final boolean isIntact()
+       {
+               return machineId.isPresent();
+       }
+
+       /**
+        * Returns true if a machine is instantiated and (possibly) running
+        */
+       public final boolean isActive()
+       {
+               return activeMachine.isPresent();
+       }
+
+       /**
+        * Sets the projects machineId. Will likely break things, if the {@link MachineContext} {@link #isActive()}.
+        */
+       public final boolean setMachineId(String machineId)
+       {
+               prefs.setValue(ProjectMachineContext.MACHINE_PROPERTY, machineId);
+               try
+               {
+                       prefs.save();
+               }
+               catch (IOException e)
+               {
+                       e.printStackTrace();
+                       return false;
+               }
+               return true;
+       }
+
+       /**
+        * Sets the active machine in the {@link MachineContext}'s project scope.
+        */
+       public final void setActiveMachine(Machine machine)
+       {
+               activeMachine = Optional.ofNullable(machine);
+       }
+
+       public final Optional<String> getMachineId()
+       {
+               return machineId;
+       }
+
+       public final Optional<MachineDefinition> getMachineDefinition()
+       {
+               return machineDefinition;
+       }
+
+       public final Optional<Machine> getActiveMachine()
+       {
+               return activeMachine;
+       }
+
+       final void updateDefinition()
+       {
+               machineDefinition = machineId.map(MachineRegistry::getMachine);
+       }
+
+       private void preferenceListener(PropertyChangeEvent changeEvent)
+       {
+               if (changeEvent.getProperty().equals(ProjectMachineContext.MACHINE_PROPERTY))
+               {
+                       machineId = Optional.ofNullable((String) changeEvent.getNewValue());
+                       updateDefinition();
+               }
+       }
+}
\ No newline at end of file
index 5422731..4ffd62e 100644 (file)
@@ -12,7 +12,7 @@ public class MograsimNature implements IProjectNature
        /**
         * ID of this project nature
         */
-       public static final String NATURE_ID = "net.mograsim";
+       public static final String NATURE_ID = "net.mograsim.plugin.core.mograsimNature";
 
        private IProject project;
 
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/ProjectMachineContext.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/ProjectMachineContext.java
new file mode 100644 (file)
index 0000000..0e6185c
--- /dev/null
@@ -0,0 +1,91 @@
+package net.mograsim.plugin.nature;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.Adapters;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ui.preferences.ScopedPreferenceStore;
+
+public class ProjectMachineContext
+{
+       private static Map<IProject, MachineContext> projectMachineContexts = Collections.synchronizedMap(new HashMap<>());
+
+       public static final String MOGRASIM_PROJECT_PREFS_NODE = "net.mograsim";
+       public static final String MACHINE_PROPERTY = "net.mograsim.projectMachineId";
+
+       public static MachineContext getMachineContextOf(IProject project)
+       {
+               MachineContext mc = projectMachineContexts.get(project);
+               if (mc != null)
+                       return mc;
+               validateMograsimNatureProject(project);
+               mc = new MachineContext(project);
+               projectMachineContexts.put(project, mc);
+               return mc;
+       }
+
+       public static MachineContext getMachineContextOf(IAdaptable mograsimProjectAdapable)
+       {
+               IProject project = Adapters.adapt(mograsimProjectAdapable, IProject.class, true);
+               Objects.requireNonNull(project, "project was null / no project found for " + mograsimProjectAdapable);
+               return getMachineContextOf(project);
+       }
+
+       static ScopedPreferenceStore getProjectPrefs(IProject mograsimProject)
+       {
+               return new ScopedPreferenceStore(new ProjectScope(mograsimProject), MOGRASIM_PROJECT_PREFS_NODE);
+       }
+
+       static IProject validateMograsimNatureProject(IAdaptable mograsimProjectAdapable)
+       {
+               IProject project;
+               if (mograsimProjectAdapable instanceof IProject)
+               {
+                       project = (IProject) mograsimProjectAdapable;
+               } else
+               {
+                       project = Adapters.adapt(mograsimProjectAdapable, IProject.class, true);
+                       Objects.requireNonNull(project, () -> mograsimProjectAdapable + " is not adaptable to IProject");
+               }
+               try
+               {
+                       if (!project.isNatureEnabled(MograsimNature.NATURE_ID))
+                               throw new IllegalArgumentException(mograsimProjectAdapable + "is not (in) a Mograsim project");
+               }
+               catch (CoreException e)
+               {
+                       e.printStackTrace();
+                       throw new IllegalArgumentException(mograsimProjectAdapable + " project nature could not be evaluated", e);
+               }
+               return project;
+       }
+
+       static boolean hasMograsimNature(IProject project)
+       {
+               if (project == null)
+                       return false;
+               try
+               {
+                       return project.isNatureEnabled(MograsimNature.NATURE_ID);
+               }
+               catch (CoreException e)
+               {
+                       e.printStackTrace();
+                       return false;
+               }
+       }
+
+       static Optional<String> getMachineIdFrom(ScopedPreferenceStore preferenceStore)
+       {
+               if (preferenceStore.contains(MACHINE_PROPERTY))
+                       return Optional.of(preferenceStore.getString(MACHINE_PROPERTY));
+               return Optional.empty();
+       }
+}
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/properties/MograsimNaturePropertyPage.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/properties/MograsimNaturePropertyPage.java
new file mode 100644 (file)
index 0000000..edf07e2
--- /dev/null
@@ -0,0 +1,137 @@
+package net.mograsim.plugin.nature.properties;
+
+import java.util.Optional;
+
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+import net.mograsim.machine.MachineRegistry;
+import net.mograsim.plugin.nature.MachineContext;
+import net.mograsim.plugin.nature.ProjectMachineContext;
+
+public class MograsimNaturePropertyPage extends PropertyPage
+{
+
+       private static final String WARNING = "Changing the Mograsim machine can completely break your project. Be careful.";
+       private static final String MACHINE_LABEL = "Machine ID";
+       private static final String MACHINE_PROPERTY = "net.mograsim.projectMachineId";
+       private static final String DEFAULT_MACHINE = "Am2900";
+
+       private Combo machineSelect;
+       private String defaultId;
+
+       private MachineContext machineContext;
+
+       /**
+        * Constructor for SamplePropertyPage.
+        */
+       public MograsimNaturePropertyPage()
+       {
+               super();
+       }
+
+       private void addFirstSection(Composite parent)
+       {
+               Composite composite = createDefaultComposite(parent);
+
+               // Label for path field
+               Label pathLabel = new Label(composite, SWT.NONE);
+               pathLabel.setText(WARNING);
+       }
+
+       private void addSeparator(Composite parent)
+       {
+               Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
+               GridData gridData = new GridData();
+               gridData.horizontalAlignment = GridData.FILL;
+               gridData.grabExcessHorizontalSpace = true;
+               separator.setLayoutData(gridData);
+       }
+
+       private void addSecondSection(Composite parent)
+       {
+               Composite composite = createDefaultComposite(parent);
+
+               // Label for machine
+               Label ownerLabel = new Label(composite, SWT.NONE);
+               ownerLabel.setText(MACHINE_LABEL);
+
+               // Machine choice
+               machineSelect = new Combo(parent, SWT.BORDER);
+               GridData gd = new GridData();
+               machineSelect.setLayoutData(gd);
+
+               Optional<String> currentId = machineContext.getMachineId();
+
+               if (currentId.isPresent())
+                       machineSelect.add(currentId.get());
+
+               for (String machineId : MachineRegistry.getInstalledMachines().keySet())
+               {
+                       if (currentId.isPresent() && currentId.get().equals(machineId))
+                               continue;
+                       machineSelect.add(machineId);
+               }
+
+               defaultId = currentId.orElse(DEFAULT_MACHINE);
+
+               machineSelect.select(machineSelect.indexOf(defaultId));
+       }
+
+       /**
+        * @see PreferencePage#createContents(Composite)
+        */
+       protected Control createContents(Composite parent)
+       {
+               machineContext = ProjectMachineContext.getMachineContextOf(getElement());
+
+               Composite composite = new Composite(parent, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               composite.setLayout(layout);
+               GridData data = new GridData(GridData.FILL);
+               data.grabExcessHorizontalSpace = true;
+               composite.setLayoutData(data);
+
+               addFirstSection(composite);
+               addSeparator(composite);
+               addSecondSection(composite);
+               return composite;
+       }
+
+       private Composite createDefaultComposite(Composite parent)
+       {
+               Composite composite = new Composite(parent, SWT.NULL);
+               GridLayout layout = new GridLayout();
+               layout.numColumns = 2;
+               composite.setLayout(layout);
+
+               GridData data = new GridData();
+               data.verticalAlignment = GridData.FILL;
+               data.horizontalAlignment = GridData.FILL;
+               composite.setLayoutData(data);
+
+               return composite;
+       }
+
+       protected void performDefaults()
+       {
+               super.performDefaults();
+               // Populate the owner text field with the default value
+               machineSelect.select(machineSelect.indexOf(DEFAULT_MACHINE));
+       }
+
+       public boolean performOk()
+       {
+               int selected = machineSelect.getSelectionIndex();
+               String newId = machineSelect.getItem(selected);
+               return machineContext.setMachineId(newId);
+       }
+
+}
\ No newline at end of file