152 lines
5.0 KiB
Java
152 lines
5.0 KiB
Java
/*******************************************************************************
|
|
* Copyright (c) 2015 MINRES Technologies GmbH and others.
|
|
* 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
|
|
*******************************************************************************/
|
|
package com.minres.scviewer.database.swt.internal;
|
|
|
|
import java.util.Collection;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
|
|
import org.eclipse.swt.SWT;
|
|
import org.eclipse.swt.graphics.Color;
|
|
import org.eclipse.swt.graphics.GC;
|
|
import org.eclipse.swt.graphics.Path;
|
|
import org.eclipse.swt.graphics.Point;
|
|
import org.eclipse.swt.graphics.Rectangle;
|
|
import org.eclipse.swt.widgets.Display;
|
|
|
|
import com.minres.scviewer.database.ITx;
|
|
import com.minres.scviewer.database.ITxRelation;
|
|
import com.minres.scviewer.database.ITxStream;
|
|
import com.minres.scviewer.database.ui.WaveformColors;
|
|
|
|
public class ArrowPainter implements IPainter {
|
|
|
|
private final int xCtrlOffset=50;
|
|
|
|
private final int yCtrlOffset=30;
|
|
|
|
private WaveformCanvas waveCanvas;
|
|
|
|
private ITx tx;
|
|
|
|
private List<Rectangle> iRect;
|
|
|
|
private List<Rectangle> oRect;
|
|
|
|
private Rectangle txRectangle;
|
|
|
|
long scaleFactor;
|
|
|
|
boolean deferredUpdate;
|
|
|
|
public ArrowPainter(WaveformCanvas waveCanvas) {
|
|
this.waveCanvas = waveCanvas;
|
|
setTx(null);
|
|
}
|
|
|
|
public ITx getTx() {
|
|
return tx;
|
|
}
|
|
|
|
public void setTx(ITx newTx) {
|
|
this.tx = newTx;
|
|
iRect=new LinkedList<>();
|
|
oRect=new LinkedList<>();
|
|
scaleFactor=waveCanvas.getScaleFactor();
|
|
if(tx!=null){
|
|
calculateGeometries();
|
|
}
|
|
}
|
|
|
|
protected void calculateGeometries() {
|
|
deferredUpdate=false;
|
|
ITxStream<?> stream=tx.getStream();
|
|
IWaveformPainter painter=waveCanvas.wave2painterMap.get(stream);
|
|
if(painter==null){ // stream has been added but painter not yet created
|
|
deferredUpdate=true;
|
|
return;
|
|
}
|
|
int laneHeight=painter.getHeight()/stream.getMaxConcurrency();
|
|
txRectangle = new Rectangle(
|
|
(int)(tx.getBeginTime()/scaleFactor),
|
|
waveCanvas.rulerHeight+painter.getVerticalOffset()+laneHeight*tx.getConcurrencyIndex(),
|
|
(int)((tx.getEndTime()-tx.getBeginTime())/scaleFactor),
|
|
laneHeight);
|
|
deriveGeom(tx.getIncomingRelations(), iRect, false);
|
|
deriveGeom(tx.getOutgoingRelations(), oRect, true);
|
|
}
|
|
|
|
protected void deriveGeom(Collection<ITxRelation> relations, List<Rectangle> res, boolean useTarget) {
|
|
for(ITxRelation iTxRelation: relations){
|
|
ITx otherTx = useTarget?iTxRelation.getTarget():iTxRelation.getSource();
|
|
if(waveCanvas.wave2painterMap.containsKey(otherTx.getStream())){
|
|
ITxStream<?> stream=otherTx.getStream();
|
|
IWaveformPainter painter=waveCanvas.wave2painterMap.get(stream);
|
|
int laneHeight=painter.getHeight()/stream.getMaxConcurrency();
|
|
Rectangle bb = new Rectangle(
|
|
(int)(otherTx.getBeginTime()/scaleFactor),
|
|
waveCanvas.rulerHeight+painter.getVerticalOffset()+laneHeight*otherTx.getConcurrencyIndex(),
|
|
(int)((otherTx.getEndTime()-otherTx.getBeginTime())/scaleFactor),
|
|
laneHeight);
|
|
res.add(bb);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void paintArea(GC gc, Rectangle area) {
|
|
Color fgColor=waveCanvas.colors[WaveformColors.REL_ARROW.ordinal()];
|
|
if(deferredUpdate || (tx!=null && waveCanvas.getScaleFactor()!=scaleFactor)){
|
|
scaleFactor=waveCanvas.getScaleFactor();
|
|
calculateGeometries();
|
|
}
|
|
for(Rectangle srcRectangle:iRect){
|
|
Point target = drawPath(gc, fgColor, srcRectangle, txRectangle);
|
|
gc.drawLine(target.x-8,target.y-5, target.x,target.y);
|
|
gc.drawLine(target.x-8,target.y+5, target.x,target.y);
|
|
}
|
|
for(Rectangle tgtRectangle:oRect){
|
|
Point target = drawPath(gc, fgColor, txRectangle, tgtRectangle);
|
|
gc.drawLine(target.x-8,target.y-5, target.x,target.y);
|
|
gc.drawLine(target.x-8,target.y+5, target.x,target.y);
|
|
}
|
|
}
|
|
|
|
protected Point drawPath(GC gc, Color fgColor, Rectangle srcRectangle, Rectangle tgtRectangle) {
|
|
Point point1=new Point(0, srcRectangle.y+srcRectangle.height/2);
|
|
Point point2=new Point(0, tgtRectangle.y+tgtRectangle.height/2);
|
|
|
|
point1.x = srcRectangle.x;
|
|
point2.x = tgtRectangle.x;
|
|
|
|
if(point2.x>point1.x+srcRectangle.width) point1.x+=srcRectangle.width;
|
|
if(point1.x>point2.x+tgtRectangle.width) point2.x+=tgtRectangle.width;
|
|
|
|
Path path=new Path(Display.getCurrent());
|
|
path.moveTo(point1.x,point1.y);
|
|
if(point1.y==point2.y){
|
|
Point center=new Point((point1.x+point2.x)/2, point1.y-yCtrlOffset);
|
|
path.cubicTo(point1.x+xCtrlOffset, point1.y,
|
|
center.x-xCtrlOffset, center.y,
|
|
center.x, center.y);
|
|
path.cubicTo(center.x+xCtrlOffset, center.y,
|
|
point2.x-xCtrlOffset, point2.y,
|
|
point2.x, point2.y);
|
|
} else
|
|
path.cubicTo(point1.x+xCtrlOffset, point1.y, point2.x-xCtrlOffset, point2.y, point2.x, point2.y);
|
|
gc.setAntialias(SWT.ON);
|
|
gc.setForeground(fgColor);
|
|
gc.drawPath(path);
|
|
path.dispose();
|
|
return point2;
|
|
}
|
|
}
|