Merge branch 'machines-are-launch-configs' into development
authorDaniel Kirschten <daniel.kirschten@gmx.de>
Mon, 30 Sep 2019 12:10:38 +0000 (14:10 +0200)
committerDaniel Kirschten <daniel.kirschten@gmx.de>
Mon, 30 Sep 2019 12:10:38 +0000 (14:10 +0200)
19 files changed:
plugins/net.mograsim.logic.model.am2900/components/net/mograsim/logic/model/am2900/components/Am2900.json
plugins/net.mograsim.logic.model.am2900/src/net/mograsim/logic/model/am2900/machine/Am2900Machine.java
plugins/net.mograsim.machine/src/net/mograsim/machine/Machine.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/AssignableMicroInstructionMemory.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/MicroInstructionMemory.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroInstructionMemory.java
plugins/net.mograsim.machine/src/net/mograsim/machine/mi/components/CoreMicroInstructionMemory.java
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/editors/SimulationViewEditor.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/nature/MachineContext.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/ActiveInstructionPreviewContentProvider.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/ColorProvider.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTable.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionView.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/IntegerColumnLabelProvider.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/ParameterLabelProvider.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/RowHighlighter.java [new file with mode: 0644]
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/util/SingleSWTRequest.java [new file with mode: 0644]

index b152294..a83e7ad 100644 (file)
           "compName": "WireCrossPoint#43",
           "pinName": ""
         },
-        "name": "unnamedWire#163",
+        "name": "wire_mpm_address",
         "path": [
           {
             "x": 205.0,
index ac1b237..f705e74 100644 (file)
@@ -1,5 +1,8 @@
 package net.mograsim.logic.model.am2900.machine;
 
+import java.util.HashSet;
+import java.util.Set;
+
 import net.mograsim.logic.core.components.CoreClock;
 import net.mograsim.logic.core.timeline.Timeline;
 import net.mograsim.logic.core.types.BitVector;
@@ -31,6 +34,9 @@ public class Am2900Machine implements Machine
        private AssignableMainMemory mainMemory;
        private AssignableMicroInstructionMemory instMemory;
        private CoreClock clock;
+       private long activeInstructionAddress;
+
+       private final Set<ActiveMicroInstructionChangedListener> amicListeners;
 
        public Am2900Machine(LogicModelModifiable model, Am2900MachineDefinition am2900MachineDefinition)
        {
@@ -38,6 +44,8 @@ public class Am2900Machine implements Machine
                this.logicModel = model;
                this.am2900 = IndirectModelComponentCreator.createComponent(logicModel,
                                "resloader:Am2900Loader:jsonres:net/mograsim/logic/model/am2900/components/Am2900.json", "Am2900");
+               this.amicListeners = new HashSet<>();
+
                CoreModelParameters params = new CoreModelParameters();
                params.gateProcessTime = 50;
                params.wireTravelTime = 10;
@@ -48,6 +56,15 @@ public class Am2900Machine implements Machine
                am2900.setHighLevelState("ram.memory_binding", mainMemory);
                am2900.setHighLevelState("mpm.memory_binding", instMemory);
                clock = logicModel.getComponentBySubmodelPath("Am2900.Clock#0", ModelClock.class).getClock();
+               clock.registerObserver(c ->
+               {
+                       if (clock.isOn())
+                       {
+                               long oldAddress = activeInstructionAddress;
+                               activeInstructionAddress = getCurrentMicroInstructionAddress();
+                               notifyActiveMicroInstructionChangedListeners(oldAddress, activeInstructionAddress);
+                       }
+               });
        }
 
        @Override
@@ -115,4 +132,34 @@ public class Am2900Machine implements Machine
        {
                return instMemory;
        }
+
+       @Override
+       public long getActiveMicroInstructionAddress()
+       {
+               return activeInstructionAddress;
+       }
+
+       private long getCurrentMicroInstructionAddress()
+       {
+               // TODO: replace with highlevelstate
+               BitVector vector = logicModel.getWireBySubmodelPath("Am2900.wire_mpm_address").getWireValues();
+               return vector.isBinary() ? vector.getUnsignedValueLong() : -1;
+       }
+
+       @Override
+       public void addActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener listener)
+       {
+               amicListeners.add(listener);
+       }
+
+       @Override
+       public void removeActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener listener)
+       {
+               amicListeners.remove(listener);
+       }
+
+       private void notifyActiveMicroInstructionChangedListeners(long oldAddress, long newAddress)
+       {
+               amicListeners.forEach(l -> l.instructionChanged(oldAddress, newAddress));
+       }
 }
\ No newline at end of file
index df99984..8325068 100644 (file)
@@ -26,4 +26,15 @@ public interface Machine
        AssignableMainMemory getMainMemory();
 
        AssignableMicroInstructionMemory getMicroInstructionMemory();
+
+       void addActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener listener);
+
+       void removeActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener listener);
+
+       long getActiveMicroInstructionAddress();
+
+       public interface ActiveMicroInstructionChangedListener
+       {
+               public void instructionChanged(long oldAddress, long newAddress);
+       }
 }
