diff --git a/com.minres.scviewer.database.sqlite/META-INF/MANIFEST.MF b/com.minres.scviewer.database.sqlite/META-INF/MANIFEST.MF index ced4ce9..7a73230 100644 --- a/com.minres.scviewer.database.sqlite/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.database.sqlite/META-INF/MANIFEST.MF @@ -15,3 +15,4 @@ Bundle-ActivationPolicy: lazy Embed-Dependency: sqlite-jdbc Embedded-Artifacts: sqlite-jdbc-3.8.7.jar;g="org.xerial"; a="sqlite-jdbc";v="3.8.7" +Automatic-Module-Name: com.minres.scviewer.database.sqlite diff --git a/com.minres.scviewer.database.test/META-INF/MANIFEST.MF b/com.minres.scviewer.database.test/META-INF/MANIFEST.MF index 28455ce..229f904 100644 --- a/com.minres.scviewer.database.test/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.database.test/META-INF/MANIFEST.MF @@ -12,3 +12,4 @@ Require-Bundle: org.junit, com.minres.scviewer.database.vcd;bundle-version="1.0.0" Bundle-ActivationPolicy: lazy Service-Component: OSGI-INF/component.xml +Automatic-Module-Name: com.minres.scviewer.database.test diff --git a/com.minres.scviewer.database.test/inputs/simple_system.vcd b/com.minres.scviewer.database.test/inputs/simple_system.vcd index 8977649..20cce8a 100755 --- a/com.minres.scviewer.database.test/inputs/simple_system.vcd +++ b/com.minres.scviewer.database.test/inputs/simple_system.vcd @@ -45,6 +45,7 @@ $var wire 1 aaabd s_gpio_29 $end $var wire 1 aaabe s_gpio_30 $end $var wire 1 aaabf s_gpio_31 $end $var wire 1 aaabg s_rst_n $end +$var real 1 bbbbb a_real $end $scope module i_platform $end $var wire 1 aaabh erst_n $end $var wire 64 aabdc s_tlclk [63:0] $end @@ -1621,6 +1622,7 @@ b1110100011010100101001010 aabdd 0aabdv 0aabdw 0aabdx +r0.0 bbbbb $end #10000 @@ -1638,6 +1640,28 @@ $end 0aabcq 0aabcy 0aabde +r1.0 bbbbb + +#20000 +r2.0 bbbbb + +#30000 +r2.5 bbbbb + +#40000 +r1.5 bbbbb + +#50000 +r-1.0 bbbbb + +#60000 +r-2.5 bbbbb + +#70000 +r-1.0 bbbbb + +#80000 +r0.0 bbbbb #1287121272 b1000000000100000000000000000100 aabcr diff --git a/com.minres.scviewer.database.test/src/com/minres/scviewer/database/test/DatabaseServicesTest.java b/com.minres.scviewer.database.test/src/com/minres/scviewer/database/test/DatabaseServicesTest.java index ce9aed8..8f5fb1b 100644 --- a/com.minres.scviewer.database.test/src/com/minres/scviewer/database/test/DatabaseServicesTest.java +++ b/com.minres.scviewer.database.test/src/com/minres/scviewer/database/test/DatabaseServicesTest.java @@ -92,7 +92,7 @@ public class DatabaseServicesTest { assertTrue(f.exists()); waveformDb.load(f); assertNotNull(waveformDb); - assertEquals(778, waveformDb.getAllWaves().size()); + assertEquals(779, waveformDb.getAllWaves().size()); assertEquals(1, waveformDb.getChildNodes().size()); } diff --git a/com.minres.scviewer.database.text/.settings/org.eclipse.jdt.groovy.core.prefs b/com.minres.scviewer.database.text/.settings/org.eclipse.jdt.groovy.core.prefs index ae98fea..021403d 100644 --- a/com.minres.scviewer.database.text/.settings/org.eclipse.jdt.groovy.core.prefs +++ b/com.minres.scviewer.database.text/.settings/org.eclipse.jdt.groovy.core.prefs @@ -1,2 +1,2 @@ eclipse.preferences.version=1 -groovy.compiler.level=24 +groovy.compiler.level=26 diff --git a/com.minres.scviewer.database.text/META-INF/MANIFEST.MF b/com.minres.scviewer.database.text/META-INF/MANIFEST.MF index d2d630f..44292a9 100644 --- a/com.minres.scviewer.database.text/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.database.text/META-INF/MANIFEST.MF @@ -15,3 +15,4 @@ Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0", com.google.guava;bundle-version="15.0.0" Service-Component: OSGI-INF/component.xml Bundle-ActivationPolicy: lazy +Automatic-Module-Name: com.minres.scviewer.database.text diff --git a/com.minres.scviewer.database.ui.swt/META-INF/MANIFEST.MF b/com.minres.scviewer.database.ui.swt/META-INF/MANIFEST.MF index 4dd40bf..26854e4 100644 --- a/com.minres.scviewer.database.ui.swt/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.database.ui.swt/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: SWT widget Bundle-SymbolicName: com.minres.scviewer.database.ui.swt -Bundle-Version: 1.1.0.qualifier +Bundle-Version: 2.0.0.qualifier Bundle-Vendor: MINRES Technologies GmbH Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.eclipse.swt;bundle-version="3.103.1", @@ -17,3 +17,4 @@ Export-Package: com.minres.scviewer.database.swt Bundle-ClassPath: . Bundle-ActivationPolicy: lazy Bundle-Activator: com.minres.scviewer.database.swt.DatabaseUiPlugin +Automatic-Module-Name: com.minres.scviewer.database.ui.swt diff --git a/com.minres.scviewer.database.ui.swt/pom.xml b/com.minres.scviewer.database.ui.swt/pom.xml index 387a391..6b6a315 100644 --- a/com.minres.scviewer.database.ui.swt/pom.xml +++ b/com.minres.scviewer.database.ui.swt/pom.xml @@ -1,6 +1,7 @@ 4.0.0 com.minres.scviewer.database.ui.swt + 2.0.0-SNAPSHOT eclipse-plugin com.minres.scviewer @@ -8,5 +9,4 @@ 1.0.0-SNAPSHOT ../com.minres.scviewer.parent - 1.1.0-SNAPSHOT \ No newline at end of file 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 955618b..934109c 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 @@ -10,6 +10,7 @@ *******************************************************************************/ package com.minres.scviewer.database.swt.internal; +import java.util.Collection; import java.util.Map.Entry; import java.util.NavigableMap; @@ -24,9 +25,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.ISignalChangeBit; +import com.minres.scviewer.database.ISignalChangeBitVector; import com.minres.scviewer.database.ISignalChangeReal; -import com.minres.scviewer.database.ISignalChangeSingle; import com.minres.scviewer.database.ui.TrackEntry; import com.minres.scviewer.database.ui.WaveformColors; @@ -66,7 +67,6 @@ public class SignalPainter extends TrackPainter { private static final JPanel DUMMY_PANEL = new JPanel(); private final WaveformCanvas waveCanvas; - private ISignal signal; int yOffsetT; int yOffsetM; @@ -76,7 +76,6 @@ public class SignalPainter extends TrackPainter { public SignalPainter(WaveformCanvas txDisplay, boolean even, TrackEntry trackEntry) { super(trackEntry, even); this.waveCanvas = txDisplay; - this.signal = trackEntry.getSignal(); } private int getXEnd(long time) { @@ -85,6 +84,7 @@ public class SignalPainter extends TrackPainter { } public void paintArea(GC gc, Rectangle area) { + ISignal signal = trackEntry.getSignal(); if (trackEntry.selected) gc.setBackground(this.waveCanvas.colors[WaveformColors.TRACK_BG_HIGHLITE.ordinal()]); else @@ -108,13 +108,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 = null; - if(left.value instanceof ISignalChangeSingle) - stencil= new SingleBitStencil(); - else if(left.value instanceof ISignalChangeMulti) - stencil= new MultiBitStencil(gc); - else - stencil= new RealStencil(left.value, entries); maxX = area.x + area.width; yOffsetT = this.waveCanvas.getTrackHeight() / 5 + area.y; yOffsetM = this.waveCanvas.getTrackHeight() / 2 + area.y; @@ -137,6 +130,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) @@ -157,6 +151,22 @@ 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) + if(trackEntry.waveDisplay==TrackEntry.WaveDisplay.DEFAULT) + return new MultiBitStencil(gc); + else + return new MultiBitStencilAnalog(entries, left.value, + trackEntry.waveDisplay==TrackEntry.WaveDisplay.CONTINOUS, + trackEntry.valueDisplay==TrackEntry.ValueDisplay.SIGNED); + else if (left.value instanceof ISignalChangeReal) + return new RealStencil(entries, left.value, trackEntry.waveDisplay==TrackEntry.WaveDisplay.CONTINOUS); + else + return null; + } + private interface SignalStencil { public void draw(GC gc, Rectangle area, ISignalChange left, ISignalChange right, int xBegin, int xEnd, boolean multiple); @@ -175,7 +185,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")) { @@ -194,7 +204,18 @@ public class SignalPainter extends TrackPainter { gc.setForeground(colorBorder); gc.drawPolygon(points); gc.setForeground(waveCanvas.colors[WaveformColors.SIGNAL_TEXT.ordinal()]); - String label = "h'" + last.getValue().toHexString(); + //TODO: this code should be provided from a central location + String label = null; + switch(trackEntry.valueDisplay) { + case SIGNED: + label=Long.toString(last.getValue().toSignedValue()); + break; + case UNSIGNED: + label=Long.toString(last.getValue().toUnsignedValue()); + break; + default: + label="h'"+last.getValue().toHexString(); + } Point bb = getBoxWidth(gc, label); if (xBegin < area.x) { xBegin = area.x; @@ -218,16 +239,71 @@ public class SignalPainter extends TrackPainter { } + private class MultiBitStencilAnalog implements SignalStencil { + + final boolean continous; + private long minVal; + private long range; + + @SuppressWarnings("unchecked") + public MultiBitStencilAnalog(NavigableMap entries, ISignalChange left, boolean continous, boolean signed) { + this.continous=continous; + Collection values = ((NavigableMap) entries).values(); + minVal=((ISignalChangeBitVector) left).getValue().toUnsignedValue(); + range=2; + if(!values.isEmpty()) { + long maxVal=minVal; + for (ISignalChange e : entries.values()) { + long v = ((ISignalChangeBitVector)e).getValue().toUnsignedValue(); + maxVal=Math.max(maxVal, v); + minVal=Math.min(minVal, v); + } + if(maxVal==minVal) { + maxVal--; + minVal++; + } + range = maxVal-minVal; + } else + minVal--; + + } + + public void draw(GC gc, Rectangle area, ISignalChange left, ISignalChange right, int xBegin, int xEnd, boolean multiple) { + long leftVal = ((ISignalChangeBitVector) left).getValue().toUnsignedValue(); + long rightVal= ((ISignalChangeBitVector) right).getValue().toUnsignedValue(); + 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(continous) { + if (xEnd > maxX) { + gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxX, yOffsetB-yOffsetRight); + } else { + gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight); + } + } else { + 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); + } + } + } + } + } + private class SingleBitStencil implements SignalStencil { public void draw(GC gc, Rectangle area, ISignalChange left, ISignalChange right, int xBegin, int xEnd, boolean multiple) { 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; @@ -247,7 +323,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; @@ -264,47 +340,45 @@ public class SignalPainter extends TrackPainter { } private class RealStencil implements SignalStencil { - double min; - double max; - double diff; + + double minVal, range; - public RealStencil(ISignalChange value, NavigableMap entries) { - min=((ISignalChangeReal) value).getValue(); - max=min; - for (ISignalChange e : entries.values()) { - double v = ((ISignalChangeReal)e).getValue(); - max= Double.isNaN(max)? v : Math.max(max, v); - min= Double.isNaN(min)? v : Math.min(min, v); - } - int nans = (Double.isNaN(max)?2:0) + (Double.isNaN(max)?1:0); - switch(nans) { - case 0: - break; - case 1: - max=min; - break; - case 2: - min=max; - case 3: - max=min=0; - } - diff=max-min; - if(diff==0.0) { - if(max>0) - min=0.0; - else if(min<0.0) - max=0.0; - else { - max=1.0; - min=0.0; + final double scaleFactor = 1.05; + + boolean continous=true; + + @SuppressWarnings("unchecked") + public RealStencil(NavigableMap entries, ISignalChange left, boolean continous) { + this.continous=continous; + Collection values = ((NavigableMap) entries).values(); + minVal=((ISignalChangeReal) left).getValue(); + range=2.0; + if(!values.isEmpty()) { + double maxVal=minVal; + for (ISignalChange e : entries.values()) { + double v = ((ISignalChangeReal)e).getValue(); + if(Double.isNaN(maxVal)) + maxVal=v; + else if(!Double.isNaN(v)) + maxVal=Math.max(maxVal, v); + if(Double.isNaN(minVal)) + minVal=v; + else if(!Double.isNaN(v)) + minVal=Math.min(minVal, v); } - diff=max-min; + if(Double.isNaN(maxVal)){ + maxVal=minVal=0.0; + } + 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 value = ((ISignalChangeReal)left).getValue(); - if(Double.isNaN(value)) { + double leftVal = ((ISignalChangeReal) left).getValue(); + double rightVal= ((ISignalChangeReal) right).getValue(); + if(Double.isNaN(leftVal)) { Color color = waveCanvas.colors[WaveformColors.SIGNAL_NAN.ordinal()]; int width = xEnd - xBegin; if (width > 1) { @@ -322,27 +396,28 @@ public class SignalPainter extends TrackPainter { gc.setForeground(color); gc.drawLine(xEnd, yOffsetT, xEnd, yOffsetB); } - } else { - Color color = waveCanvas.colors[WaveformColors.SIGNAL_ANALOG.ordinal()]; - int height=yOffsetT-yOffsetB; - double offset=value-min; - int yOffset=diff>0?(int)(height*(offset/diff)) + yOffsetB:yOffsetM; - gc.setForeground(color); - if (xEnd > maxX) { - gc.drawLine(xBegin, yOffset, maxX, yOffset); + } else { + gc.setForeground(waveCanvas.colors[WaveformColors.SIGNAL_REAL.ordinal()]); + int yOffsetLeft = (int) ((leftVal-minVal) / range * (yOffsetB-yOffsetT)); + int yOffsetRight = Double.isNaN(rightVal)?yOffsetLeft:(int) ((rightVal-minVal) / range * (yOffsetB-yOffsetT)); + if(continous) { + if (xEnd > maxX) { + gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxX, yOffsetB-yOffsetRight); + } else { + gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight); + } } else { - gc.drawLine(xBegin, yOffset, xEnd, yOffset); - double nextOffset = ((ISignalChangeReal)right).getValue()-min; - int yNext = diff>0?(int)(height*(nextOffset/diff)) + yOffsetB:height/2; - if (yOffset != yNext) - gc.drawLine(xEnd, yOffset, xEnd, yNext); + 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); + } + } } } } } - 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 22059c0..430e5b7 100644 --- a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformCanvas.java +++ b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformCanvas.java @@ -42,6 +42,7 @@ import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveformEvent; import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.ui.IWaveformViewer; +import com.minres.scviewer.database.ui.TrackEntry; import com.minres.scviewer.database.ui.WaveformColors; public class WaveformCanvas extends Canvas { @@ -126,6 +127,31 @@ 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.SIGNAL_NAN.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); + 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,35 +163,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_ANALOG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); - colors[WaveformColors.SIGNAL_NAN.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); - 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); } } @@ -181,6 +182,9 @@ public class WaveformCanvas extends Canvas { return origin; } + public int getWidth() { + return getClientArea().width; + } public void setOrigin(Point origin) { setOrigin(origin.x, origin.y); } @@ -292,9 +296,13 @@ public class WaveformCanvas extends Canvas { } public void addWaveformPainter(IWaveformPainter painter) { + addWaveformPainter(painter, true); + } + + void addWaveformPainter(IWaveformPainter painter, boolean update) { trackAreaPainter.addTrackPainter(painter); wave2painterMap.put(painter.getTrackEntry().waveform, painter); - syncScrollBars(); + if(update) syncScrollBars(); } public List getCursorPainters() { @@ -311,7 +319,7 @@ public class WaveformCanvas extends Canvas { super.dispose(); } - /* Initalize the scrollbar and register listeners. */ + /* Initialize the scrollbar and register listeners. */ private void initScrollBars() { ScrollBar horizontal = getHorizontalBar(); horizontal.setEnabled(false); @@ -469,6 +477,27 @@ public class WaveformCanvas extends Canvas { } } + public void reveal(IWaveform waveform) { + for (IWaveformPainter painter : wave2painterMap.values()) { + TrackEntry te = painter.getTrackEntry(); + if(te.waveform == waveform) { + Point size = getSize(); + //size.x -= getVerticalBar().getSize().x + 2; + size.y -=+rulerHeight; + ScrollBar sb = getHorizontalBar(); + if((sb.getStyle()&SWT.SCROLLBAR_OVERLAY)!=0 && sb.isVisible()) // TODO: check on other platform than MacOSX + size.y-= getHorizontalBar().getSize().y; + int top = te.vOffset; + int bottom = top + trackHeight; + if (top < -origin.y) { + setOrigin(origin.x, -(top-trackHeight)); + } else if (bottom > (size.y - origin.y)) { + setOrigin(origin.x, size.y - bottom); + } + } + } + } + public void reveal(long time) { int scaledTime = (int) (time / scaleFactor); Point size = getSize(); @@ -513,4 +542,11 @@ public class WaveformCanvas extends Canvas { } } + long getMaxVisibleTime() { + return (getClientArea().width+origin.x)*scaleFactor; + } + + long getOriginTime() { + return origin.x * scaleFactor; + } } diff --git a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformViewer.java b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformViewer.java index 7f38f38..d39f065 100644 --- a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformViewer.java +++ b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformViewer.java @@ -66,14 +66,15 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.ScrollBar; +import org.eclipse.swt.widgets.Widget; import org.eclipse.wb.swt.SWTResourceManager; import com.google.common.collect.Lists; import com.minres.scviewer.database.ISignal; import com.minres.scviewer.database.ISignalChange; -import com.minres.scviewer.database.ISignalChangeMulti; +import com.minres.scviewer.database.ISignalChangeBitVector; import com.minres.scviewer.database.ISignalChangeReal; -import com.minres.scviewer.database.ISignalChangeSingle; +import com.minres.scviewer.database.ISignalChangeBit; import com.minres.scviewer.database.ITx; import com.minres.scviewer.database.ITxEvent; import com.minres.scviewer.database.ITxRelation; @@ -103,12 +104,14 @@ 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 boolean revealSelected=false; + private Composite top; protected ObservableList streams; @@ -119,19 +122,16 @@ public class WaveformViewer implements IWaveformViewer { private TreeMap trackVerticalOffset; - private HashMap, String> actualValues; - private Font nameFont, nameFontB; 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); } @@ -145,12 +145,10 @@ public class WaveformViewer implements IWaveformViewer { @Override public void mouseDown(MouseEvent e) { start=new Point(e.x, e.y); + if((e.stateMask&SWT.MODIFIER_MASK)!=0) return; //don't react on modifier if (e.button == 1) { initialSelected = waveformCanvas.getClicked(start); } else if (e.button == 3) { - List hitted = waveformCanvas.getClicked(start); - if(hitted!=null && hitted.size()>0) - setSelection(new StructuredSelection(hitted)); Menu topMenu= top.getMenu(); if(topMenu!=null) topMenu.setVisible(true); } @@ -158,29 +156,18 @@ public class WaveformViewer implements IWaveformViewer { @Override public void mouseUp(MouseEvent e) { - if (e.button == 1) { + if((e.stateMask&SWT.MODIFIER_MASK&~SWT.SHIFT)!=0) return; //don't react on modifier + if (e.button == 1 && ((e.stateMask&SWT.SHIFT)==0)) { if(Math.abs(e.x-start.x)<3 && Math.abs(e.y-start.y)<3){ - // first set time + // first set cursor time setCursorTime(snapOffsetToEvent(e)); // then set selection and reveal setSelection(new StructuredSelection(initialSelected)); - e.widget.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - waveformCanvas.redraw(); - updateValueList(); - } - }); + asyncUpdate(e.widget); } - }else if (e.button == 2) { + }else if (e.button == 2 ||(e.button==1 && (e.stateMask&SWT.SHIFT)!=0)) { setMarkerTime(snapOffsetToEvent(e), selectedMarker); - e.widget.getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - waveformCanvas.redraw(); - updateValueList(); - } - }); + asyncUpdate(e.widget); } } @@ -226,7 +213,6 @@ public class WaveformViewer implements IWaveformViewer { trackVerticalOffset = new TreeMap(); trackVerticalHeight=0; - actualValues = new HashMap, String>(); nameFont = parent.getDisplay().getSystemFont(); nameFontB = SWTResourceManager.getBoldFont(nameFont); @@ -274,9 +260,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); @@ -306,9 +294,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); @@ -316,7 +306,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(); @@ -378,22 +368,33 @@ public class WaveformViewer implements IWaveformViewer { @Override public void propertyChange(PropertyChangeEvent pce) { if ("size".equals(pce.getPropertyName()) || "content".equals(pce.getPropertyName())) { + if(revealSelected) { + waveformCanvas.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + update(); + waveformCanvas.reveal(currentWaveformSelection.waveform); + valueList.redraw(); + nameList.redraw(); + } + }); + revealSelected=false; + } else waveformCanvas.getDisplay().asyncExec(new Runnable() { @Override public void run() { - updateTracklist(); + update(); } }); } } - protected void updateTracklist() { + public void update() { trackVerticalHeight = 0; int nameMaxWidth = 0; int previousHeight = trackVerticalOffset.size() == 0 ? 0 : trackVerticalOffset.lastKey(); IWaveformPainter painter = null; trackVerticalOffset.clear(); - actualValues.clear(); waveformCanvas.clearAllWaveformPainter(); boolean even = true; boolean clearSelection = true; @@ -404,20 +405,21 @@ public class WaveformViewer implements IWaveformViewer { streamEntry.vOffset=trackVerticalHeight; clearSelection &= currentWaveformSelection!=null && (streamEntry.waveform != currentWaveformSelection.waveform); if (streamEntry.isStream()) { + streamEntry.currentValue=""; streamEntry.height *= streamEntry.getStream().getMaxConcurrency(); painter = new StreamPainter(waveformCanvas, even, streamEntry); - actualValues.put(streamEntry.waveform, ""); } else if (streamEntry.isSignal()) { + streamEntry.currentValue="---"; painter = new SignalPainter(waveformCanvas, even, streamEntry); - actualValues.put(streamEntry.waveform, "---"); } - waveformCanvas.addWaveformPainter(painter); + waveformCanvas.addWaveformPainter(painter, false); trackVerticalOffset.put(trackVerticalHeight, streamEntry); tl.setText(streamEntry.waveform.getFullName()); nameMaxWidth = Math.max(nameMaxWidth, tl.getBounds().width); trackVerticalHeight += streamEntry.height; even = !even; } + waveformCanvas.syncScrollBars(); nameList.setSize(nameMaxWidth + 15, trackVerticalHeight); nameListScrolled.setMinSize(nameMaxWidth + 15, trackVerticalHeight); valueList.setSize(calculateValueWidth(), trackVerticalHeight); @@ -437,14 +439,15 @@ public class WaveformViewer implements IWaveformViewer { for(Entry> entry: trackVerticalOffset.entrySet()){ System.out.println(" "+entry.getKey()+": " +entry.getValue().getFullName()); } - */ } + */ + } private int calculateValueWidth() { TextLayout tl = new TextLayout(waveformCanvas.getDisplay()); tl.setFont(nameFontB); int valueMaxWidth = 0; - for (String v : actualValues.values()) { - tl.setText(v); + for (TrackEntry v : streams) { + tl.setText(v.currentValue); valueMaxWidth = Math.max(valueMaxWidth, tl.getBounds().width); } return valueMaxWidth + 15; @@ -452,18 +455,32 @@ public class WaveformViewer implements IWaveformViewer { private void updateValueList(){ final Long time = getCursorTime(); - 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()); + for(TrackEntry entry:streams){ + if(entry.isSignal()){ + ISignalChange event = ((ISignal)entry.waveform).getWaveformEventsBeforeTime(time); + if(event instanceof ISignalChangeBit){ + entry.currentValue="b'"+((ISignalChangeBit)event).getValue(); + } else if(event instanceof ISignalChangeBitVector){ + // TODO: same code resides in SignalPainter, fix it + switch(entry.valueDisplay) { + case SIGNED: + entry.currentValue=Long.toString(((ISignalChangeBitVector)event).getValue().toSignedValue()); + break; + case UNSIGNED: + entry.currentValue=Long.toString(((ISignalChangeBitVector)event).getValue().toUnsignedValue()); + break; + default: + entry.currentValue="h'"+((ISignalChangeBitVector)event).getValue().toHexString(); + } } else if(event instanceof ISignalChangeReal){ - entry.setValue(Double.toString(((ISignalChangeReal)event).getValue())); + double val = ((ISignalChangeReal)event).getValue(); + if(val>0.001) + entry.currentValue=String.format("%1$,.3f", val); + else + entry.currentValue=Double.toString(val); } - } else if(entry.getKey() instanceof ITxStream){ - ITxStream stream = (ITxStream) entry.getKey(); + } else if(entry.isStream()){ + ITxStream stream = (ITxStream) entry.waveform; ITx[] resultsList = new ITx[stream.getMaxConcurrency()]; Entry> firstTx=stream.getEvents().floorEntry(time); if(firstTx!=null){ @@ -485,7 +502,7 @@ public class WaveformViewer implements IWaveformViewer { value+="|"; if(o!=null) value+=((ITx)o).getGenerator().getName(); } - entry.setValue(value); + entry.currentValue=value; } } } @@ -552,11 +569,13 @@ public class WaveformViewer implements IWaveformViewer { */ @Override public ISelection getSelection() { - if (currentTxSelection != null) - return new StructuredSelection(currentTxSelection); - else if (currentWaveformSelection != null) - return new StructuredSelection(currentWaveformSelection.waveform); - else + if (currentTxSelection != null) { + Object[] elem = {currentTxSelection, currentWaveformSelection}; + return new StructuredSelection(elem); + } else if (currentWaveformSelection != null) { + Object[] elem = {currentWaveformSelection.waveform, currentWaveformSelection}; + return new StructuredSelection(elem); + } else return new StructuredSelection(); } @@ -596,6 +615,7 @@ public class WaveformViewer implements IWaveformViewer { currentWaveformSelection = (TrackEntry) sel; if(currentTxSelection!=null && currentTxSelection.getStream()!=currentWaveformSelection) currentTxSelection=null; + selectionChanged = true; } } @@ -608,6 +628,7 @@ public class WaveformViewer implements IWaveformViewer { } if(currentWaveformSelection!=null) currentWaveformSelection.selected=true; if (selectionChanged) { + waveformCanvas.reveal(currentWaveformSelection.waveform); waveformCanvas.setSelected(currentTxSelection); valueList.redraw(); nameList.redraw(); @@ -631,7 +652,16 @@ public class WaveformViewer implements IWaveformViewer { */ @Override public void moveSelection(GotoDirection direction) { - moveSelection(direction, NEXT_PREV_IN_STREAM) ; + if(direction==GotoDirection.NEXT || direction==GotoDirection.PREV) + moveSelection(direction, NEXT_PREV_IN_STREAM) ; + else { + int idx = streams.indexOf(currentWaveformSelection); + if(direction==GotoDirection.UP && idx>0) { + setSelection(new StructuredSelection(streams.get(idx-1))); + } else if(direction==GotoDirection.DOWN && idx<(streams.size()-1)) { + setSelection(new StructuredSelection(streams.get(idx+1))); + } + } } /* (non-Javadoc) @@ -741,6 +771,7 @@ public class WaveformViewer implements IWaveformViewer { setCursorTime(time); waveformCanvas.reveal(time); waveformCanvas.redraw(); + updateValueList(); } } @@ -760,17 +791,21 @@ public class WaveformViewer implements IWaveformViewer { @Override public void moveSelectedTrack(int i) { if(currentWaveformSelection!=null){ - ITx selectedTx=currentTxSelection; - TrackEntry selectedWaveform=currentWaveformSelection; int idx = streams.indexOf(currentWaveformSelection); int newIdx=idx+i; if(newIdx>=0 && newIdx w = trackEntry.waveform; if (w instanceof ITxStream) subArea.height *= ((ITxStream) w).getMaxConcurrency(); - drawValue(gc, subArea, firstKey, actualValues.get(w), trackEntry.selected); + drawValue(gc, subArea, firstKey, trackEntry.currentValue, trackEntry.selected); } else { for (Entry entry : trackVerticalOffset.subMap(firstKey, true, lastKey, true) .entrySet()) { @@ -824,7 +859,7 @@ public class WaveformViewer implements IWaveformViewer { subArea.height = waveformCanvas.getTrackHeight(); if (w instanceof ITxStream) subArea.height *= ((ITxStream) w).getMaxConcurrency(); - drawValue(gc, subArea, entry.getKey(), actualValues.get(w), entry.getValue().selected); + drawValue(gc, subArea, entry.getKey(), entry.getValue().currentValue, entry.getValue().selected); } } }catch(NoSuchElementException e){} @@ -992,7 +1027,7 @@ public class WaveformViewer implements IWaveformViewer { else streams.add(tgtIdx, srcWave); currentWaveformSelection=srcWave; - updateTracklist(); + update(); } else if(source instanceof CursorPainter){ ((CursorPainter)source).setTime(0); updateValueList(); @@ -1185,4 +1220,31 @@ public class WaveformViewer implements IWaveformViewer { 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; +// ScrollBar sb = waveformCanvas.getHorizontalBar(); +// int x = sb.getSelection(); +// System.out.println("Setting sb to "+ (x+diff)); +// if((x+diff)>0) +// sb.setSelection(x+diff); +// else +// sb.setSelection(0); + Point o = waveformCanvas.getOrigin(); + waveformCanvas.setOrigin(o.x-diff, o.y); + waveformCanvas.redraw(); + } + + public void asyncUpdate(Widget widget) { + widget.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + waveformCanvas.redraw(); + updateValueList(); + } + }); + } } diff --git a/com.minres.scviewer.database.ui/META-INF/MANIFEST.MF b/com.minres.scviewer.database.ui/META-INF/MANIFEST.MF index 1b3f7ff..7895eed 100644 --- a/com.minres.scviewer.database.ui/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.database.ui/META-INF/MANIFEST.MF @@ -2,9 +2,10 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Database UI Bundle-SymbolicName: com.minres.scviewer.database.ui -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 2.0.0.qualifier Bundle-Vendor: MINRES Technologies GmbH Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Export-Package: com.minres.scviewer.database.ui Require-Bundle: com.minres.scviewer.database, org.eclipse.jface +Automatic-Module-Name: com.minres.scviewer.database.ui diff --git a/com.minres.scviewer.database.ui/pom.xml b/com.minres.scviewer.database.ui/pom.xml index e7f049f..559e80c 100644 --- a/com.minres.scviewer.database.ui/pom.xml +++ b/com.minres.scviewer.database.ui/pom.xml @@ -1,12 +1,12 @@ 4.0.0 com.minres.scviewer.database.ui - 1.0.0-SNAPSHOT + 2.0.0-SNAPSHOT eclipse-plugin com.minres.scviewer com.minres.scviewer.parent - 1.0.0-SNAPSHOT + 2.0.0-SNAPSHOT ../com.minres.scviewer.parent \ No newline at end of file diff --git a/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/IWaveformViewer.java b/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/IWaveformViewer.java index cac7994..5a4f967 100644 --- a/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/IWaveformViewer.java +++ b/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/IWaveformViewer.java @@ -34,6 +34,8 @@ public interface IWaveformViewer extends PropertyChangeListener, ISelectionProvi public void addSelectionChangedListener(ISelectionChangedListener listener); public void removeSelectionChangedListener(ISelectionChangedListener listener); + + public void update(); public Control getControl(); @@ -100,4 +102,6 @@ public interface IWaveformViewer extends PropertyChangeListener, ISelectionProvi public long getBaselineTime(); public void setBaselineTime(Long scale); + + public void scrollHorizontal(int percent); } \ No newline at end of file diff --git a/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/TrackEntry.java b/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/TrackEntry.java index b40748a..7a9f6d9 100644 --- a/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/TrackEntry.java +++ b/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/TrackEntry.java @@ -17,7 +17,17 @@ import com.minres.scviewer.database.ITxStream; import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveformEvent; + public class TrackEntry { + public enum ValueDisplay { + DEFAULT, SIGNED, UNSIGNED + + } + + public enum WaveDisplay { + DEFAULT, STEP_WISE, CONTINOUS + } + final public IWaveform waveform; public int vOffset; @@ -26,6 +36,12 @@ public class TrackEntry { public boolean selected; + public String currentValue=""; + + public ValueDisplay valueDisplay = ValueDisplay.DEFAULT; + + public WaveDisplay waveDisplay = WaveDisplay.DEFAULT; + public TrackEntry(IWaveform waveform) { this.waveform = waveform; vOffset=0; 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 9ec2786..3c77796 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, SIGNAL_ANALOG, SIGNAL_NAN, + SIGNAL0, SIGNAL1, SIGNALZ, SIGNALX, SIGNALU, SIGNAL_TEXT, SIGNAL_REAL, SIGNAL_NAN, CURSOR, CURSOR_DRAG, CURSOR_TEXT, MARKER, MARKER_TEXT, REL_ARROW, REL_ARROW_HIGHLITE } \ No newline at end of file diff --git a/com.minres.scviewer.database.vcd/META-INF/MANIFEST.MF b/com.minres.scviewer.database.vcd/META-INF/MANIFEST.MF index 035983b..968707f 100644 --- a/com.minres.scviewer.database.vcd/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.database.vcd/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: VCD signal database Bundle-SymbolicName: com.minres.scviewer.database.vcd -Bundle-Version: 1.0.0.qualifier +Bundle-Version: 2.0.0.qualifier Bundle-Vendor: MINRES Technologies GmbH Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0", @@ -13,3 +13,4 @@ Require-Bundle: com.minres.scviewer.database;bundle-version="1.0.0", Service-Component: OSGI-INF/component.xml Bundle-ActivationPolicy: lazy Import-Package: com.google.common.collect +Automatic-Module-Name: com.minres.scviewer.database.vcd diff --git a/com.minres.scviewer.database.vcd/pom.xml b/com.minres.scviewer.database.vcd/pom.xml index f938751..f1a21ec 100644 --- a/com.minres.scviewer.database.vcd/pom.xml +++ b/com.minres.scviewer.database.vcd/pom.xml @@ -4,8 +4,9 @@ com.minres.scviewer com.minres.scviewer.parent - 1.0.0-SNAPSHOT + 2.0.0-SNAPSHOT ../com.minres.scviewer.parent eclipse-plugin - \ No newline at end of file + 2.0.0-SNAPSHOT + \ No newline at end of file diff --git a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/IVCDDatabaseBuilder.java b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/IVCDDatabaseBuilder.java index 3fd9372..9e4bab8 100644 --- a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/IVCDDatabaseBuilder.java +++ b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/IVCDDatabaseBuilder.java @@ -34,34 +34,44 @@ public interface IVCDDatabaseBuilder { * * @param netName the net name * @param i the index of the net, -1 if a new one, otherwise the id if the referenced - * @param width the width - * @return the integer + * @param width the width, -1 equals real, 0... is a bit vector + * @return the net id */ public Integer newNet(String netName, int i, int width) ; /** * Gets the net width. * - * @param intValue the int value - * @return the net width + * @param intValue the net id + * @return the net width, -1 means a real-valued net */ - public int getNetWidth(int intValue); + public int getNetWidth(int netId); /** * Append transition. * - * @param signalId the int value + * @param netId the int value * @param currentTime the current time in ps * @param decodedValues the decoded bit values */ - public void appendTransition(int signalId, long currentTime, BitVector decodedValues); + public void appendTransition(int netId, long currentTime, char decodedValue); /** * Append transition. * - * @param signalId the int value + * @param netId the int value * @param currentTime the current time in ps - * @param vValues the real values + * @param decodedValues the decoded values */ - public void appendTransition(int signalId, long currentTime, Double values); + public void appendTransition(int netId, long currentTime, BitVector decodedValue); + + /** + * Append transition. + * + * @param netId the int value + * @param currentTime the current time in ps + * @param decodedValue the decoded values + */ + public void appendTransition(int netId, long currentTime, double decodedValue); + } diff --git a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDDbLoader.java b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDDbLoader.java index 19b948e..15c5f79 100644 --- a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDDbLoader.java +++ b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDDbLoader.java @@ -15,6 +15,7 @@ import java.io.FileInputStream; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.NavigableMap; import java.util.Stack; import java.util.TreeMap; import java.util.Vector; @@ -22,9 +23,9 @@ import java.util.Vector; import com.minres.scviewer.database.BitVector; import com.minres.scviewer.database.ISignal; import com.minres.scviewer.database.ISignalChange; -import com.minres.scviewer.database.ISignalChangeMulti; +import com.minres.scviewer.database.ISignalChangeBitVector; import com.minres.scviewer.database.ISignalChangeReal; -import com.minres.scviewer.database.ISignalChangeSingle; +import com.minres.scviewer.database.ISignalChangeBit; import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveformDb; import com.minres.scviewer.database.IWaveformDbLoader; @@ -84,20 +85,25 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { moduleStack=null; if(!res) throw new InputFormatException(); // calculate max time of database - for(IWaveform waveform:signals) - maxTime= Math.max(maxTime, ((ISignal)waveform).getEvents().lastKey()); + for(IWaveform waveform:signals) { + NavigableMap events =((ISignal)waveform).getEvents(); + if(events.size()>0) + maxTime= Math.max(maxTime, events.lastKey()); + } // extend signals to hav a last value set at max time for(IWaveform waveform:signals){ TreeMap events = ((VCDSignal)waveform).values; - if(events.lastKey()0 && events.lastKey())waveform).values.put(maxTime, - new VCDSignalChangeSingle(maxTime, ((ISignalChangeSingle)x).getValue())); - else - if(x instanceof ISignalChangeMulti) - ((VCDSignal)waveform).values.put(maxTime, - new VCDSignalChangeMulti(maxTime, ((ISignalChangeMulti)x).getValue())); + if(x instanceof ISignalChangeBit) + ((VCDSignal)waveform).values.put(maxTime, + new VCDSignalChangeBit(maxTime, ((ISignalChangeBit)x).getValue())); + else if(x instanceof ISignalChangeBitVector) + ((VCDSignal)waveform).values.put(maxTime, + new VCDSignalChangeBitVector(maxTime, ((ISignalChangeBitVector)x).getValue())); + else if(x instanceof ISignalChangeReal) + ((VCDSignal)waveform).values.put(maxTime, + new VCDSignalChangeReal(maxTime, ((ISignalChangeReal)x).getValue())); } } return true; @@ -148,12 +154,15 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { String netName = moduleStack.empty()? name: moduleStack.lastElement()+"."+name; int id = signals.size(); VCDSignal signal; - if(width==1){ - signal = i<0 ? new VCDSignal(db, id, netName) : - new VCDSignal((VCDSignal)signals.get(i), id, netName); + if(width<0) { + signal = i<0 ? new VCDSignal(db, id, netName, width) : + new VCDSignal((VCDSignal)signals.get(i), id, netName); + } else if(width==1){ + signal = i<0 ? new VCDSignal(db, id, netName) : + new VCDSignal((VCDSignal)signals.get(i), id, netName); } else { - signal = i<0 ? new VCDSignal(db, id, netName, width) : - new VCDSignal((VCDSignal)signals.get(i), id, netName); + signal = i<0 ? new VCDSignal(db, id, netName, width) : + new VCDSignal((VCDSignal)signals.get(i), id, netName); }; signals.add(signal); return id; @@ -173,10 +182,12 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { */ @SuppressWarnings("unchecked") @Override - public void appendTransition(int signalId, long currentTime, Double value) { + public void appendTransition(int signalId, long currentTime, char decodedValues) { VCDSignal signal = (VCDSignal) signals.get(signalId); Long time = currentTime*TIME_RES; - ((VCDSignal)signal).values.put(time, new VCDSignalChangeReal(time, value)); + if(signal.getWidth()==1){ + ((VCDSignal)signal).values.put(time, new VCDSignalChangeBit(time, decodedValues)); + } } /* (non-Javadoc) @@ -186,11 +197,22 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder { @Override public void appendTransition(int signalId, long currentTime, BitVector decodedValues) { VCDSignal signal = (VCDSignal) signals.get(signalId); - Long time = currentTime*TIME_RES; - if(signal.getWidth()==1){ - ((VCDSignal)signal).values.put(time, new VCDSignalChangeSingle(time, decodedValues.getValue()[0])); - } else { - ((VCDSignal)signal).values.put(time, new VCDSignalChangeMulti(time, decodedValues)); + Long time = currentTime* TIME_RES; + if(signal.getWidth()>1){ + ((VCDSignal)signal).values.put(time, new VCDSignalChangeBitVector(time, decodedValues)); + } + } + + /* (non-Javadoc) + * @see com.minres.scviewer.database.vcd.ITraceBuilder#appendTransition(int, long, com.minres.scviewer.database.vcd.BitVector) + */ + @SuppressWarnings("unchecked") + @Override + public void appendTransition(int signalId, long currentTime, double decodedValue) { + VCDSignal signal = (VCDSignal) signals.get(signalId); + Long time = currentTime* TIME_RES; + if(signal.getWidth()<0){ + ((VCDSignal)signal).values.put(time, new VCDSignalChangeReal(time, decodedValue)); } } diff --git a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDFileParser.java b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDFileParser.java index 0b128ad..c714dec 100644 --- a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDFileParser.java +++ b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDFileParser.java @@ -61,9 +61,11 @@ class VCDFileParser { private void parseVar() throws Exception { nextToken(); // type + String type = tokenizer.sval; nextToken(); // size int width = Integer.parseInt(tokenizer.sval); - + if("real".equals(type)) + width*=-1; nextToken(); String id = tokenizer.sval; nextToken(); @@ -147,14 +149,14 @@ class VCDFileParser { if (tokenizer.sval.charAt(0) == '#') { // If the line begins with a #, this is a timestamp. currentTime = Long.parseLong(tokenizer.sval.substring(1)) * picoSecondsPerIncrement; } else { - boolean isReal=false; if(tokenizer.sval.equals("$comment")){ do { if (!nextToken()) return false; } while (!tokenizer.sval.equals("$end")); return true; } - if (tokenizer.sval.equals("$dumpvars") || tokenizer.sval.equals("$end")) return true; + if (tokenizer.sval.equals("$dumpvars") || tokenizer.sval.equals("$end")) + return true; String value, id; if (tokenizer.sval.charAt(0) == 'b') { // Multiple value net. Value appears first, followed by space, @@ -162,13 +164,12 @@ class VCDFileParser { value = tokenizer.sval.substring(1); nextToken(); id = tokenizer.sval; - } else if (tokenizer.sval.charAt(0) == 'r') { - // real value net. Value appears first, followed by space, - // then identifier - value = tokenizer.sval.substring(1); - nextToken(); - id = tokenizer.sval; - isReal=true; + }else if (tokenizer.sval.charAt(0) == 'r') { + // Multiple value net. Value appears first, followed by space, + // then identifier + value = tokenizer.sval.substring(1); + nextToken(); + id = tokenizer.sval; } else { // Single value net. identifier first, then value, no space. value = tokenizer.sval.substring(0, 1); @@ -181,14 +182,10 @@ class VCDFileParser { return true; } - if(isReal) { - if("nan".equals(value)) { - traceBuilder.appendTransition(net, currentTime, Double.NaN); - } else { - traceBuilder.appendTransition(net, currentTime, Double.parseDouble(value)); - } + int netWidth = traceBuilder.getNetWidth(net); + if(netWidth<0) { + traceBuilder.appendTransition(net, currentTime, Double.parseDouble(value)); } else { - int netWidth = traceBuilder.getNetWidth(net); BitVector decodedValues = new BitVector(netWidth); if (value.equals("z") && netWidth > 1) { for (int i = 0; i < netWidth; i++) @@ -221,7 +218,10 @@ class VCDFileParser { } } } - traceBuilder.appendTransition(net, currentTime, decodedValues); + if(netWidth==1) + traceBuilder.appendTransition(net, currentTime, decodedValues.getValue()[0]); + else + traceBuilder.appendTransition(net, currentTime, decodedValues); } } return true; diff --git a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeSingle.java b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeBit.java similarity index 80% rename from com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeSingle.java rename to com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeBit.java index a8fc14b..b24870c 100644 --- a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeSingle.java +++ b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeBit.java @@ -10,14 +10,14 @@ *******************************************************************************/ package com.minres.scviewer.database.vcd; -import com.minres.scviewer.database.ISignalChangeSingle; +import com.minres.scviewer.database.ISignalChangeBit; import com.minres.scviewer.database.SignalChange; -public class VCDSignalChangeSingle extends SignalChange implements ISignalChangeSingle, Cloneable { +public class VCDSignalChangeBit extends SignalChange implements ISignalChangeBit, Cloneable { private char value; - public VCDSignalChangeSingle(Long time, char value) { + public VCDSignalChangeBit(Long time, char value) { super(time); this.value=value; } diff --git a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeMulti.java b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeBitVector.java similarity index 77% rename from com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeMulti.java rename to com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeBitVector.java index e38c50f..10b8714 100644 --- a/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeMulti.java +++ b/com.minres.scviewer.database.vcd/src/com/minres/scviewer/database/vcd/VCDSignalChangeBitVector.java @@ -11,18 +11,18 @@ package com.minres.scviewer.database.vcd; import com.minres.scviewer.database.BitVector; -import com.minres.scviewer.database.ISignalChangeMulti; +import com.minres.scviewer.database.ISignalChangeBitVector; import com.minres.scviewer.database.SignalChange; -public class VCDSignalChangeMulti extends SignalChange implements ISignalChangeMulti, Cloneable { +public class VCDSignalChangeBitVector extends SignalChange implements ISignalChangeBitVector, Cloneable { private BitVector value; - public VCDSignalChangeMulti(Long time) { + public VCDSignalChangeBitVector(Long time) { super(time); } - public VCDSignalChangeMulti(Long time, BitVector decodedValues) { + public VCDSignalChangeBitVector(Long time, BitVector decodedValues) { super(time); this.value=decodedValues; } diff --git a/com.minres.scviewer.database/META-INF/MANIFEST.MF b/com.minres.scviewer.database/META-INF/MANIFEST.MF index 7260a67..c1ec1ec 100644 --- a/com.minres.scviewer.database/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.database/META-INF/MANIFEST.MF @@ -11,3 +11,4 @@ Service-Component: OSGI-INF/component.xml,OSGI-INF/component2.xml Require-Bundle: org.eclipse.equinox.ds;bundle-version="1.4.200", org.eclipse.equinox.util;bundle-version="1.0.500", org.eclipse.osgi.services;bundle-version="3.4.0" +Automatic-Module-Name: com.minres.scviewer.database diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/BitVector.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/BitVector.java index 7ceb08d..ff4104a 100644 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/BitVector.java +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/BitVector.java @@ -63,4 +63,49 @@ public class BitVector { } return new String(res); } + + public long toUnsignedValue() { + long res = 0; + for(char c:value) { + res<<=1; + switch (c) { + case VALUE_1: + res++; + break; + case VALUE_X: + case VALUE_Z: + return 0; + default: + break; + } + } + return res; + } + + public long toSignedValue() { + Boolean negative=null; + long res = 0; + for(char c:value) { + if(negative == null) { + switch (c) { + case VALUE_1: negative=true; break; + case VALUE_0: negative=false; break; + case VALUE_X: + case VALUE_Z: return 0; + default: + } + } else { + res<<=1; + switch (c) { + case VALUE_1: if(!negative) res++; break; + case VALUE_0: if(negative) res++; break; + case VALUE_X: + case VALUE_Z: return 0; + default: + } + } + } + return negative?-1*(res+1):res; + } } + diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChangeSingle.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChangeBit.java similarity index 91% rename from com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChangeSingle.java rename to com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChangeBit.java index 1319685..3cf747e 100644 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChangeSingle.java +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChangeBit.java @@ -10,7 +10,7 @@ *******************************************************************************/ package com.minres.scviewer.database; -public interface ISignalChangeSingle extends ISignalChange{ +public interface ISignalChangeBit extends ISignalChange{ public char getValue(); diff --git a/com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChangeMulti.java b/com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChangeBitVector.java similarity index 90% rename from com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChangeMulti.java rename to com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChangeBitVector.java index ec9b770..be94346 100644 --- a/com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChangeMulti.java +++ b/com.minres.scviewer.database/src/com/minres/scviewer/database/ISignalChangeBitVector.java @@ -10,8 +10,7 @@ *******************************************************************************/ package com.minres.scviewer.database; - -public interface ISignalChangeMulti extends ISignalChange { +public interface ISignalChangeBitVector extends ISignalChange { public BitVector getValue(); diff --git a/com.minres.scviewer.e4.application/Application.e4xmi b/com.minres.scviewer.e4.application/Application.e4xmi index 35149e6..8b7c1e3 100644 --- a/com.minres.scviewer.e4.application/Application.e4xmi +++ b/com.minres.scviewer.e4.application/Application.e4xmi @@ -108,7 +108,7 @@ - + @@ -142,7 +142,7 @@ - + @@ -171,6 +171,8 @@ + + @@ -204,40 +206,51 @@ + + + + + - - - - - + + + + + - - - + + + - + - + - + - + - + - + + + + + + + diff --git a/com.minres.scviewer.e4.application/META-INF/MANIFEST.MF b/com.minres.scviewer.e4.application/META-INF/MANIFEST.MF index 93b5bc6..96a8505 100644 --- a/com.minres.scviewer.e4.application/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.e4.application/META-INF/MANIFEST.MF @@ -2,36 +2,37 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Bundle-SymbolicName: com.minres.scviewer.e4.application;singleton:=true -Bundle-Version: 1.1.1.qualifier +Bundle-Version: 2.0.0.qualifier Bundle-Vendor: %Bundle-Vendor Require-Bundle: javax.inject;bundle-version="1.0.0", - org.eclipse.core.runtime;bundle-version="3.11.1", - org.eclipse.swt;bundle-version="3.104.1", - org.eclipse.e4.ui.model.workbench;bundle-version="1.1.100", - org.eclipse.jface;bundle-version="3.11.0", - org.eclipse.e4.ui.services;bundle-version="1.2.0", - org.eclipse.e4.ui.workbench;bundle-version="1.3.0", - org.eclipse.e4.core.di;bundle-version="1.5.0", - org.eclipse.e4.ui.di;bundle-version="1.1.0", - org.eclipse.e4.core.contexts;bundle-version="1.4.0", - com.minres.scviewer.database.ui.swt;bundle-version="1.0.0", - com.minres.scviewer.database.ui, - com.minres.scviewer.database;bundle-version="1.0.0", - org.eclipse.equinox.ds;bundle-version="1.4.300", - org.eclipse.equinox.util;bundle-version="1.0.500", - org.eclipse.osgi.services;bundle-version="3.5.0", - org.eclipse.e4.core.services;bundle-version="2.0.0", - org.eclipse.osgi.services;bundle-version="3.5.0", - org.eclipse.core.jobs, - org.eclipse.osgi, - com.google.guava, - org.eclipse.equinox.preferences, - org.eclipse.core.expressions, - org.eclipse.e4.core.commands;bundle-version="0.11.0", - org.eclipse.e4.ui.workbench.addons.swt, - com.opcoach.e4.preferences, - org.eclipse.e4.core.di.extensions, - org.eclipse.e4.ui.css.swt.theme;bundle-version="0.10.0" + org.eclipse.core.runtime;bundle-version="3.11.1", + org.eclipse.swt;bundle-version="3.104.1", + org.eclipse.e4.ui.model.workbench;bundle-version="1.1.100", + org.eclipse.jface;bundle-version="3.11.0", + org.eclipse.e4.ui.services;bundle-version="1.2.0", + org.eclipse.e4.ui.workbench;bundle-version="1.3.0", + org.eclipse.e4.core.di;bundle-version="1.5.0", + org.eclipse.e4.ui.di;bundle-version="1.1.0", + org.eclipse.e4.core.contexts;bundle-version="1.4.0", + com.minres.scviewer.database.ui.swt;bundle-version="1.0.0", + com.minres.scviewer.database.ui, + com.minres.scviewer.database;bundle-version="1.0.0", + org.eclipse.equinox.ds;bundle-version="1.4.300", + org.eclipse.equinox.util;bundle-version="1.0.500", + org.eclipse.osgi.services;bundle-version="3.5.0", + org.eclipse.e4.core.services;bundle-version="2.0.0", + org.eclipse.osgi.services;bundle-version="3.5.0", + org.eclipse.core.jobs, + org.eclipse.osgi, + com.google.guava, + org.eclipse.equinox.preferences, + org.eclipse.core.expressions, + org.eclipse.e4.core.commands;bundle-version="0.11.0", + org.eclipse.e4.ui.workbench.addons.swt, + com.opcoach.e4.preferences, + org.eclipse.e4.core.di.extensions, + org.eclipse.e4.ui.css.swt.theme;bundle-version="0.10.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: com.minres.scviewer.database, - javax.inject;version="1.0.0" + javax.inject;version="1.0.0" +Automatic-Module-Name: com.minres.scviewer.e4.application diff --git a/com.minres.scviewer.e4.application/plugin.xml b/com.minres.scviewer.e4.application/plugin.xml index 1368d13..236f625 100644 --- a/com.minres.scviewer.e4.application/plugin.xml +++ b/com.minres.scviewer.e4.application/plugin.xml @@ -16,6 +16,10 @@ name="appName" value="SCViewer"> + + com.minres.scviewer com.minres.scviewer.parent - 1.0.0-SNAPSHOT + 2.0.0-SNAPSHOT ../com.minres.scviewer.parent eclipse-plugin - 1.1.1-SNAPSHOT \ No newline at end of file diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/E4LifeCycle.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/E4LifeCycle.java index 07d2a46..707989f 100644 --- a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/E4LifeCycle.java +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/E4LifeCycle.java @@ -33,6 +33,10 @@ import org.eclipse.equinox.app.IApplicationContext; import org.osgi.service.event.Event; import org.osgi.service.event.EventHandler; +import com.minres.scviewer.e4.application.options.Options; +import com.minres.scviewer.e4.application.options.Options.Multiplicity; +import com.minres.scviewer.e4.application.options.Options.Separator; + /** * This implementation contains e4 LifeCycle annotated methods.
* There is a corresponding entry in plugin.xml (under the @@ -59,7 +63,14 @@ public class E4LifeCycle { */ @PostContextCreate void postContextCreate(IApplicationContext appContext, final IEventBroker eventBroker) { - final String[] args = (String[])appContext.getArguments().get(IApplicationContext.APPLICATION_ARGS); + final String[] args = (String[])appContext.getArguments().get(IApplicationContext.APPLICATION_ARGS); + Options opt = new Options(args, 1); + opt.getSet().addOption("c", Separator.BLANK, Multiplicity.ONCE); + if (!opt.check(Options.DEFAULT_SET, true, true)) { + System.exit(1); + } + final String confFile =opt.getSet().isSet("c")?opt.getSet().getOption("c").getResultValue(0):""; + // react on the first view being created, at that time the UI is available eventBroker.subscribe(UIEvents.UILifeCycle.ACTIVATE, new EventHandler() { @Override @@ -68,9 +79,10 @@ public class E4LifeCycle { if(part!=null){ IEclipseContext ctx = part.getContext(); OpenViewHandler openViewHandler= new OpenViewHandler(); + if(confFile.length()>0) openViewHandler.setConfigFile(confFile); ContextInjectionFactory.inject(openViewHandler, ctx); eventBroker.unsubscribe(this); - for(String name:args){ + for(String name:opt.getSet().getData()){ if(new File(name).exists()) openViewHandler.openViewForFile(name); } } @@ -136,6 +148,7 @@ public class E4LifeCycle { /** The part service. */ @Inject EPartService partService; + String confFile=""; /** * Open view for file. * @@ -150,7 +163,13 @@ public class E4LifeCycle { partService.showPart(part, PartState.ACTIVATE); IEclipseContext ctx=part.getContext(); ctx.modify("input", file); //$NON-NLS-1$ - ctx.declareModifiable("input"); //$NON-NLS-1$ + //ctx.declareModifiable("input"); //$NON-NLS-1$ + ctx.modify("config", confFile); //$NON-NLS-1$ + //ctx.declareModifiable("config"); //$NON-NLS-1$ + } + + public void setConfigFile(String confFile) { + this.confFile=confFile; } } } diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/elements/NavigateContribution.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/elements/NavigateToolbarContribution.java similarity index 98% rename from com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/elements/NavigateContribution.java rename to com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/elements/NavigateToolbarContribution.java index cc61765..fc8db23 100644 --- a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/elements/NavigateContribution.java +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/elements/NavigateToolbarContribution.java @@ -32,7 +32,7 @@ import com.minres.scviewer.e4.application.parts.WaveformViewer; /** * The Class NavigateContribution. Currently not used in Application.e4xmi */ -public class NavigateContribution { +public class NavigateToolbarContribution { /** The part service. */ @Inject EPartService partService; diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/elements/WaveformPopupMenuContribution.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/elements/WaveformPopupMenuContribution.java new file mode 100644 index 0000000..89eb25a --- /dev/null +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/elements/WaveformPopupMenuContribution.java @@ -0,0 +1,131 @@ + +package com.minres.scviewer.e4.application.elements; + +import java.util.Iterator; +import java.util.List; + +import javax.inject.Inject; + +import org.eclipse.e4.core.di.annotations.Evaluate; +import org.eclipse.e4.ui.di.AboutToHide; +import org.eclipse.e4.ui.di.AboutToShow; +import org.eclipse.e4.ui.model.application.MApplication; +import org.eclipse.e4.ui.model.application.commands.MCommand; +import org.eclipse.e4.ui.model.application.commands.MCommandsFactory; +import org.eclipse.e4.ui.model.application.commands.MParameter; +import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.model.application.ui.menu.ItemType; +import org.eclipse.e4.ui.model.application.ui.menu.MHandledMenuItem; +import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement; +import org.eclipse.e4.ui.model.application.ui.menu.MMenuFactory; +import org.eclipse.e4.ui.workbench.modeling.EModelService; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; + +import com.minres.scviewer.database.ISignal; +import com.minres.scviewer.database.ISignalChange; +import com.minres.scviewer.database.ISignalChangeBitVector; +import com.minres.scviewer.database.ISignalChangeReal; +import com.minres.scviewer.database.ui.TrackEntry; +import com.minres.scviewer.e4.application.parts.WaveformViewer; + +public class WaveformPopupMenuContribution { + int counter=0; + + @Inject MPart activePart; + + final TrackEntry nullEntry = new TrackEntry(null); + + @Evaluate + public boolean evaluate() { + Object obj = activePart.getObject(); + if(obj instanceof WaveformViewer){ + WaveformViewer wfv = (WaveformViewer)obj; + ISelection sel = wfv.getSelection(); + if(!sel.isEmpty() && sel instanceof IStructuredSelection) { + Object selected = ((IStructuredSelection)sel).getFirstElement(); + if(selected instanceof ISignal) { + ISignalChange s = (ISignalChange) ((ISignal) selected).getEvents().firstEntry().getValue(); + if((s instanceof ISignalChangeReal) || (s instanceof ISignalChangeBitVector)) { + return true; + } + } + } + } + return false; + } + + @AboutToShow + public void aboutToShow(List items, MApplication application, EModelService modelService) { + Object obj = activePart.getObject(); + if(obj instanceof WaveformViewer){ + WaveformViewer wfv = (WaveformViewer)obj; + ISelection sel = wfv.getSelection(); + if(!sel.isEmpty() && sel instanceof IStructuredSelection) { + Iterator it = ((IStructuredSelection)sel).iterator(); + Object first = it.next(); + Object second=null; + if(it.hasNext()) second=it.next(); + if(first instanceof ISignal) { + ISignalChange s = (ISignalChange) ((ISignal) first).getEvents().firstEntry().getValue(); + //com.minres.scviewer.e4.application.menu.mulitvaluesettings + if((s instanceof ISignalChangeReal) || (s instanceof ISignalChangeBitVector)) { + TrackEntry entry=nullEntry; + if(second instanceof TrackEntry) + entry=(TrackEntry)second; + if(s instanceof ISignalChangeBitVector) { + addValueMenuItem(items, application, modelService, "hex", TrackEntry.ValueDisplay.DEFAULT, entry.valueDisplay); + addValueMenuItem(items, application, modelService, "unsigned", TrackEntry.ValueDisplay.UNSIGNED, entry.valueDisplay); + addValueMenuItem(items, application, modelService, "signed", TrackEntry.ValueDisplay.SIGNED, entry.valueDisplay); + items.add(MMenuFactory.INSTANCE.createMenuSeparator()); + addWaveMenuItem(items, application, modelService, "bit vector", TrackEntry.WaveDisplay.DEFAULT, entry.waveDisplay); + } + addWaveMenuItem(items, application, modelService, "analog step-wise", TrackEntry.WaveDisplay.STEP_WISE, entry.waveDisplay); + addWaveMenuItem(items, application, modelService, "analog continous", TrackEntry.WaveDisplay.CONTINOUS, entry.waveDisplay); + } + } + } + } + + } + + private void addValueMenuItem(List items, MApplication application, EModelService modelService, + String label, TrackEntry.ValueDisplay value, TrackEntry.ValueDisplay actual) { + MHandledMenuItem item = MMenuFactory.INSTANCE.createHandledMenuItem(); + item.setType(ItemType.RADIO); + item.setSelected(value==actual); + item.setLabel("Show as "+label); + item.setContributorURI("platform:/plugin/com.minres.scviewer.e4.application"); + List cmds = modelService.findElements(application, "com.minres.scviewer.e4.application.command.changevaluedisplay", MCommand.class, null); + if(cmds.size()!=1) System.err.println("No command found!"); + else item.setCommand(cmds.get(0)); + MParameter param = MCommandsFactory.INSTANCE.createParameter(); + param.setName("com.minres.scviewer.e4.application.commandparameter.changevaluedisplay"); + param.setValue(value.toString()); + item.getParameters().add(param); + items.add(item); + } + + private void addWaveMenuItem(List items, MApplication application, EModelService modelService, + String label, TrackEntry.WaveDisplay value, TrackEntry.WaveDisplay actual) { + MHandledMenuItem item = MMenuFactory.INSTANCE.createHandledMenuItem(); + item.setType(ItemType.RADIO); + item.setSelected(value==actual); + item.setLabel("Render "+label); + item.setContributorURI("platform:/plugin/com.minres.scviewer.e4.application"); + List cmds = modelService.findElements(application, "com.minres.scviewer.e4.application.command.changewavedisplay", MCommand.class, null); + if(cmds.size()!=1) System.err.println("No command found!"); + else item.setCommand(cmds.get(0)); + MParameter param = MCommandsFactory.INSTANCE.createParameter(); + param.setName("com.minres.scviewer.e4.application.commandparameter.changewavedisplay"); + param.setValue(value.toString()); + item.getParameters().add(param); + items.add(item); + } + + @AboutToHide + public void aboutToHide(List items) { + + } + +} \ No newline at end of file diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/AboutHandler.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/AboutHandler.java index 440b272..6d5db35 100644 --- a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/AboutHandler.java +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/AboutHandler.java @@ -12,16 +12,17 @@ package com.minres.scviewer.e4.application.handlers; import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.e4.ui.model.application.MApplication; -import org.eclipse.e4.ui.model.application.ui.basic.MDialog; import org.eclipse.e4.ui.model.application.ui.basic.MWindow; import org.eclipse.e4.ui.workbench.modeling.EModelService; import org.eclipse.swt.widgets.Shell; public class AboutHandler { + static final String DIALOG_ID="com.minres.scviewer.e4.application.dialog.aboutscviewer"; + @Execute public void execute(Shell shell, MApplication app, MWindow window, EModelService ms /*@Named("mdialog01.dialog.0") MDialog dialog*/) { - MDialog dialog = (MDialog) ms.find("com.minres.scviewer.e4.application.dialog.aboutscviewer", app); //$NON-NLS-1$ + MWindow dialog = (MWindow) ms.find(DIALOG_ID, app); //$NON-NLS-1$ dialog.setToBeRendered(true); dialog.setToBeRendered(false); } diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/ChangeValueDisplay.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/ChangeValueDisplay.java new file mode 100644 index 0000000..caaf007 --- /dev/null +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/ChangeValueDisplay.java @@ -0,0 +1,51 @@ + +package com.minres.scviewer.e4.application.handlers; + +import java.util.Iterator; + +import javax.inject.Named; + +import org.eclipse.e4.core.di.annotations.CanExecute; +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 org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; + +import com.minres.scviewer.database.ui.TrackEntry; +import com.minres.scviewer.e4.application.parts.WaveformViewer; + +public class ChangeValueDisplay { + + static final String PARAMETER_ID="com.minres.scviewer.e4.application.commandparameter.changevaluedisplay"; //$NON-NLS-1$ + + @CanExecute + public boolean canExecute(EPartService partService) { + MPart part = partService.getActivePart(); + if(part==null) return false; + return (part.getObject() instanceof WaveformViewer); + } + + @Execute + public void execute(@Named(PARAMETER_ID) String param, EPartService partService) { + MPart part = partService.getActivePart(); + Object obj = part.getObject(); + if(obj instanceof WaveformViewer){ + WaveformViewer wfv = (WaveformViewer)obj; + ISelection sel = wfv.getSelection(); + if(!sel.isEmpty() && sel instanceof IStructuredSelection) { + Iterator it = ((IStructuredSelection)sel).iterator(); + it.next(); + if(it.hasNext()) { + Object second = it.next(); + if(second instanceof TrackEntry) { + TrackEntry.ValueDisplay val = TrackEntry.ValueDisplay.valueOf(param); + ((TrackEntry)second).valueDisplay=val; + wfv.update(); + } + } + } + } + } + +} \ No newline at end of file diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/ChangeWaveformDisplay.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/ChangeWaveformDisplay.java new file mode 100644 index 0000000..c4af6c0 --- /dev/null +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/handlers/ChangeWaveformDisplay.java @@ -0,0 +1,51 @@ + +package com.minres.scviewer.e4.application.handlers; + +import java.util.Iterator; + +import javax.inject.Named; + +import org.eclipse.e4.core.di.annotations.CanExecute; +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 org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; + +import com.minres.scviewer.database.ui.TrackEntry; +import com.minres.scviewer.e4.application.parts.WaveformViewer; + +public class ChangeWaveformDisplay { + + static final String PARAMETER_ID="com.minres.scviewer.e4.application.commandparameter.changewavedisplay"; //$NON-NLS-1$ + + @CanExecute + public boolean canExecute(EPartService partService) { + MPart part = partService.getActivePart(); + if(part==null) return false; + return (part.getObject() instanceof WaveformViewer); + } + + @Execute + public void execute(@Named(PARAMETER_ID) String param, EPartService partService) { + MPart part = partService.getActivePart(); + Object obj = part.getObject(); + if(obj instanceof WaveformViewer){ + WaveformViewer wfv = (WaveformViewer)obj; + ISelection sel = wfv.getSelection(); + if(!sel.isEmpty() && sel instanceof IStructuredSelection) { + Iterator it = ((IStructuredSelection)sel).iterator(); + it.next(); + if(it.hasNext()) { + Object second = it.next(); + if(second instanceof TrackEntry) { + TrackEntry.WaveDisplay val= TrackEntry.WaveDisplay.valueOf(param); + ((TrackEntry)second).waveDisplay=val; + wfv.update(); + } + } + } + } + } + +} \ No newline at end of file diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/messages.properties b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/messages.properties index 7848715..4a5a274 100644 --- a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/messages.properties +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/messages.properties @@ -1,5 +1,5 @@ -AboutDialog_0=\nSCViewer - a SystemC waveform viewer\n\nVersion: 1.2.2\n -AboutDialog_1=\nCopyright (c) 2015,2016,2017 MINRES Technologies GmbH and others.\n\nAll rights reserved. MINRES and the MINRES logo are trademarks of MINRES Technologies GmbH, http://www.minres.com/. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html\n\nParts of the software are governed by the Apache License Version 2.0 available at http://www.apache.org/licenses/. These are namely org.apache.jdbm and org.sqlite JDBC driver\n\nSources code is hosted at GitHub: https://github.com/minres/SCViewer\n +AboutDialog_0=\nSCViewer - a SystemC waveform viewer\n\nVersion: 2.0\n +AboutDialog_1=\nCopyright (c) 2015, 2018 MINRES Technologies GmbH and others.\n\nAll rights reserved. MINRES and the MINRES logo are trademarks of MINRES Technologies GmbH, http://www.minres.com/. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html\n\nParts of the software are governed by the Apache License Version 2.0 available at http://www.apache.org/licenses/. These are namely org.apache.jdbm and org.sqlite JDBC driver\n\nSources code is hosted at GitHub: https://github.com/minres/SCViewer\n DesignBrowser_12=Append all after DesignBrowser_16=Insert all before DesignBrowser_2=Enter text to filter waveforms diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/options/OptionData.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/options/OptionData.java new file mode 100644 index 0000000..e1218c8 --- /dev/null +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/options/OptionData.java @@ -0,0 +1,275 @@ +package com.minres.scviewer.e4.application.options; + +/** + * This class holds all the data for an option. This includes the prefix, the key, the separator + * (for value options), the multiplicity, and all the other settings describing the option. The class + * is designed to be only a data container from a user perspective, i. e. the user has read-access to + * any data determined by the {@link Options#check()}, but not access to any of the other methods + * which are used internally for the operation of the actual check. + */ + +public class OptionData { + + private final static String CLASS = "OptionData"; + + private Options.Prefix prefix = null; + private String key = null; + private boolean detail = false; + private Options.Separator separator = null; + private boolean value = false; + private Options.Multiplicity multiplicity = null; + private java.util.regex.Pattern pattern = null; + private int counter = 0; + private java.util.ArrayList values = null; + private java.util.ArrayList details = null; + +/** + * The constructor + */ + + OptionData(Options.Prefix prefix, + String key, + boolean detail, + Options.Separator separator, + boolean value, + Options.Multiplicity multiplicity) { + + if (prefix == null) throw new IllegalArgumentException(CLASS + ": prefix may not be null"); + if (key == null) throw new IllegalArgumentException(CLASS + ": key may not be null"); + if (separator == null) throw new IllegalArgumentException(CLASS + ": separator may not be null"); + if (multiplicity == null) throw new IllegalArgumentException(CLASS + ": multiplicity may not be null"); + +//.... The data describing the option + + this.prefix = prefix; + this.key = key; + this.detail = detail; + this.separator = separator; + this.value = value; + this.multiplicity = multiplicity; + +//.... Create the pattern to match this option + + if (value) { + if (separator == Options.Separator.BLANK) { + if (detail) { + pattern = java.util.regex.Pattern.compile(prefix.getName() + key + "((\\w|\\.)+)$"); + } else { + pattern = java.util.regex.Pattern.compile(prefix.getName() + key + "$"); + } + } else { + if (detail) { + pattern = java.util.regex.Pattern.compile(prefix.getName() + key + "((\\w|\\.)+)" + separator.getName() + "(.+)$"); + } else { + pattern = java.util.regex.Pattern.compile(prefix.getName() + key + separator.getName() + "(.+)$"); + } + } + } else { + pattern = java.util.regex.Pattern.compile(prefix.getName() + key + "$"); + } + +//.... Structures to hold result data + + if (value) { + values = new java.util.ArrayList(); + if (detail) + details = new java.util.ArrayList(); + } + + } + +/** + * Getter method for prefix property + *

+ * @return The value for the prefix property + */ + + Options.Prefix getPrefix() { + return prefix; + } + +/** + * Getter method for key property + *

+ * @return The value for the key property + */ + + String getKey() { + return key; + } + +/** + * Getter method for detail property + *

+ * @return The value for the detail property + */ + + boolean useDetail() { + return detail; + } + +/** + * Getter method for separator property + *

+ * @return The value for the separator property + */ + + Options.Separator getSeparator() { + return separator; + } + +/** + * Getter method for value property + *

+ * @return The value for the value property + */ + + boolean useValue() { + return value; + } + +/** + * Getter method for multiplicity property + *

+ * @return The value for the multiplicity property + */ + + Options.Multiplicity getMultiplicity() { + return multiplicity; + } + +/** + * Getter method for pattern property + *

+ * @return The value for the pattern property + */ + + java.util.regex.Pattern getPattern() { + return pattern; + } + +/** + * Get the number of results found for this option, which is number of times the key matched + *

+ * @return The number of results + */ + + public int getResultCount() { + if (value) { + return values.size(); + } else { + return counter; + } + } + +/** + * Get the value with the given index. The index can range between 0 and {@link #getResultCount()} - 1. + * However, only for value options, a non-null value will be returned. Non-value options always + * return null. + *

+ * @param index The index for the desired value + *

+ * @return The option value with the given index + *

+ * @throws IllegalArgumentException If the value for index is out of bounds + */ + + public String getResultValue(int index) { + if (!value) return null; + if (index < 0 || index >= getResultCount()) throw new IllegalArgumentException(CLASS + ": illegal value for index"); + return values.get(index); + } + +/** + * Get the detail with the given index. The index can range between 0 and {@link #getResultCount()} - 1. + * However, only for value options which take details, a non-null detail will be returned. Non-value options + * and value options which do not take details always return null. + *

+ * @param index The index for the desired value + *

+ * @return The option detail with the given index + *

+ * @throws IllegalArgumentException If the value for index is out of bounds + */ + + public String getResultDetail(int index) { + if (!detail) return null; + if (index < 0 || index >= getResultCount()) throw new IllegalArgumentException(CLASS + ": illegal value for index"); + return details.get(index); + } + +/** + * Store the data for a match found + */ + + void addResult(String valueData, String detailData) { + if (value) { + if (valueData == null) throw new IllegalArgumentException(CLASS + ": valueData may not be null"); + values.add(valueData); + if (detail) { + if (detailData == null) throw new IllegalArgumentException(CLASS + ": detailData may not be null"); + details.add(detailData); + } + } + counter++; + } + +/** + * This is the overloaded {@link Object#toString()} method, and it is provided mainly for debugging + * purposes. + *

+ * @return A string representing the instance + */ + + public String toString() { + + StringBuffer sb = new StringBuffer(); + + sb.append("Prefix : "); + sb.append(prefix); + sb.append('\n'); + sb.append("Key : "); + sb.append(key); + sb.append('\n'); + sb.append("Detail : "); + sb.append(detail); + sb.append('\n'); + sb.append("Separator : "); + sb.append(separator); + sb.append('\n'); + sb.append("Value : "); + sb.append(value); + sb.append('\n'); + sb.append("Multiplicity: "); + sb.append(multiplicity); + sb.append('\n'); + sb.append("Pattern : "); + sb.append(pattern); + sb.append('\n'); + + sb.append("Results : "); + sb.append(counter); + sb.append('\n'); + if (value) { + if (detail) { + for (int i = 0; i < values.size(); i++) { + sb.append(details.get(i)); + sb.append(" / "); + sb.append(values.get(i)); + sb.append('\n'); + } + } else { + for (int i = 0; i < values.size(); i++) { + sb.append(values.get(i)); + sb.append('\n'); + } + } + } + + return sb.toString(); + + } + +} + + diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/options/OptionSet.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/options/OptionSet.java new file mode 100644 index 0000000..c320f61 --- /dev/null +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/options/OptionSet.java @@ -0,0 +1,276 @@ +package com.minres.scviewer.e4.application.options; + +/** + * This class holds the information for a set of options. A set can hold any number of + * OptionData instances which are checked together to determine success or failure. + *

+ * The approach to use this class looks like this: + *

+ *

    + *
  1. The user uses any of the Options.addSet() (e. g. {@link Options#addSet(String)}) to create + * any number of sets required (or just relies on the default set, if only one set is required) + *
  2. The user adds all required option definitions to each set + *
  3. Using any of the Options.check() methods, each set can be checked whether the options + * that were specified on the command line satisfy its requirements + *
  4. If the check was successful for a given set, several data items are available from this class: + *
      + *
    • All options defined for the set (through with e. g. values, details, and multiplicity are available) + *
    • All data items found (these are the items on the command line which do not start with the prefix, + * i. e. non-option arguments) + *
    • All unmatched arguments on the command line (these are the items on the command line which start + * with the prefix, but do not match to one of the options). + * Programs can elect to ignore these, or react with an error + *
    + *
+ */ + +public class OptionSet { + + private final static String CLASS = "OptionSet"; + + private java.util.ArrayList options = new java.util.ArrayList(); + private java.util.HashMap keys = new java.util.HashMap(); + private java.util.ArrayList unmatched = new java.util.ArrayList(); + private java.util.ArrayList data = new java.util.ArrayList(); + private String setName = null; + private int minData = 0; + private int maxData = 0; + private Options.Prefix prefix = null; + private Options.Multiplicity defaultMultiplicity = null; + +/** + * Constructor + */ + + OptionSet(Options.Prefix prefix, Options.Multiplicity defaultMultiplicity, String setName, int minData, int maxData) { + if (setName == null) throw new IllegalArgumentException(CLASS + ": setName may not be null"); + if (minData < 0) throw new IllegalArgumentException(CLASS + ": minData must be >= 0"); + if (maxData < minData) throw new IllegalArgumentException(CLASS + ": maxData must be >= minData"); + this.prefix = prefix; + this.defaultMultiplicity = defaultMultiplicity; + this.setName = setName; + this.minData = minData; + this.maxData = maxData; + } + +/** + * Get a list of all the options defined for this set + *

+ * @return A list of {@link OptionData} instances defined for this set + */ + + public java.util.ArrayList getOptionData() { + return options; + } + +/** + * Get the data for a specific option, identified by its key name (which is unique) + *

+ * @param key The key for the option + *

+ * @return The {@link OptionData} instance + *

+ * @throws IllegalArgumentException If the key is null or unknown in this set + */ + + public OptionData getOption(String key) { + if (key == null) throw new IllegalArgumentException(CLASS + ": key may not be null"); + if (!keys.containsKey(key)) throw new IllegalArgumentException(CLASS + ": unknown key: " + key); + return keys.get(key); + } + +/** + * Check whether a specific option is set, i. e. whether it was specified at least once on the command line. + *

+ * @param key The key for the option + *

+ * @return true or false, depending on the outcome of the check + *

+ * @throws IllegalArgumentException If the key is null or unknown in this set + */ + + public boolean isSet(String key) { + if (key == null) throw new IllegalArgumentException(CLASS + ": key may not be null"); + if (!keys.containsKey(key)) throw new IllegalArgumentException(CLASS + ": unknown key: " + key); + return keys.get(key).getResultCount() > 0 ? true : false; + } + +/** + * Getter method for setName property + *

+ * @return The value for the setName property + */ + + public String getSetName() { + return setName; + } + +/** + * Getter method for minData property + *

+ * @return The value for the minData property + */ + + public int getMinData() { + return minData; + } + +/** + * Getter method for maxData property + *

+ * @return The value for the maxData property + */ + + public int getMaxData() { + return maxData; + } + +/** + * Return the data items found (these are the items on the command line which do not start with the prefix, i. e. non-option arguments) + *

+ * @return A list of strings with all data items found + */ + + public java.util.ArrayList getData() { + return data; + } + +/** + * Return all unmatched items found (these are the items on the command line which start with the prefix, but do not + * match to one of the options) + *

+ * @return A list of strings with all unmatched items found + */ + + public java.util.ArrayList getUnmatched() { + return unmatched; + } + +/** + * Add a non-value option with the given key, and the default prefix and multiplicity + *

+ * @param key The key for the option + *

+ * @return The set instance itself (to support invocation chaining for addOption() methods) + *

+ * @throws IllegalArgumentException If the key is null or a key with this name has already been defined + */ + + public OptionSet addOption(String key) { + return addOption(key, defaultMultiplicity); + } + +/** + * Add a non-value option with the given key and multiplicity, and the default prefix + *

+ * @param key The key for the option + * @param multiplicity The multiplicity for the option + *

+ * @return The set instance itself (to support invocation chaining for addOption() methods) + *

+ * @throws IllegalArgumentException If the key is null or a key with this name has already been defined + * or if multiplicity is null + */ + + public OptionSet addOption(String key, Options.Multiplicity multiplicity) { + return addOption(key, false, Options.Separator.NONE, false, multiplicity); + } + +/** + * Add a value option with the given key and separator, no details, and the default prefix and multiplicity + *

+ * @param key The key for the option + * @param separator The separator for the option + *

+ * @return The set instance itself (to support invocation chaining for addOption() methods) + *

+ * @throws IllegalArgumentException If the key is null or a key with this name has already been defined + * or if separator is null + */ + + public OptionSet addOption(String key, Options.Separator separator) { + return addOption(key, false, separator, true, defaultMultiplicity); + } + +/** + * Add a value option with the given key, separator, and multiplicity, no details, and the default prefix + *

+ * @param key The key for the option + * @param separator The separator for the option + * @param multiplicity The multiplicity for the option + *

+ * @return The set instance itself (to support invocation chaining for addOption() methods) + *

+ * @throws IllegalArgumentException If the key is null or a key with this name has already been defined + * or if separator or multiplicity are null + */ + + public OptionSet addOption(String key, Options.Separator separator, Options.Multiplicity multiplicity) { + return addOption(key, false, separator, true, multiplicity); + } + +/** + * + * Add a value option with the given key and separator, possibly details, and the default prefix and multiplicity + *

+ * @param key The key for the option + * @param details A boolean indicating whether details are expected for the option + * @param separator The separator for the option + *

+ * @return The set instance itself (to support invocation chaining for addOption() methods) + *

+ * @throws IllegalArgumentException If the key is null or a key with this name has already been defined + * or if separator is null + */ + + public OptionSet addOption(String key, boolean details, Options.Separator separator) { + return addOption(key, details, separator, true, defaultMultiplicity); + } + +/** + * Add a value option with the given key, separator, and multiplicity, possibly details, and the default prefix + *

+ * @param key The key for the option + * @param details A boolean indicating whether details are expected for the option + * @param separator The separator for the option + * @param multiplicity The multiplicity for the option + *

+ * @return The set instance itself (to support invocation chaining for addOption() methods) + *

+ * @throws IllegalArgumentException If the key is null or a key with this name has already been defined + * or if separator or multiplicity are null + */ + + public OptionSet addOption(String key, boolean details, Options.Separator separator, Options.Multiplicity multiplicity) { + return addOption(key, details, separator, true, multiplicity); + } + +/** + * The master method to add an option. Since there are combinations which are not + * acceptable (like a NONE separator and a true value), this method is not public. + * Internally, we only supply acceptable combinations. + */ + + OptionSet addOption(String key, + boolean details, + Options.Separator separator, + boolean value, + Options.Multiplicity multiplicity) { + + if (key == null) throw new IllegalArgumentException(CLASS + ": key may not be null"); + if (multiplicity == null) throw new IllegalArgumentException(CLASS + ": multiplicity may not be null"); + if (separator == null) throw new IllegalArgumentException(CLASS + ": separator may not be null"); + if (keys.containsKey(key)) throw new IllegalArgumentException(CLASS + ": the key " + + key + " has already been defined for this OptionSet"); + + OptionData od = new OptionData(prefix, key, details, separator, value, multiplicity); + options.add(od); + keys.put(key, od); + + return this; + + } + +} + + diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/options/Options.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/options/Options.java new file mode 100644 index 0000000..0e66ed0 --- /dev/null +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/options/Options.java @@ -0,0 +1,768 @@ +package com.minres.scviewer.e4.application.options; + +/** + * The central class for option processing. Sets are identified by their name, but there is also + * an anonymous default set, which is very convenient if an application requieres only one set. + */ + +public class Options { + + private final static String CLASS = "Options"; + +/** + * The name used internally for the default set + */ + + public final static String DEFAULT_SET = "DEFAULT_OPTION_SET"; + +/** + * An enum encapsulating the possible separators between value options and their actual values. + */ + + public enum Separator { + +/** + * Separate option and value by ":" + */ + + COLON(':'), + +/** + * Separate option and value by "=" + */ + + EQUALS('='), + +/** + * Separate option and value by blank space + */ + + BLANK(' '), // Or, more precisely, whitespace (as allowed by the CLI) + +/** + * This is just a placeholder in case no separator is required (i. e. for non-value options) + */ + + NONE('D'); // NONE is a placeholder in case no separator is required, 'D' is just an arbitrary dummy value + + private char c; + + private Separator(char c) { + this.c = c; + } + +/** + * Return the actual separator character + *

+ * @return The actual separator character + */ + + char getName() { + return c; + } + + } + +/** + * An enum encapsulating the possible prefixes identifying options (and separating them from command line data items) + */ + + public enum Prefix { + +/** + * Options start with a "-" (typically on Unix platforms) + */ + + DASH('-'), + +/** + * Options start with a "/" (typically on Windows platforms) + */ + + SLASH('/'); + + private char c; + + private Prefix(char c) { + this.c = c; + } + +/** + * Return the actual prefix character + *

+ * @return The actual prefix character + */ + + char getName() { + return c; + } + + } + +/** + * An enum encapsulating the possible multiplicities for options + */ + + public enum Multiplicity { + +/** + * Option needs to occur exactly once + */ + + ONCE, + +/** + * Option needs to occur at least once + */ + + ONCE_OR_MORE, + +/** + * Option needs to occur either once or not at all + */ + + ZERO_OR_ONE, + +/** + * Option can occur any number of times + */ + + ZERO_OR_MORE; + + } + + private java.util.HashMap optionSets = new java.util.HashMap(); + private Prefix prefix = null; + private Multiplicity defaultMultiplicity = null; + private String[] arguments = null; + private int defaultMinData = 0; + private int defaultMaxData = 0; + private StringBuffer checkErrors = null; + +/** + * Constructor + *

+ * @param args The command line arguments to check + * @param prefix The prefix to use for all command line options. It can only be set here for all options at + * the same time + * @param defaultMultiplicity The default multiplicity to use for all options (can be overridden when adding an option) + * @param defMinData The default minimum number of data items for all sets (can be overridden when adding a set) + * @param defMaxData The default maximum number of data items for all sets (can be overridden when adding a set) + *

+ * @throws IllegalArgumentException If either args, prefix, or defaultMultiplicity + * is null - or if the data range values don't make sense + */ + + public Options(String args[], Prefix prefix, Multiplicity defaultMultiplicity, int defMinData, int defMaxData) { + + if (args == null) throw new IllegalArgumentException(CLASS + ": args may not be null"); + if (prefix == null) throw new IllegalArgumentException(CLASS + ": prefix may not be null"); + if (defaultMultiplicity == null) throw new IllegalArgumentException(CLASS + ": defaultMultiplicity may not be null"); + + if (defMinData < 0) throw new IllegalArgumentException(CLASS + ": defMinData must be >= 0"); + if (defMaxData < defMinData) throw new IllegalArgumentException(CLASS + ": defMaxData must be >= defMinData"); + + arguments = new String[args.length]; + int i = 0; + for (String s : args) + arguments[i++] = s; + + this.prefix = prefix; + this.defaultMultiplicity = defaultMultiplicity; + this.defaultMinData = defMinData; + this.defaultMaxData = defMaxData; + + } + +/** + * Constructor + *

+ * @param args The command line arguments to check + * @param prefix The prefix to use for all command line options. It can only be set here for all options at + * the same time + * @param defaultMultiplicity The default multiplicity to use for all options (can be overridden when adding an option) + * @param data The default minimum and maximum number of data items for all sets (can be overridden when adding a set) + *

+ * @throws IllegalArgumentException If either args, prefix, or defaultMultiplicity + * is null - or if the data range value doesn't make sense + */ + + public Options(String args[], Prefix prefix, Multiplicity defaultMultiplicity, int data) { + this(args, prefix, defaultMultiplicity, data, data); + } + +/** + * Constructor. The default number of data items is set to 0. + *

+ * @param args The command line arguments to check + * @param prefix The prefix to use for all command line options. It can only be set here for all options at + * the same time + * @param defaultMultiplicity The default multiplicity to use for all options (can be overridden when adding an option) + *

+ * @throws IllegalArgumentException If either args, prefix, or defaultMultiplicity + * is null + */ + + public Options(String args[], Prefix prefix, Multiplicity defaultMultiplicity) { + this(args, prefix, defaultMultiplicity, 0, 0); + } + +/** + * Constructor. The prefix is set to {@link Prefix#DASH}. + *

+ * @param args The command line arguments to check + * @param defaultMultiplicity The default multiplicity to use for all options (can be overridden when adding an option) + * @param defMinData The default minimum number of data items for all sets (can be overridden when adding a set) + * @param defMaxData The default maximum number of data items for all sets (can be overridden when adding a set) + *

+ * @throws IllegalArgumentException If either args or defaultMultiplicity + * is null - or if the data range values don't make sense + */ + + public Options(String args[], Multiplicity defaultMultiplicity, int defMinData, int defMaxData) { + this(args, Prefix.DASH, defaultMultiplicity, defMinData, defMaxData); + } + +/** + * Constructor. The prefix is set to {@link Prefix#DASH}. + *

+ * @param args The command line arguments to check + * @param defaultMultiplicity The default multiplicity to use for all options (can be overridden when adding an option) + * @param data The default minimum and maximum number of data items for all sets (can be overridden when adding a set) + *

+ * @throws IllegalArgumentException If either args or defaultMultiplicity + * is null - or if the data range value doesn't make sense + */ + + public Options(String args[], Multiplicity defaultMultiplicity, int data) { + this(args, Prefix.DASH, defaultMultiplicity, data, data); + } + +/** + * Constructor. The prefix is set to {@link Prefix#DASH}, and the default number of data items is set to 0. + *

+ * @param args The command line arguments to check + * @param defaultMultiplicity The default multiplicity to use for all options (can be overridden when adding an option) + *

+ * @throws IllegalArgumentException If either args or defaultMultiplicity + * is null + */ + + public Options(String args[], Multiplicity defaultMultiplicity) { + this(args, Prefix.DASH, defaultMultiplicity, 0, 0); + } + +/** + * Constructor. The prefix is set to {@link Prefix#DASH}, the default number of data items is set to 0, and + * the multiplicity is set to {@link Multiplicity#ONCE}. + *

+ * @param args The command line arguments to check + *

+ * @throws IllegalArgumentException If args is null + */ + + public Options(String args[]) { + this(args, Prefix.DASH, Multiplicity.ONCE); + } + +/** + * Constructor. The prefix is set to {@link Prefix#DASH}, and + * the multiplicity is set to {@link Multiplicity#ONCE}. + *

+ * @param args The command line arguments to check + * @param data The default minimum and maximum number of data items for all sets (can be overridden when adding a set) + *

+ * @throws IllegalArgumentException If args is null - or if the data range value doesn't make sense + */ + + public Options(String args[], int data) { + this(args, Prefix.DASH, Multiplicity.ONCE, data, data); + } + +/** + * Constructor. The prefix is set to {@link Prefix#DASH}, and + * the multiplicity is set to {@link Multiplicity#ONCE}. + *

+ * @param args The command line arguments to check + * @param defMinData The default minimum number of data items for all sets (can be overridden when adding a set) + * @param defMaxData The default maximum number of data items for all sets (can be overridden when adding a set) + *

+ * @throws IllegalArgumentException If args is null - or if the data range values don't make sense + */ + + public Options(String args[], int defMinData, int defMaxData) { + this(args, Prefix.DASH, Multiplicity.ONCE, defMinData, defMaxData); + } + +/** + * Constructor. The default number of data items is set to 0, and + * the multiplicity is set to {@link Multiplicity#ONCE}. + *

+ * @param args The command line arguments to check + * @param prefix The prefix to use for all command line options. It can only be set here for all options at + * the same time + *

+ * @throws IllegalArgumentException If either args or prefix is null + */ + + public Options(String args[], Prefix prefix) { + this(args, prefix, Multiplicity.ONCE, 0, 0); + } + +/** + * Constructor. The multiplicity is set to {@link Multiplicity#ONCE}. + *

+ * @param args The command line arguments to check + * @param prefix The prefix to use for all command line options. It can only be set here for all options at + * @param data The default minimum and maximum number of data items for all sets (can be overridden when adding a set) + *

+ * @throws IllegalArgumentException If either args or prefix is null + * - or if the data range value doesn't make sense + */ + + public Options(String args[], Prefix prefix, int data) { + this(args, prefix, Multiplicity.ONCE, data, data); + } + +/** + * Constructor. The multiplicity is set to {@link Multiplicity#ONCE}. + *

+ * @param args The command line arguments to check + * @param prefix The prefix to use for all command line options. It can only be set here for all options at + * the same time + * @param defMinData The default minimum number of data items for all sets (can be overridden when adding a set) + * @param defMaxData The default maximum number of data items for all sets (can be overridden when adding a set) + *

+ * @throws IllegalArgumentException If either args or prefix is null + * - or if the data range values don't make sense + */ + + public Options(String args[], Prefix prefix, int defMinData, int defMaxData) { + this(args, prefix, Multiplicity.ONCE, defMinData, defMaxData); + } + +/** + * Return the (first) matching set. This invocation does not ignore unmatched options and requires that + * data items are the last ones on the command line. + *

+ * @return The first set which matches (i. e. the check() method returns true) - or + * null, if no set matches. + */ + + public OptionSet getMatchingSet() { + return getMatchingSet(false, true); + } + +/** + * Return the (first) matching set. + *

+ * @param ignoreUnmatched A boolean to select whether unmatched options can be ignored in the checks or not + * @param requireDataLast A boolean to indicate whether the data items have to be the last ones on the command line or not + *

+ * @return The first set which matches (i. e. the check() method returns true) - or + * null, if no set matches. + */ + + public OptionSet getMatchingSet(boolean ignoreUnmatched, boolean requireDataLast) { + for (String setName : optionSets.keySet()) + if (check(setName, ignoreUnmatched, requireDataLast)) + return optionSets.get(setName); + return null; + } + +/** + * Add an option set. + *

+ * @param setName The name for the set. This must be a unique identifier + * @param minData The minimum number of data items for this set + * @param maxData The maximum number of data items for this set + *

+ * @return The new Optionset instance created. This is useful to allow chaining of addOption() + * calls right after this method + */ + + public OptionSet addSet(String setName, int minData, int maxData) { + if (setName == null) throw new IllegalArgumentException(CLASS + ": setName may not be null"); + if (optionSets.containsKey(setName)) throw new IllegalArgumentException(CLASS + ": a set with the name " + + setName + " has already been defined"); + OptionSet os = new OptionSet(prefix, defaultMultiplicity, setName, minData, maxData); + optionSets.put(setName, os); + return os; + } + +/** + * Add an option set. + *

+ * @param setName The name for the set. This must be a unique identifier + * @param data The minimum and maximum number of data items for this set + *

+ * @return The new Optionset instance created. This is useful to allow chaining of addOption() + * calls right after this method + */ + + public OptionSet addSet(String setName, int data) { + return addSet(setName, data, data); + } + +/** + * Add an option set. The defaults for the number of data items are used. + *

+ * @param setName The name for the set. This must be a unique identifier + *

+ * @return The new Optionset instance created. This is useful to allow chaining of addOption() + * calls right after this method + */ + + public OptionSet addSet(String setName) { + return addSet(setName, defaultMinData, defaultMaxData); + } + +/** + * Return an option set - or null, if no set with the given name exists + *

+ * @param setName The name for the set to retrieve + *

+ * @return The set to retrieve (or null, if no set with the given name exists) + */ + + public OptionSet getSet(String setName) { + return optionSets.get(setName); + } + +/** + * This returns the (anonymous) default set + *

+ * @return The default set + */ + + public OptionSet getSet() { + if (getSet(DEFAULT_SET) == null) + addSet(DEFAULT_SET, defaultMinData, defaultMaxData); + return getSet(DEFAULT_SET); + } + +/** + * The error messages collected during the last option check (invocation of any of the check() methods). This + * is useful to determine what was wrong with the command line arguments provided + *

+ * @return A string with all collected error messages + */ + + public String getCheckErrors() { + return checkErrors.toString(); + } + +/** + * Run the checks for the default set. ignoreUnmatched is set to false, and + * requireDataLast is set to true. + *

+ * @return A boolean indicating whether all checks were successful or not + */ + + public boolean check() { + return check(DEFAULT_SET, false, true); + } + +/** + * Run the checks for the default set. + *

+ * @param ignoreUnmatched A boolean to select whether unmatched options can be ignored in the checks or not + * @param requireDataLast A boolean to indicate whether the data items have to be the last ones on the command line or not + *

+ * @return A boolean indicating whether all checks were successful or not + */ + + public boolean check(boolean ignoreUnmatched, boolean requireDataLast) { + return check(DEFAULT_SET, ignoreUnmatched, requireDataLast); + } + +/** + * Run the checks for the given set. ignoreUnmatched is set to false, and + * requireDataLast is set to true. + *

+ * @param setName The name for the set to check + *

+ * @return A boolean indicating whether all checks were successful or not + *

+ * @throws IllegalArgumentException If either setName is null, or the set is unknown. + */ + + public boolean check(String setName) { + return check(setName, false, true); + } + +/** + * Run the checks for the given set. + *

+ * @param setName The name for the set to check + * @param ignoreUnmatched A boolean to select whether unmatched options can be ignored in the checks or not + * @param requireDataLast A boolean to indicate whether the data items have to be the last ones on the command line or not + *

+ * @return A boolean indicating whether all checks were successful or not + *

+ * @throws IllegalArgumentException If either setName is null, or the set is unknown. + */ + + public boolean check(String setName, boolean ignoreUnmatched, boolean requireDataLast) { + + if (setName == null) throw new IllegalArgumentException(CLASS + ": setName may not be null"); + if (optionSets.get(setName) == null) throw new IllegalArgumentException(CLASS + ": Unknown OptionSet: " + setName); + + checkErrors = new StringBuffer(); + checkErrors.append("Checking set "); + checkErrors.append(setName); + checkErrors.append('\n'); + +//.... Access the data for the set to use + + OptionSet set = optionSets.get(setName); + java.util.ArrayList options = set.getOptionData(); + java.util.ArrayList data = set.getData(); + java.util.ArrayList unmatched = set.getUnmatched(); + +//.... Catch some trivial cases + + if (options.size() == 0) { // No options have been defined at all + if (arguments.length == 0) { // No arguments have been given: in this case, this is a success + return true; + } else { + checkErrors.append("No options have been defined, nothing to check\n"); + return false; + } + } else if (arguments.length == 0) { // Options have been defined, but no arguments given + checkErrors.append("Options have been defined, but no arguments have been given; nothing to check\n"); + return false; + } + +//.... Parse all the arguments given + + int ipos = 0; + int offset = 0; + java.util.regex.Matcher m = null; + String value = null; + String detail = null; + String next = null; + String key = null; + String pre = Character.toString(prefix.getName()); + boolean add = true; + boolean[] matched = new boolean[arguments.length]; + + for (int i = 0; i < matched.length; i++) // Initially, we assume there was no match at all + matched[i] = false; + + while (true) { + + value = null; + detail = null; + offset = 0; + add = true; + key = arguments[ipos]; + + for (OptionData optionData : options) { // For each argument, we may need to check all defined options + m = optionData.getPattern().matcher(key); + if (m.lookingAt()) { + if (optionData.useValue()) { // The code section for value options + if (optionData.useDetail()) { + detail = m.group(1); + offset = 2; // required for correct Matcher.group access below + } + if (optionData.getSeparator() == Separator.BLANK) { // In this case, the next argument must be the value + if (ipos + 1 == arguments.length) { // The last argument, thus no value follows it: Error + checkErrors.append("At end of arguments - no value found following argument "); + checkErrors.append(key); + checkErrors.append('\n'); + add = false; + } else { + next = arguments[ipos + 1]; + if (next.startsWith(pre)) { // The next one is an argument, not a value: Error + checkErrors.append("No value found following argument "); + checkErrors.append(key); + checkErrors.append('\n'); + add = false; + } else { + value = next; + matched[ipos++] = true; // Mark the key and the value + matched[ipos] = true; + } + } + } else { // The value follows the separator in this case + value = m.group(1 + offset); + matched[ipos] = true; + } + } else { // Simple, non-value options + matched[ipos] = true; + } + + if (add) optionData.addResult(value, detail); // Store the result + break; // No need to check more options, we have a match + } + } + + ipos++; // Advance to the next argument to check + if (ipos >= arguments.length) break; // Terminating condition for the check loop + + } + +//.... Identify unmatched arguments and actual (non-option) data + + int first = -1; // Required later for requireDataLast + for (int i = 0; i < matched.length; i++) { // Assemble the list of unmatched options + if (!matched[i]) { + if (arguments[i].startsWith(pre)) { // This is an unmatched option + unmatched.add(arguments[i]); + checkErrors.append("No matching option found for argument "); + checkErrors.append(arguments[i]); + checkErrors.append('\n'); + } else { // This is actual data + if (first < 0) first = i; + data.add(arguments[i]); + } + } + } + +//.... Checks to determine overall success; start with multiplicity of options + + boolean err = true; + + for (OptionData optionData : options) { + + key = optionData.getKey(); + err = false; // Local check result for one option + + switch (optionData.getMultiplicity()) { + case ONCE: if (optionData.getResultCount() != 1) err = true; break; + case ONCE_OR_MORE: if (optionData.getResultCount() == 0) err = true; break; + case ZERO_OR_ONE: if (optionData.getResultCount() > 1) err = true; break; + case ZERO_OR_MORE: break; + } + + if (err) { + checkErrors.append("Wrong number of occurences found for argument "); + checkErrors.append(prefix.getName()); + checkErrors.append(key); + checkErrors.append('\n'); + return false; + } + + } + +//.... Check range for data + + if (data.size() < set.getMinData() || data.size() > set.getMaxData()) { + checkErrors.append("Invalid number of data arguments: "); + checkErrors.append(data.size()); + checkErrors.append(" (allowed range: "); + checkErrors.append(set.getMinData()); + checkErrors.append(" ... "); + checkErrors.append(set.getMaxData()); + checkErrors.append(")\n"); + return false; + } + +//.... Check for location of the data in the list of command line arguments + + if (requireDataLast) { + if (first + data.size() != arguments.length) { + checkErrors.append("Invalid data specification: data arguments are not the last ones on the command line\n"); + return false; + } + } + +//.... Check for unmatched arguments + + if (!ignoreUnmatched && unmatched.size() > 0) return false; // Don't accept unmatched arguments + +//.... If we made it to here, all checks were successful + + return true; + + } + +/** + * Add the given non-value option to all known sets. + * See {@link OptionSet#addOption(String)} for details. + */ + + public void addOptionAllSets(String key) { + for (String setName : optionSets.keySet()) + optionSets.get(setName).addOption(key, defaultMultiplicity); + } + +/** + * Add the given non-value option to all known sets. + * See {@link OptionSet#addOption(String, Options.Multiplicity)} for details. + */ + + public void addOptionAllSets(String key, Multiplicity multiplicity) { + for (String setName : optionSets.keySet()) + optionSets.get(setName).addOption(key, false, Separator.NONE, false, multiplicity); + } + +/** + * Add the given value option to all known sets. + * See {@link OptionSet#addOption(String, Options.Separator)} for details. + */ + + public void addOptionAllSets(String key, Separator separator) { + for (String setName : optionSets.keySet()) + optionSets.get(setName).addOption(key, false, separator, true, defaultMultiplicity); + } + +/** + * Add the given value option to all known sets. + * See {@link OptionSet#addOption(String, Options.Separator, Options.Multiplicity)} for details. + */ + + public void addOptionAllSets(String key, Separator separator, Multiplicity multiplicity) { + for (String setName : optionSets.keySet()) + optionSets.get(setName).addOption(key, false, separator, true, multiplicity); + } + +/** + * Add the given value option to all known sets. + * See {@link OptionSet#addOption(String, boolean, Options.Separator)} for details. + */ + + public void addOptionAllSets(String key, boolean details, Separator separator) { + for (String setName : optionSets.keySet()) + optionSets.get(setName).addOption(key, details, separator, true, defaultMultiplicity); + } + +/** + * Add the given value option to all known sets. + * See {@link OptionSet#addOption(String, boolean, Options.Separator, Options.Multiplicity)} for details. + */ + + public void addOptionAllSets(String key, boolean details, Separator separator, Multiplicity multiplicity) { + for (String setName : optionSets.keySet()) + optionSets.get(setName).addOption(key, details, separator, true, multiplicity); + } + +/** + * This is the overloaded {@link Object#toString()} method, and it is provided mainly for debugging + * purposes. + *

+ * @return A string representing the instance + */ + + public String toString() { + + StringBuffer sb = new StringBuffer(); + + for (OptionSet set : optionSets.values()) { + sb.append("Set: "); + sb.append(set.getSetName()); + sb.append('\n'); + for (OptionData data : set.getOptionData()) { + sb.append(data.toString()); + sb.append('\n'); + } + } + + return sb.toString(); + + } + +} + + diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/AboutDialog.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/AboutDialog.java index e33b483..8b0745c 100644 --- a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/AboutDialog.java +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/AboutDialog.java @@ -133,7 +133,7 @@ public class AboutDialog extends Dialog { // links are activated on mouse down when the control key is held down // if ((event.stateMask & SWT.MOD1) != 0) { try { - int offset = ((StyledText)event.widget).getOffsetAtLocation(new Point (event.x, event.y)); + int offset = ((StyledText)event.widget).getOffsetAtPoint(new Point (event.x, event.y)); StyleRange style = ((StyledText)event.widget).getStyleRangeAtOffset(offset); if (style != null && style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) { Desktop.getDesktop().browse(new java.net.URI(style.data.toString())); diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java index abcfe5c..36061ab 100644 --- a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java @@ -14,10 +14,10 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -32,6 +32,7 @@ import javax.inject.Named; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.core.runtime.jobs.IJobChangeEvent; @@ -56,12 +57,16 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseTrackListener; +import org.eclipse.swt.events.MouseWheelListener; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; import com.minres.scviewer.database.ITx; import com.minres.scviewer.database.ITxRelation; @@ -75,6 +80,8 @@ import com.minres.scviewer.database.ui.GotoDirection; import com.minres.scviewer.database.ui.ICursor; import com.minres.scviewer.database.ui.IWaveformViewer; 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.WaveformColors; import com.minres.scviewer.e4.application.Messages; import com.minres.scviewer.e4.application.internal.status.WaveStatusBarControl; @@ -83,7 +90,6 @@ import com.minres.scviewer.e4.application.internal.util.IFileChangeListener; import com.minres.scviewer.e4.application.internal.util.IModificationChecker; import com.minres.scviewer.e4.application.preferences.DefaultValuesInitializer; import com.minres.scviewer.e4.application.preferences.PreferenceConstants; -//import com.minres.scviewer.database.swt.internal.WaveformCanvas; /** * The Class WaveformViewerPart. @@ -103,6 +109,10 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis /** The Constant SHOWN_WAVEFORM. */ protected static final String SHOWN_WAVEFORM = "SHOWN_WAVEFORM"; //$NON-NLS-1$ + protected static final String VALUE_DISPLAY = ".VALUE_DISPLAY"; //$NON-NLS-1$ + + protected static final String WAVE_DISPLAY = ".WAVE_DISPLAY"; //$NON-NLS-1$ + /** The Constant SHOWN_CURSOR. */ protected static final String SHOWN_CURSOR = "SHOWN_CURSOR"; //$NON-NLS-1$ @@ -142,7 +152,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis @Inject ESelectionService selectionService; - /** The e part service. */ + /** The part service. */ @Inject EPartService ePartService; @@ -237,6 +247,106 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis selectionService.setSelection(event.getSelection()); } }); + waveformPane.getWaveformControl().addMouseTrackListener(new MouseTrackListener() { + + @Override + public void mouseHover(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseExit(MouseEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void mouseEnter(MouseEvent e) { + // TODO Auto-generated method stub + + } + }); + + waveformPane.getWaveformControl().addMouseWheelListener(new MouseWheelListener() { + + @Override + public void mouseScrolled(MouseEvent e) { + // TODO Auto-generated method stub + + } + }); + + waveformPane.getWaveformControl().addListener(SWT.KeyDown, new Listener() { + + @Override + public void handleEvent(Event e) { + int state = e.stateMask & SWT.MODIFIER_MASK; + if(Platform.OS_MACOSX.equals(Platform.getOS())) { //swap cammnd and control for MacOSX + if((state&SWT.COMMAND)!=0) { + state&=~SWT.COMMAND; + state|=SWT.CONTROL; + } else if((state&SWT.CONTROL)!=0) { + state&=~SWT.CONTROL; + state|=SWT.COMMAND; + } + } + if(state==SWT.ALT) { + switch(e.keyCode) { + case SWT.ARROW_LEFT: + waveformPane.scrollHorizontal(-100); + return; + case SWT.ARROW_RIGHT: + waveformPane.scrollHorizontal(100); + return; + case SWT.KEYPAD_ADD: + return; + case SWT.KEYPAD_SUBTRACT: + return; + } + } else if(state==SWT.CTRL) { + int zoomlevel = waveformPane.getZoomLevel(); + switch(e.keyCode) { + case '+': + case SWT.KEYPAD_ADD: + if(zoomlevel>0) + waveformPane.setZoomLevel(zoomlevel-1); + return; + case '-': + case SWT.KEYPAD_SUBTRACT: + if(zoomlevel 0) loadDatabase(persistedState); eventBroker.post(WaveStatusBarControl.ZOOM_LEVEL, zoomLevel[waveformPane.getZoomLevel()]); +// menuService.registerContextMenu(waveformPane.getNameControl(), +// "com.minres.scviewer.e4.application.popupmenu.namecontext"); //$NON-NLS-1$ menuService.registerContextMenu(waveformPane.getNameControl(), - "com.minres.scviewer.e4.application.popupmenu.namecontext"); //$NON-NLS-1$ + "com.minres.scviewer.e4.application.popupmenu.wavecontext"); //$NON-NLS-1$ menuService.registerContextMenu(waveformPane.getValueControl(), - "com.minres.scviewer.e4.application.popupmenu.namecontext"); //$NON-NLS-1$ + "com.minres.scviewer.e4.application.popupmenu.wavecontext"); //$NON-NLS-1$ menuService.registerContextMenu(waveformPane.getWaveformControl(), "com.minres.scviewer.e4.application.popupmenu.wavecontext"); //$NON-NLS-1$ ePartService.addPartListener(new PartListener() { @@ -385,7 +497,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis */ @Inject @Optional - public void setPartInput(@Named("input") Object partInput) { + public void setPartInput(@Named("input") Object partInput, @Named("config") Object partConfig) { if (partInput instanceof File) { filesToLoad = new ArrayList(); File file = (File) partInput; @@ -409,6 +521,9 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis } if (filesToLoad.size() > 0) loadDatabase(persistedState); + if(partConfig instanceof String) { + loadState((String) partConfig); + } } } @@ -417,7 +532,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis */ @Focus public void setFocus() { - myParent.setFocus(); + waveformPane.getWaveformControl().setFocus(); } /** @@ -464,12 +579,13 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis FileInputStream in = new FileInputStream(fileName); props.load(in); in.close(); + @SuppressWarnings({ "unchecked", "rawtypes" }) + HashMap propMap = new HashMap((Map) props); + restoreWaveformViewerState(propMap); + } catch(FileNotFoundException e) { } catch (IOException e) { e.printStackTrace(); } - @SuppressWarnings({ "unchecked", "rawtypes" }) - HashMap propMap = new HashMap((Map) props); - restoreWaveformViewerState(propMap); } /** @@ -483,6 +599,8 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis index = 0; for (TrackEntry trackEntry : waveformPane.getStreamList()) { 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++; } List cursors = waveformPane.getCursorList(); @@ -506,8 +624,16 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis List res = new LinkedList<>(); for (int i = 0; i < waves; i++) { IWaveform waveform = database.getStreamByName(state.get(SHOWN_WAVEFORM + i)); - if (waveform != null) - res.add(new TrackEntry(waveform)); + if (waveform != null) { + TrackEntry t = new TrackEntry(waveform); + res.add(t); + String v = state.get(SHOWN_WAVEFORM + i + VALUE_DISPLAY); + if(v!=null) + t.valueDisplay=ValueDisplay.valueOf(v); + String s = state.get(SHOWN_WAVEFORM + i + WAVE_DISPLAY); + if(s!=null) + t.waveDisplay=WaveDisplay.valueOf(s); + } } if (res.size() > 0) waveformPane.getStreamList().addAll(res); @@ -663,6 +789,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis index++; waveformPane.getStreamList().addAll(index, streams); } + setFocus(); } /** @@ -741,7 +868,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis //FIXME: need to use unitString and unitMultiplier from class WaveformCanvas which is located in >com.minres.scviewer.database.swt.internal. //Trying to import com.minres.scviewer.database.swt.internal.WaveformCanvas results in the error: //'Access restriction: The type 'WaveformCanvas' is not API (restriction on required project 'com.minres.scviewer.database.ui.swt')'. - public final static String[] unitString={"fs", "ps", "ns", "µs", "ms"};//, "s"}; + public final static String[] unitString={"fs", "ps", "ns", "�s", "ms"};//, "s"}; public final static int[] unitMultiplier={1, 3, 10, 30, 100, 300}; /** @@ -916,5 +1043,9 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis if(navigationRelationType!=relationType) waveformPane.setHighliteRelation(relationType); navigationRelationType=relationType; } + + public void update() { + waveformPane.update(); + } } \ No newline at end of file diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/preferences/DefaultValuesInitializer.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/preferences/DefaultValuesInitializer.java index 5497a15..17afd9b 100644 --- a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/preferences/DefaultValuesInitializer.java +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/preferences/DefaultValuesInitializer.java @@ -41,14 +41,15 @@ public class DefaultValuesInitializer extends AbstractPreferenceInitializer { 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.SIGNAL0.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); + colors[WaveformColors.SIGNAL1.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); colors[WaveformColors.SIGNALZ.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_YELLOW); colors[WaveformColors.SIGNALX.ordinal()] = SWTResourceManager.getColor(255, 51, 51); colors[WaveformColors.SIGNALU.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_YELLOW); - colors[WaveformColors.SIGNAL_ANALOG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN); + colors[WaveformColors.SIGNAL_REAL.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_YELLOW); colors[WaveformColors.SIGNAL_NAN.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED); 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); diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/provider/TxDbLabelProvider.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/provider/TxDbLabelProvider.java index eab365c..ab0bd3b 100644 --- a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/provider/TxDbLabelProvider.java +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/provider/TxDbLabelProvider.java @@ -20,7 +20,7 @@ import org.eclipse.wb.swt.ResourceManager; import com.minres.scviewer.database.IHierNode; import com.minres.scviewer.database.ISignal; -import com.minres.scviewer.database.ISignalChangeMulti; +import com.minres.scviewer.database.ISignalChangeBitVector; import com.minres.scviewer.database.ITxStream; import com.minres.scviewer.database.IWaveformDb; import com.minres.scviewer.e4.application.parts.LoadingWaveformDb; @@ -101,7 +101,7 @@ public class TxDbLabelProvider implements ILabelProvider { return stream; }else if(element instanceof ISignal){ Object o = ((ISignal)element).getEvents().firstEntry().getValue(); - if(o instanceof ISignalChangeMulti) + if(o instanceof ISignalChangeBitVector) return wave; else return signal; diff --git a/com.minres.scviewer.e4.application/src/org/eclipse/wb/swt/ResourceManager.java b/com.minres.scviewer.e4.application/src/org/eclipse/wb/swt/ResourceManager.java index ddf492f..98642cf 100644 --- a/com.minres.scviewer.e4.application/src/org/eclipse/wb/swt/ResourceManager.java +++ b/com.minres.scviewer.e4.application/src/org/eclipse/wb/swt/ResourceManager.java @@ -147,15 +147,15 @@ public class ResourceManager extends SWTResourceManager { CompositeImageDescriptor compositImageDesc = new CompositeImageDescriptor() { @Override protected void drawCompositeImage(int width, int height) { - drawImage(baseImage.getImageData(), 0, 0); + drawImage(createCachedImageDataProvider(baseImage), 0, 0); if (corner == TOP_LEFT) { - drawImage(decorator.getImageData(), 0, 0); + drawImage(createCachedImageDataProvider(decorator), 0, 0); } else if (corner == TOP_RIGHT) { - drawImage(decorator.getImageData(), bib.width - dib.width, 0); + drawImage(createCachedImageDataProvider(decorator), bib.width - dib.width, 0); } else if (corner == BOTTOM_LEFT) { - drawImage(decorator.getImageData(), 0, bib.height - dib.height); + drawImage(createCachedImageDataProvider(decorator), 0, bib.height - dib.height); } else if (corner == BOTTOM_RIGHT) { - drawImage(decorator.getImageData(), bib.width - dib.width, bib.height - dib.height); + drawImage(createCachedImageDataProvider(decorator), bib.width - dib.width, bib.height - dib.height); } } @Override diff --git a/com.minres.scviewer.e4.product/pom.xml b/com.minres.scviewer.e4.product/pom.xml index 92a039e..ff56ab9 100644 --- a/com.minres.scviewer.e4.product/pom.xml +++ b/com.minres.scviewer.e4.product/pom.xml @@ -6,11 +6,10 @@ com.minres.scviewer com.minres.scviewer.parent - 1.0.0-SNAPSHOT + 2.0.0-SNAPSHOT ../com.minres.scviewer.parent com.minres.scviewer.e4.product - 1.3.0-SNAPSHOT eclipse-repository com.minres.scviewer diff --git a/com.minres.scviewer.e4.product/scviewer.product b/com.minres.scviewer.e4.product/scviewer.product index 73c96ec..615d49f 100644 --- a/com.minres.scviewer.e4.product/scviewer.product +++ b/com.minres.scviewer.e4.product/scviewer.product @@ -1,8 +1,7 @@ - - + @@ -34,7 +33,6 @@ - diff --git a/com.minres.scviewer.parent/pom.xml b/com.minres.scviewer.parent/pom.xml index e69be6d..736e844 100644 --- a/com.minres.scviewer.parent/pom.xml +++ b/com.minres.scviewer.parent/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.minres.scviewer com.minres.scviewer.parent - 1.0.0-SNAPSHOT + 2.0.0-SNAPSHOT pom ../com.minres.scviewer.target diff --git a/com.minres.scviewer.ui/.settings/org.eclipse.jdt.groovy.core.prefs b/com.minres.scviewer.ui/.settings/org.eclipse.jdt.groovy.core.prefs index 54bc0c1..bde59a0 100644 --- a/com.minres.scviewer.ui/.settings/org.eclipse.jdt.groovy.core.prefs +++ b/com.minres.scviewer.ui/.settings/org.eclipse.jdt.groovy.core.prefs @@ -1,3 +1,3 @@ eclipse.preferences.version=1 -groovy.compiler.level=24 +groovy.compiler.level=26 groovy.script.filters=**/*.dsld,y,**/*.gradle,n diff --git a/com.minres.scviewer.ui/META-INF/MANIFEST.MF b/com.minres.scviewer.ui/META-INF/MANIFEST.MF index fc9a3e3..60150bc 100644 --- a/com.minres.scviewer.ui/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.ui/META-INF/MANIFEST.MF @@ -23,3 +23,4 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Import-Package: com.google.common.collect Service-Component: OSGI-INF/component.xml +Automatic-Module-Name: com.minres.scviewer.ui diff --git a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/TxEditorPart.java b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/TxEditorPart.java index 3663aab..66402d9 100644 --- a/com.minres.scviewer.ui/src/com/minres/scviewer/ui/TxEditorPart.java +++ b/com.minres.scviewer.ui/src/com/minres/scviewer/ui/TxEditorPart.java @@ -347,12 +347,18 @@ public class TxEditorPart extends EditorPart implements ITabbedPropertySheetPage addStreamToList(stream); } - public void removeStreamFromList(IWaveform obj){ - if(getEditorInput() instanceof TxEditorInput && ((TxEditorInput) getEditorInput()).getStreamNames().contains(obj.getFullName())){ - ((TxEditorInput) getEditorInput()).getStreamNames().remove(obj.getFullName()); - txDisplay.getStreamList().remove(obj); - } else - txDisplay.getStreamList().remove(obj); + public void removeStreamFromList(IWaveform waveform){ + if(getEditorInput() instanceof TxEditorInput && ((TxEditorInput) getEditorInput()).getStreamNames().contains(waveform.getFullName())){ + ((TxEditorInput) getEditorInput()).getStreamNames().remove(waveform.getFullName()); + } + TrackEntry entry=null; + for(TrackEntry e:txDisplay.getStreamList()) { + if(e.waveform==waveform) { + entry=e; + break; + } + } + txDisplay.getStreamList().remove(entry); } public void removeStreamsFromList(IWaveform[] iWaveforms){ diff --git a/com.opcoach.e4.preferences/META-INF/MANIFEST.MF b/com.opcoach.e4.preferences/META-INF/MANIFEST.MF index f49535b..5ec77eb 100644 --- a/com.opcoach.e4.preferences/META-INF/MANIFEST.MF +++ b/com.opcoach.e4.preferences/META-INF/MANIFEST.MF @@ -16,3 +16,4 @@ Require-Bundle: javax.inject, Export-Package: com.opcoach.e4.preferences, com.opcoach.e4.preferences.handlers Bundle-ActivationPolicy: lazy +Automatic-Module-Name: com.opcoach.e4.preferences