Memory Editor is now more intuitive
authorFabian Stemmler <stemmler@in.tum.de>
Fri, 11 Oct 2019 13:17:29 +0000 (15:17 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Fri, 11 Oct 2019 13:29:42 +0000 (15:29 +0200)
Users no longer need to specify the block of memory they want to see.
Instead they can jump to an address or scroll through the table freely.

Issue:
The table does not load new elements when the top or bottom end is
reached with keyboard inputs.

plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/editors/MemoryEditor.java
plugins/net.mograsim.plugin.core/src/net/mograsim/plugin/tables/memory/MemoryTableContentProvider.java

index cddc880..0186780 100644 (file)
@@ -16,9 +16,11 @@ import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Font;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.ScrollBar;
 import org.eclipse.swt.widgets.Table;
 import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.swt.widgets.Text;
@@ -78,8 +80,7 @@ public class MemoryEditor extends EditorPart
                provider = new MemoryTableContentProvider();
                displaySettings = new DisplaySettings();
 
-               parent.setLayout(new GridLayout(7, false));
-
+               parent.setLayout(new GridLayout(8, false));
                createHeader(parent);
                createViewer(parent);
 
@@ -89,48 +90,40 @@ public class MemoryEditor extends EditorPart
        @SuppressWarnings("unused") // RadixSelector and exceptions
        private void createHeader(Composite parent)
        {
-               Label fromLabel = new Label(parent, SWT.NONE);
-               fromLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
-               fromLabel.setText("Address: ");
-
-               Text fromText = new Text(parent, SWT.BORDER);
-               fromText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               Text gotoText = new Text(parent, SWT.BORDER);
+               gotoText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
                NumberVerifyListener vl = new NumberVerifyListener();
-               fromText.addVerifyListener(vl);
-               fromText.setText("0");
-               fromText.addModifyListener(e ->
+               gotoText.addVerifyListener(vl);
+               gotoText.setText("0");
+
+               Runnable gotoAction = () ->
                {
                        try
                        {
-                               provider.setLowerBound(AsmNumberUtil.valueOf(fromText.getText()).longValue());
-                               viewer.refresh();
+                               loadAround((int) (AsmNumberUtil.valueOf(gotoText.getText()).longValue() - provider.getLowerBound()));
+                               viewer.getTable().deselectAll();
                        }
                        catch (NumberFormatException x)
                        {
                                // Nothing to do here
                        }
+               };
+
+               gotoText.addTraverseListener((e) ->
+               {
+                       if (e.detail == SWT.TRAVERSE_RETURN)
+                               gotoAction.run();
                });
-               Label amountLabel = new Label(parent, SWT.NONE);
-               amountLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
-               amountLabel.setText("Number of cells: ");
-               Text amountText = new Text(parent, SWT.BORDER);
-               amountText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               amountText.addVerifyListener(vl);
-               amountText.addModifyListener(e ->
+
+               Button gotoButton = new Button(parent, SWT.PUSH);
+               gotoButton.setText("Go to");
+               gotoButton.addListener(SWT.Selection, e ->
                {
-                       try
-                       {
-                               if (provider != null)
-                                       provider.setAmount(AsmNumberUtil.valueOf(amountText.getText()).intValue());
-                               if (viewer != null)
-                                       viewer.refresh();
-                       }
-                       catch (NumberFormatException x)
-                       {
-                               // Nothing to do here
-                       }
+                       gotoAction.run();
                });
-               amountText.setText("100");// do this after registering the ModifyListener
+
+               new Label(parent, SWT.NONE).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+
                new RadixSelector(parent, displaySettings);
        }
 
@@ -144,8 +137,20 @@ public class MemoryEditor extends EditorPart
                table.setLinesVisible(true);
                viewer.setUseHashlookup(true);
                viewer.setContentProvider(provider);
-               getSite().setSelectionProvider(viewer);// TODO what does this do?
-               viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 7, 1));
+               getSite().setSelectionProvider(viewer);
+               viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 8, 1));
+
+               // TODO: Also support keyboard inputs for flexible scrolling
+               ScrollBar vBar = table.getVerticalBar();
+               vBar.addListener(SWT.Selection, (e) ->
+               {
+                       int sel;
+                       if ((sel = vBar.getSelection()) < vBar.getMinimum() + vBar.getThumb() * 2 || sel > vBar.getMaximum() - vBar.getThumb() * 2)
+                       {
+                               loadAround(table.getTopIndex());
+                               table.deselectAll();
+                       }
+               });
 
                IThemeManager themeManager = getSite().getWorkbenchWindow().getWorkbench().getThemeManager();
                themeManager.addPropertyChangeListener(fontChangeListener = (e) ->
@@ -169,6 +174,27 @@ public class MemoryEditor extends EditorPart
                fontDependent.forEach(c -> c.setFont(newFont));
        }
 
