Added keyboard navigation to scroll, move selection, move selected and

zoom
This commit is contained in:
Eyck Jentzsch 2018-10-14 17:30:37 +02:00
parent 048fa93b53
commit dba8b2731d
4 changed files with 243 additions and 34 deletions

View File

@ -42,6 +42,7 @@ import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.IWaveformEvent; import com.minres.scviewer.database.IWaveformEvent;
import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.RelationType;
import com.minres.scviewer.database.ui.IWaveformViewer; import com.minres.scviewer.database.ui.IWaveformViewer;
import com.minres.scviewer.database.ui.TrackEntry;
import com.minres.scviewer.database.ui.WaveformColors; import com.minres.scviewer.database.ui.WaveformColors;
public class WaveformCanvas extends Canvas { public class WaveformCanvas extends Canvas {
@ -181,6 +182,9 @@ public class WaveformCanvas extends Canvas {
return origin; return origin;
} }
public int getWidth() {
return getClientArea().width;
}
public void setOrigin(Point origin) { public void setOrigin(Point origin) {
setOrigin(origin.x, origin.y); setOrigin(origin.x, origin.y);
} }
@ -292,9 +296,13 @@ public class WaveformCanvas extends Canvas {
} }
public void addWaveformPainter(IWaveformPainter painter) { public void addWaveformPainter(IWaveformPainter painter) {
addWaveformPainter(painter, true);
}
void addWaveformPainter(IWaveformPainter painter, boolean update) {
trackAreaPainter.addTrackPainter(painter); trackAreaPainter.addTrackPainter(painter);
wave2painterMap.put(painter.getTrackEntry().waveform, painter); wave2painterMap.put(painter.getTrackEntry().waveform, painter);
syncScrollBars(); if(update) syncScrollBars();
} }
public List<CursorPainter> getCursorPainters() { public List<CursorPainter> getCursorPainters() {
@ -311,7 +319,7 @@ public class WaveformCanvas extends Canvas {
super.dispose(); super.dispose();
} }
/* Initalize the scrollbar and register listeners. */ /* Initialize the scrollbar and register listeners. */
private void initScrollBars() { private void initScrollBars() {
ScrollBar horizontal = getHorizontalBar(); ScrollBar horizontal = getHorizontalBar();
horizontal.setEnabled(false); horizontal.setEnabled(false);
@ -469,6 +477,27 @@ public class WaveformCanvas extends Canvas {
} }
} }
public void reveal(IWaveform<? extends IWaveformEvent> 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) { public void reveal(long time) {
int scaledTime = (int) (time / scaleFactor); int scaledTime = (int) (time / scaleFactor);
Point size = getSize(); 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;
}
} }

View File

