Added Memory View to the plugin
authorFabian Stemmler <stemmler@in.tum.de>
Sun, 25 Aug 2019 15:30:07 +0000 (17:30 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Sun, 25 Aug 2019 15:30:07 +0000 (17:30 +0200)
net.mograsim.plugin.core.nl_de/OSGI-INF/l10n/bundle_de.properties
net.mograsim.plugin.core/META-INF/MANIFEST.MF
net.mograsim.plugin.core/OSGI-INF/l10n/bundle.properties
net.mograsim.plugin.core/plugin.xml
net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryCellEditingSupport.java [new file with mode: 0644]
net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryTableContentProvider.java [new file with mode: 0644]
net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryTableRow.java [new file with mode: 0644]
net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryView.java [new file with mode: 0644]
net.mograsim.plugin.core/src/net/mograsim/plugin/memory/NumberCellEditorValidator.java [new file with mode: 0644]
net.mograsim.plugin.core/src/net/mograsim/plugin/memory/NumberVerifyListener.java [new file with mode: 0644]

index ef3435f..6297d7d 100644 (file)
@@ -29,4 +29,5 @@ colorDefinition.label.9 = Simulation Farbe 0
 colorDefinition.label.10 = Simulation Textfarbe
 fontDefinition.label = Assembler Operation Textstil
 view.name.0 = Simulation View
+view.name.1 = Speicher
 themeElementCategory.label.0 = Simulation
\ No newline at end of file
index fa50b3b..02cb0fa 100644 (file)
@@ -22,7 +22,8 @@ Require-Bundle: org.eclipse.core.runtime,
  net.mograsim.logic.model;bundle-version="0.1.0";visibility:=reexport,
  net.mograsim.logic.model.am2900;bundle-version="0.1.0";visibility:=reexport,
  javax.annotation;bundle-version="1.0.0",
- net.mograsim.preferences;bundle-version="0.1.0"
+ net.mograsim.preferences;bundle-version="0.1.0",
+ net.mograsim.machine
 Bundle-RequiredExecutionEnvironment: JavaSE-11
 Automatic-Module-Name: net.mograsim.plugin.core
 Bundle-Vendor: %Bundle-Vendor.0
index d9cb195..87fc3ee 100644 (file)
@@ -29,5 +29,6 @@ colorDefinition.label.9 = Simulation Color 0
 colorDefinition.label.10 = Simulation text color
 fontDefinition.label = Assembler Operation Style
 view.name.0 = Simulation View
+view.name.1 = Memory
 themeElementCategory.label.0 = Simulation
 Bundle-Vendor.0 = Mograsim Team
\ No newline at end of file
index 47d83d2..5932f6d 100644 (file)
             name="%view.name.0"
             restorable="true">
       </view>
+      <view
+            category="net.mograsim.plugin"
+               id="net.mograsim.plugin.memory.MemoryView"
+               class="net.mograsim.plugin.memory.MemoryView"
+            icon="icons/mograsim/blue-orange/icon_blue-orange_16.png"
+               name="%view.name.1">
+      </view>
    </extension>
    <extension
          id="net.mograsim.plugin.nature.mograsimBuilder"
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryCellEditingSupport.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryCellEditingSupport.java
new file mode 100644 (file)
index 0000000..10498f6
--- /dev/null
@@ -0,0 +1,61 @@
+package net.mograsim.plugin.memory;
+
+import java.math.BigInteger;
+
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TextCellEditor;
+
+import net.mograsim.plugin.asm.AsmNumberUtil;
+import net.mograsim.plugin.memory.MemoryView.DisplaySettings;
+
+public class MemoryCellEditingSupport extends EditingSupport
+{
+       private final TableViewer viewer;
+       private final CellEditor editor;
+       private final DisplaySettings displaySettings;
+
+       public MemoryCellEditingSupport(TableViewer viewer, DisplaySettings displaySettings)
+       {
+               super(viewer);
+               this.viewer = viewer;
+               this.displaySettings = displaySettings;
+               editor = new TextCellEditor(viewer.getTable());
+               editor.setValidator(new NumberCellEditorValidator());
+       }
+
+       @Override
+       protected boolean canEdit(Object element)
+       {
+               return true;
+       }
+
+       @Override
+       protected CellEditor getCellEditor(Object element)
+       {
+               return editor;
+       }
+
+       @Override
+       protected Object getValue(Object element)
+       {
+               MemoryTableRow row = (MemoryTableRow) element;
+               return AsmNumberUtil.toString(row.getMemory().getCellAsBigInteger(row.address), displaySettings.getDataNumberType());
+       }
+
+       @Override
+       protected void setValue(Object element, Object userInput)
+       {
+               MemoryTableRow row = (MemoryTableRow) element;
+               try
+               {
+                       row.getMemory().setCellAsBigInteger(row.address, AsmNumberUtil.valueOf((String) userInput));
+               }
+               catch (@SuppressWarnings("unused") NumberFormatException e)
+               {
+                       row.getMemory().setCellAsBigInteger(row.address, BigInteger.valueOf(0));
+               }
+               viewer.update(element, null);
+       }
+}
\ No newline at end of file
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryTableContentProvider.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryTableContentProvider.java
new file mode 100644 (file)
index 0000000..1d553e2
--- /dev/null
@@ -0,0 +1,57 @@
+package net.mograsim.plugin.memory;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+
+import net.mograsim.machine.MainMemory;
+
+public class MemoryTableContentProvider implements IStructuredContentProvider
+{
+       private long lower;
+       private int amount;
+       public final static int limit = 128;
+
+       @Override
+       public Object[] getElements(Object arg0)
+       {
+               if (arg0 == null)
+                       return new Object[0];
+               MainMemory memory = (MainMemory) arg0;
+               lower = Long.max(lower, memory.getDefinition().getMinimalAddress());
+               Object[] rows = new Object[amount];
+               for (int i = 0; i < amount; i++)
+                       rows[i] = new MemoryTableRow(lower + i, memory);
+               return rows;
+       }
+
+       /**
+        * Sets the bounds for the addresses in memory to be provided to the table.
+        * 
+        * @param lower  lower bound for address (inclusive)
+        * @param amount amount of cells to show; limited to {@link MemoryTableContentProvider#limit}
+        */
+       public void setAddressRange(long lower, int amount)
+       {
+               this.lower = lower;
+               this.amount = Integer.min(Integer.max(amount, 0), limit);
+       }
+
+       public void setLowerBound(long lower)
+       {
+               setAddressRange(lower, amount);
+       }
+
+       public void setAmount(int amount)
+       {
+               setAddressRange(lower, amount);
+       }
+
+       public long getLowerBound()
+       {
+               return lower;
+       }
+
+       public int getAmount()
+       {
+               return amount;
+       }
+}
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryTableRow.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryTableRow.java
new file mode 100644 (file)
index 0000000..fa5b626
--- /dev/null
@@ -0,0 +1,20 @@
+package net.mograsim.plugin.memory;
+
+import net.mograsim.machine.MainMemory;
+
+public class MemoryTableRow
+{
+       public final long address;
+       private final MainMemory memory;
+
+       public MemoryTableRow(long address, MainMemory memory)
+       {
+               this.address = address;
+               this.memory = memory;
+       }
+
+       public MainMemory getMemory()
+       {
+               return memory;
+       }
+}
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryView.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/MemoryView.java
new file mode 100644 (file)
index 0000000..dc03e45
--- /dev/null
@@ -0,0 +1,208 @@
+package net.mograsim.plugin.memory;
+
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.VerifyListener;
+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.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.part.ViewPart;
+
+import net.mograsim.machine.DefaultMainMemoryDefinition;
+import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.standard.memory.WordAddressableMemory;
+import net.mograsim.plugin.asm.AsmNumberUtil;
+import net.mograsim.plugin.asm.AsmNumberUtil.NumberType;
+
+public class MemoryView extends ViewPart
+{
+       private TableViewer viewer;
+       private MemoryTableContentProvider provider;
+       private DisplaySettings displaySettings;
+       private String addressFormat;
+
+       @Override
+       public void createPartControl(Composite parent)
+       {
+               // TODO: externalize Strings!
+               provider = new MemoryTableContentProvider();
+               displaySettings = new DisplaySettings();
+               displaySettings.setDataNumberType(NumberType.HEXADECIMAL);
+
+               GridLayout layout = new GridLayout(6, false);
+               parent.setLayout(layout);
+               Label fromLabel = new Label(parent, SWT.NONE);
+               fromLabel.setText("Address: ");
+               Text fromText = new Text(parent, SWT.BORDER | SWT.SEARCH);
+               fromText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL));
+               VerifyListener vl = new NumberVerifyListener();
+               fromText.addVerifyListener(vl);
+               fromText.setText("0");
+               fromText.addModifyListener(e ->
+               {
+                       try
+                       {
+                               provider.setLowerBound(AsmNumberUtil.valueOf(fromText.getText()).longValue());
+                               viewer.refresh();
+                       }
+                       catch (@SuppressWarnings("unused") NumberFormatException ex)
+                       {
+                               // Nothing to do here
+                       }
+//                     fromText.setText(AsmNumberUtil.toString(BigInteger.valueOf(provider.getLowerBound()), NumberType.HEXADECIMAL));
+               });
+
+               Label amountLabel = new Label(parent, SWT.NONE);
+               amountLabel.setText("Number of cells: ");
+               Text amountText = new Text(parent, SWT.BORDER | SWT.SEARCH);
+               amountText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.FILL_HORIZONTAL));
+               amountText.addVerifyListener(vl);
+               amountText.setText("0");
+               amountText.addModifyListener(e ->
+               {
+                       try
+                       {
+                               provider.setAmount(AsmNumberUtil.valueOf(amountText.getText()).intValue());
+                               viewer.refresh();
+                       }
+                       catch (@SuppressWarnings("unused") NumberFormatException ex)
+                       {
+                               // Nothing to do here
+                       }
+//                     amountText.setText(Integer.toString(provider.getAmount()));
+               });
+
+               setupRadixSelector(parent);
+
+               createViewer(parent);
+       }
+
+       private void setupRadixSelector(Composite parent)
+       {
+               Label radixLabel = new Label(parent, SWT.NONE);
+               radixLabel.setText("Radix: ");
+               Combo selectRadix = new Combo(parent, SWT.READ_ONLY);
+
+               String entries[] = new String[] { "Binary", "Octal", "Decimal", "Hexadecimal" };
+               NumberType corTypes[] = new NumberType[] { NumberType.BINARY, NumberType.OCTAL, NumberType.DECIMAL, NumberType.HEXADECIMAL };
+               selectRadix.setItems(entries);
+               selectRadix.addSelectionListener(new SelectionListener()
+               {
+                       @Override
+                       public void widgetSelected(SelectionEvent e)
+                       {
+                               int index = selectRadix.getSelectionIndex();
+                               if (index == -1)
+                                       displaySettings.setDataNumberType(NumberType.HEXADECIMAL);
+                               else
+                               {
+                                       displaySettings.setDataNumberType(corTypes[index]);
+                               }
+                               viewer.refresh();
+                       }
+
+                       @Override
+                       public void widgetDefaultSelected(SelectionEvent e)
+                       {
+                               widgetSelected(e);
+                       }
+               });
+       }
+
+       private void createViewer(Composite parent)
+       {
+               viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
+               createColumns();
+               Table table = viewer.getTable();
+               table.setHeaderVisible(true);
+               table.setLinesVisible(true);
+               viewer.setContentProvider(provider);
+               setMemoryBinding(new WordAddressableMemory(new DefaultMainMemoryDefinition(8, 8, 8L, 256L)));
+               getSite().setSelectionProvider(viewer);
+
+               GridData gd = new GridData();
+               gd.verticalAlignment = GridData.FILL;
+               gd.horizontalSpan = 6;
+               gd.grabExcessHorizontalSpace = true;
+               gd.grabExcessVerticalSpace = true;
+               gd.horizontalAlignment = GridData.FILL;
+               viewer.getControl().setLayoutData(gd);
+       }
+
+       private void createColumns()
+       {
+               String[] titles = { "Address", "Data" };
+               int[] bounds = { 100, 100 };
+
+               TableViewerColumn col = createTableViewerColumn(titles[0], bounds[0]);
+               col.setLabelProvider(new ColumnLabelProvider()
+               {
+                       @Override
+                       public String getText(Object element)
+                       {
+                               MemoryTableRow row = (MemoryTableRow) element;
+                               return String.format(addressFormat, row.address);// TODO: make the string length dependent on memory address length
+                       }
+               });
+
+               col = createTableViewerColumn(titles[1], bounds[1]);
+               col.setLabelProvider(new ColumnLabelProvider()
+               {
+                       @Override
+                       public String getText(Object element)
+                       {
+                               MemoryTableRow row = (MemoryTableRow) element;
+                               return AsmNumberUtil.toString(row.getMemory().getCellAsBigInteger(row.address), displaySettings.getDataNumberType());
+                       }
+               });
+               col.setEditingSupport(new MemoryCellEditingSupport(viewer, displaySettings));
+       }
+
+       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;
+       }
+
+       @Override
+       public void setFocus()
+       {
+               viewer.getControl().setFocus();
+       }
+
+       public void setMemoryBinding(MainMemory m)
+       {
+               int hexAddressLength = Long.toUnsignedString(m.getDefinition().getMaximalAddress(), 16).length();
+               addressFormat = "0x%0" + hexAddressLength + "X";
+               viewer.setInput(m);
+       }
+
+       public static class DisplaySettings
+       {
+               private AsmNumberUtil.NumberType dataNumberType;
+
+               public AsmNumberUtil.NumberType getDataNumberType()
+               {
+                       return dataNumberType;
+               }
+
+               public void setDataNumberType(AsmNumberUtil.NumberType dataNumberType)
+               {
+                       this.dataNumberType = dataNumberType;
+               }
+       }
+}
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/NumberCellEditorValidator.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/NumberCellEditorValidator.java
new file mode 100644 (file)
index 0000000..236eaa0
--- /dev/null
@@ -0,0 +1,17 @@
+package net.mograsim.plugin.memory;
+
+import org.eclipse.jface.viewers.ICellEditorValidator;
+
+import net.mograsim.plugin.asm.AsmNumberUtil;
+
+public class NumberCellEditorValidator implements ICellEditorValidator
+{
+
+       @Override
+       public String isValid(Object value)
+       {
+               return AsmNumberUtil.NumberType.NONE.equals(AsmNumberUtil.getType((String) value)) ? (String) value + "is not a valid number"
+                               : null;
+       }
+
+}
diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/NumberVerifyListener.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/memory/NumberVerifyListener.java
new file mode 100644 (file)
index 0000000..4e5d11c
--- /dev/null
@@ -0,0 +1,26 @@
+package net.mograsim.plugin.memory;
+
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.widgets.Text;
+
+import net.mograsim.plugin.asm.AsmNumberUtil;
+import net.mograsim.plugin.asm.AsmNumberUtil.NumberType;
+
+public class NumberVerifyListener implements VerifyListener
+{
+
+       @Override
+       public void verifyText(VerifyEvent e)
+       {
+               String text = computeModifiedText(e);
+               e.doit = !NumberType.NONE.equals(AsmNumberUtil.prefixOfType(text));
+       }
+
+       private static String computeModifiedText(VerifyEvent e)
+       {
+               String modifiedText = ((Text) e.getSource()).getText();
+               modifiedText = modifiedText.substring(0, e.start).concat(e.text).concat(modifiedText.substring(e.end));
+               return modifiedText;
+       }
+}