\ No newline at end of file
index a366ae0..623d632 100644 (file)
@@ -4,14 +4,12 @@ import java.util.HashSet;
 import java.util.Set;
 
 import net.mograsim.machine.Memory.MemoryCellModifiedListener;
-import net.mograsim.machine.mi.MicroInstructionMemory.ActiveMicroInstructionChangedListener;
 
-public class AssignableMicroInstructionMemory
-               implements MicroInstructionMemory, MemoryCellModifiedListener, ActiveMicroInstructionChangedListener
+public class AssignableMicroInstructionMemory implements MicroInstructionMemory, MemoryCellModifiedListener
 {
 
        private Set<MemoryCellModifiedListener> observers = new HashSet<>();
-       private Set<ActiveMicroInstructionChangedListener> activeInstructionListeners = new HashSet<>();
+
        private Set<MIMemoryReassignedListener> reassignmentListeners = new HashSet<>();
        private MicroInstructionMemory real = null;
 
@@ -54,28 +52,11 @@ public class AssignableMicroInstructionMemory
                observers.remove(ob);
        }
 
-       @Override
-       public void registerActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener ob)
-       {
-               activeInstructionListeners.add(ob);
-       }
-
-       @Override
-       public void deregisterActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener ob)
-       {
-               activeInstructionListeners.remove(ob);
-       }
-
        private void notifyMemoryChanged(long address)
        {
                observers.forEach(o -> o.update(address));
        }
 
-       private void notifyActiveInstructionChanged(long address)
-       {
-               activeInstructionListeners.forEach(o -> o.activeMicroInstructionChanged(address));
-       }
-
        @Override
        public MicroInstructionMemoryDefinition getDefinition()
        {
@@ -88,18 +69,6 @@ public class AssignableMicroInstructionMemory
                notifyMemoryChanged(address);
        }
 
-       @Override
-       public void setActiveInstruction(long address)
-       {
-               real.setActiveInstruction(address);
-       }
-
-       @Override
-       public void activeMicroInstructionChanged(long address)
-       {
-               notifyActiveInstructionChanged(address);
-       }
-
        public void registerMemoryReassignedListener(MIMemoryReassignedListener listener)
        {
                reassignmentListeners.add(listener);
index abfed46..6409f78 100644 (file)
@@ -6,15 +6,4 @@ public interface MicroInstructionMemory extends Memory<MicroInstruction>
 {
        @Override
        public MicroInstructionMemoryDefinition getDefinition();
-
-       public void registerActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener ob);
-
-       public void deregisterActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener ob);
-
-       public void setActiveInstruction(long address);
-
-       public static interface ActiveMicroInstructionChangedListener
-       {
-               public void activeMicroInstructionChanged(long address);
-       }
 }
index 94905a5..c8866fd 100644 (file)
@@ -1,7 +1,6 @@
 package net.mograsim.machine.mi;
 
 import java.util.HashSet;
-import java.util.Set;
 
 import net.mograsim.machine.standard.memory.MemoryException;
 
@@ -10,8 +9,6 @@ public class StandardMicroInstructionMemory implements MicroInstructionMemory
        private MicroInstruction[] data;
        private MicroInstructionMemoryDefinition definition;
        private HashSet<MemoryCellModifiedListener> observers = new HashSet<>();
-       private Set<ActiveMicroInstructionChangedListener> activeInstructionListeners = new HashSet<>();
-       private long activeInstruction = -1;
 
        public StandardMicroInstructionMemory(MicroInstructionMemoryDefinition definition)
        {
@@ -55,42 +52,14 @@ public class StandardMicroInstructionMemory implements MicroInstructionMemory
                observers.remove(ob);
        }
 
-       @Override
-       public void registerActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener ob)
-       {
-               activeInstructionListeners.add(ob);
-       }
-
-       @Override
-       public void deregisterActiveMicroInstructionChangedListener(ActiveMicroInstructionChangedListener ob)
-       {
-               activeInstructionListeners.remove(ob);
-       }
-
        private void notifyMemoryChanged(long address)
        {
                observers.forEach(ob -> ob.update(address));
        }
 
-       private void notifyActiveInstructionChanged(long address)
-       {
-               activeInstructionListeners.forEach(o -> o.activeMicroInstructionChanged(address));
-       }
-
        @Override
        public MicroInstructionMemoryDefinition getDefinition()
        {
                return definition;
        }
-
-       @Override
-       public void setActiveInstruction(long address)
-       {
-               if (address != activeInstruction)
-               {
-                       activeInstruction = address;
-                       notifyActiveInstructionChanged(address);
-               }
-       }
-
 }
index b01802c..96ac46c 100644 (file)
@@ -77,7 +77,6 @@ public class CoreMicroInstructionMemory extends BasicCoreComponent
                        return e -> data.feedSignals(Bit.U.toVector(data.width()));// TODO don't always feed U, but decide to feed X or U.
                long addressed = address.getValues().getUnsignedValueLong();
                BitVector storedData = memory.getCell(addressed).toBitVector();
