Added View for micro instruction editor
authorFabian Stemmler <stemmler@in.tum.de>
Mon, 2 Sep 2019 15:14:24 +0000 (17:14 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Mon, 2 Sep 2019 15:14:24 +0000 (17:14 +0200)
16 files changed:
net.mograsim.machine/META-INF/MANIFEST.MF
net.mograsim.machine/src/net/mograsim/machine/MemoryDefinition.java
net.mograsim.machine/src/net/mograsim/machine/mi/MicroprogramMemoryParseException.java [new file with mode: 0644]
net.mograsim.machine/src/net/mograsim/machine/mi/MicroprogramMemoryParser.java
net.mograsim.machine/src/net/mograsim/machine/mi/StandardMicroprogramMemory.java
net.mograsim.plugin.core.nl_de/OSGI-INF/l10n/bundle_de.properties
net.mograsim.plugin.core/OSGI-INF/l10n/bundle.properties
net.mograsim.plugin.core/plugin.xml
net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/BooleanEditingSupport.java [new file with mode: 0644]
net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTableContentProvider.java [new file with mode: 0644]
net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionView.java [new file with mode: 0644]
net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/IntegerEditingSupport.java [new file with mode: 0644]
net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/MnemonicCellEditorValidator.java [new file with mode: 0644]
net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/MnemonicEditingSupport.java [new file with mode: 0644]
net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/ParameterLabelProvider.java [new file with mode: 0644]
net.mograsim.plugin.core/src/net/mograsim/plugin/util/DropDownMenu.java [new file with mode: 0644]

index 518b6a1..dfdcb05 100644 (file)
@@ -12,4 +12,6 @@ Require-Bundle: net.mograsim.logic.core;bundle-version="0.1.0",
 Export-Package: net.mograsim.machine,
  net.mograsim.machine.isa,
  net.mograsim.machine.isa.types,
+ net.mograsim.machine.mi,
+ net.mograsim.machine.mi.parameters,
  net.mograsim.machine.standard.memory
index 5f42d10..78e1e4e 100644 (file)
@@ -34,7 +34,7 @@ public interface MemoryDefinition {
         */
        default long size()
        {
-               return getMaximalAddress() - getMinimalAddress();
+               return getMaximalAddress() - getMinimalAddress() + 1;
        }
        
        public static MemoryDefinition create(int memoryAddressBits, long minimalAddress, long maximalAddress)
diff --git a/net.mograsim.machine/src/net/mograsim/machine/mi/MicroprogramMemoryParseException.java b/net.mograsim.machine/src/net/mograsim/machine/mi/MicroprogramMemoryParseException.java
new file mode 100644 (file)
index 0000000..eea81af
--- /dev/null
@@ -0,0 +1,28 @@
+package net.mograsim.machine.mi;
+
+import net.mograsim.machine.MachineException;
+
+public class MicroprogramMemoryParseException extends MachineException
+{
+
+       /**
+        * 
+        */
+       private static final long serialVersionUID = 6820101808901789906L;
+
+       public MicroprogramMemoryParseException()
+       {
+               super();
+       }
+
+       public MicroprogramMemoryParseException(String message)
+       {
+               super(message);
+       }
+
+       public MicroprogramMemoryParseException(Throwable cause)
+       {
+               super(cause);
+       }
+       
+}
index 065ba15..1e34762 100644 (file)
@@ -7,6 +7,8 @@ import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
 import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
 
 import net.mograsim.logic.core.types.BitVector;
 import net.mograsim.machine.MemoryDefinition;
@@ -21,28 +23,34 @@ import net.mograsim.machine.mi.parameters.ParameterClassification;
 
 public class MicroprogramMemoryParser
 {
-       public static void parse(MicroprogramMemory memory, long startAddress, MicroInstructionDefinition definition, String input) throws IOException
+       public static MicroprogramMemory parseMemory(MicroInstructionDefinition definition, String input) throws IOException
        {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(input))))
                {
-                       parse(memory, startAddress, definition, reader);
+                       return parseMemory(definition, reader);
                }
        }
 
