From dba8b2731d333a4c72b006e522b611d1a0a00e16 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 14 Oct 2018 17:30:37 +0200 Subject: [PATCH] Added keyboard navigation to scroll, move selection, move selected and zoom --- .../database/swt/internal/WaveformCanvas.java | 40 +++++- .../database/swt/internal/WaveformViewer.java | 110 ++++++++++----- .../scviewer/database/ui/IWaveformViewer.java | 2 + .../e4/application/parts/WaveformViewer.java | 125 ++++++++++++++++++ 4 files changed, 243 insertions(+), 34 deletions(-) diff --git a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformCanvas.java b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformCanvas.java index 815ae84..430e5b7 100644 --- a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformCanvas.java +++ b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformCanvas.java @@ -42,6 +42,7 @@ import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveformEvent; import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.ui.IWaveformViewer; +import com.minres.scviewer.database.ui.TrackEntry; import com.minres.scviewer.database.ui.WaveformColors; public class WaveformCanvas extends Canvas { @@ -181,6 +182,9 @@ public class WaveformCanvas extends Canvas { return origin; } + public int getWidth() { + return getClientArea().width; + } public void setOrigin(Point origin) { setOrigin(origin.x, origin.y); } @@ -292,9 +296,13 @@ public class WaveformCanvas extends Canvas { } public void addWaveformPainter(IWaveformPainter painter) { + addWaveformPainter(painter, true); + } + + void addWaveformPainter(IWaveformPainter painter, boolean update) { trackAreaPainter.addTrackPainter(painter); wave2painterMap.put(painter.getTrackEntry().waveform, painter); - syncScrollBars(); + if(update) syncScrollBars(); } public List getCursorPainters() { @@ -311,7 +319,7 @@ public class WaveformCanvas extends Canvas { super.dispose(); } - /* Initalize the scrollbar and register listeners. */ + /* Initialize the scrollbar and register listeners. */ private void initScrollBars() { ScrollBar horizontal = getHorizontalBar(); horizontal.setEnabled(false); @@ -469,6 +477,27 @@ public class WaveformCanvas extends Canvas { } } + public void reveal(IWaveform waveform) { + for (IWaveformPainter painter : wave2painterMap.values()) { + TrackEntry te = painter.getTrackEntry(); + if(te.waveform == waveform) { + Point size = getSize(); + //size.x -= getVerticalBar().getSize().x + 2; + size.y -=+rulerHeight; + ScrollBar sb = getHorizontalBar(); + if((sb.getStyle()&SWT.SCROLLBAR_OVERLAY)!=0 && sb.isVisible()) // TODO: check on other platform than MacOSX + size.y-= getHorizontalBar().getSize().y; + int top = te.vOffset; + int bottom = top + trackHeight; + if (top < -origin.y) { + setOrigin(origin.x, -(top-trackHeight)); + } else if (bottom > (size.y - origin.y)) { + setOrigin(origin.x, size.y - bottom); + } + } + } + } + public void reveal(long time) { int scaledTime = (int) (time / scaleFactor); Point size = getSize(); @@ -513,4 +542,11 @@ public class WaveformCanvas extends Canvas { } } + long getMaxVisibleTime() { + return (getClientArea().width+origin.x)*scaleFactor; + } + + long getOriginTime() { + return origin.x * scaleFactor; + } } diff --git a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformViewer.java b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformViewer.java index 139e26f..d39f065 100644 --- a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformViewer.java +++ b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformViewer.java @@ -66,6 +66,7 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.ScrollBar; +import org.eclipse.swt.widgets.Widget; import org.eclipse.wb.swt.SWTResourceManager; import com.google.common.collect.Lists; @@ -109,6 +110,8 @@ public class WaveformViewer implements IWaveformViewer { final WaveformCanvas waveformCanvas; + private boolean revealSelected=false; + private Composite top; protected ObservableList streams; @@ -142,12 +145,10 @@ public class WaveformViewer implements IWaveformViewer { @Override public void mouseDown(MouseEvent e) { start=new Point(e.x, e.y); + if((e.stateMask&SWT.MODIFIER_MASK)!=0) return; //don't react on modifier if (e.button == 1) { initialSelected = waveformCanvas.getClicked(start); } else if (e.button == 3) { - List hitted = waveformCanvas.getClicked(start); - if(hitted!=null && hitted.size()>0) - setSelection(new StructuredSelection(hitted)); Menu topMenu= top.getMenu(); if(topMenu!=null) topMenu.setVisible(true); } @@ -155,29 +156,18 @@ public class WaveformViewer implements IWaveformViewer { @Override public void mouseUp(MouseEvent e) { - if (e.button == 1) { + if((e.stateMask&SWT.MODIFIER_MASK&~SWT.SHIFT)!=0) return; //don't react on modifier + if (e.button == 1 && ((e.stateMask&SWT.SHIFT)==0)) { if(Math.abs(e.x-start.x)<3 && Math.abs(e.y-start.y)<3){ - // first set time + // first set cursor time setCursorTime(snapOffsetToEvent(e)); // then set selection and reveal setSelection(new StructuredSelection(initialSelected)); - e.widget.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - waveformCanvas.redraw(); - updateValueList(); - } - }); + asyncUpdate(e.widget); } - }else if (e.button == 2) { + }else if (e.button == 2 ||(e.button==1 && (e.stateMask&SWT.SHIFT)!=0)) { setMarkerTime(snapOffsetToEvent(e), selectedMarker); - e.widget.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - waveformCanvas.redraw(); - updateValueList(); - } - }); + asyncUpdate(e.widget); } } @@ -378,6 +368,18 @@ public class WaveformViewer implements IWaveformViewer { @Override public void propertyChange(PropertyChangeEvent pce) { if ("size".equals(pce.getPropertyName()) || "content".equals(pce.getPropertyName())) { + if(revealSelected) { + waveformCanvas.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + update(); + waveformCanvas.reveal(currentWaveformSelection.waveform); + valueList.redraw(); + nameList.redraw(); + } + }); + revealSelected=false; + } else waveformCanvas.getDisplay().asyncExec(new Runnable() { @Override public void run() { @@ -410,13 +412,14 @@ public class WaveformViewer implements IWaveformViewer { streamEntry.currentValue="---"; painter = new SignalPainter(waveformCanvas, even, streamEntry); } - waveformCanvas.addWaveformPainter(painter); + waveformCanvas.addWaveformPainter(painter, false); trackVerticalOffset.put(trackVerticalHeight, streamEntry); tl.setText(streamEntry.waveform.getFullName()); nameMaxWidth = Math.max(nameMaxWidth, tl.getBounds().width); trackVerticalHeight += streamEntry.height; even = !even; } + waveformCanvas.syncScrollBars(); nameList.setSize(nameMaxWidth + 15, trackVerticalHeight); nameListScrolled.setMinSize(nameMaxWidth + 15, trackVerticalHeight); valueList.setSize(calculateValueWidth(), trackVerticalHeight); @@ -566,9 +569,10 @@ public class WaveformViewer implements IWaveformViewer { */ @Override public ISelection getSelection() { - if (currentTxSelection != null) - return new StructuredSelection(currentTxSelection); - else if (currentWaveformSelection != null) { + if (currentTxSelection != null) { + Object[] elem = {currentTxSelection, currentWaveformSelection}; + return new StructuredSelection(elem); + } else if (currentWaveformSelection != null) { Object[] elem = {currentWaveformSelection.waveform, currentWaveformSelection}; return new StructuredSelection(elem); } else @@ -611,6 +615,7 @@ public class WaveformViewer implements IWaveformViewer { currentWaveformSelection = (TrackEntry) sel; if(currentTxSelection!=null && currentTxSelection.getStream()!=currentWaveformSelection) currentTxSelection=null; + selectionChanged = true; } } @@ -623,6 +628,7 @@ public class WaveformViewer implements IWaveformViewer { } if(currentWaveformSelection!=null) currentWaveformSelection.selected=true; if (selectionChanged) { + waveformCanvas.reveal(currentWaveformSelection.waveform); waveformCanvas.setSelected(currentTxSelection); valueList.redraw(); nameList.redraw(); @@ -646,7 +652,16 @@ public class WaveformViewer implements IWaveformViewer { */ @Override public void moveSelection(GotoDirection direction) { - moveSelection(direction, NEXT_PREV_IN_STREAM) ; + if(direction==GotoDirection.NEXT || direction==GotoDirection.PREV) + moveSelection(direction, NEXT_PREV_IN_STREAM) ; + else { + int idx = streams.indexOf(currentWaveformSelection); + if(direction==GotoDirection.UP && idx>0) { + setSelection(new StructuredSelection(streams.get(idx-1))); + } else if(direction==GotoDirection.DOWN && idx<(streams.size()-1)) { + setSelection(new StructuredSelection(streams.get(idx+1))); + } + } } /* (non-Javadoc) @@ -776,17 +791,21 @@ public class WaveformViewer implements IWaveformViewer { @Override public void moveSelectedTrack(int i) { if(currentWaveformSelection!=null){ - ITx selectedTx=currentTxSelection; - TrackEntry selectedWaveform=currentWaveformSelection; int idx = streams.indexOf(currentWaveformSelection); int newIdx=idx+i; if(newIdx>=0 && newIdx100) percent=100; + int diff = (waveformCanvas.getWidth()*percent)/100; +// ScrollBar sb = waveformCanvas.getHorizontalBar(); +// int x = sb.getSelection(); +// System.out.println("Setting sb to "+ (x+diff)); +// if((x+diff)>0) +// sb.setSelection(x+diff); +// else +// sb.setSelection(0); + Point o = waveformCanvas.getOrigin(); + waveformCanvas.setOrigin(o.x-diff, o.y); + waveformCanvas.redraw(); + } + + public void asyncUpdate(Widget widget) { + widget.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + waveformCanvas.redraw(); + updateValueList(); + } + }); + } } diff --git a/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/IWaveformViewer.java b/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/IWaveformViewer.java index 7f4bd6a..5a4f967 100644 --- a/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/IWaveformViewer.java +++ b/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/IWaveformViewer.java @@ -102,4 +102,6 @@ public interface IWaveformViewer extends PropertyChangeListener, ISelectionProvi public long getBaselineTime(); public void setBaselineTime(Long scale); + + public void scrollHorizontal(int percent); } \ No newline at end of file diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java index 9b76489..7b8ad35 100644 --- a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java @@ -32,6 +32,7 @@ import javax.inject.Named; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.IJobChangeEvent; @@ -56,12 +57,23 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseTrackListener; +import org.eclipse.swt.events.MouseWheelListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; import com.minres.scviewer.database.ITx; import com.minres.scviewer.database.ITxRelation; @@ -237,6 +249,117 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis selectionService.setSelection(event.getSelection()); } }); + waveformPane.getWaveformControl().addMouseTrackListener(new MouseTrackListener() { + + @Override + public void mouseHover(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseExit(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseEnter(MouseEvent e) { + // TODO Auto-generated method stub + + } + }); + + waveformPane.getWaveformControl().addMouseWheelListener(new MouseWheelListener() { + + @Override + public void mouseScrolled(MouseEvent e) { + // TODO Auto-generated method stub + + } + }); + + waveformPane.getWaveformControl().addListener(SWT.KeyDown, new Listener() { + + @Override + public void handleEvent(Event e) { + int state = e.stateMask & SWT.MODIFIER_MASK; + if(Platform.OS_MACOSX.equals(Platform.getOS())) { //swap cammnd and control for MacOSX + if((state&SWT.COMMAND)!=0) { + state&=~SWT.COMMAND; + state|=SWT.CONTROL; + } else if((state&SWT.CONTROL)!=0) { + state&=~SWT.CONTROL; + state|=SWT.COMMAND; + } + } + if(state==SWT.ALT) { + switch(e.keyCode) { + case SWT.ARROW_LEFT: + waveformPane.scrollHorizontal(-100); + return; + case SWT.ARROW_RIGHT: + waveformPane.scrollHorizontal(100); + return; + case SWT.KEYPAD_ADD: + return; + case SWT.KEYPAD_SUBTRACT: + return; + } + } else if(state==SWT.CTRL) { + int zoomlevel = waveformPane.getZoomLevel(); + switch(e.keyCode) { + case '+': + case SWT.KEYPAD_ADD: + if(zoomlevel>0) + waveformPane.setZoomLevel(zoomlevel-1); + return; + case '-': + case SWT.KEYPAD_SUBTRACT: + if(zoomlevel cursors = waveformPane.getCursorList();