-               memory.setActiveInstruction(addressed);
                return e -> data.feedSignals(storedData);
        }
 }
\ No newline at end of file
index 9faa5ee..2c6f94c 100644 (file)
@@ -15,6 +15,8 @@ command.label = Convert to Mograsim Project
 extension.name.1 = XML Problem
 decorator.label = Resource Decorator
 themeElementCategory.label = Mograsim
+themeElementCategory.label.0 = Simulation
+themeElementCategory.label.1 = Microinstructions
 colorDefinition.label = Simulation Background
 colorDefinition.description = The Background of the Simulation Visualisation
 colorDefinition.label.0 = Simulation Foreground Color
@@ -28,11 +30,15 @@ colorDefinition.label.7 = Simulation Color X
 colorDefinition.label.8 = Simulation Color Z
 colorDefinition.label.9 = Simulation Color 0
 colorDefinition.label.10 = Simulation text color
+colorDefinition.label.11 = Modified Cell Background Color
+colorDefinition.label.12 = Modified Cell Foreground Color
+colorDefinition.label.13 = Highlighted Cell Background Color
+colorDefinition.label.14 = Highlighted Cell Foreground Color
 fontDefinition.label = Assembler Operation Style
+fontDefinition.label.0 = Table Font
 view.name.0 = Simulation View
 view.name.1 = Memory
 wizards.newWizards.category = Mograsim
 wizards.newWizards.mpm.name = Microprogram Memory
 wizards.newWizards.mpm.desc = Creates a default new Microprogram Memory
-themeElementCategory.label.0 = Simulation
 Bundle-Vendor.0 = Mograsim Team
\ No newline at end of file
index 6b5cdc5..7d7e5e1 100644 (file)
             label="%themeElementCategory.label.0"
             parentId="net.mograsim.plugin.mograsim">
       </themeElementCategory>
+      <themeElementCategory
+            class="net.mograsim.plugin.SimulationPreview"
+            id="net.mograsim.plugin.mi"
+            label="%themeElementCategory.label.1"
+            parentId="net.mograsim.plugin.mograsim">
+      </themeElementCategory>
       <colorDefinition
             categoryId="net.mograsim.logic.model"
             id="net.mograsim.logic.model.color.background"
             isEditable="true"
             label="%fontDefinition.label">
       </fontDefinition>
+      <colorDefinition
+            categoryId="net.mograsim.plugin.mi"
+            id="net.mograsim.plugin.modified_cell_bg_color"
+            isEditable="true"
+            label="%colorDefinition.label.11"
+            value="COLOR_GREEN">
+      </colorDefinition>
+      <colorDefinition
+            categoryId="net.mograsim.plugin.mi"
+            id="net.mograsim.plugin.modified_cell_fg_color"
+            isEditable="true"
+            label="%colorDefinition.label.12"
+            value="COLOR_BLACK">
+      </colorDefinition>
+      <fontDefinition
+            categoryId="net.mograsim.plugin.mi"
+            id="net.mograsim.plugin.table_font"
+            isEditable="true"
+            label="%fontDefinition.label.0">
+      </fontDefinition>
+      <colorDefinition
+            categoryId="net.mograsim.plugin.mi"
+            id="net.mograsim.plugin.highlighted_cell_bg_color"
+            isEditable="true"
+            label="%colorDefinition.label.13"
+            value="COLOR_YELLOW">
+      </colorDefinition>
+      <colorDefinition
+            categoryId="net.mograsim.plugin.mi"
+            id="net.mograsim.plugin.highlighted_cell_fg_color"
+            isEditable="true"
+            label="%colorDefinition.label.14"
+            value="COLOR_BLACK">
+      </colorDefinition>
    </extension>
    <extension
          point="org.eclipse.ui.preferencePages">
