Added handler and configurability of wavefrom view

This commit is contained in:
2018-10-14 08:59:17 +02:00
parent 694423be3b
commit 6cc5597c25
12 changed files with 469 additions and 175 deletions

View File

@ -67,7 +67,6 @@ public class SignalPainter extends TrackPainter {
private static final JPanel DUMMY_PANEL = new JPanel();
private final WaveformCanvas waveCanvas;
private ISignal<? extends ISignalChange> signal;
int yOffsetT;
int yOffsetM;
@ -77,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) {
@ -86,6 +84,7 @@ public class SignalPainter extends TrackPainter {
}
public void paintArea(GC gc, Rectangle area) {
ISignal<? extends ISignalChange> signal = trackEntry.getSignal();
if (trackEntry.selected)
gc.setBackground(this.waveCanvas.colors[WaveformColors.TRACK_BG_HIGHLITE.ordinal()]);
else
@ -156,9 +155,14 @@ public class SignalPainter extends TrackPainter {
if(left.value instanceof ISignalChangeBit)
return new SingleBitStencil();
else if (left.value instanceof ISignalChangeBitVector)
return new MultiBitStencil(gc);
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);
return new RealStencil(entries, left.value, trackEntry.waveDisplay==TrackEntry.WaveDisplay.CONTINOUS);
else
return null;
}
@ -200,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;
@ -224,6 +239,62 @@ public class SignalPainter extends TrackPainter {
}
private class MultiBitStencilAnalog implements SignalStencil {
final boolean continous;
final boolean signed;
private long minVal;
private long range;
@SuppressWarnings("unchecked")
public MultiBitStencilAnalog(NavigableMap<Long, ? extends ISignalChange> entries, ISignalChange left, boolean continous, boolean signed) {
this.continous=continous;
this.signed=signed;
Collection<ISignalChangeBitVector> values = ((NavigableMap<Long, ISignalChangeBitVector>) 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) {
@ -269,49 +340,47 @@ public class SignalPainter extends TrackPainter {
}
}
}
/*
private class RealStencil implements SignalStencil {
double min;
double max;
double diff;
double minVal, range;
public RealStencil(ISignalChange value, NavigableMap<Long, ? extends ISignalChange> 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<Long, ? extends ISignalChange> entries, ISignalChange left, boolean continous) {
this.continous=continous;
Collection<ISignalChangeReal> values = ((NavigableMap<Long, ISignalChangeReal>) 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) {
@ -329,82 +398,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.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);
}
}
}
}
*/
private class RealStencil implements SignalStencil {
double minVal, range;
final double scaleFactor = 1.05;
boolean stepWise=true;
@SuppressWarnings("unchecked")
public RealStencil(NavigableMap<Long, ? extends ISignalChange> entries, ISignalChange left) {
Collection<ISignalChangeReal> values = ((NavigableMap<Long, ISignalChangeReal>) entries).values();
minVal=((ISignalChangeReal) left).getValue();
range=2.0;
if(!values.isEmpty()) {
double maxVal=minVal;
for(ISignalChangeReal v:values) {
minVal=Math.min(minVal, v.getValue());
maxVal=Math.max(maxVal, v.getValue());
}
range = (maxVal-minVal)*scaleFactor;
double avg = (maxVal+minVal)/2.0;
minVal=avg-(avg-minVal)*scaleFactor;
}
}
public void draw(GC gc, Rectangle area, ISignalChange left, ISignalChange right, int xBegin, int xEnd, boolean multiple) {
double leftVal = ((ISignalChangeReal) left).getValue();
double rightVal= ((ISignalChangeReal) right).getValue();
// if (multiple) {
// gc.setForeground(waveCanvas.colors[WaveformColors.SIGNALX.ordinal()]);
// } else {
} else {
gc.setForeground(waveCanvas.colors[WaveformColors.SIGNAL_REAL.ordinal()]);
// }
int yOffsetLeft = (int) ((leftVal-minVal) / range * (yOffsetB-yOffsetT));
int yOffsetRight = (int) ((rightVal-minVal) / range * (yOffsetB-yOffsetT));
if(stepWise) {
if (xEnd > maxX) {
gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxX, yOffsetB-yOffsetLeft);
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, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetLeft);
if(yOffsetRight!=yOffsetLeft) {
gc.drawLine(xEnd, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight);
if (xEnd > maxX) {
gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxX, yOffsetB-yOffsetLeft);
} else {
gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetLeft);
if(yOffsetRight!=yOffsetLeft) {
gc.drawLine(xEnd, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight);
}
}
}
} else {
if (xEnd > maxX) {
gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxX, yOffsetB-yOffsetRight);
} else {
gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight);
}
}
}
}
public ISignal<? extends ISignalChange> getSignal() {
return signal;
}
}