-       public static void parse(MicroprogramMemory memory, long startAddress, MicroInstructionDefinition definition,
-                       BufferedReader input)
+       public static MicroprogramMemory parseMemory(MicroInstructionDefinition definition, BufferedReader input)
        {
-               MemoryDefinition def = memory.getDefinition();
-               long minAddress = Long.max(startAddress, def.getMinimalAddress()), maxAddress = def.getMaximalAddress();
+               List<MicroInstruction> instructions = new ArrayList<>();
                try
                {
                        String line;
-                       for (long i = minAddress; i < maxAddress && input.ready() && !"".equals((line = input.readLine())); i++)
-                               memory.setCell(i, parse(definition, line));
+                       while (input.ready() && !"".equals((line = input.readLine())))
+                               instructions.add(parse(definition, line));
                } catch (IOException e)
                {
                        e.printStackTrace();
                }
+
+               int maxAddress = instructions.size() - 1;
+               MicroprogramMemory memory = MicroprogramMemory
+                               .create(MemoryDefinition.create((int) Math.ceil(Math.log(maxAddress)), 0, maxAddress));
+               int i = 0;
+               for (MicroInstruction inst : instructions)
+                       memory.setCell(i++, inst);
+               return memory;
        }
 
        public static MicroInstruction parse(MicroInstructionDefinition definition, String toParse)
@@ -50,40 +58,46 @@ public class MicroprogramMemoryParser
                int size = definition.size();
                String[] strings = toParse.split(",");
                if (size != strings.length)
-                       throw new IllegalArgumentException(
+                       throw new MicroprogramMemoryParseException(
                                        "String does not match definition! The number of parameters does not match.");
                MicroInstructionParameter[] params = new MicroInstructionParameter[size];
                ParameterClassification[] classes = definition.getParameterClassifications();
-               for (int i = 0; i < size; i++)
+               try
                {
-                       params[i] = classes[i].parse(strings[i]);
+                       for (int i = 0; i < size; i++)
+                       {
+                               params[i] = classes[i].parse(strings[i]);
+                       }
+                       return new StandardMicroInstruction(params);
+               } catch (Exception e)
+               {
+                       throw new MicroprogramMemoryParseException(e.getCause());
                }
-               return new StandardMicroInstruction(params);
        }
-       
-       public static void write(MicroprogramMemory memory, long startAddress, long endAddress, String output) throws IOException
+
+       public static void write(MicroprogramMemory memory, String output) throws IOException
        {
-               try(OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(output)))
+               try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(output)))
                {
-                       write(memory, startAddress, endAddress, writer);
+                       write(memory, writer);
                }
        }
-       
-       public static void write(MicroprogramMemory memory, long startAddress, long endAddress, OutputStreamWriter output) throws IOException
+
+       public static void write(MicroprogramMemory memory, OutputStreamWriter output) throws IOException
        {
                MemoryDefinition def = memory.getDefinition();
-               long min = Long.max(def.getMinimalAddress(), startAddress), max = Long.min(def.getMaximalAddress(), endAddress) + 1;
-               for(long i = min; i < max; i++)
+               long min = def.getMinimalAddress(), max = def.getMaximalAddress() + 1;
+               for (long i = min; i < max; i++)
                {
                        output.write(toCSV(memory.getCell(i)) + "\n");
                }
        }
-       
+
        private static String toCSV(MicroInstruction inst)
        {
                int max = inst.getSize() - 1;
                StringBuilder sb = new StringBuilder();
-               for(int i = 0; i < max; i++)
+               for (int i = 0; i < max; i++)
                {
                        sb.append(inst.getParameter(i).toString());
                        sb.append(",");
@@ -91,4 +105,26 @@ public class MicroprogramMemoryParser
                sb.append(inst.getParameter(max).toString());
                return sb.toString();
        }
+
+       public static void main(String[] args)
+       {
+               MnemonicFamily family = new MnemonicFamily(new MnemonicPair("ZERO", BitVector.SINGLE_0),
+                               new MnemonicPair("ONE", BitVector.SINGLE_1));
+               MicroInstructionDefinition def = MicroInstructionDefinition.create(new BooleanClassification(),
+                               new IntegerClassification(8), family);
+               MicroprogramMemory memory = new StandardMicroprogramMemory(MemoryDefinition.create(4, 0, 16));
+               for (int i = 0; i < 17; i++)
+                       memory.setCell(i, new StandardMicroInstruction(new BooleanImmediate(false),
+                                       new IntegerImmediate(BigInteger.valueOf(i), 8), family.get(i % 2)));
+               try
+               {
+                       write(memory, "test.txt");
+                       MicroprogramMemory newMemory = parseMemory(def, "test.txt");
+                       write(newMemory, "test2.txt");
+               } catch (IOException e)
+               {
+                       e.printStackTrace();
+               }
+
+       }
 }