+       private void loadAround(int row)
+       {
+               long prevLb = provider.getLowerBound();
+               long address = prevLb + row;
+               long actualLb = Long.max(address - MemoryTableContentProvider.MAX_VISIBLE_ROWS / 2, memory.getDefinition().getMinimalAddress());
+
+               long prevHb = provider.getUpperBound();
+               // +- 1 row is not really important
+               long actualHb = Long.min(address + MemoryTableContentProvider.MAX_VISIBLE_ROWS / 2, memory.getDefinition().getMaximalAddress());
+
+               if (actualLb != prevLb || actualHb != prevHb)
+               {
+                       Table table = viewer.getTable();
+                       provider.setBounds(actualLb, actualHb);
+                       int rowIndex = (int) (address - actualLb);
+                       if (rowIndex >= 0 && rowIndex < table.getItemCount())
+                               table.showItem(table.getItem(rowIndex));
+                       viewer.refresh();
+               }
+       }
+
        private void createColumns()
        {
                TableViewerColumn addrCol = createTableViewerColumn("Address", 100);
index a27f31f..983e822 100644 (file)
@@ -6,34 +6,35 @@ import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.swt.widgets.Display;
 
 import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.MainMemoryDefinition;
 import net.mograsim.machine.Memory.MemoryCellModifiedListener;
 
 public class MemoryTableContentProvider implements ILazyContentProvider, MemoryCellModifiedListener
 {
-       private long lower;
+       private long lower, upper;
        private TableViewer viewer;
-       private final static int limit = 10_000;
-       private int amount = 0;
+       public final static int MAX_VISIBLE_ROWS = 1_000;
        private MainMemory memory;
 
-       public void setLowerBound(long lower)
+       public void setBounds(long lower, long upper)
        {
                if (memory != null)
-                       this.lower = Long.min(memory.getDefinition().getMaximalAddress(), Long.max(memory.getDefinition().getMinimalAddress(), lower));
-               else
+               {
+                       MainMemoryDefinition definition = memory.getDefinition();
+                       this.lower = Long.min(definition.getMaximalAddress(), Long.max(definition.getMinimalAddress(), lower));
+                       this.upper = Long.max(this.lower, Long.min(definition.getMaximalAddress(), upper));
+               } else
+               {
                        this.lower = lower;
+                       this.upper = Long.max(this.lower, upper);
+               }
                updateItemCount();
        }
 
        public void updateItemCount()
        {
                if (viewer != null)
-                       if (memory != null)
-                       {
-                               long size = memory.getDefinition().getMaximalAddress() - lower;
-                               viewer.setItemCount(size > amount ? amount : (int) size);
-                       } else
-                               viewer.setItemCount(0);
+                       viewer.setItemCount(getAmount());
        }
 
        public long getLowerBound()
@@ -41,21 +42,20 @@ public class MemoryTableContentProvider implements ILazyContentProvider, MemoryC
                return lower;
        }
 
-       public void setAmount(int amount)
+       public long getUpperBound()
        {
-               this.amount = Integer.min(amount, limit);
-               updateItemCount();
+               return upper;
        }
 
        public int getAmount()
        {
-               return amount;
+               return (int) (upper - lower);
        }
 
        @Override
        public void updateElement(int index)
        {
-               if (index < amount)
+               if (index < getAmount())
                {
                        long address = lower + index;
                        if (address <= memory.getDefinition().getMaximalAddress())
@@ -72,7 +72,7 @@ public class MemoryTableContentProvider implements ILazyContentProvider, MemoryC
                        ((MainMemory) oldInput).deregisterCellModifiedListener(this);
                if (memory != null)
                        memory.registerCellModifiedListener(this);
-               setLowerBound(0L);
+               setBounds(0, MAX_VISIBLE_ROWS);
        }
 
        @Override