View File

@ -119,8 +119,6 @@ public class WaveformViewer implements IWaveformViewer {
private TreeMap<Integer, TrackEntry> trackVerticalOffset;
private HashMap<IWaveform<? extends IWaveformEvent>, String> actualValues;
private Font nameFont, nameFontB;
protected MouseListener nameValueMouseListener = new MouseAdapter() {
@ -225,7 +223,6 @@ public class WaveformViewer implements IWaveformViewer {
trackVerticalOffset = new TreeMap<Integer, TrackEntry>();
trackVerticalHeight=0;
actualValues = new HashMap<IWaveform<? extends IWaveformEvent>, String>();
nameFont = parent.getDisplay().getSystemFont();
nameFontB = SWTResourceManager.getBoldFont(nameFont);
@ -384,19 +381,18 @@ public class WaveformViewer implements IWaveformViewer {
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;
@ -407,12 +403,12 @@ 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);
trackVerticalOffset.put(trackVerticalHeight, streamEntry);
@ -440,14 +436,15 @@ public class WaveformViewer implements IWaveformViewer {
for(Entry<Integer, IWaveform<? extends IWaveformEvent>> 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;
@ -455,22 +452,32 @@ public class WaveformViewer implements IWaveformViewer {
private void updateValueList(){
final Long time = getCursorTime();
for(Entry<IWaveform<? extends IWaveformEvent>, String> entry:actualValues.entrySet()){
if(entry.getKey() instanceof ISignal){
ISignalChange event = ((ISignal<?>)entry.getKey()).getWaveformEventsBeforeTime(time);
for(TrackEntry entry:streams){
if(entry.isSignal()){
ISignalChange event = ((ISignal<?>)entry.waveform).getWaveformEventsBeforeTime(time);
if(event instanceof ISignalChangeBit){
entry.setValue("b'"+((ISignalChangeBit)event).getValue());
entry.currentValue="b'"+((ISignalChangeBit)event).getValue();
} else if(event instanceof ISignalChangeBitVector){
entry.setValue("h'"+((ISignalChangeBitVector)event).getValue().toHexString());
// 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){
double val = ((ISignalChangeReal)event).getValue();
if(val>0.001)
entry.setValue(String.format("%1$,.3f", val));
entry.currentValue=String.format("%1$,.3f", val);
else
entry.setValue(Double.toString(val));
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<Long, List<ITxEvent>> firstTx=stream.getEvents().floorEntry(time);
if(firstTx!=null){
@ -492,7 +499,7 @@ public class WaveformViewer implements IWaveformViewer {
value+="|";
if(o!=null) value+=((ITx)o).getGenerator().getName();
}
entry.setValue(value);
entry.currentValue=value;
}
}
}
@ -775,7 +782,7 @@ public class WaveformViewer implements IWaveformViewer {
int newIdx=idx+i;
if(newIdx>=0 && newIdx<streams.size()){
Collections.swap(streams,idx,newIdx);
updateTracklist();
update();
if(selectedTx!=null){
setSelection(new StructuredSelection(new Object[]{selectedTx, selectedWaveform.waveform}));
} else
@ -825,7 +832,7 @@ public class WaveformViewer implements IWaveformViewer {
IWaveform<? extends IWaveformEvent> 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<Integer, TrackEntry> entry : trackVerticalOffset.subMap(firstKey, true, lastKey, true)
.entrySet()) {
@ -833,7 +840,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){}
@ -1001,7 +1008,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();