2015-01-21 21:58:35 +01:00
|
|
|
/*******************************************************************************
|
2015-10-22 00:25:12 +02:00
|
|
|
* Copyright (c) 2015 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
|
|
|
|
*******************************************************************************/
|
2015-01-25 14:23:34 +01:00
|
|
|
package com.minres.scviewer.database.swt.internal;
|
2015-01-20 18:50:15 +01:00
|
|
|
|
|
|
|
import java.util.Collection;
|
2015-01-21 21:58:35 +01:00
|
|
|
import java.util.List;
|
2015-01-20 18:50:15 +01:00
|
|
|
import java.util.Map.Entry;
|
2015-01-21 21:58:35 +01:00
|
|
|
import java.util.NavigableMap;
|
|
|
|
import java.util.TreeSet;
|
2015-01-20 18:50:15 +01:00
|
|
|
|
|
|
|
import org.eclipse.swt.SWT;
|
|
|
|
import org.eclipse.swt.graphics.GC;
|
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;
|
|
|
|
|
|
|
|
import com.minres.scviewer.database.ITx;
|
|
|
|
import com.minres.scviewer.database.ITxEvent;
|
|
|
|
import com.minres.scviewer.database.ITxStream;
|
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;
|
|
|
|
private ITxStream<? extends ITxEvent> stream;
|
2015-11-06 19:29:36 +01:00
|
|
|
private int txBase, txHeight;
|
2015-01-20 18:50:15 +01:00
|
|
|
private boolean even;
|
2015-01-21 21:58:35 +01:00
|
|
|
private TreeSet<ITx> 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;
|
|
|
|
this.stream=trackEntry.getStream();
|
2015-01-21 21:58:35 +01:00
|
|
|
this.seenTx=new TreeSet<ITx>();
|
2015-01-20 18:50:15 +01:00
|
|
|
}
|
|
|
|
|
2015-01-21 21:58:35 +01:00
|
|
|
@SuppressWarnings("unchecked")
|
2015-01-20 18:50:15 +01:00
|
|
|
public void paintArea(GC gc, Rectangle area) {
|
2015-01-21 23:10:39 +01:00
|
|
|
if(stream.getEvents().size()==0) return;
|
2015-11-06 19:29:36 +01:00
|
|
|
int trackHeight=trackEntry.height/stream.getMaxConcurrency();
|
|
|
|
txBase=trackHeight/5;
|
|
|
|
txHeight=trackHeight*3/5;
|
|
|
|
if(trackEntry.selected)
|
2015-11-12 23:35:13 +01:00
|
|
|
gc.setBackground(this.waveCanvas.colors[WaveformColors.TRACK_BG_HIGHLITE.ordinal()]);
|
2015-01-21 21:58:35 +01:00
|
|
|
else
|
2015-11-12 23:35:13 +01:00
|
|
|
gc.setBackground(this.waveCanvas.colors[even?WaveformColors.TRACK_BG_EVEN.ordinal():WaveformColors.TRACK_BG_ODD.ordinal()]);
|
2015-01-20 18:50:15 +01:00
|
|
|
gc.setFillRule(SWT.FILL_EVEN_ODD);
|
2015-10-22 00:02:58 +02:00
|
|
|
gc.fillRectangle(area);
|
2015-01-20 18:50:15 +01:00
|
|
|
Entry<Long, ?> firstTx=stream.getEvents().floorEntry(area.x*waveCanvas.getScaleFactor());
|
|
|
|
Entry<Long, ?> lastTx=stream.getEvents().ceilingEntry((area.x+area.width)*waveCanvas.getScaleFactor());
|
2015-01-21 23:10:39 +01:00
|
|
|
if(firstTx==null) firstTx = stream.getEvents().firstEntry();
|
|
|
|
if(lastTx==null) lastTx=stream.getEvents().lastEntry();
|
2015-01-20 18:50:15 +01:00
|
|
|
gc.setFillRule(SWT.FILL_EVEN_ODD);
|
|
|
|
gc.setLineStyle(SWT.LINE_SOLID);
|
|
|
|
gc.setLineWidth(1);
|
2015-11-12 23:35:13 +01:00
|
|
|
gc.setForeground(this.waveCanvas.colors[WaveformColors.LINE.ordinal()]);
|
2015-11-06 19:29:36 +01:00
|
|
|
for(int y1=area.y+trackHeight/2; y1<area.y+trackEntry.height; y1+=trackHeight)
|
2015-01-20 18:50:15 +01:00
|
|
|
gc.drawLine(area.x, y1, area.x+area.width, y1);
|
|
|
|
if(firstTx==lastTx)
|
2015-02-04 16:20:59 +01:00
|
|
|
for(ITxEvent txEvent:(Collection<? extends ITxEvent>)firstTx.getValue())
|
|
|
|
drawTx(gc, area, txEvent.getTransaction());
|
2015-01-20 18:50:15 +01:00
|
|
|
else{
|
2015-01-21 21:58:35 +01:00
|
|
|
seenTx.clear();
|
|
|
|
NavigableMap<Long,?> entries = stream.getEvents().subMap(firstTx.getKey(), true, lastTx.getKey(), true);
|
2015-02-04 16:20:59 +01:00
|
|
|
boolean highlighed=false;
|
2015-11-12 23:35:13 +01:00
|
|
|
gc.setForeground(this.waveCanvas.colors[WaveformColors.LINE.ordinal()]);
|
|
|
|
gc.setBackground(this.waveCanvas.colors[WaveformColors.TX_BG.ordinal()]);
|
2015-02-04 16:20:59 +01:00
|
|
|
for(Entry<Long, ?> entry: entries.entrySet())
|
|
|
|
for(ITxEvent txEvent:(Collection<? extends ITxEvent>)entry.getValue()){
|
|
|
|
if(txEvent.getType()==ITxEvent.Type.BEGIN)
|
|
|
|
seenTx.add(txEvent.getTransaction());
|
|
|
|
if(txEvent.getType()==ITxEvent.Type.END){
|
|
|
|
ITx tx = txEvent.getTransaction();
|
2015-10-22 00:02:58 +02:00
|
|
|
highlighed|=waveCanvas.currentSelection!=null && waveCanvas.currentSelection.equals(tx);
|
2015-02-04 16:20:59 +01:00
|
|
|
drawTx(gc, area, tx);
|
|
|
|
seenTx.remove(tx);
|
2015-01-21 21:58:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for(ITx tx:seenTx){
|
|
|
|
drawTx(gc, area, tx);
|
|
|
|
}
|
2015-02-04 16:20:59 +01:00
|
|
|
if(highlighed){
|
2015-11-12 23:35:13 +01:00
|
|
|
gc.setForeground(this.waveCanvas.colors[WaveformColors.LINE_HIGHLITE.ordinal()]);
|
|
|
|
gc.setBackground(this.waveCanvas.colors[WaveformColors.TX_BG_HIGHLITE.ordinal()]);
|
2015-02-04 16:20:59 +01:00
|
|
|
drawTx(gc, area, waveCanvas.currentSelection);
|
|
|
|
}
|
2015-01-20 18:50:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void drawTx(GC gc, Rectangle area, ITx tx) {
|
|
|
|
int offset = tx.getConcurrencyIndex()*this.waveCanvas.getTrackHeight();
|
|
|
|
Rectangle bb = new Rectangle(
|
2015-11-06 19:29:36 +01: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);
|
|
|
|
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){
|
|
|
|
gc.drawLine(bb.x, bb.y, bb.x, bb.y+bb.height);
|
|
|
|
} else if(bb.width<10){
|
2015-01-20 18:50:15 +01:00
|
|
|
gc.fillRectangle(bb);
|
|
|
|
gc.drawRectangle(bb);
|
|
|
|
} else {
|
|
|
|
gc.fillRoundRectangle(bb.x, bb.y, bb.width, bb.height, 5, 5);
|
|
|
|
gc.drawRoundRectangle(bb.x, bb.y, bb.width, bb.height, 5, 5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-06 19:29:36 +01:00
|
|
|
public ITx getClicked(Point point) {
|
2015-01-21 21:58:35 +01:00
|
|
|
int lane=point.y/waveCanvas.getTrackHeight();
|
|
|
|
Entry<Long, List<ITxEvent>> firstTx=stream.getEvents().floorEntry(point.x*waveCanvas.getScaleFactor());
|
|
|
|
if(firstTx!=null){
|
|
|
|
do {
|
2015-02-11 09:32:46 +01:00
|
|
|
ITx tx = getTxFromEntry(lane, point.x, firstTx);
|
2015-01-21 21:58:35 +01:00
|
|
|
if(tx!=null) return tx;
|
|
|
|
firstTx=stream.getEvents().lowerEntry(firstTx.getKey());
|
|
|
|
}while(firstTx!=null);
|
|
|
|
}
|
2015-11-06 19:29:36 +01:00
|
|
|
return null;
|
2015-01-21 21:58:35 +01:00
|
|
|
}
|
|
|
|
|
2015-01-29 11:02:03 +01:00
|
|
|
public ITxStream<? extends ITxEvent> getStream() {
|
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setStream(ITxStream<? extends ITxEvent> stream) {
|
|
|
|
this.stream = stream;
|
|
|
|
}
|
|
|
|
|
2015-02-11 09:32:46 +01:00
|
|
|
protected ITx getTxFromEntry(int lane, int offset, Entry<Long, List<ITxEvent>> firstTx) {
|
|
|
|
long timePoint=offset*waveCanvas.getScaleFactor();
|
2015-01-21 21:58:35 +01:00
|
|
|
for(ITxEvent evt:firstTx.getValue()){
|
2015-02-11 09:32:46 +01:00
|
|
|
ITx tx=evt.getTransaction();
|
|
|
|
if(evt.getType()==ITxEvent.Type.BEGIN && tx.getConcurrencyIndex()==lane && tx.getBeginTime()<=timePoint && tx.getEndTime()>=timePoint){
|
2015-01-21 21:58:35 +01:00
|
|
|
return evt.getTransaction();
|
|
|
|
}
|
|
|
|
}
|
2015-02-11 09:32:46 +01:00
|
|
|
// now with some fuzziness
|
|
|
|
timePoint=(offset-5)*waveCanvas.getScaleFactor();
|
|
|
|
long timePointHigh=(offset+5)*waveCanvas.getScaleFactor();
|
|
|
|
for(ITxEvent evt:firstTx.getValue()){
|
|
|
|
ITx tx=evt.getTransaction();
|
|
|
|
if(evt.getType()==ITxEvent.Type.BEGIN && tx.getConcurrencyIndex()==lane && tx.getBeginTime()<=timePointHigh && tx.getEndTime()>=timePoint){
|
|
|
|
return evt.getTransaction();
|
|
|
|
}
|
|
|
|
}
|
2015-01-21 21:58:35 +01:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2015-01-20 18:50:15 +01:00
|
|
|
}
|