index 6b17dcf..651852e 100644 (file)
@@ -72,7 +72,7 @@ public class SimulationViewEditor extends EditorPart
 
        public SimulationViewEditor()
        {
-               activeMachineListener = m -> recreateContextDependentControls();
+               activeMachineListener = (oldM, newM) -> recreateContextDependentControls();
                memCellListener = a -> instPreview.refresh();
                clockObserver = o ->
                {
@@ -159,6 +159,9 @@ public class SimulationViewEditor extends EditorPart
 
                        canvasParent.layout();
 
+                       // update preview
+                       ((ActiveInstructionPreviewContentProvider) instPreview.getTableViewer().getContentProvider()).setMachine(machine);
+
                        // initialize executer
                        exec = new LogicExecuter(machine.getTimeline());
                        updateSpeedFactorFromInput(simSpeedInput.getValue());
@@ -298,9 +301,11 @@ public class SimulationViewEditor extends EditorPart
 
        private void addInstructionPreviewControlWidgets(Composite parent)
        {
-               instPreview = new InstructionTable(parent, new DisplaySettings());
+               instPreview = new InstructionTable(parent, new DisplaySettings(), getSite().getWorkbenchWindow().getWorkbench().getThemeManager());
                instPreview.getTableViewer().getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               instPreview.setContentProvider(new ActiveInstructionPreviewContentProvider(instPreview.getTableViewer()));
+               ActiveInstructionPreviewContentProvider cProv;
+               instPreview.setContentProvider(cProv = new ActiveInstructionPreviewContentProvider(instPreview.getTableViewer()));
+               cProv.setMachine(machine);
        }
 
        private static void setPauseText(Button pauseButton, boolean hovered)
index 1be6b2a..c84e622 100644 (file)
@@ -122,9 +122,10 @@ public class MachineContext
         */
        public final void setActiveMachine(Machine machine)
        {
+               Optional<Machine> oldMachine = activeMachine;
                activeMachine = Optional.ofNullable(machine);
                updateStatus();
-               notifyActiveMachineListeners();
+               notifyActiveMachineListeners(oldMachine, activeMachine);
        }
 
        public final Optional<String> getMachineId()
@@ -208,8 +209,9 @@ public class MachineContext
        {
                if ((status == DEAD || status == CLOSED) && activeMachine.isPresent())
                {
+                       Optional<Machine> oldMachine = activeMachine;
                        activeMachine = Optional.empty();
-                       notifyActiveMachineListeners();
+                       notifyActiveMachineListeners(oldMachine, activeMachine);
                }
        }
 
@@ -247,15 +249,15 @@ public class MachineContext
                }
        }
 
-       private void notifyActiveMachineListeners()
+       private void notifyActiveMachineListeners(Optional<Machine> oldMachine, Optional<Machine> newMachine)
        {
-               machineListeners.forEach(ob -> ob.setMachine(activeMachine));
+               machineListeners.forEach(ob -> ob.setMachine(oldMachine, newMachine));
        }
 
        public void addActiveMachineListener(ActiveMachineListener ob)
        {
                machineListeners.add(ob);
-               ob.setMachine(activeMachine);
+               ob.setMachine(Optional.empty(), activeMachine);
        }
 
        public void removeActiveMachineListener(ActiveMachineListener ob)
@@ -282,7 +284,7 @@ public class MachineContext
        @FunctionalInterface
        public static interface ActiveMachineListener
        {
-               void setMachine(Optional<Machine> machine);
+               void setMachine(Optional<Machine> oldMachine, Optional<Machine> newMachine);
        }
 
        @FunctionalInterface
index 604c285..d3a14ec 100644 (file)
@@ -3,14 +3,24 @@ package net.mograsim.plugin.tables.mi;
 import org.eclipse.jface.viewers.TableViewer;
 import org.eclipse.jface.viewers.Viewer;
 
+import net.mograsim.machine.Machine;
+import net.mograsim.machine.Machine.ActiveMicroInstructionChangedListener;
 import net.mograsim.machine.mi.MicroInstructionMemory;
-import net.mograsim.machine.mi.MicroInstructionMemory.ActiveMicroInstructionChangedListener;
+import net.mograsim.plugin.util.SingleSWTRequest;
 
