From 9d4c951e7fa838b5a1fb482e74ce45a07aad0ec7 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Thu, 11 Oct 2018 14:44:41 +0200 Subject: [PATCH] Added support for real valued signals in waveform UI --- .../database/swt/internal/SignalPainter.java | 86 +++++++++++++++++-- .../database/swt/internal/WaveformCanvas.java | 49 +++++------ .../database/swt/internal/WaveformViewer.java | 59 ++++++++----- .../scviewer/database/ui/WaveformColors.java | 2 +- 4 files changed, 140 insertions(+), 56 deletions(-) diff --git a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/SignalPainter.java b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/SignalPainter.java index d41ff93..42ead12 100644 --- a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/SignalPainter.java +++ b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/SignalPainter.java @@ -11,6 +11,8 @@ package com.minres.scviewer.database.swt.internal; import java.util.Map.Entry; +import java.util.Collection; +import java.util.Map; import java.util.NavigableMap; import javax.swing.JPanel; @@ -24,8 +26,9 @@ import org.eclipse.swt.graphics.Rectangle; import com.minres.scviewer.database.ISignal; import com.minres.scviewer.database.ISignalChange; -import com.minres.scviewer.database.ISignalChangeMulti; -import com.minres.scviewer.database.ISignalChangeSingle; +import com.minres.scviewer.database.ISignalChangeBitVector; +import com.minres.scviewer.database.ISignalChangeReal; +import com.minres.scviewer.database.ISignalChangeBit; import com.minres.scviewer.database.ui.TrackEntry; import com.minres.scviewer.database.ui.WaveformColors; @@ -107,7 +110,6 @@ public class SignalPainter extends TrackPainter { NavigableMap entries = signal.getEvents().subMap(first.getKey(), false, last.getKey(), true); SignalChange left = new SignalChange(first); SignalChange right = new SignalChange(entries.size() > 0 ? entries.firstEntry() : first); - SignalStencil stencil = left.value instanceof ISignalChangeSingle ? new SingleBitStencil() : new MultiBitStencil(gc); maxX = area.x + area.width; yOffsetT = this.waveCanvas.getTrackHeight() / 5 + area.y; @@ -132,6 +134,7 @@ public class SignalPainter extends TrackPainter { xEnd = getXEnd(right.time); } + SignalStencil stencil = getStencil(gc, left, entries); do { stencil.draw(gc, area, left.value, right.value, xBegin, xEnd, multiple); if (right.time >= endTime) @@ -150,6 +153,17 @@ public class SignalPainter extends TrackPainter { } while (left.time < endTime); } + private SignalStencil getStencil(GC gc, SignalChange left, NavigableMap entries) { + if(left.value instanceof ISignalChangeBit) + return new SingleBitStencil(); + else if (left.value instanceof ISignalChangeBitVector) + return new MultiBitStencil(gc); + else if (left.value instanceof ISignalChangeReal) + return new RealStencil(entries, left.value); + else + return null; + } + private interface SignalStencil { public void draw(GC gc, Rectangle area, ISignalChange left, ISignalChange right, int xBegin, int xEnd, boolean multiple); @@ -168,7 +182,7 @@ public class SignalPainter extends TrackPainter { public void draw(GC gc, Rectangle area, ISignalChange left, ISignalChange right, int xBegin, int xEnd, boolean multiple) { Color colorBorder = waveCanvas.colors[WaveformColors.SIGNAL0.ordinal()]; - ISignalChangeMulti last = (ISignalChangeMulti) left; + ISignalChangeBitVector last = (ISignalChangeBitVector) left; if (last.getValue().toString().contains("X")) { colorBorder = waveCanvas.colors[WaveformColors.SIGNALX.ordinal()]; } else if (last.getValue().toString().contains("Z")) { @@ -216,11 +230,12 @@ public class SignalPainter extends TrackPainter { if (multiple) { gc.setForeground(waveCanvas.colors[WaveformColors.SIGNALU.ordinal()]); gc.drawLine(xBegin, yOffsetT, xBegin, yOffsetB); - gc.drawLine(xEnd, yOffsetT, xEnd, yOffsetB); + if(xEnd>xBegin) + gc.drawLine(xEnd, yOffsetT, xEnd, yOffsetB); } else { Color color = waveCanvas.colors[WaveformColors.SIGNALX.ordinal()]; int yOffset = yOffsetM; - switch (((ISignalChangeSingle) left).getValue()) { + switch (((ISignalChangeBit) left).getValue()) { case '1': color = waveCanvas.colors[WaveformColors.SIGNAL1.ordinal()]; yOffset = yOffsetT; @@ -240,7 +255,7 @@ public class SignalPainter extends TrackPainter { } else { gc.drawLine(xBegin, yOffset, xEnd, yOffset); int yNext = yOffsetM; - switch (((ISignalChangeSingle) right).getValue()) { + switch (((ISignalChangeBit) right).getValue()) { case '1': yNext = yOffsetT; break; @@ -257,8 +272,63 @@ public class SignalPainter extends TrackPainter { } + private class RealStencil implements SignalStencil { + + double minVal, range; + + final double scaleFactor = 1.05; + + boolean stepWise=true; + + @SuppressWarnings("unchecked") + public RealStencil(NavigableMap entries, ISignalChange left) { + Collection values = ((NavigableMap) entries).values(); + minVal=((ISignalChangeReal) left).getValue(); + range=2.0; + if(!values.isEmpty()) { + double maxVal=minVal; + for(ISignalChangeReal v:values) { + minVal=Math.min(minVal, v.getValue()); + maxVal=Math.max(maxVal, v.getValue()); + } + range = (maxVal-minVal)*scaleFactor; + double avg = (maxVal+minVal)/2.0; + minVal=avg-(avg-minVal)*scaleFactor; + } + } + + public void draw(GC gc, Rectangle area, ISignalChange left, ISignalChange right, int xBegin, int xEnd, boolean multiple) { + double leftVal = ((ISignalChangeReal) left).getValue(); + double rightVal= ((ISignalChangeReal) right).getValue(); +// if (multiple) { +// gc.setForeground(waveCanvas.colors[WaveformColors.SIGNALX.ordinal()]); +// } else { + gc.setForeground(waveCanvas.colors[WaveformColors.SIGNAL_REAL.ordinal()]); +// } + int yOffsetLeft = (int) ((leftVal-minVal) / range * (yOffsetB-yOffsetT)); + int yOffsetRight = (int) ((rightVal-minVal) / range * (yOffsetB-yOffsetT)); + if(stepWise) { + if (xEnd > maxX) { + gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxX, yOffsetB-yOffsetLeft); + } else { + gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetLeft); + if(yOffsetRight!=yOffsetLeft) { + gc.drawLine(xEnd, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight); + } + } + + } else { + if (xEnd > maxX) { + gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxX, yOffsetB-yOffsetRight); + } else { + gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight); + } + } + } + } + public ISignal getSignal() { return signal; } -} \ No newline at end of file +} 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 333cb4f..4621e54 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 @@ -126,6 +126,30 @@ public class WaveformCanvas extends Canvas { painterList.add(marker); cursorPainters.add(marker); wave2painterMap=new HashMap<>(); + // fall back initialization + colors[WaveformColors.LINE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); + colors[WaveformColors.LINE_HIGHLITE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_CYAN); + colors[WaveformColors.TRACK_BG_EVEN.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_BLACK); + colors[WaveformColors.TRACK_BG_ODD.ordinal()] = SWTResourceManager.getColor(40, 40, 40); + colors[WaveformColors.TRACK_BG_HIGHLITE.ordinal()] = SWTResourceManager.getColor(40, 40, 80); + colors[WaveformColors.TX_BG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); + colors[WaveformColors.TX_BG_HIGHLITE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); + colors[WaveformColors.TX_BORDER.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); + colors[WaveformColors.SIGNAL0.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); + colors[WaveformColors.SIGNAL1.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); + colors[WaveformColors.SIGNALZ.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_YELLOW); + colors[WaveformColors.SIGNALX.ordinal()] = SWTResourceManager.getColor(255, 51, 51); + colors[WaveformColors.SIGNALU.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_YELLOW); + colors[WaveformColors.SIGNAL_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); + colors[WaveformColors.SIGNAL_REAL.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_YELLOW); + colors[WaveformColors.CURSOR.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); + colors[WaveformColors.CURSOR_DRAG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GRAY); + colors[WaveformColors.CURSOR_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); + colors[WaveformColors.MARKER.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GRAY); + colors[WaveformColors.MARKER_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); + colors[WaveformColors.REL_ARROW.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_MAGENTA); + colors[WaveformColors.REL_ARROW_HIGHLITE.ordinal()] = SWTResourceManager.getColor(255, 128, 255); + } public void addCursoPainter(CursorPainter cursorPainter){ @@ -137,33 +161,10 @@ public class WaveformCanvas extends Canvas { Display d = getDisplay(); if (colourMap != null) { for (WaveformColors c : WaveformColors.values()) { - if (colourMap.containsKey(c)) { + if (colourMap.containsKey(c)) colors[c.ordinal()] = new Color(d, colourMap.get(c)); - } } redraw(); - } else { - colors[WaveformColors.LINE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); - colors[WaveformColors.LINE_HIGHLITE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_CYAN); - colors[WaveformColors.TRACK_BG_EVEN.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_BLACK); - colors[WaveformColors.TRACK_BG_ODD.ordinal()] = SWTResourceManager.getColor(40, 40, 40); - colors[WaveformColors.TRACK_BG_HIGHLITE.ordinal()] = SWTResourceManager.getColor(40, 40, 80); - colors[WaveformColors.TX_BG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); - colors[WaveformColors.TX_BG_HIGHLITE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); - colors[WaveformColors.TX_BORDER.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); - colors[WaveformColors.SIGNAL0.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); - colors[WaveformColors.SIGNAL1.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN); - colors[WaveformColors.SIGNALZ.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_YELLOW); - colors[WaveformColors.SIGNALX.ordinal()] = SWTResourceManager.getColor(255, 51, 51); - colors[WaveformColors.SIGNALU.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_YELLOW); - colors[WaveformColors.SIGNAL_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); - colors[WaveformColors.CURSOR.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); - colors[WaveformColors.CURSOR_DRAG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GRAY); - colors[WaveformColors.CURSOR_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); - colors[WaveformColors.MARKER.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GRAY); - colors[WaveformColors.MARKER_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE); - colors[WaveformColors.REL_ARROW.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_MAGENTA); - colors[WaveformColors.REL_ARROW_HIGHLITE.ordinal()] = SWTResourceManager.getColor(255, 128, 255); } } 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 59d2b78..470b3af 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 @@ -13,6 +13,7 @@ package com.minres.scviewer.database.swt.internal; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -71,8 +72,9 @@ import org.eclipse.wb.swt.SWTResourceManager; import com.google.common.collect.Lists; import com.minres.scviewer.database.ISignal; import com.minres.scviewer.database.ISignalChange; -import com.minres.scviewer.database.ISignalChangeMulti; -import com.minres.scviewer.database.ISignalChangeSingle; +import com.minres.scviewer.database.ISignalChangeBitVector; +import com.minres.scviewer.database.ISignalChangeReal; +import com.minres.scviewer.database.ISignalChangeBit; import com.minres.scviewer.database.ITx; import com.minres.scviewer.database.ITxEvent; import com.minres.scviewer.database.ITxRelation; @@ -102,11 +104,11 @@ public class WaveformViewer implements IWaveformViewer { private Control namePaneHeader; - private Canvas nameList; + final private Canvas nameList; - private Canvas valueList; + final private Canvas valueList; - WaveformCanvas waveformCanvas; + final WaveformCanvas waveformCanvas; private Composite top; @@ -125,12 +127,11 @@ public class WaveformViewer implements IWaveformViewer { protected MouseListener nameValueMouseListener = new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { - if ((e.button == 1 || e.button == 3)) { + if (e.button == 1) { Entry entry = trackVerticalOffset.floorEntry(e.y); if (entry != null) setSelection(new StructuredSelection(entry.getValue())); - } - if (e.button == 3) { + } else if (e.button == 3) { Menu topMenu= top.getMenu(); if(topMenu!=null) topMenu.setVisible(true); } @@ -171,7 +172,7 @@ public class WaveformViewer implements IWaveformViewer { } }); } - }else if (e.button == 2) { + }else if (e.button == 2) { setMarkerTime(snapOffsetToEvent(e), selectedMarker); e.widget.getDisplay().asyncExec(new Runnable() { @Override @@ -273,9 +274,11 @@ public class WaveformViewer implements IWaveformViewer { nameList.addListener(SWT.Paint, new Listener() { @Override public void handleEvent(Event event) { - GC gc = event.gc; - Rectangle rect = ((Canvas) event.widget).getClientArea(); - paintNames(gc, rect); + if(!trackVerticalOffset.isEmpty()) { + GC gc = event.gc; + Rectangle rect = ((Canvas) event.widget).getClientArea(); + paintNames(gc, rect); + } } }); nameList.addMouseListener(nameValueMouseListener); @@ -305,9 +308,11 @@ public class WaveformViewer implements IWaveformViewer { valueList.addListener(SWT.Paint, new Listener() { @Override public void handleEvent(Event event) { - GC gc = event.gc; - Rectangle rect = ((Canvas) event.widget).getClientArea(); - paintValues(gc, rect); + if(!trackVerticalOffset.isEmpty()) { + GC gc = event.gc; + Rectangle rect = ((Canvas) event.widget).getClientArea(); + paintValues(gc, rect); + } } }); valueList.addMouseListener(nameValueMouseListener); @@ -315,7 +320,7 @@ public class WaveformViewer implements IWaveformViewer { waveformCanvas.setMaxTime(1); waveformCanvas.addMouseListener(waveformMouseListener); - + nameListScrolled.getVerticalBar().addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int y = ((ScrollBar) e.widget).getSelection(); @@ -454,10 +459,16 @@ public class WaveformViewer implements IWaveformViewer { for(Entry, String> entry:actualValues.entrySet()){ if(entry.getKey() instanceof ISignal){ ISignalChange event = ((ISignal)entry.getKey()).getWaveformEventsBeforeTime(time); - if(event instanceof ISignalChangeSingle){ - entry.setValue("b'"+((ISignalChangeSingle)event).getValue()); - } else if(event instanceof ISignalChangeMulti){ - entry.setValue("h'"+((ISignalChangeMulti)event).getValue().toHexString()); + if(event instanceof ISignalChangeBit){ + entry.setValue("b'"+((ISignalChangeBit)event).getValue()); + } else if(event instanceof ISignalChangeBitVector){ + entry.setValue("h'"+((ISignalChangeBitVector)event).getValue().toHexString()); + } else if(event instanceof ISignalChangeReal){ + double val = ((ISignalChangeReal)event).getValue(); + if(val>0.001) + entry.setValue(String.format("%1$,.3f", val)); + else + entry.setValue(Double.toString(val)); } } else if(entry.getKey() instanceof ITxStream){ ITxStream stream = (ITxStream) entry.getKey(); @@ -551,9 +562,10 @@ public class WaveformViewer implements IWaveformViewer { public ISelection getSelection() { if (currentTxSelection != null) return new StructuredSelection(currentTxSelection); - else if (currentWaveformSelection != null) - return new StructuredSelection(currentWaveformSelection.waveform); - else + else if (currentWaveformSelection != null) { + Object[] elem = {currentWaveformSelection.waveform, currentWaveformSelection}; + return new StructuredSelection(elem); + } else return new StructuredSelection(); } @@ -738,6 +750,7 @@ public class WaveformViewer implements IWaveformViewer { setCursorTime(time); waveformCanvas.reveal(time); waveformCanvas.redraw(); + updateValueList(); } } diff --git a/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/WaveformColors.java b/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/WaveformColors.java index 382f526..72fb07e 100644 --- a/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/WaveformColors.java +++ b/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/WaveformColors.java @@ -14,7 +14,7 @@ public enum WaveformColors { LINE, LINE_HIGHLITE, TRACK_BG_EVEN, TRACK_BG_ODD, TRACK_BG_HIGHLITE, TX_BG, TX_BG_HIGHLITE, TX_BORDER, - SIGNAL0, SIGNAL1, SIGNALZ, SIGNALX, SIGNALU, SIGNAL_TEXT, + SIGNAL0, SIGNAL1, SIGNALZ, SIGNALX, SIGNALU, SIGNAL_TEXT, SIGNAL_REAL, CURSOR, CURSOR_DRAG, CURSOR_TEXT, MARKER, MARKER_TEXT, REL_ARROW, REL_ARROW_HIGHLITE } \ No newline at end of file