From 44812310b0e6c193ac4201d6f7c157909393fe16 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 27 Nov 2021 14:04:06 +0100 Subject: [PATCH] implement continous zoom and removed zoom level status control --- .../scviewer/database/ui/IWaveformView.java | 23 +- .../scviewer/database/ui/IWaveformZoom.java | 24 + .../minres/scviewer/database/ui/ZoomKind.java | 3 + .../scviewer/database/ui/swt/Constants.java | 39 +- .../ui/swt/internal/ArrowPainter.java | 4 +- .../ui/swt/internal/CursorPainter.java | 6 +- .../ui/swt/internal/RulerPainter.java | 51 +- .../ui/swt/internal/SignalPainter.java | 10 +- .../ui/swt/internal/StreamPainter.java | 14 +- .../ui/swt/internal/WaveformCanvas.java | 920 +++++++++--------- .../ui/swt/internal/WaveformView.java | 156 +-- .../e4/application/handlers/ZoomHandler.java | 10 +- .../internal/status/WaveStatusBarControl.java | 18 +- .../e4/application/parts/WaveformViewer.java | 86 +- plugins/com.minres.scviewer.ui/plugin.xml | 172 +--- .../com/minres/scviewer/ui/TxEditorPart.java | 24 +- .../com/minres/scviewer/ui/handler/Zoom.java | 29 +- .../minres/scviewer/ui/handler/ZoomInOut.java | 39 - 18 files changed, 674 insertions(+), 954 deletions(-) create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/IWaveformZoom.java create mode 100644 plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/ZoomKind.java delete mode 100644 plugins/com.minres.scviewer.ui/src/com/minres/scviewer/ui/handler/ZoomInOut.java diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/IWaveformView.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/IWaveformView.java index 2677577..cdc41fc 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/IWaveformView.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/IWaveformView.java @@ -79,23 +79,17 @@ public interface IWaveformView extends PropertyChangeListener, ISelectionProvide public void setHighliteRelation(RelationType relationType); - public long getMaxTime(); - public void setMaxTime(long maxTime); - public void setZoomLevel(int scale); - - public int getZoomLevel(); - public void setCursorTime(long time); - public void setMarkerTime(long time, int index); + public void setMarkerTime(int marker, long time); public long getCursorTime(); - public int getSelectedMarkerId(); + public int getSelectedMarker(); - public long getMarkerTime(int index); + public long getMarkerTime(int marker); public void addPropertyChangeListener(PropertyChangeListener listener); @@ -105,16 +99,8 @@ public interface IWaveformView extends PropertyChangeListener, ISelectionProvide public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener); - public String getScaledTime(long time); - - public String[] getZoomLevels(); - public List getCursorList(); - public long getBaselineTime(); - - public void setBaselineTime(Long scale); - public void scrollHorizontal(int percent); public void scrollTo(int pos); @@ -124,4 +110,7 @@ public interface IWaveformView extends PropertyChangeListener, ISelectionProvide public void deleteSelectedTracks(); public TrackEntry addWaveform(IWaveform waveform, int pos); + + public IWaveformZoom getWaveformZoom(); + } \ No newline at end of file diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/IWaveformZoom.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/IWaveformZoom.java new file mode 100644 index 0000000..bbcaf08 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/IWaveformZoom.java @@ -0,0 +1,24 @@ +package com.minres.scviewer.database.ui; + +public interface IWaveformZoom { + + long getMaxVisibleTime(); + + long getMinVisibleTime(); + + void setMinVisibleTime(long scale); + + long getMaxTime(); + + long getScale(); + + void setScale(long factor); + + void setVisibleRange(long startTime, long endTime); + + void centerAt(long time); + + void zoom(ZoomKind kind); + + String timeToString(long time); +} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/ZoomKind.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/ZoomKind.java new file mode 100644 index 0000000..631d168 --- /dev/null +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/ZoomKind.java @@ -0,0 +1,3 @@ +package com.minres.scviewer.database.ui; + +public enum ZoomKind {IN, OUT, FIT, FULL} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/Constants.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/Constants.java index 73f2ae6..c56add4 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/Constants.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/Constants.java @@ -4,8 +4,8 @@ import java.text.DecimalFormat; public class Constants { - public static final String[] UNIT_STRING={"fs", "ps", "ns", "us", "ms"};//, "s"}; - public static final long[] UNIT_MULTIPLIER={1, 1000, 1000*1000, 1000*1000*1000, 1000*1000*1000*1000, 1000*1000*1000*1000*1000 }; + public static final String[] UNIT_STRING={"fs", "ps", "ns", "us", "ms", "s"}; + public static final long[] UNIT_MULTIPLIER={1l, 1000l, 1000l*1000, 1000l*1000*1000, 1000l*1000*1000*1000, 1000l*1000*1000*1000*1000 }; //public static final int[] UNIT_MULTIPLIER={1, 3, 10, 30, 100, 300}; public static final long[] SCALE_MULTIPLIER={1, 2, 5, 10, 20, 50, 100, 200, 500}; @@ -13,22 +13,35 @@ public class Constants { public static final String CONTENT_PROVIDER_TAG = "TOOLTIP_CONTENT_PROVIDER"; public static final String HELP_PROVIDER_TAG = "TOOLTIP_HELP_PROVIDER"; - public static final DecimalFormat TIME_FORMAT_FS = new DecimalFormat("#"); - public static final DecimalFormat TIME_FORMAT_PS = new DecimalFormat("#"); - public static final DecimalFormat TIME_FORMAT_NS = new DecimalFormat("#.0##"); - public static final DecimalFormat TIME_FORMAT_US = new DecimalFormat("#.0#####"); - public static final DecimalFormat TIME_FORMAT_MS = new DecimalFormat("#.0#####"); - + public static final DecimalFormat TIME_FORMAT_FS = new DecimalFormat("#"); + public static final DecimalFormat TIME_FORMAT_PS = new DecimalFormat("#"); + public static final DecimalFormat TIME_FORMAT_NS = new DecimalFormat("#.0##"); + public static final DecimalFormat TIME_FORMAT_UMS = new DecimalFormat("#.0#####"); + public static final long[] POWERS_OF_TEN = { + 1L, + 10L, + 100L, + 1_000L, + 10_000L, + 100_000L, + 1_000_000L, + 10_000_000L, + 100_000_000L, + 1_000_000_000L, + 10_000_000_000L, + 100_000_000_000L, + 1_000_000_000_000L, + 10_000_000_000_000L, + 100_000_000_000_000L, + 1_000_000_000_000_000L}; - public static DecimalFormat getTimeFormatForLevel(int level) { - switch(level/SCALE_MULTIPLIER.length) { + public static DecimalFormat getTimeFormatForLevel(int idx) { + switch(idx) { case 0: return TIME_FORMAT_FS; case 1: return TIME_FORMAT_PS; case 2: return TIME_FORMAT_NS; - case 3: return TIME_FORMAT_US; - case 4: return TIME_FORMAT_MS; default: - return TIME_FORMAT_FS; + return TIME_FORMAT_UMS; } } private Constants() {} diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ArrowPainter.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ArrowPainter.java index e3426df..155bbd4 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ArrowPainter.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/ArrowPainter.java @@ -75,7 +75,7 @@ public class ArrowPainter implements IPainter { this.tx = newTx; iRect = new LinkedList<>(); oRect = new LinkedList<>(); - scaleFactor = waveCanvas.getScaleFactor(); + scaleFactor = waveCanvas.getScale(); if (tx != null) { calculateGeometries(); } @@ -133,7 +133,7 @@ public class ArrowPainter implements IPainter { Color highliteColor = waveCanvas.styleProvider.getColor(WaveformColors.REL_ARROW_HIGHLITE); if(tx==null) return; - scaleFactor = waveCanvas.getScaleFactor(); + scaleFactor = waveCanvas.getScale(); if(calculateGeometries()) return; int correctionValue = (int)(selectionOffset); diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/CursorPainter.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/CursorPainter.java index 25ff338..a484c78 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/CursorPainter.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/CursorPainter.java @@ -15,7 +15,6 @@ import org.eclipse.swt.graphics.Rectangle; import com.minres.scviewer.database.ui.ICursor; import com.minres.scviewer.database.ui.WaveformColors; -import com.minres.scviewer.database.ui.swt.Constants; public class CursorPainter implements IPainter, ICursor { @@ -66,7 +65,7 @@ public class CursorPainter implements IPainter, ICursor { Rectangle area = proj.unProject(clientRect); if(!waveCanvas.painterList.isEmpty()){ - long scaleFactor=waveCanvas.getScaleFactor(); + long scaleFactor=waveCanvas.getScale(); long beginPos = area.x; maxPosX = area.x + area.width; @@ -84,8 +83,7 @@ public class CursorPainter implements IPainter, ICursor { proj.drawLine(x, top, x, area.y+area.height); proj.setBackground(drawColor); proj.setForeground(textColor); - double dTime=time; - proj.drawText(Constants.getTimeFormatForLevel(waveCanvas.getZoomLevel()).format(dTime/waveCanvas.getScaleFactorPow10())+waveCanvas.getUnitStr(), x+1, top); + proj.drawText(waveCanvas.timeToString(time), x+1, top); } } } diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/RulerPainter.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/RulerPainter.java index 16d6289..d3c7a1e 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/RulerPainter.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/RulerPainter.java @@ -13,6 +13,7 @@ package com.minres.scviewer.database.ui.swt.internal; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.wb.swt.SWTResourceManager; @@ -37,26 +38,26 @@ public class RulerPainter implements IPainter { Color headerBgColor = waveCanvas.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); if(headerBgColor.isDisposed()) headerBgColor=SWTResourceManager.getColor(255,255,255); - String unit=waveCanvas.getUnitStr(); - long unitMultiplier=waveCanvas.getUnitMultiplier(); - long scaleFactor=waveCanvas.getScaleFactor(); - - long startPos=area.x*scaleFactor; - long startVal=startPos - proj.getTranslation().x*scaleFactor; - long endPos=startPos+area.width*scaleFactor; - - long rulerTickMinor = RULER_TICK_MINOR*scaleFactor; - long rulerTickMajor = RULER_TICK_MAJOR*scaleFactor; + + long scaleFactor=waveCanvas.getScale(); + long startTime=waveCanvas.getMinVisibleTime(); + long endTime=waveCanvas.getMaxVisibleTime(); + long multiplier = Constants.POWERS_OF_TEN[waveCanvas.getScaleMagnitude()]; + long rulerTickMinor = RULER_TICK_MINOR*multiplier; + long rulerTickMajor = RULER_TICK_MAJOR*multiplier; + if((endTime-startTime)/rulerTickMinor>area.width/5) { + rulerTickMinor*=10; + rulerTickMajor*=10; + } int minorTickY = waveCanvas.rulerHeight-5; int majorTickY = waveCanvas.rulerHeight-15; int textY=waveCanvas.rulerHeight-30; int baselineY=waveCanvas.rulerHeight - 1; int bottom=waveCanvas.rulerHeight - 2; - long modulo = startVal % rulerTickMinor; - long startMinorIncrPos = startPos+rulerTickMinor-modulo; - long startMinorIncrVal = startVal+rulerTickMinor-modulo; + long startTickTime = startTime+rulerTickMinor-(startTime % rulerTickMinor); + long majorTickDist = rulerTickMajor/scaleFactor; gc.setBackground(waveCanvas.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); gc.fillRectangle(new Rectangle(area.x, area.y, area.width, waveCanvas.rulerHeight)); @@ -64,20 +65,20 @@ public class RulerPainter implements IPainter { gc.fillRectangle(new Rectangle(area.x, area.y, area.width, baselineY)); gc.setForeground(headerFgColor); gc.drawLine(area.x, area.y+bottom, area.x+area.width, area.y+bottom); - boolean allMarker=true; - for (long pos = startMinorIncrPos, tick = startMinorIncrVal; pos < endPos; pos+= rulerTickMinor, tick += rulerTickMinor) { - if ((tick % rulerTickMajor) == 0) { - String text = Constants.getTimeFormatForLevel(waveCanvas.getZoomLevel()).format(tick/scaleFactor*unitMultiplier); - if(text.length()>8) allMarker=false; + int maxTextLength=0; + for (long tickTime = startTickTime; tickTime < endTime; tickTime+= rulerTickMinor) { + if ((tickTime % rulerTickMajor) == 0) { + Point textSize = gc.textExtent(waveCanvas.timeToString(tickTime)); + maxTextLength=textSize.x>maxTextLength?textSize.x:maxTextLength; } } - boolean drawText = true; - for (long pos = startMinorIncrPos, tick = startMinorIncrVal; pos < endPos; pos+= rulerTickMinor, tick += rulerTickMinor) { - int x0Pos = (int) (pos/scaleFactor); - long x0Val = tick/scaleFactor; - if ((tick % rulerTickMajor) == 0) { - if(allMarker || drawText) - gc.drawText(Constants.getTimeFormatForLevel(waveCanvas.getZoomLevel()).format(x0Val*unitMultiplier)+unit, x0Pos, area.y+textY); + boolean drawEvery = majorTickDist>maxTextLength; + boolean drawText=true; + for (long tickTime = startTickTime; tickTime < endTime; tickTime+= rulerTickMinor) { + int x0Pos = (int) (tickTime/scaleFactor) + proj.getTranslation().x; + if ((tickTime % rulerTickMajor) == 0) { + if(drawEvery || drawText) + gc.drawText(waveCanvas.timeToString(tickTime), x0Pos, area.y+textY); gc.drawLine(x0Pos, area.y+majorTickY, x0Pos,area.y+ bottom); drawText=!drawText; } else { diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/SignalPainter.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/SignalPainter.java index 449e884..43a9f2a 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/SignalPainter.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/SignalPainter.java @@ -82,7 +82,7 @@ public class SignalPainter extends TrackPainter { } private int getXPosEnd(long time) { - long ltmp = time / this.waveCanvas.getScaleFactor(); + long ltmp = time / this.waveCanvas.getScale(); return ltmp > maxPosX ? maxPosX : (int) ltmp; } @@ -95,7 +95,7 @@ public class SignalPainter extends TrackPainter { proj.setFillRule(SWT.FILL_EVEN_ODD); proj.fillRectangle(area); - long scaleFactor = this.waveCanvas.getScaleFactor(); + long scaleFactor = this.waveCanvas.getScale(); long beginPos = area.x; long beginTime = beginPos*scaleFactor; long endTime = beginTime + area.width*scaleFactor; @@ -114,7 +114,7 @@ public class SignalPainter extends TrackPainter { yOffsetT = this.waveCanvas.styleProvider.getTrackHeight() / 5 + area.y; yOffsetM = this.waveCanvas.styleProvider.getTrackHeight() / 2 + area.y; yOffsetB = 4 * this.waveCanvas.styleProvider.getTrackHeight() / 5 + area.y; - int xSigChangeBeginVal = Math.max(area.x, (int) (left.time / this.waveCanvas.getScaleFactor())); + int xSigChangeBeginVal = Math.max(area.x, (int) (left.time / this.waveCanvas.getScale())); int xSigChangeBeginPos = area.x; int xSigChangeEndPos = Math.max(area.x, getXPosEnd(right.time)); @@ -127,7 +127,7 @@ public class SignalPainter extends TrackPainter { right.time = endTime; } else { multiple = true; - long eTime = (xSigChangeBeginVal + 1) * this.waveCanvas.getScaleFactor(); + long eTime = (xSigChangeBeginVal + 1) * this.waveCanvas.getScale(); right.set(entries.floorEntry(eTime), endTime); right.time = eTime; } @@ -147,7 +147,7 @@ public class SignalPainter extends TrackPainter { multiple = false; if (xSigChangeEndPos == xSigChangeBeginPos) { multiple = true; - long eTime = (xSigChangeBeginPos + 1) * this.waveCanvas.getScaleFactor(); + long eTime = (xSigChangeBeginPos + 1) * this.waveCanvas.getScale(); EventEntry entry = entries.floorEntry(eTime); if(entry!=null && entry.timestamp> right.time) right.set(entry, endTime); diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/StreamPainter.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/StreamPainter.java index 75780da..64743bf 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/StreamPainter.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/StreamPainter.java @@ -67,7 +67,7 @@ public class StreamPainter extends TrackPainter{ proj.setFillRule(SWT.FILL_EVEN_ODD); proj.fillRectangle(area); - long scaleFactor = this.waveCanvas.getScaleFactor(); + long scaleFactor = this.waveCanvas.getScale(); long beginPos = area.x; long beginTime = beginPos*scaleFactor; long endTime = beginTime + area.width*scaleFactor; @@ -130,8 +130,8 @@ public class StreamPainter extends TrackPainter{ int offset = concurrencyIndex*this.waveCanvas.styleProvider.getTrackHeight(); Rectangle bb = new Rectangle( - (int)(tx.getBeginTime()/this.waveCanvas.getScaleFactor()), area.y+offset+txBase, - (int)((tx.getEndTime()-tx.getBeginTime())/this.waveCanvas.getScaleFactor()), txHeight); + (int)(tx.getBeginTime()/this.waveCanvas.getScale()), area.y+offset+txBase, + (int)((tx.getEndTime()-tx.getBeginTime())/this.waveCanvas.getScale()), txHeight); if(bb.x+bb.widtharea.x+area.width) return; if(bb.width==0){ @@ -155,7 +155,7 @@ public class StreamPainter extends TrackPainter{ public ITx getClicked(Point point) { int lane=point.y/waveCanvas.styleProvider.getTrackHeight(); - EventEntry firstTx=stream.getEvents().floorEntry(point.x*waveCanvas.getScaleFactor()); + EventEntry firstTx=stream.getEvents().floorEntry(point.x*waveCanvas.getScale()); if(firstTx!=null){ do { ITx tx = getTxFromEntry(lane, point.x, firstTx.events); @@ -175,9 +175,9 @@ public class StreamPainter extends TrackPainter{ } protected ITx getTxFromEntry(int lane, int offset, IEvent[] firstTx) { - long timePoint=offset*waveCanvas.getScaleFactor(); - long timePointLow=(offset-5)*waveCanvas.getScaleFactor(); - long timePointHigh=(offset+5)*waveCanvas.getScaleFactor(); + long timePoint=offset*waveCanvas.getScale(); + long timePointLow=(offset-5)*waveCanvas.getScale(); + long timePointHigh=(offset+5)*waveCanvas.getScale(); for(IEvent e:firstTx){ if(e instanceof ITxEvent) { ITxEvent evt = (ITxEvent) e; diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java index 966651b..01d9705 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformCanvas.java @@ -42,32 +42,36 @@ import com.minres.scviewer.database.tx.ITx; import com.minres.scviewer.database.tx.ITxEvent; import com.minres.scviewer.database.ui.IWaveformStyleProvider; import com.minres.scviewer.database.ui.IWaveformView; +import com.minres.scviewer.database.ui.IWaveformZoom; import com.minres.scviewer.database.ui.TrackEntry; +import com.minres.scviewer.database.ui.ZoomKind; import com.minres.scviewer.database.ui.swt.Constants; -public class WaveformCanvas extends Canvas { +public class WaveformCanvas extends Canvas implements IWaveformZoom{ + + public static final long ZOOM_FIT = -2; + + public static final long ZOOM_FULL = -1; - private boolean doubleBuffering = true; - - IWaveformStyleProvider styleProvider; - - private long scaleFactor = 1000000L; // 1ns - - String unit="ns"; - - private int level = 12; - - private long maxTime; - - protected Point origin; /* original size */ - - protected int rulerHeight=40; - - protected List painterList; - - ITx currentSelection; - - private List selectionListeners; + private boolean doubleBuffering = true; + + IWaveformStyleProvider styleProvider; + + private int scaleMagnitude = 6; + + private long scaleFactor = Constants.POWERS_OF_TEN[scaleMagnitude]; + + private long maxTime; + + protected Point origin; /* original size */ + + protected int rulerHeight=40; + + protected List painterList; + + ITx currentSelection; + + private List selectionListeners; private RulerPainter rulerPainter; @@ -78,38 +82,38 @@ public class WaveformCanvas extends Canvas { private List cursorPainters; HashMap wave2painterMap; - /** - * Constructor for ScrollableCanvas. - * - * @param parent - * the parent of this control.super(parent, style | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.V_SCROLL | SWT.H_SCROLL); - * @param style - * the style of this control. - */ - public WaveformCanvas(final Composite parent, int style, IWaveformStyleProvider styleProvider) { - super(parent, style | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.V_SCROLL | SWT.H_SCROLL); - this.styleProvider=styleProvider; - addControlListener(new ControlAdapter() { /* resize listener. */ + /** + * Constructor for ScrollableCanvas. + * + * @param parent + * the parent of this control.super(parent, style | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.V_SCROLL | SWT.H_SCROLL); + * @param style + * the style of this control. + */ + public WaveformCanvas(final Composite parent, int style, IWaveformStyleProvider styleProvider) { + super(parent, style | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.V_SCROLL | SWT.H_SCROLL); + this.styleProvider=styleProvider; + addControlListener(new ControlAdapter() { /* resize listener. */ @Override public void controlResized(ControlEvent event) { - syncScrollBars(); - } - }); - addPaintListener((final PaintEvent event) -> paint(event.gc)); - painterList = new LinkedList<>(); - origin = new Point(0, 0); - selectionListeners = new LinkedList<>(); - cursorPainters= new ArrayList<>(); - wave2painterMap=new HashMap<>(); - - initScrollBars(); + syncScrollBars(); + } + }); + addPaintListener((final PaintEvent event) -> paint(event.gc)); + painterList = new LinkedList<>(); + origin = new Point(0, 0); + selectionListeners = new LinkedList<>(); + cursorPainters= new ArrayList<>(); + wave2painterMap=new HashMap<>(); + + initScrollBars(); // order is important: it is bottom to top - trackAreaPainter=new TrackAreaPainter(this); - painterList.add(trackAreaPainter); - arrowPainter=new ArrowPainter(this, IWaveformView.NEXT_PREV_IN_STREAM); - painterList.add(arrowPainter); - rulerPainter=new RulerPainter(this); - painterList.add(rulerPainter); + trackAreaPainter=new TrackAreaPainter(this); + painterList.add(trackAreaPainter); + arrowPainter=new ArrowPainter(this, IWaveformView.NEXT_PREV_IN_STREAM); + painterList.add(arrowPainter); + rulerPainter=new RulerPainter(this); + painterList.add(rulerPainter); CursorPainter cp = new CursorPainter(this, scaleFactor * 10, cursorPainters.size()-1); painterList.add(cp); cursorPainters.add(cp); @@ -117,95 +121,110 @@ public class WaveformCanvas extends Canvas { painterList.add(marker); cursorPainters.add(marker); wave2painterMap=new HashMap<>(); - } - + } + public void addCursoPainter(CursorPainter cursorPainter){ painterList.add(cursorPainter); cursorPainters.add(cursorPainter); } + + public void setHighliteRelation(RelationType relationType){ + if(arrowPainter!=null){ + boolean redraw = arrowPainter.getHighlightType()!=relationType; + arrowPainter.setHighlightType(relationType); + if(redraw) redraw(); + } + } + + public Point getOrigin() { + return origin; + } + + public int getWidth() { + return getClientArea().width; + } + public void setOrigin(Point origin) { + setOrigin(origin.x, origin.y); + } + + public void setOrigin(int x, int y) { + checkWidget(); + ScrollBar hBar = getHorizontalBar(); + if(x<=0) hBar.setSelection(-x); + x = -hBar.getSelection(); + ScrollBar vBar = getVerticalBar(); + if(y<=0) vBar.setSelection(-y); + y = -vBar.getSelection(); + origin.x = x; + origin.y = y; + syncScrollBars(); + } + + @Override + public long getMaxTime() { + return maxTime; + } + + public void setMaxTime(long maxTime) { + this.maxTime = maxTime; + syncScrollBars(); + } + + @Override + public long getScale() { + return scaleFactor; + } - public void setHighliteRelation(RelationType relationType){ - if(arrowPainter!=null){ - boolean redraw = arrowPainter.getHighlightType()!=relationType; - arrowPainter.setHighlightType(relationType); - if(redraw) redraw(); - } - } - - public Point getOrigin() { - return origin; - } - - public int getWidth() { - return getClientArea().width; - } - public void setOrigin(Point origin) { - setOrigin(origin.x, origin.y); - } - - public void setOrigin(int x, int y) { - checkWidget(); - ScrollBar hBar = getHorizontalBar(); - hBar.setSelection(-x); - x = -hBar.getSelection(); - ScrollBar vBar = getVerticalBar(); - vBar.setSelection(-y); - y = -vBar.getSelection(); - origin.x = x; - origin.y = y; - syncScrollBars(); - } - - public long getMaxTime() { - return maxTime; - } - - public void setMaxTime(long maxTime) { - this.maxTime = maxTime; - syncScrollBars(); - } - - public int getZoomLevel() { - return level; - } - - public int getMaxZoomLevel(){ - return Constants.SCALE_MULTIPLIER.length*Constants.UNIT_STRING.length-1; - } - - public void setZoomLevel(int level) { + @Override + public void setScale(long factor) { long tc=cursorPainters.get(0).getTime(); // cursor time - setZoomLevel(level, tc); - } + setScalingFactor(factor, tc); + } - public void setZoomLevel(int level, long centerTime) { - int maxLevel = findFitZoomLevel(maxTime); - if(level<0) { - if(level<-1) { - long cTime = getCursorPainters().get(0).getTime(); - long time_diff = centerTime>cTime?centerTime-cTime:cTime-centerTime; - level = findFitZoomLevel(time_diff); - centerTime = (centerTime>cTime?cTime:centerTime)+time_diff/2; - } else - level=maxLevel; - if(level<0) level = 0; - } - //FIXME: keep center if zoom-out and cursor is not in view - if(levelcTime?centerTime-cTime:cTime-centerTime; + centerTime = (centerTime>cTime?cTime:centerTime)+time_diff/2; + factor = (time_diff*11/10)/clientAreaWidth; + } else if(factor== ZOOM_FULL) + factor = maxFactor; + } + if(factor==0) + factor=1; + else if(factor>maxFactor) + factor=maxFactor; + if(factor!=scaleFactor || (getMaxVisibleTime()+getMinVisibleTime()/2) != centerTime) { + scaleFactor = factor; + scaleMagnitude = 0; + for(int i=Constants.POWERS_OF_TEN.length-1; i>0; i--) { + if(scaleFactor>=Constants.POWERS_OF_TEN[i]) { + scaleMagnitude = i; + break; + } + } + ITx tx = arrowPainter.getTx(); + arrowPainter.setTx(null); + /* + * xc = tc/oldScaleFactor + * xoffs = xc+origin.x + * xcn = tc/newScaleFactor + * t0n = (xcn-xoffs)*scaleFactor + */ + long xoffs = clientAreaWidth/2; long xcn=centerTime/scaleFactor; // new total x-offset long originX=xcn-xoffs; if(originX>0) { @@ -213,345 +232,356 @@ public class WaveformCanvas extends Canvas { }else { origin.x=0; } - syncScrollBars(); - arrowPainter.setTx(tx); - redraw(); - this.level = level; - } - } - - private int findFitZoomLevel(long duration) { - //get area actually capable of displaying data, i.e. area of the receiver which is capable of displaying data - Rectangle clientArea = getClientArea(); - long clientAreaWidth = clientArea.width; - //try to find existing zoomlevel where scaleFactor*clientAreaWidth >= maxTime, if one is found set it as new zoomlevel - for(int unitIdx=0; unitIdx= duration) - return unitIdx*Constants.SCALE_MULTIPLIER.length+scaleIdx; - } + syncScrollBars(); + arrowPainter.setTx(tx); + redraw(); } - return -1; } - public long getScaleFactor() { - return scaleFactor; - } + @Override + public String timeToString(long time) { + int idx = scaleMagnitude/3; + double fTime = (double)time/Constants.UNIT_MULTIPLIER[idx]; + return Constants.getTimeFormatForLevel(idx).format(fTime)+Constants.UNIT_STRING[idx]; + } - public long getScaleFactorPow10() { - int scale = level/Constants.SCALE_MULTIPLIER.length; - double res = Math.pow(1000, scale); - return (long) res; - } + public long getTimeForOffset(int xOffset){ + return (xOffset-origin.x) * scaleFactor; + } - public String getUnitStr(){ - return Constants.UNIT_STRING[level/Constants.SCALE_MULTIPLIER.length]; - } - - public long getUnitMultiplier(){ - return Constants.SCALE_MULTIPLIER[level%Constants.SCALE_MULTIPLIER.length]; - } - - public long getTimeForOffset(int xOffset){ - return (xOffset-origin.x) * scaleFactor; - } - - public void addPainter(IPainter painter) { - painterList.add(painter); - redraw(); - } + public void addPainter(IPainter painter) { + painterList.add(painter); + redraw(); + } - public void removePainter(IPainter painter) { - painterList.remove(painter); - redraw(); - } + public void removePainter(IPainter painter) { + painterList.remove(painter); + redraw(); + } - public void clearAllWaveformPainter() { - clearAllWaveformPainter(true); - } - - void clearAllWaveformPainter(boolean update) { - trackAreaPainter.trackVerticalOffset.clear(); - wave2painterMap.clear(); - if(update) syncScrollBars(); - } + public void clearAllWaveformPainter() { + clearAllWaveformPainter(true); + } - public void addWaveformPainter(IWaveformPainter painter) { - addWaveformPainter(painter, true); - } - - void addWaveformPainter(IWaveformPainter painter, boolean update) { - trackAreaPainter.addTrackPainter(painter); - wave2painterMap.put(painter.getTrackEntry().waveform, painter); - if(update) syncScrollBars(); - } + void clearAllWaveformPainter(boolean update) { + trackAreaPainter.trackVerticalOffset.clear(); + wave2painterMap.clear(); + if(update) syncScrollBars(); + } - public List getCursorPainters() { + public void addWaveformPainter(IWaveformPainter painter) { + addWaveformPainter(painter, true); + } + + void addWaveformPainter(IWaveformPainter painter, boolean update) { + trackAreaPainter.addTrackPainter(painter); + wave2painterMap.put(painter.getTrackEntry().waveform, painter); + if(update) syncScrollBars(); + } + + public List getCursorPainters() { return cursorPainters; } - /* Initialize the scrollbar and register listeners. */ - private void initScrollBars() { - ScrollBar horizontal = getHorizontalBar(); - horizontal.setEnabled(false); - horizontal.setVisible(true); - horizontal.addSelectionListener(new SelectionAdapter() { + /* Initialize the scrollbar and register listeners. */ + private void initScrollBars() { + ScrollBar horizontal = getHorizontalBar(); + horizontal.setEnabled(false); + horizontal.setVisible(true); + horizontal.addSelectionListener(new SelectionAdapter() { @Override - public void widgetSelected(SelectionEvent event) { - if (painterList.isEmpty()) - return; - setOrigin(-((ScrollBar) event.widget).getSelection(), origin.y); - } - }); - ScrollBar vertical = getVerticalBar(); - vertical.setEnabled(false); - vertical.setVisible(true); - vertical.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + if (painterList.isEmpty()) + return; + setOrigin(-((ScrollBar) event.widget).getSelection(), origin.y); + } + }); + ScrollBar vertical = getVerticalBar(); + vertical.setEnabled(false); + vertical.setVisible(true); + vertical.addSelectionListener(new SelectionAdapter() { @Override - public void widgetSelected(SelectionEvent event) { - if (painterList.isEmpty()) - return; - setOrigin(origin.x, -((ScrollBar) event.widget).getSelection()); - } - }); - } - - /** - * Synchronize the scrollbar with the image. If the transform is out of - * range, it will correct it. This function considers only following factors - * : transform, image size, client area. - */ - public void syncScrollBars() { - if (painterList.isEmpty()) { - redraw(); - return; - } - int height = trackAreaPainter.getHeight(); // incl. Ruler - long width = maxTime / scaleFactor; - Rectangle clientArea=getClientArea(); - ScrollBar horizontal = getHorizontalBar(); - horizontal.setIncrement(getClientArea().width / 100); - horizontal.setPageIncrement(getClientArea().width); - int clientWidthw = clientArea.width; - if (width > clientWidthw) { /* image is wider than client area */ - horizontal.setMinimum(0); - horizontal.setMaximum((int)width); - horizontal.setEnabled(true); - if (-origin.x > horizontal.getMaximum() - clientWidthw) { - origin.x = -horizontal.getMaximum() + clientWidthw; - } - } else { /* image is narrower than client area */ - horizontal.setEnabled(false); - } - horizontal.setThumb(clientWidthw); - horizontal.setSelection(-origin.x); - - ScrollBar vertical = getVerticalBar(); - vertical.setIncrement(getClientArea().height / 100); - vertical.setPageIncrement(getClientArea().height); - int clientHeighth = clientArea.height; - if (height > clientHeighth) { /* image is higher than client area */ - vertical.setMinimum(0); - vertical.setMaximum(height); - vertical.setEnabled(true); - if ( -origin.y > vertical.getMaximum() - clientHeighth) { - origin.y = -vertical.getMaximum() + clientHeighth; - } - } else { /* image is less higher than client area */ - vertical.setMaximum(clientHeighth); - vertical.setEnabled(false); - } - vertical.setThumb(clientHeighth); - vertical.setSelection(-origin.y); - redraw(); - fireSelectionEvent(); - } - - /* Paint function */ - private void paint(GC gc) { - Point pt = getSize(); - if(pt.x==0 || pt.y==0) return; - Rectangle clientRect = getClientArea(); /* Canvas' painting area */ - GC thisGc = gc; - Image dBackingImg = null; - if(doubleBuffering) { - dBackingImg = new Image(getDisplay(), pt.x, pt.y); - thisGc = new GC(dBackingImg); - thisGc.setBackground(gc.getBackground()); - thisGc.setForeground(gc.getForeground()); - thisGc.setFont(gc.getFont()); - - } - Projection p = new Projection(thisGc); - p.setTranslation(origin); - if (!painterList.isEmpty() ) { - for (IPainter painter : painterList) - painter.paintArea(p, clientRect); - } else { - gc.fillRectangle(clientRect); - initScrollBars(); - } - if(doubleBuffering) { - gc.drawImage(dBackingImg, 0, 0); - if(dBackingImg!=null) dBackingImg.dispose(); - thisGc.dispose(); - } - } - - public List getElementsAt(Point point) { - LinkedList result=new LinkedList<>(); - for (IPainter p : Lists.reverse(painterList)) { - if (p instanceof TrackAreaPainter) { - int y = point.y - origin.y; - int x = point.x - origin.x; - Entry entry = trackAreaPainter.trackVerticalOffset.floorEntry(y); - if (entry != null) { - if (entry.getValue() instanceof StreamPainter) { - ITx tx = ((StreamPainter) entry.getValue()).getClicked(new Point(x, y - entry.getKey())); - if(tx!=null) - result.add(tx); - } - result.add(entry.getValue().getTrackEntry()); - } - } else if (p instanceof CursorPainter) { - if (Math.abs(point.x - origin.x - ((CursorPainter) p).getTime()/scaleFactor) < 2) { - result.add(p); - } - } - } - return result; - } - - public List getEntriesAtPosition(IWaveform iWaveform, int i) { - LinkedList result=new LinkedList<>(); - int x = i - origin.x; - for(IWaveformPainter p: wave2painterMap.values()){ - if (p instanceof StreamPainter && ((StreamPainter)p).getStream()==iWaveform) { - result.add(((StreamPainter) p).getClicked(new Point(x, styleProvider.getTrackHeight()/2))); - } - } - return result; - } - - public void setSelected(ITx currentSelection) { - this.currentSelection = currentSelection; - if (currentSelection != null) - reveal(currentSelection); - arrowPainter.setTx(currentSelection); - redraw(); - } - - public void reveal(ITx tx) { - int lower = (int) (tx.getBeginTime() / scaleFactor); - int higher = (int) (tx.getEndTime() / scaleFactor); - Point size = getSize(); - size.x -= getVerticalBar().getSize().x + 2; - size.y -= getHorizontalBar().getSize().y; - if (lower < -origin.x) { - setOrigin(-lower, origin.y); - } else if (higher > (size.x - origin.x)) { - setOrigin(size.x - higher, origin.y); - } - for (IWaveformPainter painter : wave2painterMap.values()) { - if (painter instanceof StreamPainter && ((StreamPainter) painter).getStream() == tx.getStream()) { - EventEntry entry = tx.getStream().getEvents().floorEntry(tx.getBeginTime()); - Optional res = Arrays.stream(entry.events).filter(e -> ((ITxEvent)e).getTransaction().equals(tx)).findFirst(); - if(res.isPresent()) { - int top = painter.getVerticalOffset() + styleProvider.getTrackHeight() * ((ITxEvent)res.get()).getRowIndex(); - int bottom = top + styleProvider.getTrackHeight(); - if (top < -origin.y) { - setOrigin(origin.x, -(top-styleProvider.getTrackHeight())); - } else if (bottom > (size.y - origin.y)) { - setOrigin(origin.x, size.y - bottom); - } - } - } - } - } - - public void reveal(IWaveform waveform) { - for (IWaveformPainter painter : wave2painterMap.values()) { - TrackEntry te = painter.getTrackEntry(); - if(te.waveform == waveform) { - Point size = getSize(); - size.y -=+rulerHeight; - ScrollBar sb = getHorizontalBar(); - if((sb.getStyle()&SWT.SCROLLBAR_OVERLAY)!=0 && sb.isVisible()) - size.y-= getHorizontalBar().getSize().y; - int top = te.vOffset; - int bottom = top + styleProvider.getTrackHeight(); - if (top < -origin.y) { - setOrigin(origin.x, -(top-styleProvider.getTrackHeight())); - } else if (bottom > (size.y - origin.y)) { - setOrigin(origin.x, size.y - bottom); - } - } - } + public void widgetSelected(SelectionEvent event) { + if (painterList.isEmpty()) + return; + setOrigin(origin.x, -((ScrollBar) event.widget).getSelection()); + } + }); } - public void reveal(long time) { - int scaledTime = (int) (time / scaleFactor); - Point size = getSize(); - size.x -= getVerticalBar().getSize().x + 2; - size.y -= getHorizontalBar().getSize().y; - if (scaledTime < -origin.x) { - setOrigin(-scaledTime+10, origin.y); - } else if (scaledTime > (size.x - origin.x)) { - setOrigin(size.x - scaledTime-30, origin.y); - } - } + /** + * Synchronize the scrollbar with the image. If the transform is out of + * range, it will correct it. This function considers only following factors + * : transform, image size, client area. + */ + public void syncScrollBars() { + if (painterList.isEmpty()) { + redraw(); + return; + } + int height = trackAreaPainter.getHeight(); // incl. Ruler + long width = maxTime / scaleFactor; + Rectangle clientArea=getClientArea(); + ScrollBar horizontal = getHorizontalBar(); + horizontal.setIncrement(getClientArea().width / 100); + horizontal.setPageIncrement(getClientArea().width); + int clientWidthw = clientArea.width; + if (width > clientWidthw) { /* image is wider than client area */ + horizontal.setMinimum(0); + horizontal.setMaximum((int)width); + horizontal.setEnabled(true); + if (-origin.x > horizontal.getMaximum() - clientWidthw) { + origin.x = -horizontal.getMaximum() + clientWidthw; + } + } else { /* image is narrower than client area */ + horizontal.setEnabled(false); + } + horizontal.setThumb(clientWidthw); + horizontal.setSelection(-origin.x); - public void centerAt(long time) { - int scaledTime = (int) (time / scaleFactor); - int newX = -scaledTime+getWidth()/2; - setOrigin(newX>0?0:newX, origin.y); - } + ScrollBar vertical = getVerticalBar(); + vertical.setIncrement(getClientArea().height / 100); + vertical.setPageIncrement(getClientArea().height); + int clientHeighth = clientArea.height; + if (height > clientHeighth) { /* image is higher than client area */ + vertical.setMinimum(0); + vertical.setMaximum(height); + vertical.setEnabled(true); + if ( -origin.y > vertical.getMaximum() - clientHeighth) { + origin.y = -vertical.getMaximum() + clientHeighth; + } + } else { /* image is less higher than client area */ + vertical.setMaximum(clientHeighth); + vertical.setEnabled(false); + } + vertical.setThumb(clientHeighth); + vertical.setSelection(-origin.y); + redraw(); + fireSelectionEvent(); + } - public int getRulerHeight() { - return rulerHeight; - } + /* Paint function */ + private void paint(GC gc) { + Point pt = getSize(); + if(pt.x==0 || pt.y==0) return; + Rectangle clientRect = getClientArea(); /* Canvas' painting area */ + GC thisGc = gc; + Image dBackingImg = null; + if(doubleBuffering) { + dBackingImg = new Image(getDisplay(), pt.x, pt.y); + thisGc = new GC(dBackingImg); + thisGc.setBackground(gc.getBackground()); + thisGc.setForeground(gc.getForeground()); + thisGc.setFont(gc.getFont()); - public void setRulerHeight(int rulerHeight) { - this.rulerHeight = rulerHeight; - } + } + Projection p = new Projection(thisGc); + p.setTranslation(origin); + if (!painterList.isEmpty() ) { + for (IPainter painter : painterList) + painter.paintArea(p, clientRect); + } else { + gc.fillRectangle(clientRect); + initScrollBars(); + } + if(doubleBuffering) { + gc.drawImage(dBackingImg, 0, 0); + if(dBackingImg!=null) dBackingImg.dispose(); + thisGc.dispose(); + } + } - public void addSelectionListener(SelectionAdapter selectionAdapter) { - selectionListeners.add(selectionAdapter); - } + public List getElementsAt(Point point) { + LinkedList result=new LinkedList<>(); + for (IPainter p : Lists.reverse(painterList)) { + if (p instanceof TrackAreaPainter) { + int y = point.y - origin.y; + int x = point.x - origin.x; + Entry entry = trackAreaPainter.trackVerticalOffset.floorEntry(y); + if (entry != null) { + if (entry.getValue() instanceof StreamPainter) { + ITx tx = ((StreamPainter) entry.getValue()).getClicked(new Point(x, y - entry.getKey())); + if(tx!=null) + result.add(tx); + } + result.add(entry.getValue().getTrackEntry()); + } + } else if (p instanceof CursorPainter) { + if (Math.abs(point.x - origin.x - ((CursorPainter) p).getTime()/scaleFactor) < 2) { + result.add(p); + } + } + } + return result; + } - public void removeSelectionListener(SelectionAdapter selectionAdapter) { - selectionListeners.remove(selectionAdapter); - } + public List getEntriesAtPosition(IWaveform iWaveform, int i) { + LinkedList result=new LinkedList<>(); + int x = i - origin.x; + for(IWaveformPainter p: wave2painterMap.values()){ + if (p instanceof StreamPainter && ((StreamPainter)p).getStream()==iWaveform) { + result.add(((StreamPainter) p).getClicked(new Point(x, styleProvider.getTrackHeight()/2))); + } + } + return result; + } - /** - * - */ - protected void fireSelectionEvent() { - Event e = new Event(); - e.widget = this; - e.detail=SWT.SELECTED; - e.type=SWT.Selection; - SelectionEvent ev = new SelectionEvent(e); - ev.x = origin.x; - ev.y = origin.y; - for (SelectionAdapter a : selectionListeners) { - a.widgetSelected(ev); - } - } + public void setSelected(ITx currentSelection) { + this.currentSelection = currentSelection; + if (currentSelection != null) + reveal(currentSelection); + arrowPainter.setTx(currentSelection); + redraw(); + } - long getMaxVisibleTime() { - return (getClientArea().width+origin.x)*scaleFactor; - } + public void reveal(ITx tx) { + int lower = (int) (tx.getBeginTime() / scaleFactor); + int higher = (int) (tx.getEndTime() / scaleFactor); + Point size = getSize(); + size.x -= getVerticalBar().getSize().x + 2; + size.y -= getHorizontalBar().getSize().y; + if (lower < -origin.x) { + setOrigin(-lower, origin.y); + } else if (higher > (size.x - origin.x)) { + setOrigin(size.x - higher, origin.y); + } + for (IWaveformPainter painter : wave2painterMap.values()) { + if (painter instanceof StreamPainter && ((StreamPainter) painter).getStream() == tx.getStream()) { + EventEntry entry = tx.getStream().getEvents().floorEntry(tx.getBeginTime()); + Optional res = Arrays.stream(entry.events).filter(e -> ((ITxEvent)e).getTransaction().equals(tx)).findFirst(); + if(res.isPresent()) { + int top = painter.getVerticalOffset() + styleProvider.getTrackHeight() * ((ITxEvent)res.get()).getRowIndex(); + int bottom = top + styleProvider.getTrackHeight(); + if (top < -origin.y) { + setOrigin(origin.x, -(top-styleProvider.getTrackHeight())); + } else if (bottom > (size.y - origin.y)) { + setOrigin(origin.x, size.y - bottom); + } + } + } + } + } - long getMinVisibleTime() { - return origin.x * scaleFactor; - } + public void reveal(IWaveform waveform) { + for (IWaveformPainter painter : wave2painterMap.values()) { + TrackEntry te = painter.getTrackEntry(); + if(te.waveform == waveform) { + Point size = getSize(); + size.y -=+rulerHeight; + ScrollBar sb = getHorizontalBar(); + if((sb.getStyle()&SWT.SCROLLBAR_OVERLAY)!=0 && sb.isVisible()) + size.y-= getHorizontalBar().getSize().y; + int top = te.vOffset; + int bottom = top + styleProvider.getTrackHeight(); + if (top < -origin.y) { + setOrigin(origin.x, -(top-styleProvider.getTrackHeight())); + } 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(); + size.x -= getVerticalBar().getSize().x + 2; + size.y -= getHorizontalBar().getSize().y; + if (scaledTime < -origin.x) { + setOrigin(-scaledTime+10, origin.y); + } else if (scaledTime > (size.x - origin.x)) { + setOrigin(size.x - scaledTime-30, origin.y); + } + } + + @Override + public void centerAt(long time) { + int scaledTime = (int) (time / scaleFactor); + int newX = -scaledTime+getWidth()/2; + setOrigin(newX>0?0:newX, origin.y); + } + + public int getRulerHeight() { + return rulerHeight; + } + + public void setRulerHeight(int rulerHeight) { + this.rulerHeight = rulerHeight; + } + + public void addSelectionListener(SelectionAdapter selectionAdapter) { + selectionListeners.add(selectionAdapter); + } + + public void removeSelectionListener(SelectionAdapter selectionAdapter) { + selectionListeners.remove(selectionAdapter); + } + + /** + * + */ + protected void fireSelectionEvent() { + Event e = new Event(); + e.widget = this; + e.detail=SWT.SELECTED; + e.type=SWT.Selection; + SelectionEvent ev = new SelectionEvent(e); + ev.x = origin.x; + ev.y = origin.y; + for (SelectionAdapter a : selectionListeners) { + a.widgetSelected(ev); + } + } + + + @Override + public long getMaxVisibleTime() { + return (getClientArea().width-origin.x)*scaleFactor; + } + + @Override + public long getMinVisibleTime() { + return -origin.x * scaleFactor; + } + + @Override + public void setMinVisibleTime(long time) { + long duration = getMaxVisibleTime()-getMinVisibleTime(); + if(time>0) { + if((time+duration) index + 1) { - final Long oldVal = waveformCanvas.getCursorPainters().get(1 + index).getTime(); - waveformCanvas.getCursorPainters().get(1 + index).setTime(time); + public void setMarkerTime(int marker, long time) { + if (waveformCanvas.getCursorPainters().size() > marker + 1) { + final Long oldVal = waveformCanvas.getCursorPainters().get(1 + marker).getTime(); + waveformCanvas.getCursorPainters().get(1 + marker).setTime(time); pcs.firePropertyChange(MARKER_PROPERTY, oldVal, time); } } @@ -1224,7 +1164,7 @@ public class WaveformView implements IWaveformView { * @see com.minres.scviewer.database.swt.IWaveformPanel#getActMarkerTime() */ @Override - public int getSelectedMarkerId() { + public int getSelectedMarker() { return selectedMarker; } @@ -1476,58 +1416,16 @@ public class WaveformView implements IWaveformView { return this.pcs.hasListeners(propertyName); } - /* - * (non-Javadoc) - * - * @see com.minres.scviewer.database.swt.IWaveformPanel#getScaledTime(long) - */ - @Override - public String getScaledTime(long time) { - StringBuilder sb = new StringBuilder(); - double dTime = time; - double scaledTime = dTime / waveformCanvas.getScaleFactorPow10(); - return sb.append(Constants.getTimeFormatForLevel(waveformCanvas.getZoomLevel()).format(scaledTime)).append(waveformCanvas.getUnitStr()).toString(); - } - - /* - * (non-Javadoc) - * - * @see com.minres.scviewer.database.swt.IWaveformPanel#getZoomLevels() - */ - @Override - public String[] getZoomLevels() { - String[] res = new String[Constants.SCALE_MULTIPLIER.length * Constants.UNIT_STRING.length]; - int index = 0; - for (String unit : Constants.UNIT_STRING) { - for (long factor : Constants.SCALE_MULTIPLIER) { - res[index++] = Long.toString(factor) + unit; - } - } - return res; - } - - @Override - public long getBaselineTime() { - return -waveformCanvas.getScaleFactorPow10() * waveformCanvas.getOrigin().x; - } - - @Override - public void setBaselineTime(Long time) { - Point origin = waveformCanvas.getOrigin(); - origin.x = (int) (-time / waveformCanvas.getScaleFactorPow10()); - 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; - Point o = waveformCanvas.getOrigin(); - waveformCanvas.setOrigin(o.x - diff, o.y); - waveformCanvas.redraw(); + long minTime = waveformCanvas.getMinVisibleTime(); + long duration = waveformCanvas.getMaxVisibleTime()-minTime; + long diff = (duration * percent) / 100; + waveformCanvas.setMinVisibleTime(minTime+diff); } @Override @@ -1580,4 +1478,8 @@ public class WaveformView implements IWaveformView { return streams.stream().filter(e -> e.waveform.getType() == WaveformType.TRANSACTION).findFirst().isPresent(); } + @Override + public IWaveformZoom getWaveformZoom() { + return waveformCanvas; + } } diff --git a/plugins/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/ZoomHandler.java b/plugins/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/ZoomHandler.java index a632a23..863a911 100644 --- a/plugins/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/ZoomHandler.java +++ b/plugins/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/ZoomHandler.java @@ -18,6 +18,7 @@ import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.e4.ui.workbench.modeling.EPartService; +import com.minres.scviewer.database.ui.ZoomKind; import com.minres.scviewer.e4.application.parts.WaveformViewer; public class ZoomHandler { @@ -35,15 +36,14 @@ public class ZoomHandler { Object obj = part.getObject(); if(obj instanceof WaveformViewer){ WaveformViewer waveformViewerPart = (WaveformViewer) obj; - int zoomLevel = waveformViewerPart.getZoomLevel(); if("in".equalsIgnoreCase(level)) //$NON-NLS-1$ - waveformViewerPart.setZoomLevel(zoomLevel-1); + waveformViewerPart.setZoom(ZoomKind.IN); else if("out".equalsIgnoreCase(level)) //$NON-NLS-1$ - waveformViewerPart.setZoomLevel(zoomLevel+1); + waveformViewerPart.setZoom(ZoomKind.OUT); else if("fit".equalsIgnoreCase(level)) //$NON-NLS-1$ - waveformViewerPart.setZoomFit(); + waveformViewerPart.setZoom(ZoomKind.FIT); else if("full".equalsIgnoreCase(level)) //$NON-NLS-1$ - waveformViewerPart.setZoomFull(); + waveformViewerPart.setZoom(ZoomKind.FULL); } } diff --git a/plugins/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/internal/status/WaveStatusBarControl.java b/plugins/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/internal/status/WaveStatusBarControl.java index 56ff3fa..6d23686 100644 --- a/plugins/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/internal/status/WaveStatusBarControl.java +++ b/plugins/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/internal/status/WaveStatusBarControl.java @@ -27,9 +27,6 @@ import com.minres.scviewer.e4.application.Messages; */ public class WaveStatusBarControl extends StatusBarControl { - /** The Constant ZOOM_LEVEL. */ - public static final String ZOOM_LEVEL="ZoomLevelUpdate"; //$NON-NLS-1$ - /** The Constant CURSOR_TIME. */ public static final String CURSOR_TIME="CursorPosUpdate"; //$NON-NLS-1$ @@ -45,7 +42,7 @@ public class WaveStatusBarControl extends StatusBarControl { /** The zoom contribution. */ - StatusLineContributionItem cursorContribution, markerContribution, markerDiffContribution, zoomContribution; + StatusLineContributionItem cursorContribution, markerContribution, markerDiffContribution; /** * Instantiates a new wave status bar control. @@ -59,11 +56,9 @@ public class WaveStatusBarControl extends StatusBarControl { cursorContribution = new StatusLineContributionItem(Messages.WaveStatusBarControl_5, true, 20); markerContribution = new StatusLineContributionItem(Messages.WaveStatusBarControl_6, true, 20); markerDiffContribution = new StatusLineContributionItem(Messages.WaveStatusBarControl_7, true, 20); - zoomContribution = new StatusLineContributionItem(Messages.WaveStatusBarControl_8, true, 8); manager.appendToGroup(StatusLineManager.BEGIN_GROUP,cursorContribution); manager.appendToGroup(StatusLineManager.BEGIN_GROUP,markerContribution); manager.appendToGroup(StatusLineManager.BEGIN_GROUP,markerDiffContribution); - manager.appendToGroup(StatusLineManager.BEGIN_GROUP, zoomContribution); } /** @@ -88,17 +83,6 @@ public class WaveStatusBarControl extends StatusBarControl { } } - /** - * Gets the zoom event. - * - * @param text the text - * @return the zoom event - */ - @Inject @Optional - public void getZoomEvent(@UIEventTopic(ZOOM_LEVEL) String text) { - zoomContribution.setText(text); - } - /** * Gets the cursor event. * diff --git a/plugins/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java b/plugins/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java index b31fc01..08e3e01 100644 --- a/plugins/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java +++ b/plugins/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java @@ -94,6 +94,7 @@ import com.minres.scviewer.database.ui.IWaveformView; import com.minres.scviewer.database.ui.TrackEntry; import com.minres.scviewer.database.ui.TrackEntry.ValueDisplay; import com.minres.scviewer.database.ui.TrackEntry.WaveDisplay; +import com.minres.scviewer.database.ui.ZoomKind; import com.minres.scviewer.database.ui.swt.Constants; import com.minres.scviewer.database.ui.swt.IToolTipContentProvider; import com.minres.scviewer.database.ui.swt.IToolTipHelpTextProvider; @@ -131,7 +132,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis protected static final String SHOWN_CURSOR = "SHOWN_CURSOR"; //$NON-NLS-1$ /** The Constant ZOOM_LEVEL. */ - protected static final String ZOOM_LEVEL = "ZOOM_LEVEL"; //$NON-NLS-1$ + protected static final String SCALING_FACTOR = "SCALING_FACTOR"; //$NON-NLS-1$ /** The Constant BASE_LINE_TIME. */ protected static final String BASE_LINE_TIME = "BASE_LINE_TIME"; //$NON-NLS-1$ @@ -151,9 +152,6 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis /** The Constant TX_DETAILS_SHOWN. */ protected static final String TX_DETAILS_SHOWN = "TX_DETAILS_SHOWN"; //$NON-NLS-1$ - /** The zoom level. */ - private String[] zoomLevel; - /** The Constant ID. */ public static final String ID = "com.minres.scviewer.ui.TxEditorPart"; //$NON-NLS-1$ @@ -299,15 +297,15 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis waveformPane.addPropertyChangeListener(IWaveformView.CURSOR_PROPERTY, evt -> { Long time = (Long) evt.getNewValue(); - eventBroker.post(WaveStatusBarControl.CURSOR_TIME, waveformPane.getScaledTime(time)); - long marker = waveformPane.getMarkerTime(waveformPane.getSelectedMarkerId()); - eventBroker.post(WaveStatusBarControl.MARKER_DIFF, waveformPane.getScaledTime(time - marker)); + eventBroker.post(WaveStatusBarControl.CURSOR_TIME, waveformPane.getWaveformZoom().timeToString(time)); + long marker = waveformPane.getMarkerTime(waveformPane.getSelectedMarker()); + eventBroker.post(WaveStatusBarControl.MARKER_DIFF, waveformPane.getWaveformZoom().timeToString(time - marker)); }); waveformPane.addPropertyChangeListener(IWaveformView.MARKER_PROPERTY, evt -> { Long time = (Long) evt.getNewValue(); - eventBroker.post(WaveStatusBarControl.MARKER_TIME, waveformPane.getScaledTime(time)); + eventBroker.post(WaveStatusBarControl.MARKER_TIME, waveformPane.getWaveformZoom().timeToString(time)); long cursor = waveformPane.getCursorTime(); - eventBroker.post(WaveStatusBarControl.MARKER_DIFF, waveformPane.getScaledTime(cursor - time)); + eventBroker.post(WaveStatusBarControl.MARKER_DIFF, waveformPane.getWaveformZoom().timeToString(cursor - time)); }); waveformPane.addSelectionChangedListener(event -> { @@ -319,17 +317,14 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis waveformPane.getWaveformControl().addListener(SWT.KeyDown, e -> { if((e.stateMask&SWT.MOD3)!=0) { // Alt key } else if((e.stateMask&SWT.MOD1)!=0) { //Ctrl/Cmd - int zoomlevel = waveformPane.getZoomLevel(); switch(e.keyCode) { case '+': case SWT.KEYPAD_ADD: - if(zoomlevel>0) - waveformPane.setZoomLevel(zoomlevel-1); + waveformPane.getWaveformZoom().zoom(ZoomKind.IN); return; case '-': case SWT.KEYPAD_SUBTRACT: - if(zoomlevel(); persistedState = part.getPersistedState(); @@ -392,7 +386,6 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis } if (!filesToLoad.isEmpty()) loadDatabase(persistedState); - eventBroker.post(WaveStatusBarControl.ZOOM_LEVEL, zoomLevel[waveformPane.getZoomLevel()]); menuService.registerContextMenu(waveformPane.getNameControl(), MENU_CONTEXT); menuService.registerContextMenu(waveformPane.getValueControl(), MENU_CONTEXT); menuService.registerContextMenu(waveformPane.getWaveformControl(), MENU_CONTEXT); @@ -750,8 +743,8 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis persistingState.put(SHOWN_CURSOR + index, Long.toString(cursor.getTime())); index++; } - persistingState.put(ZOOM_LEVEL, Integer.toString(waveformPane.getZoomLevel())); - persistingState.put(BASE_LINE_TIME, Long.toString(waveformPane.getBaselineTime())); + persistingState.put(SCALING_FACTOR, Long.toString(waveformPane.getWaveformZoom().getScale())); + persistingState.put(BASE_LINE_TIME, Long.toString(waveformPane.getWaveformZoom().getMinVisibleTime())); // get selected transaction of a stream ISelection selection = waveformPane.getSelection(); @@ -822,17 +815,17 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis cursors.get(i).setTime(time); } } - if (state.containsKey(ZOOM_LEVEL)) { + if (state.containsKey(SCALING_FACTOR)) { try { - Integer scale = Integer.parseInt(state.get(ZOOM_LEVEL)); - waveformPane.setZoomLevel(scale); + long scale = Long.parseLong(state.get(SCALING_FACTOR)); + waveformPane.getWaveformZoom().setScale(scale); } catch (NumberFormatException e) { } } if (state.containsKey(BASE_LINE_TIME)) { try { Long scale = Long.parseLong(state.get(BASE_LINE_TIME)); - waveformPane.setBaselineTime(scale); + waveformPane.getWaveformZoom().setMinVisibleTime(scale); } catch (NumberFormatException e) { } } @@ -871,12 +864,11 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis */ private void updateAll() { eventBroker.post(ACTIVE_WAVEFORMVIEW, this); - eventBroker.post(WaveStatusBarControl.ZOOM_LEVEL, zoomLevel[waveformPane.getZoomLevel()]); long cursor = waveformPane.getCursorTime(); - long marker = waveformPane.getMarkerTime(waveformPane.getSelectedMarkerId()); - eventBroker.post(WaveStatusBarControl.CURSOR_TIME, waveformPane.getScaledTime(cursor)); - eventBroker.post(WaveStatusBarControl.MARKER_TIME, waveformPane.getScaledTime(marker)); - eventBroker.post(WaveStatusBarControl.MARKER_DIFF, waveformPane.getScaledTime(cursor - marker)); + long marker = waveformPane.getMarkerTime(waveformPane.getSelectedMarker()); + eventBroker.post(WaveStatusBarControl.CURSOR_TIME, waveformPane.getWaveformZoom().timeToString(cursor)); + eventBroker.post(WaveStatusBarControl.MARKER_TIME, waveformPane.getWaveformZoom().timeToString(marker)); + eventBroker.post(WaveStatusBarControl.MARKER_DIFF, waveformPane.getWaveformZoom().timeToString(cursor - marker)); } /** @@ -1047,44 +1039,13 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis } /** - * Sets the zoom level. - * - * @param level the new zoom level + * Execute the zoom kind. */ - public void setZoomLevel(Integer level) { - if (level < 0) - level = 0; - if (level > zoomLevel.length - 1) - level = zoomLevel.length - 1; - waveformPane.setZoomLevel(level); + public void setZoom(ZoomKind kind) { + waveformPane.getWaveformZoom().zoom(kind); updateAll(); } - /** - * Sets the zoom fit. - */ - public void setZoomFit() { - waveformPane.setZoomLevel(-2); - updateAll(); - } - - /** - * Sets the zoom fit. - */ - public void setZoomFull() { - waveformPane.setZoomLevel(-1); - updateAll(); - } - - /** - * Gets the zoom level. - * - * @return the zoom level - */ - public int getZoomLevel() { - return waveformPane.getZoomLevel(); - } - /** * Gets the selection. * @@ -1113,7 +1074,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis * @return the scaled time */ public String getScaledTime(Long time) { - return waveformPane.getScaledTime(time); + return waveformPane.getWaveformZoom().timeToString(time); } /** @@ -1239,7 +1200,6 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis public void widgetDisposed(DisposeEvent e) { disposeListenerNumber -= 1; if( disposeListenerNumber == 0) { //if the last tab is closed, reset statusbar - eventBroker.post(WaveStatusBarControl.ZOOM_LEVEL, null); eventBroker.post(WaveStatusBarControl.CURSOR_TIME, null); eventBroker.post(WaveStatusBarControl.MARKER_TIME, null); eventBroker.post(WaveStatusBarControl.MARKER_DIFF, null); diff --git a/plugins/com.minres.scviewer.ui/plugin.xml b/plugins/com.minres.scviewer.ui/plugin.xml index ca5912b..7861519 100644 --- a/plugins/com.minres.scviewer.ui/plugin.xml +++ b/plugins/com.minres.scviewer.ui/plugin.xml @@ -139,19 +139,7 @@ - - - - - - @@ -163,7 +151,7 @@ @@ -176,119 +164,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -305,7 +180,7 @@ @@ -317,7 +192,7 @@ @@ -367,24 +242,21 @@ name="Prev"> - - - - + + + + @@ -411,8 +283,8 @@ + class="com.minres.scviewer.ui.handler.Zoom" + commandId="com.minres.scviewer.ui.zoom.in"> @@ -420,8 +292,8 @@ + class="com.minres.scviewer.ui.handler.Zoom" + commandId="com.minres.scviewer.ui.zoom.out"> @@ -493,15 +365,11 @@ icon="res/images/next-green.png"> - -