index a253f22..e06a94d 100644 (file)
@@ -10,7 +10,7 @@ class StandardMicroprogramMemory implements MicroprogramMemory
 {
        private MicroInstruction[] data;
        private MemoryDefinition definition;
-       private HashSet<MemoryObserver> observers;
+       private HashSet<MemoryObserver> observers = new HashSet<>();
        
        StandardMicroprogramMemory(MemoryDefinition definition)
        {
index 6297d7d..5f8222d 100644 (file)
@@ -30,4 +30,5 @@ colorDefinition.label.10 = Simulation Textfarbe
 fontDefinition.label = Assembler Operation Textstil
 view.name.0 = Simulation View
 view.name.1 = Speicher
+view.name.2 = Instruktionseditor
 themeElementCategory.label.0 = Simulation
\ No newline at end of file
index 87fc3ee..856144a 100644 (file)
@@ -30,5 +30,6 @@ colorDefinition.label.10 = Simulation text color
 fontDefinition.label = Assembler Operation Style
 view.name.0 = Simulation View
 view.name.1 = Memory
+view.name.1 = Instruction Editor
 themeElementCategory.label.0 = Simulation
 Bundle-Vendor.0 = Mograsim Team
\ No newline at end of file
index 5932f6d..dccf76c 100644 (file)
       </view>
       <view
             category="net.mograsim.plugin"
-               id="net.mograsim.plugin.memory.MemoryView"
-               class="net.mograsim.plugin.memory.MemoryView"
+               id="net.mograsim.plugin.tables.memory.MemoryView"
+               class="net.mograsim.plugin.tables.memory.MemoryView"
             icon="icons/mograsim/blue-orange/icon_blue-orange_16.png"
                name="%view.name.1">
+      </view>
+            <view
+            category="net.mograsim.plugin"
+               id="net.mograsim.plugin.tables.mi.InstructionView"
+               class="net.mograsim.plugin.tables.mi.InstructionView"
+            icon="icons/mograsim/blue-orange/icon_blue-orange_16.png"
+               name="%view.name.2">
       </view>
    </extension>
    <extension
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/BooleanEditingSupport.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/BooleanEditingSupport.java
new file mode 100644 (file)
index 0000000..7d21714
--- /dev/null
@@ -0,0 +1,50 @@
+package net.mograsim.plugin.tables.mi;
+
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.CheckboxCellEditor;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.TableViewer;
+
+import net.mograsim.machine.mi.MicroInstruction;
+import net.mograsim.machine.mi.parameters.BooleanImmediate;
+
+public class BooleanEditingSupport extends EditingSupport
+{
+       private final CheckboxCellEditor editor;
+       private final TableViewer viewer;
+       private final int index;
+
+       public BooleanEditingSupport(TableViewer viewer, int index)
+       {
+               super(viewer);
+               this.viewer = viewer;
+               editor = new CheckboxCellEditor(viewer.getTable());
+               this.index = index;
+       }
+
+       @Override
+       protected boolean canEdit(Object element)
+       {
+               return true;
+       }
+
+       @Override
+       protected CellEditor getCellEditor(Object element)
+       {
+               return editor;
+       }
+
+       @Override
+       protected Object getValue(Object element)
+       {
+               return ((BooleanImmediate) ((MicroInstruction) element).getParameter(index)).getBooleanValue();
+       }
+
+       @Override
+       protected void setValue(Object element, Object value)
+       {
+               ((MicroInstruction) element).setParameter(index, new BooleanImmediate((Boolean) value));
+               viewer.update(element, null);
+       }
+
+}
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTableContentProvider.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionTableContentProvider.java
new file mode 100644 (file)
index 0000000..00a6f19
--- /dev/null
@@ -0,0 +1,28 @@
+package net.mograsim.plugin.tables.mi;
+
+import org.eclipse.jface.viewers.ILazyContentProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+
+import net.mograsim.machine.mi.MicroprogramMemory;
+
+public class InstructionTableContentProvider implements ILazyContentProvider
+{
+       private TableViewer viewer;
+       private MicroprogramMemory memory;
+
+       @Override
+       public void updateElement(int index)
+       {
+               viewer.replace(memory.getCell(index), index);
+       }
+
+       @Override
+       public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
+       {
+               this.viewer = (TableViewer) viewer;
+               this.memory = (MicroprogramMemory) newInput;
+               if (this.memory != null)
+                       this.viewer.setItemCount((int) memory.size());
+       }
+}
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionView.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/InstructionView.java
new file mode 100644 (file)
index 0000000..0af63e5
--- /dev/null
@@ -0,0 +1,194 @@
+package net.mograsim.plugin.tables.mi;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.part.ViewPart;
+
+import net.mograsim.machine.mi.MicroInstructionDefinition;
+import net.mograsim.machine.mi.MicroprogramMemory;
+import net.mograsim.machine.mi.MicroprogramMemoryParseException;
+import net.mograsim.machine.mi.MicroprogramMemoryParser;
+import net.mograsim.machine.mi.parameters.ParameterClassification;
+import net.mograsim.plugin.asm.AsmNumberUtil.NumberType;
+import net.mograsim.plugin.tables.memory.DisplaySettings;
+import net.mograsim.plugin.util.DropDownMenu;
+import net.mograsim.plugin.util.DropDownMenu.DropDownEntry;
+
+public class InstructionView extends ViewPart
+{
+       private String saveLoc = null;
+       private TableViewer viewer;
+       private TableViewerColumn[] columns = new TableViewerColumn[0];
+       private MicroInstructionDefinition miDef;
+       private MicroprogramMemory memory;
+
+       @Override
+       public void createPartControl(Composite parent)
+       {
+               InstructionTableContentProvider provider = new InstructionTableContentProvider();
+               GridLayout layout = new GridLayout(1, false);
+               setupMenuButtons(parent);
+               parent.setLayout(layout);
+               viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER | SWT.VIRTUAL);
+               Table table = viewer.getTable();
+               table.setHeaderVisible(true);
+               table.setLinesVisible(true);
+               viewer.setUseHashlookup(true);
+               viewer.setContentProvider(provider);
+
+               viewer.getTable().setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH));
+       }
+
+       @SuppressWarnings("unused")
+       private void setupMenuButtons(Composite parent)
+       {
+               DropDownEntry open = new DropDownEntry("Open", (e) ->
+               {
+                       FileDialog d = new FileDialog(parent.getShell(), SWT.NONE);
+                       d.open();
+                       String filename = d.getFileName();
+                       if (!filename.equals(""))
+                               open(d.getFilterPath() + File.separator + filename);
+               });
+
+               DropDownEntry save = new DropDownEntry("Save", (e) ->
+               {
+                       if (saveLoc == null)
+                               openSaveAsDialog(parent);
+                       save(saveLoc);
+               });
+               DropDownEntry saveAs = new DropDownEntry("SaveAs", (e) ->
+               {
+                       openSaveAsDialog(parent);
+                       save(saveLoc);
+               });
+               new DropDownMenu(parent, "File", open, save, saveAs);
+       }
+
+       private void openSaveAsDialog(Composite parent)
+       {
+               FileDialog d = new FileDialog(parent.getShell(), SWT.SAVE);
+               d.open();
+               String filename = d.getFileName();
+               if (!filename.equals(""))
+                       saveLoc = d.getFilterPath() + File.separator + filename;
+       }
+
+       public void bindMicroprogramMemory(MicroprogramMemory memory)
+       {
+               this.memory = memory;
+               viewer.setInput(memory);
+       }
+
+       public void bindMicroInstructionDef(MicroInstructionDefinition miDef)
+       {
+               this.miDef = miDef;
+               createColumns();
+       }
+
+       private void createColumns()
+       {
+               for (TableViewerColumn col : columns)
+                       col.getColumn().dispose();
+               int size = miDef.size();
+               int bit = 0;
+               columns = new TableViewerColumn[size];
+               ParameterClassification[] classes = miDef.getParameterClassifications();
+
+               for (int i = 0; i < size; i++)
+               {
+                       int startBit = bit;
+                       int endBit = (bit = bit + classes[i].getExpectedBits()) - 1;
+                       String name = startBit == endBit ? Integer.toString(startBit) : startBit + "..." + endBit;
+                       int bounds = 20 + 20 * classes[i].getExpectedBits();
+
+                       TableViewerColumn col = createTableViewerColumn(name, bounds);
+                       col.setLabelProvider(new ParameterLabelProvider(i));
+                       col.setEditingSupport(createEditingSupport(miDef, i));
+               }
+
+       }
+
+       private EditingSupport createEditingSupport(MicroInstructionDefinition miDef, int index)
+       {
+               ParameterClassification parameterClassification = miDef.getParameterClassifications()[index];
+               switch (parameterClassification.getExpectedType())
+               {
+               case BOOLEAN_IMMEDIATE:
+                       return new BooleanEditingSupport(viewer, index);
+               case INTEGER_IMMEDIATE:
+                       return new IntegerEditingSupport(viewer, miDef, index, new DisplaySettings(NumberType.DECIMAL));
+               case MNEMONIC:
+                       return new MnemonicEditingSupport(viewer, miDef, index);
+               default:
+                       throw new IllegalStateException(
+                                       "Unable to create EditingSupport for unknown ParameterType " + parameterClassification.getExpectedType());
+               }
+       }
+
+       private TableViewerColumn createTableViewerColumn(String title, int bound)
+       {
+               TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
+               TableColumn column = viewerColumn.getColumn();
+               column.setText(title);
+               column.setWidth(bound);
+               column.setResizable(true);
+               column.setMoveable(false);
+               return viewerColumn;
+       }
+
+       private void open(String file)
+       {
+               if (miDef == null)
+               {
+                       System.err.println("Failed to parse MicroprogrammingMemory from File. No MicroInstructionDefinition assigned.");
+                       return;
+               }
+               try
+               {
+                       MicroprogramMemory newMemory = MicroprogramMemoryParser.parseMemory(miDef, file);
+                       bindMicroprogramMemory(newMemory);
+                       saveLoc = file;
+               }
+               catch (IOException | MicroprogramMemoryParseException e)
+               {
+                       e.printStackTrace();
+               }
+       }
+
+       private void save(String file)
+       {
+               if (memory == null)
+               {
+                       System.err.println("Failed to write MicroprogrammingMemory to File. No MicroprogrammingMemory assigned.");
+               }
+               if (saveLoc != null)
+               {
+                       try
+                       {
+                               MicroprogramMemoryParser.write(memory, file);
+                       }
+                       catch (IOException e)
+                       {
+                               e.printStackTrace();
+                       }
+               }
+       }
+
+       @Override
+       public void setFocus()
+       {
+               viewer.getControl().setFocus();
+       }
+}
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/IntegerEditingSupport.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/IntegerEditingSupport.java
new file mode 100644 (file)
index 0000000..43d6041
--- /dev/null
@@ -0,0 +1,38 @@
+package net.mograsim.plugin.tables.mi;
+
+import java.math.BigInteger;
+
+import org.eclipse.jface.viewers.TableViewer;
+
+import net.mograsim.machine.mi.MicroInstruction;
+import net.mograsim.machine.mi.MicroInstructionDefinition;
+import net.mograsim.machine.mi.parameters.IntegerClassification;
+import net.mograsim.machine.mi.parameters.IntegerImmediate;
+import net.mograsim.plugin.tables.NumberCellEditingSupport;
+import net.mograsim.plugin.tables.memory.DisplaySettings;
+
+public class IntegerEditingSupport extends NumberCellEditingSupport
+{
+       private IntegerClassification classification;
+       private int index;
+
+       public IntegerEditingSupport(TableViewer viewer, MicroInstructionDefinition miDef, int index, DisplaySettings displaySettings)
+       {
+               super(viewer, displaySettings);
+               classification = (IntegerClassification) miDef.getParameterClassifications()[index];
+               this.index = index;
+       }
+
+       @Override
+       protected void setAsBigInteger(Object element, BigInteger value)
+       {
+               ((MicroInstruction) element).setParameter(index, new IntegerImmediate(value, classification.getExpectedBits()));
+       }
+
+       @Override
+       protected BigInteger getAsBigInteger(Object element)
+       {
+               return ((IntegerImmediate) ((MicroInstruction) element).getParameter(index)).getValueAsBigInteger();
+       }
+
+}
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/MnemonicCellEditorValidator.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/MnemonicCellEditorValidator.java
new file mode 100644 (file)
index 0000000..98181c4
--- /dev/null
@@ -0,0 +1,24 @@
+package net.mograsim.plugin.tables.mi;
+
+import org.eclipse.jface.viewers.ICellEditorValidator;
+
+import net.mograsim.machine.mi.parameters.MnemonicFamily;
+
+public class MnemonicCellEditorValidator implements ICellEditorValidator
+{
+       private MnemonicFamily family;
+
+       public MnemonicCellEditorValidator(MnemonicFamily family)
+       {
+               this.family = family;
+       }
+
+       @Override
+       public String isValid(Object value)
+       {
+               int index = (Integer) value;
+               return index >= 0 && index < family.size() ? null
+                               : String.format("MnemonicFamily has %s elements, index %s is out of bounds", family.size(), value.toString());
+       }
+
+}
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/MnemonicEditingSupport.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/MnemonicEditingSupport.java
new file mode 100644 (file)
index 0000000..9530c20
--- /dev/null
@@ -0,0 +1,56 @@
+package net.mograsim.plugin.tables.mi;
+
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ComboBoxCellEditor;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.SWT;
+
+import net.mograsim.machine.mi.MicroInstruction;
+import net.mograsim.machine.mi.MicroInstructionDefinition;
+import net.mograsim.machine.mi.parameters.Mnemonic;
+import net.mograsim.machine.mi.parameters.MnemonicFamily;
+
+public class MnemonicEditingSupport extends EditingSupport
+{
+       private final ComboBoxCellEditor editor;
+       private final MnemonicFamily family;
+       private final TableViewer viewer;
+       private final int index;
+
+       public MnemonicEditingSupport(TableViewer viewer, MicroInstructionDefinition definition, int index)
+       {
+               super(viewer);
+               this.viewer = viewer;
+               family = (MnemonicFamily) definition.getParameterClassifications()[index];
+               editor = new ComboBoxCellEditor(viewer.getTable(), family.getStringValues(), SWT.READ_ONLY);
+               this.index = index;
+               editor.setValidator(new MnemonicCellEditorValidator(family));
+       }
+
+       @Override
+       protected boolean canEdit(Object element)
+       {
+               return true;
+       }
+
+       @Override
+       protected CellEditor getCellEditor(Object element)
+       {
+               return editor;
+       }
+
+       @Override
+       protected Object getValue(Object element)
+       {
+               return ((Mnemonic) ((MicroInstruction) element).getParameter(index)).ordinal();
+       }
+
+       @Override
+       protected void setValue(Object element, Object value)
+       {
+               ((MicroInstruction) element).setParameter(index, family.get((Integer) value));
+               viewer.update(element, null);
+       }
+
+}
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/ParameterLabelProvider.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/mi/ParameterLabelProvider.java
new file mode 100644 (file)
index 0000000..b4acd15
--- /dev/null
@@ -0,0 +1,22 @@
+package net.mograsim.plugin.tables.mi;
+
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+
+import net.mograsim.machine.mi.MicroInstruction;
+
+public class ParameterLabelProvider extends ColumnLabelProvider
+{
+       private final int index;
+
+       public ParameterLabelProvider(int index)
+       {
+               super();
+               this.index = index;
+       }
+
+       @Override
+       public String getText(Object element)
+       {
+               return ((MicroInstruction) element).getParameter(index).toString();
+       }
+}
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/util/DropDownMenu.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/util/DropDownMenu.java
new file mode 100644 (file)
index 0000000..ffa1857
--- /dev/null
@@ -0,0 +1,86 @@
+package net.mograsim.plugin.util;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+
+public class DropDownMenu
+{
+       private Button button;
+
+       public DropDownMenu(Composite parent, String label, DropDownEntry... entries)
+       {
+               button = new Button(parent, SWT.PUSH);
+               button.setText(label);
+               setupDrowpDownMenu(entries);
+       }
+
+       private void setupDrowpDownMenu(DropDownEntry[] entries)
+       {
+               Menu menu = new Menu(button);
+               for (DropDownEntry entry : entries)
+               {
+                       MenuItem item = new MenuItem(menu, SWT.PUSH);
+                       item.addSelectionListener(new SelectionListener()
+                       {
+                               @Override
+                               public void widgetSelected(SelectionEvent e)
+                               {
+                                       entry.listener.widgetSelected(e);
+                               }
+
+                               @Override
+                               public void widgetDefaultSelected(SelectionEvent e)
+                               {
+                                       widgetSelected(e);
+                               }
+                       });
+                       item.setText(entry.title);
+               }
+
+               button.addListener(SWT.Selection, new Listener()
+               {
+                       @Override
+                       public void handleEvent(Event event)
+                       {
+                               Rectangle rect = button.getBounds();
+                               Point pt = new Point(rect.x, rect.y + rect.height);
+                               pt = button.getParent().toDisplay(pt);
+                               menu.setLocation(pt.x, pt.y);
+                               menu.setVisible(true);
+                       }
+               });
+       }
+
+       public Button getButton()
+       {
+               return button;
+       }
+
+       public static class DropDownEntry
+       {
+               public final String title;
+               public final EntrySelectedListener listener;
+
+               public DropDownEntry(String title, EntrySelectedListener listener)
+               {
+                       super();
+                       this.title = title;
+                       this.listener = listener;
+               }
+       }
+
+       @FunctionalInterface
+       public static interface EntrySelectedListener
+       {
+               public void widgetSelected(SelectionEvent e);
+       }
+}