2015-01-21 21:58:35 +01:00
|
|
|
/*******************************************************************************
|
2021-01-09 14:26:49 +01:00
|
|
|
* Copyright (c) 2015-2021 MINRES Technologies GmbH and others.
|
2015-01-21 21:58:35 +01:00
|
|
|
* All rights reserved. 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
|
|
|
|
*
|
|
|
|
* Contributors:
|
|
|
|
* MINRES Technologies GmbH - initial API and implementation
|
|
|
|
*******************************************************************************/
|
2020-07-15 21:42:10 +02:00
|
|
|
package com.minres.scviewer.database.ui.swt.internal;
|
2015-01-20 18:50:15 +01:00
|
|
|
|
2021-01-14 23:14:22 +01:00
|
|
|
import java.util.TreeMap;
|
2015-01-20 18:50:15 +01:00
|
|
|
|
|
|
|
import org.eclipse.swt.SWT;
|
2020-11-28 20:32:11 +01:00
|
|
|
import org.eclipse.swt.graphics.Color;
|
2015-01-21 21:58:35 +01:00
|
|
|
import org.eclipse.swt.graphics.Point;
|
2015-01-20 18:50:15 +01:00
|
|
|
import org.eclipse.swt.graphics.Rectangle;
|
|
|
|
|
2021-02-27 13:26:07 +01:00
|
|
|
import com.minres.scviewer.database.EventEntry;
|
2020-11-28 14:08:34 +01:00
|
|
|
import com.minres.scviewer.database.EventKind;
|
2021-02-27 14:33:15 +01:00
|
|
|
import com.minres.scviewer.database.EventList;
|
2020-11-28 14:08:34 +01:00
|
|
|
import com.minres.scviewer.database.IEvent;
|
2021-02-27 14:33:15 +01:00
|
|
|
import com.minres.scviewer.database.IEventList;
|
2020-11-28 14:08:34 +01:00
|
|
|
import com.minres.scviewer.database.IWaveform;
|
2020-11-28 14:47:43 +01:00
|
|
|
import com.minres.scviewer.database.tx.ITx;
|
|
|
|
import com.minres.scviewer.database.tx.ITxEvent;
|
2015-11-06 19:29:36 +01:00
|
|
|
import com.minres.scviewer.database.ui.TrackEntry;
|
2015-11-12 23:35:13 +01:00
|
|
|
import com.minres.scviewer.database.ui.WaveformColors;
|
2015-01-20 18:50:15 +01:00
|
|
|
|
2015-11-06 19:29:36 +01:00
|
|
|
public class StreamPainter extends TrackPainter{
|
2015-01-20 18:50:15 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
private final WaveformCanvas waveCanvas;
|
2020-11-28 14:08:34 +01:00
|
|
|
private IWaveform stream;
|
2020-11-29 12:42:51 +01:00
|
|
|
private int txBase;
|
|
|
|
private int txHeight;
|
2021-02-26 12:57:54 +01:00
|
|
|
// TODO: remove TreeMap usage
|
2021-01-14 23:14:22 +01:00
|
|
|
private TreeMap<ITx, ITxEvent> seenTx;
|
2015-01-20 18:50:15 +01:00
|
|
|
|
2015-11-06 19:29:36 +01:00
|
|
|
public StreamPainter(WaveformCanvas waveCanvas, boolean even, TrackEntry trackEntry) {
|
|
|
|
super(trackEntry, even);
|
|
|
|
this.waveCanvas = waveCanvas;
|
2020-11-28 14:08:34 +01:00
|
|
|
this.stream=trackEntry.waveform;
|
2021-01-14 23:14:22 +01:00
|
|
|
this.seenTx=new TreeMap<>();
|
2015-01-20 18:50:15 +01:00
|
|
|
}
|
2020-11-28 14:08:34 +01:00
|
|
|
|
2020-06-20 17:58:26 +02:00
|
|
|
public void paintArea(Projection proj, Rectangle area) {
|
2021-01-14 23:14:22 +01:00
|
|
|
int trackHeight=trackEntry.height/stream.getRowCount();
|
2021-02-17 21:24:25 +01:00
|
|
|
if(stream.getEvents().size()==0) {
|
|
|
|
proj.setFillRule(SWT.FILL_EVEN_ODD);
|
|
|
|
proj.setLineStyle(SWT.LINE_SOLID);
|
|
|
|
proj.setLineWidth(1);
|
|
|
|
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE));
|
|
|
|
for( int y1=area.y+trackHeight/2; y1<area.y+trackEntry.height; y1+=trackHeight)
|
|
|
|
proj.drawLine(area.x, y1, area.x+area.width, y1);
|
|
|
|
return;
|
|
|
|
}
|
2015-11-06 19:29:36 +01:00
|
|
|
txBase=trackHeight/5;
|
|
|
|
txHeight=trackHeight*3/5;
|
2019-06-09 17:29:22 +02:00
|
|
|
if(trackEntry.selected) {
|
2020-11-28 19:41:00 +01:00
|
|
|
proj.setBackground(this.waveCanvas.styleProvider.getColor(WaveformColors.TRACK_BG_HIGHLITE));
|
2019-06-09 17:29:22 +02:00
|
|
|
}
|
2015-01-21 21:58:35 +01:00
|
|
|
else
|
2020-11-28 19:41:00 +01:00
|
|
|
proj.setBackground(this.waveCanvas.styleProvider.getColor(even?WaveformColors.TRACK_BG_EVEN:WaveformColors.TRACK_BG_ODD));
|
2020-06-20 17:58:26 +02:00
|
|
|
proj.setFillRule(SWT.FILL_EVEN_ODD);
|
|
|
|
proj.fillRectangle(area);
|
2020-11-28 14:08:34 +01:00
|
|
|
|
2019-03-17 20:03:22 +01:00
|
|
|
long scaleFactor = this.waveCanvas.getScaleFactor();
|
|
|
|
long beginPos = area.x;
|
2020-06-20 17:58:26 +02:00
|
|
|
long beginTime = beginPos*scaleFactor;
|
2020-11-28 14:08:34 +01:00
|
|
|
long endTime = beginTime + area.width*scaleFactor;
|
2019-03-17 20:03:22 +01:00
|
|
|
|
2021-02-27 14:33:15 +01:00
|
|
|
IEventList events = stream.getEvents();
|
|
|
|
EventEntry firstTx = events.floorEntry(beginTime);
|
|
|
|
EventEntry lastTx = events.ceilingEntry(endTime);
|
|
|
|
if(firstTx==null) firstTx = events.firstEntry();
|
|
|
|
if(lastTx==null) lastTx = events.lastEntry();
|
2020-06-20 17:58:26 +02:00
|
|
|
proj.setFillRule(SWT.FILL_EVEN_ODD);
|
|
|
|
proj.setLineStyle(SWT.LINE_SOLID);
|
|
|
|
proj.setLineWidth(1);
|
2020-11-28 19:41:00 +01:00
|
|
|
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE));
|
2020-11-28 14:08:34 +01:00
|
|
|
|
|
|
|
for( int y1=area.y+trackHeight/2; y1<area.y+trackEntry.height; y1+=trackHeight)
|
|
|
|
proj.drawLine(area.x, y1, area.x+area.width, y1);
|
2019-06-09 17:29:22 +02:00
|
|
|
if(firstTx==lastTx) {
|
2021-02-27 13:26:07 +01:00
|
|
|
for(IEvent txEvent: firstTx.events)
|
2021-01-14 23:14:22 +01:00
|
|
|
drawTx(proj, area, ((ITxEvent)txEvent).getTransaction(), ((ITxEvent)txEvent).getRowIndex(), false);
|
2019-06-09 17:29:22 +02:00
|
|
|
}else{
|
2015-01-21 21:58:35 +01:00
|
|
|
seenTx.clear();
|
2021-01-14 23:14:22 +01:00
|
|
|
ITxEvent highlighed=null;
|
2020-11-28 19:41:00 +01:00
|
|
|
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE));
|
2021-01-03 14:16:56 +01:00
|
|
|
long selectedId=waveCanvas.currentSelection!=null? waveCanvas.currentSelection.getId():-1;
|
2021-02-27 14:33:15 +01:00
|
|
|
for(EventEntry entry: events.subMap(firstTx.timestamp, true, lastTx.timestamp))
|
2021-02-27 13:26:07 +01:00
|
|
|
for(IEvent e:entry.events){
|
2021-01-14 23:14:22 +01:00
|
|
|
ITxEvent evt = (ITxEvent) e;
|
|
|
|
ITx tx = evt.getTransaction();
|
|
|
|
if(selectedId==tx.getId())
|
|
|
|
highlighed=evt;
|
2021-01-03 14:16:56 +01:00
|
|
|
switch(evt.getKind()) {
|
|
|
|
case BEGIN:
|
2021-01-14 23:14:22 +01:00
|
|
|
seenTx.put(tx, evt);
|
2021-01-03 14:16:56 +01:00
|
|
|
break;
|
|
|
|
case END:
|
2021-01-14 23:14:22 +01:00
|
|
|
drawTx(proj, area, tx, evt.getRowIndex(), false);
|
2015-02-04 16:20:59 +01:00
|
|
|
seenTx.remove(tx);
|
2021-01-14 23:14:22 +01:00
|
|
|
break;
|
2021-01-03 14:16:56 +01:00
|
|
|
case SINGLE:
|
2021-01-14 23:14:22 +01:00
|
|
|
drawTx(proj, area, tx, evt.getRowIndex(), false);
|
2021-01-03 14:16:56 +01:00
|
|
|
break;
|
2015-01-21 21:58:35 +01:00
|
|
|
}
|
|
|
|
}
|
2021-01-14 23:14:22 +01:00
|
|
|
seenTx.entrySet().stream().forEach(e -> {
|
|
|
|
drawTx(proj, area, e.getKey(), e.getValue().getRowIndex(), false);
|
|
|
|
});
|
|
|
|
|
|
|
|
if(highlighed!=null){
|
2020-11-28 19:41:00 +01:00
|
|
|
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE_HIGHLITE));
|
2021-01-14 23:14:22 +01:00
|
|
|
drawTx(proj, area, highlighed.getTransaction(), highlighed.getRowIndex(), true);
|
2015-02-04 16:20:59 +01:00
|
|
|
}
|
2015-01-20 18:50:15 +01:00
|
|
|
}
|
|
|
|
}
|
2020-11-28 14:08:34 +01:00
|
|
|
|
2021-01-14 23:14:22 +01:00
|
|
|
protected void drawTx(Projection proj, Rectangle area, ITx tx, int concurrencyIndex, boolean highlighted ) {
|
2019-06-09 17:29:22 +02:00
|
|
|
// compute colors
|
2020-11-28 20:32:11 +01:00
|
|
|
Color[] transColor = waveCanvas.styleProvider.computeColor( tx.getGenerator().getName());
|
2020-11-28 14:08:34 +01:00
|
|
|
|
2020-11-28 20:32:11 +01:00
|
|
|
proj.setBackground(transColor[highlighted?1:0]);
|
2020-11-28 14:08:34 +01:00
|
|
|
|
2021-01-14 23:14:22 +01:00
|
|
|
int offset = concurrencyIndex*this.waveCanvas.styleProvider.getTrackHeight();
|
2015-01-20 18:50:15 +01:00
|
|
|
Rectangle bb = new Rectangle(
|
2020-06-20 17:58:26 +02:00
|
|
|
(int)(tx.getBeginTime()/this.waveCanvas.getScaleFactor()), area.y+offset+txBase,
|
2015-01-20 18:50:15 +01:00
|
|
|
(int)((tx.getEndTime()-tx.getBeginTime())/this.waveCanvas.getScaleFactor()), txHeight);
|
2019-03-17 20:03:22 +01:00
|
|
|
|
2015-01-20 18:50:15 +01:00
|
|
|
if(bb.x+bb.width<area.x || bb.x>area.x+area.width) return;
|
2015-01-29 11:02:03 +01:00
|
|
|
if(bb.width==0){
|
2020-06-20 17:58:26 +02:00
|
|
|
proj.drawLine(bb.x, bb.y, bb.x, bb.y+bb.height);
|
2015-01-20 18:50:15 +01:00
|
|
|
} else {
|
2018-08-27 23:46:06 +02:00
|
|
|
if(bb.x < area.x) {
|
|
|
|
bb.width = bb.width-(area.x-bb.x)+5;
|
|
|
|
bb.x=area.x-5;
|
|
|
|
}
|
2020-11-29 12:42:51 +01:00
|
|
|
int bbX2 = bb.x+bb.width;
|
|
|
|
int areaX2 = area.x+area.width;
|
|
|
|
if(bbX2>areaX2){
|
|
|
|
bbX2=areaX2+5;
|
|
|
|
bb.width= bbX2-bb.x;
|
2018-08-27 23:46:06 +02:00
|
|
|
}
|
2020-10-17 12:44:33 +02:00
|
|
|
int arc = bb.width<10?1:5;
|
|
|
|
proj.fillRoundRectangle(bb.x, bb.y, bb.width, bb.height, arc, arc);
|
|
|
|
proj.drawRoundRectangle(bb.x, bb.y, bb.width, bb.height, arc, arc);
|
2015-01-20 18:50:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-06 19:29:36 +01:00
|
|
|
public ITx getClicked(Point point) {
|
2020-11-28 19:41:00 +01:00
|
|
|
int lane=point.y/waveCanvas.styleProvider.getTrackHeight();
|
2021-02-27 13:26:07 +01:00
|
|
|
EventEntry firstTx=stream.getEvents().floorEntry(point.x*waveCanvas.getScaleFactor());
|
2015-01-21 21:58:35 +01:00
|
|
|
if(firstTx!=null){
|
|
|
|
do {
|
2021-02-27 13:26:07 +01:00
|
|
|
ITx tx = getTxFromEntry(lane, point.x, firstTx.events);
|
2015-01-21 21:58:35 +01:00
|
|
|
if(tx!=null) return tx;
|
2021-02-27 13:26:07 +01:00
|
|
|
firstTx=stream.getEvents().lowerEntry(firstTx.timestamp);
|
2015-01-21 21:58:35 +01:00
|
|
|
}while(firstTx!=null);
|
|
|
|
}
|
2015-11-06 19:29:36 +01:00
|
|
|
return null;
|
2015-01-21 21:58:35 +01:00
|
|
|
}
|
|
|
|
|
2020-11-28 14:08:34 +01:00
|
|
|
public IWaveform getStream() {
|
2015-01-29 11:02:03 +01:00
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
2020-11-28 14:08:34 +01:00
|
|
|
public void setStream(IWaveform stream) {
|
2015-01-29 11:02:03 +01:00
|
|
|
this.stream = stream;
|
|
|
|
}
|
|
|
|
|
2021-02-26 12:57:54 +01:00
|
|
|
protected ITx getTxFromEntry(int lane, int offset, IEvent[] firstTx) {
|
2020-11-28 14:08:34 +01:00
|
|
|
long timePoint=offset*waveCanvas.getScaleFactor();
|
2021-01-14 23:14:22 +01:00
|
|
|
long timePointLow=(offset-5)*waveCanvas.getScaleFactor();
|
2020-11-28 14:08:34 +01:00
|
|
|
long timePointHigh=(offset+5)*waveCanvas.getScaleFactor();
|
2021-02-26 12:57:54 +01:00
|
|
|
for(IEvent e:firstTx){
|
2021-01-14 23:14:22 +01:00
|
|
|
if(e instanceof ITxEvent) {
|
|
|
|
ITxEvent evt = (ITxEvent) e;
|
|
|
|
ITx tx=evt.getTransaction();
|
|
|
|
if(
|
|
|
|
(evt.getKind()==EventKind.SINGLE && evt.getTime()==timePoint) ||
|
|
|
|
(evt.getKind()==EventKind.SINGLE && evt.getTime()>timePointLow && evt.getTime()<timePointHigh) ||
|
|
|
|
(evt.getKind()==EventKind.BEGIN && evt.getRowIndex()==lane && evt.getTime()<=timePoint && tx.getEndTime()>=timePoint)
|
|
|
|
){
|
|
|
|
return tx;
|
|
|
|
}
|
2020-11-28 14:08:34 +01:00
|
|
|
}
|
|
|
|
}
|
2015-01-21 21:58:35 +01:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2015-01-20 18:50:15 +01:00
|
|
|
}
|