-public class ActiveInstructionPreviewContentProvider implements InstructionTableContentProvider, ActiveMicroInstructionChangedListener
+public class ActiveInstructionPreviewContentProvider implements InstructionTableContentProvider
 {
        private TableViewer viewer;
        private MicroInstructionMemory memory;
        private InstructionTableRow activeRow;
+       private Machine machine;
+       private SingleSWTRequest requester = new SingleSWTRequest();
+
+       private ActiveMicroInstructionChangedListener instChanged = (oldAddress, newAddress) ->
+       {
+               activeRow = new InstructionTableRow(Long.max(0, newAddress), memory);
+               requester.request(() -> updateElement(0));
+       };
 
        public ActiveInstructionPreviewContentProvider(TableViewer viewer)
        {
@@ -18,13 +28,6 @@ public class ActiveInstructionPreviewContentProvider implements InstructionTable
                viewer.setItemCount(1);
        }
 
-       @Override
-       public void activeMicroInstructionChanged(long address)
-       {
-               this.activeRow = new InstructionTableRow(address, memory);
-               viewer.refresh();
-       }
-
        @Override
        public void update(long address)
        {
@@ -34,14 +37,19 @@ public class ActiveInstructionPreviewContentProvider implements InstructionTable
        @Override
        public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
        {
-               if (oldInput != null)
-                       ((MicroInstructionMemory) oldInput).deregisterActiveMicroInstructionChangedListener(this);
-
                memory = (MicroInstructionMemory) newInput;
-               if (memory != null)
+       }
+
+       public void setMachine(Machine newMachine)
+       {
+               if (machine != null)
+                       machine.removeActiveMicroInstructionChangedListener(instChanged);
+
+               machine = newMachine;
+               if (machine != null)
                {
-                       activeMicroInstructionChanged(0);
-                       memory.registerActiveMicroInstructionChangedListener(this);
+                       instChanged.instructionChanged(-1, 0);
+                       machine.addActiveMicroInstructionChangedListener(instChanged);
                }
        }
 
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/ColorProvider.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/ColorProvider.java
new file mode 100644 (file)
index 0000000..0a1dc0c
--- /dev/null
@@ -0,0 +1,122 @@
+package net.mograsim.plugin.tables.mi;
+
+import org.eclipse.jface.resource.ColorRegistry;
+import org.eclipse.jface.resource.FontRegistry;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.themes.ITheme;
+import org.eclipse.ui.themes.IThemeManager;
+
+import net.mograsim.machine.mi.MicroInstructionMemory;
+
+public class ColorProvider
+{
+       private final TableViewer viewer;
+       private final IThemeManager themeManager;
+       private long highlightedAddress = -1;
+       private ColorRegistry cRegistry;
+       private FontRegistry fRegistry;
+       private Font boldItalic;
+
+       private final static String font = "net.mograsim.plugin.table_font",
+                       colorModifBackground = "net.mograsim.plugin.modified_cell_bg_color",
+                       colorModifForeground = "net.mograsim.plugin.modified_cell_fg_color",
+                       colorHighlightedForeground = "net.mograsim.plugin.highlighted_cell_fg_color",
+                       colorHighlightedBackground = "net.mograsim.plugin.highlighted_cell_bg_color";
+       private final IPropertyChangeListener updateListener;
+
+       public ColorProvider(TableViewer viewer, IThemeManager themeManager)
+       {
+               this.viewer = viewer;
+               this.themeManager = themeManager;
+               themeChanged(themeManager.getCurrentTheme());
+               updateListener = e ->
+               {
+                       switch (e.getProperty())
+                       {
+                       case IThemeManager.CHANGE_CURRENT_THEME:
+                               themeChanged(themeManager.getCurrentTheme());
+                               //$FALL-THROUGH$
+                       case font:
+                       case colorModifBackground:
+                       case colorModifForeground:
+                               viewer.refresh();
+                               break;
+                       default:
+                               break;
+                       }
+               };
+               themeManager.addPropertyChangeListener(updateListener);
+       }
+
+       private void themeChanged(ITheme theme)
+       {
+               cRegistry = theme.getColorRegistry();
+               fRegistry = theme.getFontRegistry();
+               boldItalic = fRegistry.getDescriptor(font).setStyle(SWT.BOLD | SWT.ITALIC).createFont(Display.getDefault());
+       }
+
+       public Color getBackground(Object element, int column)
+       {
+               InstructionTableRow row = (InstructionTableRow) element;
+               if (isDefault(row, column))
+               {
+                       if (isHighlighted(row))
+                               return cRegistry.get(colorHighlightedBackground);
+                       return viewer.getTable().getBackground();
+               }
+               return cRegistry.get(colorModifBackground);
+       }
+
+       public Color getForeground(Object element, int column)
+       {
+               InstructionTableRow row = (InstructionTableRow) element;
+               if (isDefault(row, column))
+               {
+                       if (isHighlighted(row))
+                               return cRegistry.get(colorHighlightedForeground);
+                       return viewer.getTable().getForeground();
+               }
+               return cRegistry.get(colorModifForeground);
+       }
+
+       public Font getFont(Object element, int column)
+       {
+               InstructionTableRow row = (InstructionTableRow) element;
+               boolean modified = !isDefault(row, column), highlighted = isHighlighted(row);
+               if (modified && highlighted)
+                       return boldItalic;
+               if (modified)
+                       return fRegistry.getItalic(font);
+               if (highlighted)
+                       return fRegistry.getBold(font);
+               return fRegistry.get(font);
+       }
+
+       private static boolean isDefault(InstructionTableRow row, int column)
+       {
+               return column == -1 ? true : row.data.getCell(row.address).getParameter(column).isDefault();
+       }
+
+       private boolean isHighlighted(InstructionTableRow row)
+       {
+               return highlightedAddress == row.address;
+       }
+
+       /**
+        * @param index Index of the row to highlight; An negative index means no row is highlighted
+        */
+       public void highlight(long row)
+       {
+               highlightedAddress = row + ((MicroInstructionMemory) viewer.getInput()).getDefinition().getMinimalAddress();
+       }
+
+       public void dispose()
+       {
+               themeManager.removePropertyChangeListener(updateListener);
+       }
+}
index afa7f40..a806bd2 100644 (file)
@@ -12,11 +12,14 @@ import org.eclipse.jface.viewers.TableViewerColumn;
 import org.eclipse.jface.viewers.TableViewerEditor;
 import org.eclipse.jface.viewers.TableViewerFocusCellManager;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.themes.IThemeManager;
 
 import net.mograsim.machine.mi.MicroInstructionDefinition;
 import net.mograsim.machine.mi.MicroInstructionMemory;
@@ -28,22 +31,27 @@ import net.mograsim.plugin.tables.LazyTableViewer;
 
 public class InstructionTable
 {
-       protected DisplaySettings displaySettings;
-       protected LazyTableViewer viewer;
+       protected final DisplaySettings displaySettings;
+       protected final LazyTableViewer viewer;
        private TableViewerColumn[] columns = new TableViewerColumn[0];
        private MicroInstructionDefinition miDef;
        private MicroInstructionMemory memory;
        private InstructionTableContentProvider provider;
+       private final RowHighlighter highlighter;
+       private final ColorProvider cProv;
 
-       public InstructionTable(Composite parent, DisplaySettings displaySettings)
+       public InstructionTable(Composite parent, DisplaySettings displaySettings, IThemeManager themeManager)
        {
                viewer = new LazyTableViewer(parent, SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
                this.displaySettings = displaySettings;
+               this.cProv = new ColorProvider(viewer, themeManager);
+               this.highlighter = new RowHighlighter(viewer, cProv);
 
                Table table = viewer.getTable();
                table.setHeaderVisible(true);
                table.setLinesVisible(true);
                viewer.setUseHashlookup(true);
+               table.addDisposeListener(e -> dispose());
 
                TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(viewer, new FocusCellOwnerDrawHighlighter(viewer));
 
@@ -84,7 +92,26 @@ public class InstructionTable
 
                TableViewerColumn col = createTableViewerColumn("Address");
                columns[0] = col;
-               col.setLabelProvider(new AddressLabelProvider());
+               col.setLabelProvider(new AddressLabelProvider()
+               {
+                       @Override
+                       public Color getBackground(Object element)
+                       {
+                               return cProv.getBackground(element, -1);
+                       }
+
+                       @Override
+                       public Color getForeground(Object element)
+                       {
+                               return cProv.getForeground(element, -1);
+                       }
+
+                       @Override
+                       public Font getFont(Object element)
+                       {
+                               return cProv.getFont(element, -1);
+                       }
+               });
 
                String[] columnTitles = new String[size];
 
@@ -157,15 +184,15 @@ public class InstructionTable
                {
                case BOOLEAN_IMMEDIATE:
                        support = new BooleanEditingSupport(viewer, miDef, index);
-                       provider = new ParameterLabelProvider(index);
+                       provider = new ParameterLabelProvider(cProv, index);
                        break;
                case INTEGER_IMMEDIATE:
                        support = new IntegerEditingSupport(viewer, miDef, index, displaySettings, this.provider);
-                       provider = new IntegerColumnLabelProvider(displaySettings, index);
+                       provider = new IntegerColumnLabelProvider(displaySettings, cProv, index);
                        break;
                case MNEMONIC:
                        support = new MnemonicEditingSupport(viewer, miDef, index, this.provider);
-                       provider = new ParameterLabelProvider(index);
+                       provider = new ParameterLabelProvider(cProv, index);
                        break;
                default:
                        throw new IllegalStateException(
@@ -230,4 +257,15 @@ public class InstructionTable
        {
                Display.getDefault().asyncExec(() -> viewer.refresh());
        }
+
+       private void dispose()
+       {
+               cProv.dispose();
+               viewer.getTable().dispose();
+       }
+
+       public void highlight(int row)
+       {
+               highlighter.highlight(row);
+       }
 }
index 235e3e5..93a7632 100644 (file)
@@ -11,34 +11,61 @@ 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.Display;
 import org.eclipse.ui.IEditorInput;
 import org.eclipse.ui.IEditorSite;
 import org.eclipse.ui.IFileEditorInput;
 import org.eclipse.ui.PartInitException;
 import org.eclipse.ui.part.EditorPart;
 
+import net.mograsim.machine.Machine.ActiveMicroInstructionChangedListener;
 import net.mograsim.machine.Memory.MemoryCellModifiedListener;
 import net.mograsim.machine.mi.AssignableMicroInstructionMemory.MIMemoryReassignedListener;
 import net.mograsim.machine.mi.MicroInstructionMemory;
-import net.mograsim.machine.mi.MicroInstructionMemory.ActiveMicroInstructionChangedListener;
 import net.mograsim.machine.mi.MicroInstructionMemoryParseException;
 import net.mograsim.machine.mi.MicroInstructionMemoryParser;
 import net.mograsim.plugin.nature.MachineContext;
+import net.mograsim.plugin.nature.MachineContext.ActiveMachineListener;
 import net.mograsim.plugin.nature.ProjectMachineContext;
 import net.mograsim.plugin.tables.DisplaySettings;
-import net.mograsim.plugin.tables.LazyTableViewer;
 import net.mograsim.plugin.tables.RadixSelector;
 
-public class InstructionView extends EditorPart implements MemoryCellModifiedListener, ActiveMicroInstructionChangedListener
+public class InstructionView extends EditorPart
 {
        private InstructionTableContentProvider provider;
-       private int highlighted = 0;
        private boolean dirty = false;
        private MicroInstructionMemory memory;
        private InstructionTable table;
        private MachineContext context;
 
+       // Listeners
+       private MemoryCellModifiedListener cellModifiedListener = address ->
+       {
+               setDirty(true);
+               table.refresh();
+       };
+
+       private ActiveMicroInstructionChangedListener instChangeListener = (oldAddress, newAddress) ->
+       {
+               highlight((int) (newAddress - memory.getDefinition().getMinimalAddress()));
+       };
+
+       private MIMemoryReassignedListener reassignedListener = newAssignee ->
+       {
+               // clear highlighting if the memory is reassigned
+               if (newAssignee != memory)
+                       highlight(-1);
+       };
+
+       private ActiveMachineListener activeMachineListener = (oldMachine, newMachine) ->
+       {
+               // clear highlighting if the active machine changes
+               if (newMachine.isEmpty() || !newMachine.equals(oldMachine))
+               {
+                       highlight(-1);
+                       oldMachine.ifPresent(m -> m.getMicroInstructionMemory().deregisterMemoryReassignedListener(reassignedListener));
+               }
+       };
+
        @SuppressWarnings("unused")
        @Override
        public void createPartControl(Composite parent)
@@ -51,8 +78,7 @@ public class InstructionView extends EditorPart implements MemoryCellModifiedLis
                new RadixSelector(parent, displaySettings);
 
                addActivationButton(parent);
-
-               table = new InstructionTable(parent, displaySettings);
+               table = new InstructionTable(parent, displaySettings, getSite().getWorkbenchWindow().getWorkbench().getThemeManager());
                table.setContentProvider(provider);
                table.bindMicroInstructionMemory(memory);
 
@@ -61,21 +87,9 @@ public class InstructionView extends EditorPart implements MemoryCellModifiedLis
                table.getTableViewer().getTable().setLayoutData(viewerData);
        }
 
-       public void highlight(int index)
+       public void highlight(int row)
        {
-               Display.getDefault().asyncExec(() ->
-               {
-                       LazyTableViewer viewer = table.getTableViewer();
-                       viewer.highlightRow(highlighted, false);
-                       highlighted = index;
-                       if (index != -1)
-                       {
-                               viewer.highlightRow(index, true);
-                               viewer.getTable()
-                                               .showItem(viewer.getTable().getItem(Math.min((int) memory.getDefinition().getMaximalAddress(), index + 2)));
-                               viewer.getTable().showItem(viewer.getTable().getItem(index));
-                       }
-               });
+               table.highlight(row);
        }
 
        private void addActivationButton(Composite parent)
@@ -84,23 +98,10 @@ public class InstructionView extends EditorPart implements MemoryCellModifiedLis
                activationButton.setText("Set Active");
                activationButton.addListener(SWT.Selection, e -> context.getActiveMachine().ifPresent(m ->
                {
-                       // clear highlighting if the memory is reassigned
-                       MIMemoryReassignedListener memReassignedListener = n ->
-                       {
-                               if (n != memory)
-                                       highlight(-1);
-                       };
-                       m.getMicroInstructionMemory().registerMemoryReassignedListener(memReassignedListener);
-                       // clear highlighting if the active machine changes
-                       context.addActiveMachineListener(n ->
-                       {
-                               if (n.isEmpty() || n.get() != m)
-                               {
-                                       highlight(-1);
-                                       m.getMicroInstructionMemory().deregisterMemoryReassignedListener(memReassignedListener);
-                               }
-                       });
+                       m.getMicroInstructionMemory().registerMemoryReassignedListener(reassignedListener);
+                       context.addActiveMachineListener(activeMachineListener);
                        m.getMicroInstructionMemory().bind(memory);
+                       m.addActiveMicroInstructionChangedListener(instChangeListener);
                }));
        }
 
@@ -108,14 +109,12 @@ public class InstructionView extends EditorPart implements MemoryCellModifiedLis
        {
                if (this.memory != null)
                {
-                       this.memory.deregisterCellModifiedListener(this);
-                       this.memory.deregisterActiveMicroInstructionChangedListener(this);
+                       this.memory.deregisterCellModifiedListener(cellModifiedListener);
                }
                this.memory = memory;
                if (memory != null)
                {
-                       this.memory.registerCellModifiedListener(this);
-                       this.memory.registerActiveMicroInstructionChangedListener(this);
+                       this.memory.registerCellModifiedListener(cellModifiedListener);
                }
                if (table != null)
                        table.bindMicroInstructionMemory(memory);
@@ -222,13 +221,6 @@ public class InstructionView extends EditorPart implements MemoryCellModifiedLis
                return false;
        }
 
-       @Override
-       public void update(long address)
-       {
-               setDirty(true);
-               table.refresh();
-       }
-
        private void setDirty(boolean value)
        {
                dirty = value;
@@ -236,8 +228,15 @@ public class InstructionView extends EditorPart implements MemoryCellModifiedLis
        }
 
        @Override
-       public void activeMicroInstructionChanged(long address)
+       public void dispose()
        {
-               highlight((int) (address - memory.getDefinition().getMinimalAddress()));
+               memory.deregisterCellModifiedListener(cellModifiedListener);
+               context.getActiveMachine().ifPresent(m ->
+               {
+                       m.removeActiveMicroInstructionChangedListener(instChangeListener);
+                       m.getMicroInstructionMemory().deregisterMemoryReassignedListener(reassignedListener);
+               });
+               context.removeActiveMachineListener(activeMachineListener);
+               super.dispose();
        }
 }
index a2d5087..648eb85 100644 (file)
@@ -2,17 +2,22 @@ package net.mograsim.plugin.tables.mi;
 
 import java.math.BigInteger;
 
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+
 import net.mograsim.machine.mi.parameters.IntegerImmediate;
 import net.mograsim.plugin.tables.DisplaySettings;
 import net.mograsim.plugin.tables.NumberColumnLabelProvider;
 
 public class IntegerColumnLabelProvider extends NumberColumnLabelProvider
 {
-       private int index;
+       private final int index;
+       private final ColorProvider cProv;
 
-       public IntegerColumnLabelProvider(DisplaySettings displaySettings, int index)
+       public IntegerColumnLabelProvider(DisplaySettings displaySettings, ColorProvider cProv, int index)
        {
                super(displaySettings);
+               this.cProv = cProv;
                this.index = index;
        }
 
@@ -30,4 +35,21 @@ public class IntegerColumnLabelProvider extends NumberColumnLabelProvider
                                .getExpectedBits();
        }
 
+       @Override
+       public Color getBackground(Object element)
+       {
+               return cProv.getBackground(element, index);
+       }
+
+       @Override
+       public Color getForeground(Object element)
+       {
+               return cProv.getForeground(element, index);
+       }
+
+       @Override
+       public Font getFont(Object element)
+       {
+               return cProv.getFont(element, index);
+       }
 }
index 46e3ea7..07ae3ae 100644 (file)
@@ -1,15 +1,19 @@
 package net.mograsim.plugin.tables.mi;
 
 import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
 
 public class ParameterLabelProvider extends ColumnLabelProvider
 {
        private final int index;
+       private final ColorProvider cProv;
 
-       public ParameterLabelProvider(int index)
+       public ParameterLabelProvider(ColorProvider cProv, int index)
        {
                super();
                this.index = index;
+               this.cProv = cProv;
        }
 
        @Override
@@ -18,4 +22,22 @@ public class ParameterLabelProvider extends ColumnLabelProvider
                InstructionTableRow row = (InstructionTableRow) element;
                return row.data.getCell(row.address).getParameter(index).toString();
        }
+
+       @Override
+       public Color getBackground(Object element)
+       {
+               return cProv.getBackground(element, index);
+       }
+
+       @Override
+       public Color getForeground(Object element)
+       {
+               return cProv.getForeground(element, index);
+       }
+
+       @Override
+       public Font getFont(Object element)
+       {
+               return cProv.getFont(element, index);
+       }
 }
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/RowHighlighter.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/RowHighlighter.java
new file mode 100644 (file)
index 0000000..03cb37c
--- /dev/null
@@ -0,0 +1,46 @@
+package net.mograsim.plugin.tables.mi;
+
+import java.util.Optional;
+
+import org.eclipse.swt.widgets.Table;
+
+import net.mograsim.plugin.tables.LazyTableViewer;
+import net.mograsim.plugin.util.SingleSWTRequest;
+
+public class RowHighlighter
+{
+       private int highlighted = -1;
+       private LazyTableViewer viewer;
+       private ColorProvider cProv;
+       private SingleSWTRequest requester = new SingleSWTRequest();
+
+       public RowHighlighter(LazyTableViewer viewer, ColorProvider cProv)
+       {
+               this.viewer = viewer;
+               this.cProv = cProv;
+       }
+
+       public void highlight(int row)
+       {
+               requester.request(() ->
+               {
+                       if (!viewer.getTable().isDisposed())
+                               innerHighlight(row);
+               });
+       }
+
+       private void innerHighlight(int row)
+       {
+               Table table = viewer.getTable();
+               cProv.highlight(row);
+               if (row != -1)
+               {
+                       table.showItem(table.getItem(Math.min(table.getItemCount(), row + 2)));
+                       table.showItem(table.getItem(row));
+                       Optional.ofNullable(table.getItem(row).getData()).ifPresent(d -> viewer.update(d, null));
+               }
+               if (highlighted != -1)
+                       Optional.ofNullable(table.getItem(highlighted).getData()).ifPresent(d -> viewer.update(d, null));
+               highlighted = row;
+       }
+}
diff --git a/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/util/SingleSWTRequest.java b/plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/util/SingleSWTRequest.java
new file mode 100644 (file)
index 0000000..fa4d558
--- /dev/null
@@ -0,0 +1,29 @@
+package net.mograsim.plugin.util;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.eclipse.swt.widgets.Display;
+
+public class SingleSWTRequest
+{
+       private AtomicBoolean waiting = new AtomicBoolean();
+
+       public void request(Runnable request)
+       {
+               synchronized (waiting)
+               {
+                       if (!waiting.get())
+                       {
+                               waiting.set(true);
+                               Display.getDefault().asyncExec(() ->
+                               {
+                                       synchronized (waiting)
+                                       {
+                                               waiting.set(false);
+                                               request.run();
+                                       }
+                               });
+                       }
+               }
+       }
+}