@ -66,6 +66,7 @@ import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ScrollBar; import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.wb.swt.SWTResourceManager; import org.eclipse.wb.swt.SWTResourceManager;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -109,6 +110,8 @@ public class WaveformViewer implements IWaveformViewer {
final WaveformCanvas waveformCanvas; final WaveformCanvas waveformCanvas;
private boolean revealSelected=false;
private Composite top; private Composite top;
protected ObservableList<TrackEntry> streams; protected ObservableList<TrackEntry> streams;
@ -142,12 +145,10 @@ public class WaveformViewer implements IWaveformViewer {
@Override @Override
public void mouseDown(MouseEvent e) { public void mouseDown(MouseEvent e) {
start=new Point(e.x, e.y); start=new Point(e.x, e.y);
if((e.stateMask&SWT.MODIFIER_MASK)!=0) return; //don't react on modifier
if (e.button == 1) { if (e.button == 1) {
initialSelected = waveformCanvas.getClicked(start); initialSelected = waveformCanvas.getClicked(start);
} else if (e.button == 3) { } else if (e.button == 3) {
List<Object> hitted = waveformCanvas.getClicked(start);
if(hitted!=null && hitted.size()>0)
setSelection(new StructuredSelection(hitted));
Menu topMenu= top.getMenu(); Menu topMenu= top.getMenu();
if(topMenu!=null) topMenu.setVisible(true); if(topMenu!=null) topMenu.setVisible(true);
} }
@ -155,29 +156,18 @@ public class WaveformViewer implements IWaveformViewer {
@Override @Override
public void mouseUp(MouseEvent e) { 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){ 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)); setCursorTime(snapOffsetToEvent(e));
// then set selection and reveal // then set selection and reveal
setSelection(new StructuredSelection(initialSelected)); setSelection(new StructuredSelection(initialSelected));
e.widget.getDisplay().asyncExec(new Runnable() { asyncUpdate(e.widget);
@Override
public void run() {
waveformCanvas.redraw();
updateValueList();
} }
}); }else if (e.button == 2 ||(e.button==1 && (e.stateMask&SWT.SHIFT)!=0)) {
}
}else if (e.button == 2) {
setMarkerTime(snapOffsetToEvent(e), selectedMarker); setMarkerTime(snapOffsetToEvent(e), selectedMarker);
e.widget.getDisplay().asyncExec(new Runnable() { asyncUpdate(e.widget);
@Override
public void run() {
waveformCanvas.redraw();
updateValueList();
}
});
} }
} }
@ -378,6 +368,18 @@ public class WaveformViewer implements IWaveformViewer {
@Override @Override
public void propertyChange(PropertyChangeEvent pce) { public void propertyChange(PropertyChangeEvent pce) {
if ("size".equals(pce.getPropertyName()) || "content".equals(pce.getPropertyName())) { 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() { waveformCanvas.getDisplay().asyncExec(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -410,13 +412,14 @@ public class WaveformViewer implements IWaveformViewer {
streamEntry.currentValue="---"; streamEntry.currentValue="---";
painter = new SignalPainter(waveformCanvas, even, streamEntry); painter = new SignalPainter(waveformCanvas, even, streamEntry);
} }
waveformCanvas.addWaveformPainter(painter); waveformCanvas.addWaveformPainter(painter, false);
trackVerticalOffset.put(trackVerticalHeight, streamEntry); trackVerticalOffset.put(trackVerticalHeight, streamEntry);
tl.setText(streamEntry.waveform.getFullName()); tl.setText(streamEntry.waveform.getFullName());
nameMaxWidth = Math.max(nameMaxWidth, tl.getBounds().width); nameMaxWidth = Math.max(nameMaxWidth, tl.getBounds().width);
trackVerticalHeight += streamEntry.height; trackVerticalHeight += streamEntry.height;
even = !even; even = !even;
} }
waveformCanvas.syncScrollBars();
nameList.setSize(nameMaxWidth + 15, trackVerticalHeight); nameList.setSize(nameMaxWidth + 15, trackVerticalHeight);
nameListScrolled.setMinSize(nameMaxWidth + 15, trackVerticalHeight); nameListScrolled.setMinSize(nameMaxWidth + 15, trackVerticalHeight);
valueList.setSize(calculateValueWidth(), trackVerticalHeight); valueList.setSize(calculateValueWidth(), trackVerticalHeight);
@ -566,9 +569,10 @@ public class WaveformViewer implements IWaveformViewer {
*/ */
@Override @Override
public ISelection getSelection() { public ISelection getSelection() {
if (currentTxSelection != null) if (currentTxSelection != null) {
return new StructuredSelection(currentTxSelection); Object[] elem = {currentTxSelection, currentWaveformSelection};
else if (currentWaveformSelection != null) { return new StructuredSelection(elem);
} else if (currentWaveformSelection != null) {
Object[] elem = {currentWaveformSelection.waveform, currentWaveformSelection}; Object[] elem = {currentWaveformSelection.waveform, currentWaveformSelection};
return new StructuredSelection(elem); return new StructuredSelection(elem);
} else } else
@ -611,6 +615,7 @@ public class WaveformViewer implements IWaveformViewer {
currentWaveformSelection = (TrackEntry) sel; currentWaveformSelection = (TrackEntry) sel;
if(currentTxSelection!=null && currentTxSelection.getStream()!=currentWaveformSelection) if(currentTxSelection!=null && currentTxSelection.getStream()!=currentWaveformSelection)
currentTxSelection=null; currentTxSelection=null;
selectionChanged = true; selectionChanged = true;
} }
} }
@ -623,6 +628,7 @@ public class WaveformViewer implements IWaveformViewer {
} }
if(currentWaveformSelection!=null) currentWaveformSelection.selected=true; if(currentWaveformSelection!=null) currentWaveformSelection.selected=true;
if (selectionChanged) { if (selectionChanged) {
waveformCanvas.reveal(currentWaveformSelection.waveform);
waveformCanvas.setSelected(currentTxSelection); waveformCanvas.setSelected(currentTxSelection);
valueList.redraw(); valueList.redraw();
nameList.redraw(); nameList.redraw();
@ -646,7 +652,16 @@ public class WaveformViewer implements IWaveformViewer {
*/ */
@Override @Override
public void moveSelection(GotoDirection direction) { public void moveSelection(GotoDirection direction) {
if(direction==GotoDirection.NEXT || direction==GotoDirection.PREV)
moveSelection(direction, NEXT_PREV_IN_STREAM) ; 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) /* (non-Javadoc)
@ -776,17 +791,21 @@ public class WaveformViewer implements IWaveformViewer {
@Override @Override
public void moveSelectedTrack(int i) { public void moveSelectedTrack(int i) {
if(currentWaveformSelection!=null){ if(currentWaveformSelection!=null){
ITx selectedTx=currentTxSelection;
TrackEntry selectedWaveform=currentWaveformSelection;
int idx = streams.indexOf(currentWaveformSelection); int idx = streams.indexOf(currentWaveformSelection);
int newIdx=idx+i; int newIdx=idx+i;
if(newIdx>=0 && newIdx<streams.size()){ if(newIdx>=0 && newIdx<streams.size()){
Collections.swap(streams,idx,newIdx); Collections.swap(streams,idx,newIdx);
update(); revealSelected=true;
if(selectedTx!=null){ // update();
setSelection(new StructuredSelection(new Object[]{selectedTx, selectedWaveform.waveform})); // ITx selectedTx=currentTxSelection;
} else // if(selectedTx!=null){
setSelection(new StructuredSelection(selectedWaveform.waveform)); // setSelection(new StructuredSelection(new Object[]{selectedTx, currentWaveformSelection.waveform}));
// } else {
// setSelection(new StructuredSelection(currentWaveformSelection.waveform));
// }
// waveformCanvas.reveal(currentWaveformSelection.waveform);
// valueList.redraw();
// nameList.redraw();
} }
} }
} }
@ -1201,4 +1220,31 @@ public class WaveformViewer implements IWaveformViewer {
origin.x=(int) (-time/waveformCanvas.getScaleFactorPow10()); origin.x=(int) (-time/waveformCanvas.getScaleFactorPow10());
waveformCanvas.setOrigin(origin); waveformCanvas.setOrigin(origin);
} }
@Override
public void scrollHorizontal(int percent) {
if(percent<-100) percent=-100;
if(percent>100) 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();
}
});
}
} }

View File

@ -102,4 +102,6 @@ public interface IWaveformViewer extends PropertyChangeListener, ISelectionProvi
public long getBaselineTime(); public long getBaselineTime();
public void setBaselineTime(Long scale); public void setBaselineTime(Long scale);
public void scrollHorizontal(int percent);
} }

View File

@ -32,6 +32,7 @@ import javax.inject.Named;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeEvent; 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.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent; 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.Point;
import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display; 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.ITx;
import com.minres.scviewer.database.ITxRelation; import com.minres.scviewer.database.ITxRelation;
@ -237,6 +249,117 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis
selectionService.setSelection(event.getSelection()); 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<waveformPane.getZoomLevels().length-1)
waveformPane.setZoomLevel(zoomlevel+1);
return;
case SWT.ARROW_UP:
waveformPane.moveSelectedTrack(-1);
return;
case SWT.ARROW_DOWN:
waveformPane.moveSelectedTrack(1);
return;
}
} else if(state==SWT.SHIFT) {
} else {
switch(e.keyCode) {
case SWT.ARROW_LEFT:
waveformPane.scrollHorizontal(-10);
return;
case SWT.ARROW_RIGHT:
waveformPane.scrollHorizontal(10);
return;
case SWT.ARROW_UP:
waveformPane.moveSelection(GotoDirection.UP);
return;
case SWT.ARROW_DOWN:
waveformPane.moveSelection(GotoDirection.DOWN);
return;
case SWT.HOME: return; //TODO: should be handled
case SWT.END: return; //TODO: should be handled
}
// String string = e.type == SWT.KeyDown ? "DOWN:" : "UP :";
// string += " stateMask=0x" + Integer.toHexString (e.stateMask) + ","; // SWT.CTRL, SWT.ALT, SWT.SHIFT, SWT.COMMAND
// string += " keyCode=0x" + Integer.toHexString (e.keyCode) + ",";
// string += " character=0x" + Integer.toHexString (e.character) ;
// if (e.keyLocation != 0) {
// string += " location=";
// if (e.keyLocation == SWT.LEFT) string += "LEFT";
// if (e.keyLocation == SWT.RIGHT) string += "RIGHT";
// if (e.keyLocation == SWT.KEYPAD) string += "KEYPAD";
// }
// System.out.println (string);
}
}
});
zoomLevel = waveformPane.getZoomLevels(); zoomLevel = waveformPane.getZoomLevels();
setupColors(); setupColors();
checkForUpdates = prefs.getBoolean(PreferenceConstants.DATABASE_RELOAD, true); checkForUpdates = prefs.getBoolean(PreferenceConstants.DATABASE_RELOAD, true);
@ -485,6 +608,8 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis
index = 0; index = 0;
for (TrackEntry trackEntry : waveformPane.getStreamList()) { for (TrackEntry trackEntry : waveformPane.getStreamList()) {
persistedState.put(SHOWN_WAVEFORM + index, trackEntry.waveform.getFullName()); persistedState.put(SHOWN_WAVEFORM + index, trackEntry.waveform.getFullName());
persistedState.put(SHOWN_WAVEFORM + index+".VALUE_DISPLAY", trackEntry.valueDisplay.toString());
persistedState.put(SHOWN_WAVEFORM + index+".WAVE_DISPLAY", trackEntry.waveDisplay.toString());
index++; index++;
} }
List<ICursor> cursors = waveformPane.getCursorList(); List<ICursor> cursors = waveformPane.getCursorList();