[WIP ]reorganized dir structure
This commit is contained in:
@ -0,0 +1,12 @@
|
||||
package com.minres.scviewer.database.swt;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final String[] unitString={"fs", "ps", "ns", "us", "ms"};//, "s"};
|
||||
|
||||
public static final int[] unitMultiplier={1, 3, 10, 30, 100, 300};
|
||||
|
||||
public static final String CONTENT_PROVIDER_TAG = "TOOLTIP_CONTENT_PROVIDER";
|
||||
public static final String HELP_PROVIDER_TAG = "TOOLTIP_HELP_PROVIDER";
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*******************************************************************************
|
||||
* 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;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Plugin;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
public class DatabaseUiPlugin extends Plugin {
|
||||
|
||||
public void start(BundleContext context) throws Exception {
|
||||
getLog().log(new Status(IStatus.OK, "org.eclipse.e4.core", "Starting org.eclipse.e4.core bundle..."));
|
||||
}
|
||||
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
getLog().log(new Status(IStatus.OK, "org.eclipse.e4.core", "Stopping org.eclipse.e4.core bundle..."));
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package com.minres.scviewer.database.swt;
|
||||
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
public interface ToolTipContentProvider {
|
||||
|
||||
public boolean createContent(Composite parent, Point pt);
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.minres.scviewer.database.swt;
|
||||
|
||||
import org.eclipse.swt.widgets.Widget;
|
||||
|
||||
public interface ToolTipHelpTextProvider {
|
||||
/**
|
||||
* Get help text
|
||||
* @param widget the widget that is under help
|
||||
* @return a help text string
|
||||
*/
|
||||
public String getHelpText(Widget widget);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*******************************************************************************
|
||||
* 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;
|
||||
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
|
||||
import com.minres.scviewer.database.swt.internal.WaveformViewer;
|
||||
import com.minres.scviewer.database.ui.IWaveformViewer;
|
||||
import com.minres.scviewer.database.ui.IWaveformViewerFactory;
|
||||
|
||||
public class WaveformViewerFactory implements IWaveformViewerFactory {
|
||||
|
||||
@Override
|
||||
public IWaveformViewer createPanel(Composite parent) {
|
||||
return new WaveformViewer(parent);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
/*******************************************************************************
|
||||
* 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.RelationType;
|
||||
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<LinkEntry> iRect;
|
||||
|
||||
private List<LinkEntry> oRect;
|
||||
|
||||
private Rectangle txRectangle;
|
||||
|
||||
private RelationType highlightType;
|
||||
|
||||
private long selectionOffset;
|
||||
|
||||
long scaleFactor;
|
||||
|
||||
boolean deferredUpdate;
|
||||
|
||||
public ArrowPainter(WaveformCanvas waveCanvas, RelationType relationType) {
|
||||
this.waveCanvas = waveCanvas;
|
||||
highlightType=relationType;
|
||||
setTx(null);
|
||||
}
|
||||
|
||||
public RelationType getHighlightType() {
|
||||
return highlightType;
|
||||
}
|
||||
|
||||
public void setHighlightType(RelationType highlightType) {
|
||||
this.highlightType = highlightType;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
selectionOffset = waveCanvas.getXOffset();
|
||||
int laneHeight = painter.getHeight() / stream.getMaxConcurrency();
|
||||
txRectangle = new Rectangle((int) (tx.getBeginTime() / scaleFactor-waveCanvas.getXOffset()),
|
||||
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<LinkEntry> 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.getXOffset()),
|
||||
waveCanvas.rulerHeight + painter.getVerticalOffset()
|
||||
+ laneHeight * otherTx.getConcurrencyIndex(),
|
||||
(int) ((otherTx.getEndTime() - otherTx.getBeginTime()) / scaleFactor), laneHeight);
|
||||
res.add(new LinkEntry(bb, iTxRelation.getRelationType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintArea(GC gc, Rectangle area) {
|
||||
Color fgColor = waveCanvas.colors[WaveformColors.REL_ARROW.ordinal()];
|
||||
Color highliteColor = waveCanvas.colors[WaveformColors.REL_ARROW_HIGHLITE.ordinal()];
|
||||
|
||||
if (deferredUpdate || (tx != null && waveCanvas.getScaleFactor() != scaleFactor)) {
|
||||
scaleFactor = waveCanvas.getScaleFactor();
|
||||
calculateGeometries();
|
||||
}
|
||||
if(txRectangle == null) return;
|
||||
int correctionValue = (int)(selectionOffset - waveCanvas.getXOffset());
|
||||
Rectangle correctedTargetRectangle = new Rectangle(txRectangle.x+correctionValue, txRectangle.y, txRectangle.width, txRectangle.height);
|
||||
for (LinkEntry entry : iRect) {
|
||||
Rectangle correctedRectangle = new Rectangle(entry.rectangle.x+correctionValue, entry.rectangle.y, entry.rectangle.width, entry.rectangle.height);
|
||||
Point target = drawPath(gc, highlightType.equals(entry.relationType) ? highliteColor : fgColor,
|
||||
correctedRectangle, correctedTargetRectangle);
|
||||
drawArrow(gc, target);
|
||||
}
|
||||
for (LinkEntry entry : oRect) {
|
||||
Rectangle correctedRectangle = new Rectangle(entry.rectangle.x+correctionValue, entry.rectangle.y, entry.rectangle.width, entry.rectangle.height);
|
||||
Point target = drawPath(gc, highlightType.equals(entry.relationType) ? highliteColor : fgColor, correctedTargetRectangle,
|
||||
correctedRectangle);
|
||||
drawArrow(gc, target);
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawArrow(GC gc, Point target) {
|
||||
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;
|
||||
}
|
||||
|
||||
class LinkEntry {
|
||||
public Rectangle rectangle;
|
||||
public RelationType relationType;
|
||||
|
||||
public LinkEntry(Rectangle rectangle, RelationType relationType) {
|
||||
super();
|
||||
this.rectangle = rectangle;
|
||||
this.relationType = relationType;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*******************************************************************************
|
||||
* 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 org.eclipse.swt.graphics.Color;
|
||||
import org.eclipse.swt.graphics.GC;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
|
||||
import com.minres.scviewer.database.ui.ICursor;
|
||||
import com.minres.scviewer.database.ui.WaveformColors;
|
||||
|
||||
public class CursorPainter implements IPainter, ICursor {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final WaveformCanvas waveCanvas;
|
||||
|
||||
private long time;
|
||||
|
||||
private boolean isDragging;
|
||||
|
||||
public final int id;
|
||||
|
||||
/// maximum visible canvas position in canvas coordinates
|
||||
int maxPosX;
|
||||
/// maximum visible position in waveform coordinates
|
||||
int maxValX;
|
||||
|
||||
/**
|
||||
* @param i
|
||||
* @param txDisplay
|
||||
*/
|
||||
public CursorPainter(WaveformCanvas txDisplay, long time, int id) {
|
||||
this.waveCanvas = txDisplay;
|
||||
this.time=time;
|
||||
this.id=id;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public boolean isDragging() {
|
||||
return isDragging;
|
||||
}
|
||||
|
||||
public void setDragging(boolean isDragging) {
|
||||
this.isDragging = isDragging;
|
||||
}
|
||||
|
||||
|
||||
public void paintArea(GC gc, Rectangle area) {
|
||||
if(this.waveCanvas.painterList.size()>0){
|
||||
|
||||
long scaleFactor=waveCanvas.getScaleFactor();
|
||||
long beginPos = area.x;
|
||||
|
||||
maxPosX = area.x + area.width;
|
||||
maxValX = maxPosX + (int)waveCanvas.getXOffset();
|
||||
|
||||
// x position of marker in pixels on canvas
|
||||
int x = (int) (time/scaleFactor);
|
||||
// distance of marker from the top of Canvas' painting area
|
||||
int top = id<0?area.y:area.y+15;
|
||||
|
||||
Color drawColor=waveCanvas.colors[id<0?WaveformColors.CURSOR.ordinal():WaveformColors.MARKER.ordinal()];
|
||||
Color dragColor = waveCanvas.colors[WaveformColors.CURSOR_DRAG.ordinal()];
|
||||
Color textColor=waveCanvas.colors[id<0?WaveformColors.CURSOR_TEXT.ordinal():WaveformColors.MARKER_TEXT.ordinal()];
|
||||
if(x>=beginPos && x<=maxValX){
|
||||
gc.setForeground(isDragging?dragColor:drawColor);
|
||||
gc.drawLine(x-(int)waveCanvas.getXOffset(), top, x-(int)waveCanvas.getXOffset(), area.y+area.height);
|
||||
gc.setBackground(drawColor);
|
||||
gc.setForeground(textColor);
|
||||
Double dTime=new Double(time);
|
||||
gc.drawText((dTime/waveCanvas.getScaleFactorPow10())+waveCanvas.getUnitStr(), x+1-(int)waveCanvas.getXOffset(), top);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*******************************************************************************
|
||||
* 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 org.eclipse.swt.graphics.GC;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
|
||||
public interface IPainter {
|
||||
|
||||
void paintArea(GC gc,Rectangle area);
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*******************************************************************************
|
||||
* 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 com.minres.scviewer.database.ui.TrackEntry;
|
||||
|
||||
public interface IWaveformPainter extends IPainter {
|
||||
|
||||
public int getHeight();
|
||||
|
||||
public int getVerticalOffset();
|
||||
|
||||
public TrackEntry getTrackEntry();
|
||||
|
||||
}
|
@ -0,0 +1,566 @@
|
||||
/*******************************************************************************
|
||||
* 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.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
public class ObservableList<E> implements List<E> {
|
||||
private List<E> delegate;
|
||||
private PropertyChangeSupport pcs;
|
||||
public static final String SIZE_PROPERTY = "size";
|
||||
public static final String CONTENT_PROPERTY = "content";
|
||||
|
||||
public ObservableList() {
|
||||
this(new ArrayList<E>());
|
||||
}
|
||||
|
||||
public ObservableList(List<E> delegate) {
|
||||
this.delegate = delegate;
|
||||
this.pcs = new PropertyChangeSupport(this);
|
||||
}
|
||||
|
||||
public List<E> getContent() {
|
||||
return Collections.unmodifiableList(this.delegate);
|
||||
}
|
||||
|
||||
protected List<E> getDelegateList() {
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
protected void fireElementAddedEvent(int index, Object element) {
|
||||
fireElementEvent(new ElementAddedEvent(this, element, index));
|
||||
}
|
||||
|
||||
protected void fireMultiElementAddedEvent(int index, List<E> values) {
|
||||
fireElementEvent(new MultiElementAddedEvent(this, index, values));
|
||||
}
|
||||
|
||||
protected void fireElementClearedEvent(List<E> values) {
|
||||
fireElementEvent(new ElementClearedEvent(this, values));
|
||||
}
|
||||
|
||||
protected void fireElementRemovedEvent(int index, Object element) {
|
||||
fireElementEvent(new ElementRemovedEvent(this, element, index));
|
||||
}
|
||||
|
||||
protected void fireMultiElementRemovedEvent(List<E> values) {
|
||||
fireElementEvent(new MultiElementRemovedEvent(this, values));
|
||||
}
|
||||
|
||||
protected void fireElementUpdatedEvent(int index, Object oldValue, Object newValue) {
|
||||
fireElementEvent(new ElementUpdatedEvent(this, oldValue, newValue, index));
|
||||
}
|
||||
|
||||
protected void fireElementEvent(ElementEvent event) {
|
||||
this.pcs.firePropertyChange(event);
|
||||
}
|
||||
|
||||
protected void fireSizeChangedEvent(int oldValue, int newValue) {
|
||||
this.pcs.firePropertyChange(new PropertyChangeEvent(this, "size", Integer.valueOf(oldValue), Integer
|
||||
.valueOf(newValue)));
|
||||
}
|
||||
|
||||
public void add(int index, E element) {
|
||||
int oldSize = size();
|
||||
this.delegate.add(index, element);
|
||||
fireElementAddedEvent(index, element);
|
||||
fireSizeChangedEvent(oldSize, size());
|
||||
}
|
||||
|
||||
public boolean add(E o) {
|
||||
int oldSize = size();
|
||||
boolean success = this.delegate.add(o);
|
||||
if (success) {
|
||||
fireElementAddedEvent(size() - 1, o);
|
||||
fireSizeChangedEvent(oldSize, size());
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
int oldSize = size();
|
||||
int index = size() - 1;
|
||||
index = (index < 0) ? 0 : index;
|
||||
|
||||
boolean success = this.delegate.addAll(c);
|
||||
if ((success) && (c != null)) {
|
||||
List<E> values = new ArrayList<E>();
|
||||
for (Iterator<? extends E> i = c.iterator(); i.hasNext();) {
|
||||
values.add(i.next());
|
||||
}
|
||||
if (values.size() > 0) {
|
||||
fireMultiElementAddedEvent(index, values);
|
||||
fireSizeChangedEvent(oldSize, size());
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public boolean addAll(int index, Collection<? extends E> c) {
|
||||
int oldSize = size();
|
||||
boolean success = this.delegate.addAll(index, c);
|
||||
|
||||
if ((success) && (c != null)) {
|
||||
List<E> values = new ArrayList<E>();
|
||||
for (Iterator<? extends E> i = c.iterator(); i.hasNext();) {
|
||||
values.add(i.next());
|
||||
}
|
||||
if (values.size() > 0) {
|
||||
fireMultiElementAddedEvent(index, values);
|
||||
fireSizeChangedEvent(oldSize, size());
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
int oldSize = size();
|
||||
List<E> values = new ArrayList<E>();
|
||||
values.addAll(this.delegate);
|
||||
this.delegate.clear();
|
||||
if (!(values.isEmpty())) {
|
||||
fireElementClearedEvent(values);
|
||||
}
|
||||
fireSizeChangedEvent(oldSize, size());
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
return this.delegate.contains(o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return this.delegate.containsAll(c);
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return this.delegate.equals(o);
|
||||
}
|
||||
|
||||
public E get(int index) {
|
||||
return this.delegate.get(index);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return this.delegate.hashCode();
|
||||
}
|
||||
|
||||
public int indexOf(Object o) {
|
||||
return this.delegate.indexOf(o);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.delegate.isEmpty();
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return new ObservableIterator(this.delegate.iterator());
|
||||
}
|
||||
|
||||
public int lastIndexOf(Object o) {
|
||||
return this.delegate.lastIndexOf(o);
|
||||
}
|
||||
|
||||
public ListIterator<E> listIterator() {
|
||||
return new ObservableListIterator(this.delegate.listIterator(), 0);
|
||||
}
|
||||
|
||||
public ListIterator<E> listIterator(int index) {
|
||||
return new ObservableListIterator(this.delegate.listIterator(index), index);
|
||||
}
|
||||
|
||||
public E remove(int index) {
|
||||
int oldSize = size();
|
||||
E element = this.delegate.remove(index);
|
||||
fireElementRemovedEvent(index, element);
|
||||
fireSizeChangedEvent(oldSize, size());
|
||||
return element;
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
int index = this.delegate.indexOf(o);
|
||||
if(index<0) return false;
|
||||
return remove(index)!=null;
|
||||
}
|
||||
|
||||
public boolean remove(Collection<?> o) {
|
||||
int oldSize = size();
|
||||
int index = this.delegate.indexOf(o);
|
||||
boolean success = this.delegate.remove(o);
|
||||
if (success) {
|
||||
fireElementRemovedEvent(index, o);
|
||||
fireSizeChangedEvent(oldSize, size());
|
||||
}
|
||||
return success;
|
||||
}
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
if (c == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<E> values = new ArrayList<E>();
|
||||
if (c != null) {
|
||||
for (Iterator<?> i = c.iterator(); i.hasNext();) {
|
||||
@SuppressWarnings("unchecked")
|
||||
E element = (E) i.next();
|
||||
if (this.delegate.contains(element)) {
|
||||
values.add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int oldSize = size();
|
||||
boolean success = this.delegate.removeAll(c);
|
||||
if ((success) && (!(values.isEmpty()))) {
|
||||
fireMultiElementRemovedEvent(values);
|
||||
fireSizeChangedEvent(oldSize, size());
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
if (c == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<E> values = new ArrayList<E>();
|
||||
Iterator<? extends E> i;
|
||||
if (c != null) {
|
||||
for (i = this.delegate.iterator(); i.hasNext();) {
|
||||
E element = i.next();
|
||||
if (!(c.contains(element))) {
|
||||
values.add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int oldSize = size();
|
||||
boolean success = this.delegate.retainAll(c);
|
||||
if ((success) && (!(values.isEmpty()))) {
|
||||
fireMultiElementRemovedEvent(values);
|
||||
fireSizeChangedEvent(oldSize, size());
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public E set(int index, E o) {
|
||||
E oldValue = this.delegate.set(index, o);
|
||||
fireElementUpdatedEvent(index, oldValue, o);
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.delegate.size();
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size();
|
||||
}
|
||||
|
||||
public List<E> subList(int fromIndex, int toIndex) {
|
||||
return this.delegate.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
public void rotate(int fromIndex, int toIndex, int distance){
|
||||
Collections.rotate(this.delegate.subList(fromIndex, toIndex), distance);
|
||||
fireElementEvent(new MultiElementUpdatedEvent(this, this.delegate.subList(fromIndex, toIndex)));
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
return this.delegate.toArray();
|
||||
}
|
||||
|
||||
public <T> T[] toArray(T[] a){
|
||||
return this.delegate.toArray(a);
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.pcs.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
||||
this.pcs.addPropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
public PropertyChangeListener[] getPropertyChangeListeners() {
|
||||
return this.pcs.getPropertyChangeListeners();
|
||||
}
|
||||
|
||||
public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
|
||||
return this.pcs.getPropertyChangeListeners(propertyName);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
this.pcs.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
||||
this.pcs.removePropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
public boolean hasListeners(String propertyName) {
|
||||
return this.pcs.hasListeners(propertyName);
|
||||
}
|
||||
|
||||
public static class MultiElementUpdatedEvent extends ObservableList.ElementEvent {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 7819626246672640599L;
|
||||
|
||||
private List<Object> values = new ArrayList<Object>();
|
||||
|
||||
public MultiElementUpdatedEvent(Object source, List<?> values) {
|
||||
super(source, ObservableList.ChangeType.oldValue, ObservableList.ChangeType.newValue, 0,
|
||||
ObservableList.ChangeType.MULTI_UPDATED);
|
||||
if (values != null)
|
||||
this.values.addAll(values);
|
||||
}
|
||||
|
||||
public List<?> getValues() {
|
||||
return Collections.unmodifiableList(this.values);
|
||||
}
|
||||
}
|
||||
|
||||
public static class MultiElementRemovedEvent extends ObservableList.ElementEvent {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 7819626246672640599L;
|
||||
|
||||
private List<Object> values = new ArrayList<Object>();
|
||||
|
||||
public MultiElementRemovedEvent(Object source, List<?> values) {
|
||||
super(source, ObservableList.ChangeType.oldValue, ObservableList.ChangeType.newValue, 0,
|
||||
ObservableList.ChangeType.MULTI_REMOVE);
|
||||
if (values != null)
|
||||
this.values.addAll(values);
|
||||
}
|
||||
|
||||
public List<?> getValues() {
|
||||
return Collections.unmodifiableList(this.values);
|
||||
}
|
||||
}
|
||||
|
||||
public static class MultiElementAddedEvent extends ObservableList.ElementEvent {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -116376519087713082L;
|
||||
private List<Object> values = new ArrayList<Object>();
|
||||
|
||||
public MultiElementAddedEvent(Object source, int index, List<?> values) {
|
||||
super(source, ObservableList.ChangeType.oldValue, ObservableList.ChangeType.newValue, index,
|
||||
ObservableList.ChangeType.MULTI_ADD);
|
||||
if (values != null)
|
||||
this.values.addAll(values);
|
||||
}
|
||||
|
||||
public List<?> getValues() {
|
||||
return Collections.unmodifiableList(this.values);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ElementClearedEvent extends ObservableList.ElementEvent {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -8654027608903811577L;
|
||||
private List<Object> values = new ArrayList<Object>();
|
||||
|
||||
public ElementClearedEvent(Object source, List<?> values) {
|
||||
super(source, ObservableList.ChangeType.oldValue, ObservableList.ChangeType.newValue, 0,
|
||||
ObservableList.ChangeType.CLEARED);
|
||||
if (values != null)
|
||||
this.values.addAll(values);
|
||||
}
|
||||
|
||||
public List<?> getValues() {
|
||||
return Collections.unmodifiableList(this.values);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ElementRemovedEvent extends ObservableList.ElementEvent {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -6664217547528652003L;
|
||||
|
||||
public ElementRemovedEvent(Object source, Object value, int index) {
|
||||
super(source, value, null, index, ObservableList.ChangeType.REMOVED);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ElementUpdatedEvent extends ObservableList.ElementEvent {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 7793549621724991011L;
|
||||
|
||||
public ElementUpdatedEvent(Object source, Object oldValue, Object newValue, int index) {
|
||||
super(source, oldValue, newValue, index, ObservableList.ChangeType.UPDATED);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ElementAddedEvent extends ObservableList.ElementEvent {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -6990071468319043554L;
|
||||
|
||||
public ElementAddedEvent(Object source, Object newValue, int index) {
|
||||
super(source, null, newValue, index, ObservableList.ChangeType.ADDED);
|
||||
}
|
||||
}
|
||||
|
||||
public static abstract class ElementEvent extends PropertyChangeEvent {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 964946867437728530L;
|
||||
private final ObservableList.ChangeType type;
|
||||
private final int index;
|
||||
|
||||
public ElementEvent(Object source, Object oldValue, Object newValue, int index, ObservableList.ChangeType type) {
|
||||
super(source, "content", oldValue, newValue);
|
||||
this.type = type;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return this.index;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return this.type.ordinal();
|
||||
}
|
||||
|
||||
public ObservableList.ChangeType getChangeType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public String getTypeAsString() {
|
||||
return this.type.name().toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
public static enum ChangeType {
|
||||
ADDED, UPDATED, REMOVED, CLEARED, MULTI_ADD, MULTI_UPDATED, MULTI_REMOVE, NONE;
|
||||
|
||||
public static final Object oldValue;
|
||||
public static final Object newValue;
|
||||
|
||||
public static ChangeType resolve(int ordinal) {
|
||||
switch (ordinal) {
|
||||
case 0:
|
||||
return ADDED;
|
||||
case 2:
|
||||
return REMOVED;
|
||||
case 3:
|
||||
return CLEARED;
|
||||
case 4:
|
||||
return MULTI_ADD;
|
||||
case 5:
|
||||
return MULTI_REMOVE;
|
||||
case 6:
|
||||
return NONE;
|
||||
case 1:
|
||||
}
|
||||
return UPDATED;
|
||||
}
|
||||
|
||||
static {
|
||||
oldValue = new Object();
|
||||
newValue = new Object();
|
||||
}
|
||||
}
|
||||
|
||||
protected class ObservableListIterator extends ObservableList<E>.ObservableIterator implements ListIterator<E> {
|
||||
|
||||
public ObservableListIterator(ListIterator<E> listIterator, int index) {
|
||||
super(listIterator);
|
||||
this.cursor = (index - 1);
|
||||
}
|
||||
|
||||
public ListIterator<E> getListIterator() {
|
||||
return ((ListIterator<E>) getDelegate());
|
||||
}
|
||||
|
||||
public void add(E o) {
|
||||
ObservableList.this.add(o);
|
||||
this.cursor += 1;
|
||||
}
|
||||
|
||||
public boolean hasPrevious() {
|
||||
return getListIterator().hasPrevious();
|
||||
}
|
||||
|
||||
public int nextIndex() {
|
||||
return getListIterator().nextIndex();
|
||||
}
|
||||
|
||||
public E previous() {
|
||||
return getListIterator().previous();
|
||||
}
|
||||
|
||||
public int previousIndex() {
|
||||
return getListIterator().previousIndex();
|
||||
}
|
||||
|
||||
public void set(E o) {
|
||||
ObservableList.this.set(this.cursor, o);
|
||||
}
|
||||
}
|
||||
|
||||
protected class ObservableIterator implements Iterator<E> {
|
||||
|
||||
private Iterator<E> iterDelegate;
|
||||
|
||||
protected int cursor = -1;
|
||||
|
||||
public ObservableIterator(Iterator<E> paramIterator) {
|
||||
this.iterDelegate = paramIterator;
|
||||
}
|
||||
|
||||
public Iterator<E> getDelegate() {
|
||||
return this.iterDelegate;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return this.iterDelegate.hasNext();
|
||||
}
|
||||
|
||||
public E next() {
|
||||
this.cursor += 1;
|
||||
return this.iterDelegate.next();
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
int oldSize = ObservableList.this.size();
|
||||
Object element = ObservableList.this.get(this.cursor);
|
||||
this.iterDelegate.remove();
|
||||
ObservableList.this.fireElementRemovedEvent(this.cursor, element);
|
||||
ObservableList.this.fireSizeChangedEvent(oldSize, ObservableList.this.size());
|
||||
this.cursor -= 1;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package com.minres.scviewer.database.swt.internal;
|
||||
|
||||
import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.layout.RowLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Dialog;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.List;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
|
||||
import com.minres.scviewer.database.ITx;
|
||||
import com.minres.scviewer.database.ITxRelation;
|
||||
|
||||
class RelSelectionDialog extends Dialog {
|
||||
private java.util.List<ITxRelation> entries;
|
||||
|
||||
private java.util.List<ITx> entryTx;
|
||||
|
||||
private ITxRelation selected = null;
|
||||
|
||||
public RelSelectionDialog(Shell shell, ArrayList<ITxRelation> candidates, boolean target) {
|
||||
super(shell);
|
||||
entries = candidates;
|
||||
entryTx = entries.stream().map(r->target?r.getTarget():r.getSource()).collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
public ITxRelation open() {
|
||||
Shell parent = getParent();
|
||||
Shell dialog = new Shell(parent, SWT.SHEET | SWT.APPLICATION_MODAL);
|
||||
dialog.setMinimumSize(10, 10);
|
||||
|
||||
RowLayout rowLayout = new RowLayout(SWT.VERTICAL);
|
||||
//rowLayout.fill = true; // Overriding default values.
|
||||
rowLayout.marginWidth=3;
|
||||
rowLayout.marginHeight=0;
|
||||
rowLayout.marginLeft = 3;
|
||||
rowLayout.marginTop = 0;
|
||||
rowLayout.marginRight = 3;
|
||||
rowLayout.marginBottom = 0;
|
||||
dialog.setLayout(rowLayout);
|
||||
final Label lbl = new Label(dialog,SWT.NONE);
|
||||
lbl.setText("Select one:");
|
||||
final List list = new List (dialog, SWT.NONE);
|
||||
for (ITx iTx : entryTx) {
|
||||
list.add ("#tx" + iTx.getId()+" ("+iTx.getStream().getFullName()+")");
|
||||
}
|
||||
list.addListener (SWT.Selection, e -> {
|
||||
int selection = list.getSelectionIndex();
|
||||
if(selection>=0) {
|
||||
selected=entries.get(selection);
|
||||
dialog.close();
|
||||
}
|
||||
});
|
||||
final Button bt = new Button(dialog, SWT.PUSH | SWT.RIGHT);
|
||||
bt.setText("Dismiss");
|
||||
bt.setAlignment(SWT.CENTER);
|
||||
bt.addSelectionListener(widgetSelectedAdapter(e -> dialog.close()));
|
||||
dialog.pack();
|
||||
dialog.open();
|
||||
Display display = parent.getDisplay();
|
||||
while (!dialog.isDisposed()) {
|
||||
if (!display.readAndDispatch())
|
||||
display.sleep();
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
/*******************************************************************************
|
||||
* 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.text.DecimalFormat;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Color;
|
||||
import org.eclipse.swt.graphics.GC;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
import org.eclipse.wb.swt.SWTResourceManager;
|
||||
|
||||
public class RulerPainter implements IPainter {
|
||||
protected WaveformCanvas waveCanvas;
|
||||
|
||||
static final int rulerTickMinorC = 10;
|
||||
static final int rulerTickMajorC = 100;
|
||||
|
||||
static final DecimalFormat df = new DecimalFormat("#.00####");
|
||||
|
||||
public RulerPainter(WaveformCanvas waveCanvas) {
|
||||
this.waveCanvas=waveCanvas;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintArea(GC gc, Rectangle area) {
|
||||
|
||||
Color headerFgColor=waveCanvas.getDisplay().getSystemColor(SWT.COLOR_WIDGET_FOREGROUND);
|
||||
if(headerFgColor.isDisposed())
|
||||
headerFgColor=SWTResourceManager.getColor(0,0,0);
|
||||
Color headerBgColor = waveCanvas.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
|
||||
if(headerBgColor.isDisposed())
|
||||
headerBgColor=SWTResourceManager.getColor(255,255,255);
|
||||
String unit=waveCanvas.getUnitStr();
|
||||
int unitMultiplier=waveCanvas.getUnitMultiplier();
|
||||
long scaleFactor=waveCanvas.getScaleFactor();
|
||||
|
||||
long startPos=area.x*scaleFactor;
|
||||
long startVal=startPos + waveCanvas.getXOffset()*scaleFactor;
|
||||
long endPos=startPos+area.width*scaleFactor;
|
||||
|
||||
long rulerTickMinor = rulerTickMinorC*scaleFactor;
|
||||
long rulerTickMajor = rulerTickMajorC*scaleFactor;
|
||||
|
||||
int minorTickY = waveCanvas.rulerHeight-5;
|
||||
int majorTickY = waveCanvas.rulerHeight-15;
|
||||
int textY=waveCanvas.rulerHeight-20;
|
||||
int baselineY=waveCanvas.rulerHeight - 1;
|
||||
int bottom=waveCanvas.rulerHeight - 2;
|
||||
|
||||
long modulo = startVal % rulerTickMinor;
|
||||
long startMinorIncrPos = startPos+rulerTickMinor-modulo;
|
||||
long startMinorIncrVal = startVal+rulerTickMinor-modulo;
|
||||
|
||||
gc.setBackground(waveCanvas.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
|
||||
gc.fillRectangle(new Rectangle(area.x, area.y, area.width, waveCanvas.rulerHeight));
|
||||
gc.setBackground(headerBgColor);
|
||||
gc.fillRectangle(new Rectangle(area.x, area.y, area.width, baselineY));
|
||||
gc.setForeground(headerFgColor);
|
||||
gc.drawLine(area.x, area.y+bottom, area.x+area.width, area.y+bottom);
|
||||
|
||||
for (long pos = startMinorIncrPos, tick = startMinorIncrVal; pos < endPos; pos+= rulerTickMinor, tick += rulerTickMinor) {
|
||||
int x0_pos = (int) (pos/scaleFactor);
|
||||
long x0_val = tick/scaleFactor;
|
||||
if ((tick % rulerTickMajor) == 0) {
|
||||
gc.drawText(df.format(x0_val*unitMultiplier)+unit, x0_pos, area.y+textY);
|
||||
gc.drawLine(x0_pos, area.y+majorTickY, x0_pos,area.y+ bottom);
|
||||
} else {
|
||||
gc.drawLine(x0_pos, area.y+minorTickY, x0_pos, area.y+bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,431 @@
|
||||
/*******************************************************************************
|
||||
* 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.Map.Entry;
|
||||
import java.util.NavigableMap;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Color;
|
||||
import org.eclipse.swt.graphics.FontData;
|
||||
import org.eclipse.swt.graphics.GC;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
|
||||
import com.minres.scviewer.database.BitVector;
|
||||
import com.minres.scviewer.database.ISignal;
|
||||
import com.minres.scviewer.database.ui.TrackEntry;
|
||||
import com.minres.scviewer.database.ui.WaveformColors;
|
||||
|
||||
public class SignalPainter extends TrackPainter {
|
||||
private class SignalChange {
|
||||
long time;
|
||||
Object value;
|
||||
boolean fromMap;
|
||||
|
||||
public SignalChange(Entry<Long, ?> entry) {
|
||||
time = entry.getKey();
|
||||
value = entry.getValue();
|
||||
fromMap = true;
|
||||
}
|
||||
|
||||
public void set(Entry<Long, ?> entry, Long actTime) {
|
||||
if (entry != null) {
|
||||
time = entry.getKey();
|
||||
value = entry.getValue();
|
||||
fromMap = true;
|
||||
} else {
|
||||
time = actTime;
|
||||
fromMap = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void assign(SignalChange other) {
|
||||
time = other.time;
|
||||
value = other.value;
|
||||
fromMap = other.fromMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final JPanel DUMMY_PANEL = new JPanel();
|
||||
|
||||
private final WaveformCanvas waveCanvas;
|
||||
|
||||
int yOffsetT;
|
||||
int yOffsetM;
|
||||
int yOffsetB;
|
||||
/// maximum visible canvas position in canvas coordinates
|
||||
int maxPosX;
|
||||
/// maximum visible position in waveform coordinates
|
||||
int maxValX;
|
||||
|
||||
public SignalPainter(WaveformCanvas txDisplay, boolean even, TrackEntry trackEntry) {
|
||||
super(trackEntry, even);
|
||||
this.waveCanvas = txDisplay;
|
||||
}
|
||||
|
||||
private int getXPosEnd(long time) {
|
||||
long ltmp = time / this.waveCanvas.getScaleFactor() - waveCanvas.getXOffset();
|
||||
return ltmp > maxPosX ? maxPosX : (int) ltmp;
|
||||
}
|
||||
|
||||
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
|
||||
gc.setBackground(this.waveCanvas.colors[even ? WaveformColors.TRACK_BG_EVEN.ordinal() : WaveformColors.TRACK_BG_ODD.ordinal()]);
|
||||
gc.setFillRule(SWT.FILL_EVEN_ODD);
|
||||
gc.fillRectangle(area);
|
||||
|
||||
long scaleFactor = this.waveCanvas.getScaleFactor();
|
||||
long beginPos = area.x;
|
||||
long beginTime = (beginPos + waveCanvas.getXOffset())*scaleFactor;
|
||||
long endTime = beginTime + area.width*scaleFactor;
|
||||
|
||||
Entry<Long, ?> first = signal.getEvents().floorEntry(beginTime);
|
||||
Entry<Long, ?> last = signal.getEvents().floorEntry(endTime);
|
||||
if (first == null) {
|
||||
if (last == null)
|
||||
return;
|
||||
first = signal.getEvents().firstEntry();
|
||||
} else if (last == null) {
|
||||
last = signal.getEvents().lastEntry();
|
||||
}
|
||||
gc.setForeground(this.waveCanvas.colors[WaveformColors.LINE.ordinal()]);
|
||||
gc.setLineStyle(SWT.LINE_SOLID);
|
||||
gc.setLineWidth(1);
|
||||
NavigableMap<Long, ?> 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);
|
||||
maxPosX = area.x + area.width;
|
||||
maxValX = maxPosX + (int)waveCanvas.getXOffset();
|
||||
yOffsetT = this.waveCanvas.getTrackHeight() / 5 + area.y;
|
||||
yOffsetM = this.waveCanvas.getTrackHeight() / 2 + area.y;
|
||||
yOffsetB = 4 * this.waveCanvas.getTrackHeight() / 5 + area.y;
|
||||
int xSigChangeBeginVal = Math.max(area.x + (int)waveCanvas.getXOffset(), (int) (left.time / this.waveCanvas.getScaleFactor()));
|
||||
int xSigChangeBeginPos = area.x;
|
||||
int xSigChangeEndPos = Math.max(area.x, getXPosEnd(right.time));
|
||||
|
||||
boolean multiple = false;
|
||||
if (xSigChangeEndPos == xSigChangeBeginPos) {
|
||||
// this can trigger if
|
||||
// a) left == right
|
||||
// b) left to close to right
|
||||
if (left.time == right.time) {
|
||||
right.time = endTime;
|
||||
} else {
|
||||
multiple = true;
|
||||
long eTime = (xSigChangeBeginVal + 1) * this.waveCanvas.getScaleFactor();
|
||||
right.set(entries.floorEntry(eTime), endTime);
|
||||
right.time = eTime;
|
||||
}
|
||||
xSigChangeEndPos = getXPosEnd(right.time);
|
||||
}
|
||||
|
||||
|
||||
SignalStencil stencil = getStencil(gc, left, entries);
|
||||
do {
|
||||
stencil.draw(gc, area, left.value, right.value, xSigChangeBeginPos, xSigChangeEndPos, multiple);
|
||||
if (right.time >= endTime)
|
||||
break;
|
||||
left.assign(right);
|
||||
xSigChangeBeginPos = xSigChangeEndPos;
|
||||
right.set(entries.higherEntry(left.time), endTime);
|
||||
xSigChangeEndPos = getXPosEnd(right.time);
|
||||
multiple = false;
|
||||
if (xSigChangeEndPos == xSigChangeBeginPos) {
|
||||
multiple = true;
|
||||
long eTime = (xSigChangeBeginPos + 1) * this.waveCanvas.getScaleFactor();
|
||||
Entry<Long, ?> entry = entries.floorEntry(eTime);
|
||||
if(entry!=null && entry.getKey()> right.time)
|
||||
right.set(entry, endTime);
|
||||
xSigChangeEndPos = getXPosEnd(eTime);
|
||||
}
|
||||
} while (left.time < endTime);
|
||||
}
|
||||
|
||||
private SignalStencil getStencil(GC gc, SignalChange left, NavigableMap<Long, ?> entries) {
|
||||
Object val = left.value;
|
||||
if(val instanceof BitVector) {
|
||||
BitVector bv = (BitVector) val;
|
||||
if(bv.getWidth()==1)
|
||||
return new SingleBitStencil();
|
||||
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 (val instanceof Double)
|
||||
return new RealStencil(entries, left.value, trackEntry.waveDisplay==TrackEntry.WaveDisplay.CONTINOUS);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
private interface SignalStencil {
|
||||
|
||||
public void draw(GC gc, Rectangle area, Object left, Object right, int xBegin, int xEnd, boolean multiple);
|
||||
}
|
||||
|
||||
private class MultiBitStencil implements SignalStencil {
|
||||
|
||||
private java.awt.Font tmpAwtFont;
|
||||
private int height;
|
||||
|
||||
public MultiBitStencil(GC gc) {
|
||||
FontData fd = gc.getFont().getFontData()[0];
|
||||
height = gc.getDevice().getDPI().y * fd.getHeight() / 72;
|
||||
tmpAwtFont = new java.awt.Font(fd.getName(), fd.getStyle(), height);
|
||||
}
|
||||
|
||||
public void draw(GC gc, Rectangle area, Object left, Object right, int xBegin, int xEnd, boolean multiple) {
|
||||
Color colorBorder = waveCanvas.colors[WaveformColors.SIGNAL0.ordinal()];
|
||||
BitVector last = (BitVector) left;
|
||||
if (last.getValue().toString().contains("X")) {
|
||||
colorBorder = waveCanvas.colors[WaveformColors.SIGNALX.ordinal()];
|
||||
} else if (last.getValue().toString().contains("Z")) {
|
||||
colorBorder = waveCanvas.colors[WaveformColors.SIGNALZ.ordinal()];
|
||||
}
|
||||
int width = xEnd - xBegin;
|
||||
if (width > 1) {
|
||||
int[] points = {
|
||||
xBegin, yOffsetM,
|
||||
xBegin + 1, yOffsetT,
|
||||
xEnd - 1, yOffsetT,
|
||||
xEnd, yOffsetM,
|
||||
xEnd - 1, yOffsetB,
|
||||
xBegin + 1, yOffsetB
|
||||
};
|
||||
gc.setForeground(colorBorder);
|
||||
gc.drawPolygon(points);
|
||||
gc.setForeground(waveCanvas.colors[WaveformColors.SIGNAL_TEXT.ordinal()]);
|
||||
//TODO: this code should be provided from a central location
|
||||
String label = null;
|
||||
switch(trackEntry.valueDisplay) {
|
||||
case SIGNED:
|
||||
label=Long.toString(last.toSignedValue());
|
||||
break;
|
||||
case UNSIGNED:
|
||||
label=Long.toString(last.toUnsignedValue());
|
||||
break;
|
||||
default:
|
||||
label="h'"+last.toHexString();
|
||||
}
|
||||
Point bb = getBoxWidth(gc, label);
|
||||
if (xBegin < area.x) {
|
||||
xBegin = area.x;
|
||||
width = xEnd - xBegin;
|
||||
}
|
||||
if (width > (bb.x+1)) {
|
||||
Rectangle old = gc.getClipping();
|
||||
gc.setClipping(xBegin + 3, yOffsetT, xEnd - xBegin - 5, yOffsetB - yOffsetT);
|
||||
gc.drawText(label, xBegin + 3, yOffsetM - bb.y / 2 - 1);
|
||||
gc.setClipping(old);
|
||||
}
|
||||
} else {
|
||||
gc.setForeground(colorBorder);
|
||||
gc.drawLine(xEnd, yOffsetT, xEnd, yOffsetB);
|
||||
}
|
||||
}
|
||||
|
||||
private Point getBoxWidth(GC gc, String label) {
|
||||
return new Point(DUMMY_PANEL.getFontMetrics(tmpAwtFont).stringWidth(label), height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class MultiBitStencilAnalog implements SignalStencil {
|
||||
|
||||
final boolean continous;
|
||||
private long minVal;
|
||||
private long range;
|
||||
|
||||
public MultiBitStencilAnalog(NavigableMap<Long, ?> entries, Object left, boolean continous, boolean signed) {
|
||||
this.continous=continous;
|
||||
Collection<?> values = ((NavigableMap<Long, ?>) entries).values();
|
||||
minVal=((BitVector) left).toUnsignedValue();
|
||||
range=2;
|
||||
if(!values.isEmpty()) {
|
||||
long maxVal=minVal;
|
||||
for (Object e : entries.values()) {
|
||||
long v = ((BitVector)e).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, Object left, Object right, int xBegin, int xEnd, boolean multiple) {
|
||||
long leftVal = ((BitVector) left).toUnsignedValue();
|
||||
long rightVal= ((BitVector) right).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 > maxPosX) {
|
||||
gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxPosX, yOffsetB-yOffsetRight);
|
||||
} else {
|
||||
gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight);
|
||||
}
|
||||
} else {
|
||||
if (xEnd > maxPosX) {
|
||||
gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxPosX, 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, Object left, Object right, int xBegin, int xEnd, boolean multiple) {
|
||||
if (multiple) {
|
||||
gc.setForeground(waveCanvas.colors[WaveformColors.SIGNALU.ordinal()]);
|
||||
gc.drawLine(xBegin, yOffsetT, xBegin, yOffsetB);
|
||||
if(xEnd>xBegin)
|
||||
gc.drawLine(xEnd, yOffsetT, xEnd, yOffsetB);
|
||||
} else {
|
||||
Color color = waveCanvas.colors[WaveformColors.SIGNALX.ordinal()];
|
||||
int yOffset = yOffsetM;
|
||||
switch (((BitVector) left).getValue()[0]) {
|
||||
case '1':
|
||||
color = waveCanvas.colors[WaveformColors.SIGNAL1.ordinal()];
|
||||
yOffset = yOffsetT;
|
||||
break;
|
||||
case '0':
|
||||
color = waveCanvas.colors[WaveformColors.SIGNAL0.ordinal()];
|
||||
yOffset = yOffsetB;
|
||||
break;
|
||||
case 'Z':
|
||||
color = waveCanvas.colors[WaveformColors.SIGNALZ.ordinal()];
|
||||
break;
|
||||
default:
|
||||
}
|
||||
gc.setForeground(color);
|
||||
if (xEnd > maxPosX) {
|
||||
gc.drawLine(xBegin, yOffset, maxPosX, yOffset);
|
||||
} else {
|
||||
gc.drawLine(xBegin, yOffset, xEnd, yOffset);
|
||||
int yNext = yOffsetM;
|
||||
switch (((BitVector) right).getValue()[0]) {
|
||||
case '1':
|
||||
yNext = yOffsetT;
|
||||
break;
|
||||
case '0':
|
||||
yNext = yOffsetB;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
if (yOffset != yNext)
|
||||
gc.drawLine(xEnd, yOffset, xEnd, yNext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class RealStencil implements SignalStencil {
|
||||
|
||||
double minVal, range;
|
||||
|
||||
final double scaleFactor = 1.05;
|
||||
|
||||
boolean continous=true;
|
||||
|
||||
public RealStencil(NavigableMap<Long, ?> entries, Object left, boolean continous) {
|
||||
this.continous=continous;
|
||||
Collection<?> values = ((NavigableMap<Long, ?>) entries).values();
|
||||
minVal=(Double) left;
|
||||
range=2.0;
|
||||
if(!values.isEmpty()) {
|
||||
double maxVal=minVal;
|
||||
for (Object e : entries.values()) {
|
||||
double v = ((Double)e);
|
||||
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);
|
||||
}
|
||||
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, Object left, Object right, int xBegin, int xEnd, boolean multiple) {
|
||||
double leftVal = (Double) left;
|
||||
double rightVal= (Double) right;
|
||||
if(Double.isNaN(leftVal)) {
|
||||
Color color = waveCanvas.colors[WaveformColors.SIGNAL_NAN.ordinal()];
|
||||
int width = xEnd - xBegin;
|
||||
if (width > 1) {
|
||||
int[] points = {
|
||||
xBegin, yOffsetT,
|
||||
xEnd, yOffsetT,
|
||||
xEnd, yOffsetB,
|
||||
xBegin, yOffsetB
|
||||
};
|
||||
gc.setForeground(color);
|
||||
gc.drawPolygon(points);
|
||||
gc.setBackground(color);
|
||||
gc.fillPolygon(points);
|
||||
} else {
|
||||
gc.setForeground(color);
|
||||
gc.drawLine(xEnd, yOffsetT, xEnd, yOffsetB);
|
||||
}
|
||||
} 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 > maxPosX) {
|
||||
gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxPosX, yOffsetB-yOffsetRight);
|
||||
} else {
|
||||
gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight);
|
||||
}
|
||||
} else {
|
||||
if (xEnd > maxPosX) {
|
||||
gc.drawLine(xBegin, yOffsetB-yOffsetLeft, maxPosX, yOffsetB-yOffsetLeft);
|
||||
} else {
|
||||
gc.drawLine(xBegin, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetLeft);
|
||||
if(yOffsetRight!=yOffsetLeft) {
|
||||
gc.drawLine(xEnd, yOffsetB-yOffsetLeft, xEnd, yOffsetB-yOffsetRight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,198 @@
|
||||
/*******************************************************************************
|
||||
* 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.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.GC;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
|
||||
import com.minres.scviewer.database.ITx;
|
||||
import com.minres.scviewer.database.ITxEvent;
|
||||
import com.minres.scviewer.database.ITxStream;
|
||||
import com.minres.scviewer.database.ui.TrackEntry;
|
||||
import com.minres.scviewer.database.ui.WaveformColors;
|
||||
|
||||
public class StreamPainter extends TrackPainter{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final WaveformCanvas waveCanvas;
|
||||
private ITxStream<? extends ITxEvent> stream;
|
||||
private int txBase, txHeight;
|
||||
private boolean even;
|
||||
private TreeSet<ITx> seenTx;
|
||||
|
||||
public StreamPainter(WaveformCanvas waveCanvas, boolean even, TrackEntry trackEntry) {
|
||||
super(trackEntry, even);
|
||||
this.waveCanvas = waveCanvas;
|
||||
this.stream=trackEntry.getStream();
|
||||
this.seenTx=new TreeSet<ITx>();
|
||||
}
|
||||
|
||||
/*
|
||||
* convert java.awt.Color to org.eclipse.swt.graphics.Color
|
||||
*/
|
||||
static org.eclipse.swt.graphics.Color toSwtColor( GC gc, java.awt.Color awtColor ){
|
||||
return new org.eclipse.swt.graphics.Color( gc.getDevice(), awtColor.getRed(), awtColor.getGreen(), awtColor.getBlue() );
|
||||
}
|
||||
|
||||
static org.eclipse.swt.graphics.Color[] toSwtColors( GC gc, java.awt.Color[] awtColors ){
|
||||
org.eclipse.swt.graphics.Color[] swtColors = new org.eclipse.swt.graphics.Color[awtColors.length];
|
||||
for( int i=0; i<awtColors.length; i++ )
|
||||
swtColors[i] = toSwtColor( gc, awtColors[i] );
|
||||
return swtColors;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void paintArea(GC gc, Rectangle area) {
|
||||
if(stream.getEvents().size()==0) return;
|
||||
int trackHeight=trackEntry.height/stream.getMaxConcurrency();
|
||||
txBase=trackHeight/5;
|
||||
txHeight=trackHeight*3/5;
|
||||
if(trackEntry.selected) {
|
||||
gc.setBackground(this.waveCanvas.colors[WaveformColors.TRACK_BG_HIGHLITE.ordinal()]);
|
||||
}
|
||||
else
|
||||
gc.setBackground(this.waveCanvas.colors[even?WaveformColors.TRACK_BG_EVEN.ordinal():WaveformColors.TRACK_BG_ODD.ordinal()]);
|
||||
gc.setFillRule(SWT.FILL_EVEN_ODD);
|
||||
gc.fillRectangle(area);
|
||||
|
||||
long scaleFactor = this.waveCanvas.getScaleFactor();
|
||||
long beginPos = area.x;
|
||||
long beginTime = (beginPos + waveCanvas.getXOffset())*scaleFactor;
|
||||
//long endPos = beginPos + area.width;
|
||||
long endTime = beginTime + area.width*scaleFactor;
|
||||
|
||||
Entry<Long, ?> firstTx=stream.getEvents().floorEntry(beginTime);
|
||||
Entry<Long, ?> lastTx=stream.getEvents().ceilingEntry(endTime);
|
||||
if(firstTx==null) firstTx = stream.getEvents().firstEntry();
|
||||
if(lastTx==null) lastTx=stream.getEvents().lastEntry();
|
||||
gc.setFillRule(SWT.FILL_EVEN_ODD);
|
||||
gc.setLineStyle(SWT.LINE_SOLID);
|
||||
gc.setLineWidth(1);
|
||||
gc.setForeground(this.waveCanvas.colors[WaveformColors.LINE.ordinal()]);
|
||||
|
||||
for( int y1=area.y+trackHeight/2; y1<area.y+trackEntry.height; y1+=trackHeight)
|
||||
gc.drawLine(area.x, y1, area.x+area.width, y1);
|
||||
if(firstTx==lastTx) {
|
||||
for(ITxEvent txEvent:(Collection<? extends ITxEvent>)firstTx.getValue())
|
||||
drawTx(gc, area, txEvent.getTransaction(), false);
|
||||
}else{
|
||||
seenTx.clear();
|
||||
NavigableMap<Long,?> entries = stream.getEvents().subMap(firstTx.getKey(), true, lastTx.getKey(), true);
|
||||
boolean highlighed=false;
|
||||
gc.setForeground(this.waveCanvas.colors[WaveformColors.LINE.ordinal()]);
|
||||
|
||||
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();
|
||||
highlighed|=waveCanvas.currentSelection!=null && waveCanvas.currentSelection.equals(tx);
|
||||
drawTx(gc, area, tx, false);
|
||||
seenTx.remove(tx);
|
||||
}
|
||||
}
|
||||
for(ITx tx:seenTx){
|
||||
drawTx(gc, area, tx, false);
|
||||
}
|
||||
if(highlighed){
|
||||
gc.setForeground(this.waveCanvas.colors[WaveformColors.LINE_HIGHLITE.ordinal()]);
|
||||
drawTx(gc, area, waveCanvas.currentSelection, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawTx(GC gc, Rectangle area, ITx tx, boolean highlighted ) {
|
||||
// compute colors
|
||||
java.awt.Color[] fallbackColors = trackEntry.getColors();
|
||||
java.awt.Color[] transColor = TrackEntry.computeColor( tx.getGenerator().getName(), fallbackColors[0], fallbackColors[1] );
|
||||
|
||||
gc.setBackground( toSwtColor( gc, transColor[highlighted?1:0] ) );
|
||||
|
||||
int offset = tx.getConcurrencyIndex()*this.waveCanvas.getTrackHeight();
|
||||
Rectangle bb = new Rectangle(
|
||||
(int)(tx.getBeginTime()/this.waveCanvas.getScaleFactor()-waveCanvas.getXOffset()), area.y+offset+txBase,
|
||||
(int)((tx.getEndTime()-tx.getBeginTime())/this.waveCanvas.getScaleFactor()), txHeight);
|
||||
|
||||
if(bb.x+bb.width<area.x || bb.x>area.x+area.width) return;
|
||||
if(bb.width==0){
|
||||
gc.drawLine(bb.x, bb.y, bb.x, bb.y+bb.height);
|
||||
} else if(bb.width<10){
|
||||
gc.fillRectangle(bb);
|
||||
gc.drawRectangle(bb);
|
||||
} else {
|
||||
if(bb.x < area.x) {
|
||||
bb.width = bb.width-(area.x-bb.x)+5;
|
||||
bb.x=area.x-5;
|
||||
}
|
||||
int bb_x2 = bb.x+bb.width;
|
||||
int area_x2 = area.x+area.width;
|
||||
if(bb_x2>area_x2){
|
||||
bb_x2=area_x2+5;
|
||||
bb.width= bb_x2-bb.x;
|
||||
}
|
||||
gc.fillRoundRectangle(bb.x, bb.y, bb.width, bb.height, 5, 5);
|
||||
gc.drawRoundRectangle(bb.x, bb.y, bb.width, bb.height, 5, 5);
|
||||
}
|
||||
}
|
||||
|
||||
public ITx getClicked(Point point) {
|
||||
int lane=point.y/waveCanvas.getTrackHeight();
|
||||
Entry<Long, List<ITxEvent>> firstTx=stream.getEvents().floorEntry(point.x*waveCanvas.getScaleFactor());
|
||||
if(firstTx!=null){
|
||||
do {
|
||||
ITx tx = getTxFromEntry(lane, point.x, firstTx);
|
||||
if(tx!=null) return tx;
|
||||
firstTx=stream.getEvents().lowerEntry(firstTx.getKey());
|
||||
}while(firstTx!=null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ITxStream<? extends ITxEvent> getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void setStream(ITxStream<? extends ITxEvent> stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
protected ITx getTxFromEntry(int lane, int offset, Entry<Long, List<ITxEvent>> firstTx) {
|
||||
long timePoint=offset*waveCanvas.getScaleFactor();
|
||||
for(ITxEvent evt:firstTx.getValue()){
|
||||
ITx tx=evt.getTransaction();
|
||||
if(evt.getType()==ITxEvent.Type.BEGIN && tx.getConcurrencyIndex()==lane && tx.getBeginTime()<=timePoint && tx.getEndTime()>=timePoint){
|
||||
return evt.getTransaction();
|
||||
}
|
||||
}
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
package com.minres.scviewer.database.swt.internal;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
import org.eclipse.swt.layout.FillLayout;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Listener;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Widget;
|
||||
|
||||
import com.minres.scviewer.database.swt.Constants;
|
||||
import com.minres.scviewer.database.swt.ToolTipContentProvider;
|
||||
import com.minres.scviewer.database.swt.ToolTipHelpTextProvider;
|
||||
|
||||
class ToolTipHandler {
|
||||
|
||||
private final Display display;
|
||||
private Shell parentShell;
|
||||
private Shell shell;
|
||||
|
||||
private Widget tipWidget; // widget this tooltip is hovering over
|
||||
private Point tipPosition; // the position being hovered over
|
||||
|
||||
private static final int hoverYOffset = 1;
|
||||
|
||||
/**
|
||||
* Creates a new tooltip handler
|
||||
*
|
||||
* @param parent the parent Shell
|
||||
*/
|
||||
public ToolTipHandler(Shell parent) {
|
||||
display = parent.getDisplay();
|
||||
parentShell = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables customized hover help for a specified control
|
||||
*
|
||||
* @control the control on which to enable hoverhelp
|
||||
*/
|
||||
public void activateHoverHelp(final Control control) {
|
||||
Listener listener = new Listener () {
|
||||
Shell tip = null;
|
||||
@Override
|
||||
public void handleEvent (Event event) {
|
||||
switch (event.type) {
|
||||
case SWT.KeyDown:{
|
||||
if (tip != null && tip.isVisible() && event.keyCode == SWT.F2) {
|
||||
tip.setFocus();
|
||||
break;
|
||||
}
|
||||
}
|
||||
case SWT.Dispose:
|
||||
case SWT.MouseMove:
|
||||
case SWT.MouseDown: {
|
||||
if (tip != null){
|
||||
tip.dispose ();
|
||||
tip = null;
|
||||
tipWidget=null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SWT.MouseHover: {
|
||||
Object o = control.getData(Constants.CONTENT_PROVIDER_TAG);
|
||||
if(o != null && o instanceof ToolTipContentProvider) {
|
||||
ToolTipContentProvider provider = ((ToolTipContentProvider)o);
|
||||
Point pt = new Point (event.x, event.y);
|
||||
tipPosition = control.toDisplay(pt);
|
||||
if (tip != null && !tip.isDisposed ()) tip.dispose ();
|
||||
tip = new Shell (parentShell, SWT.NO_FOCUS | SWT.TOOL);
|
||||
tip.setBackground (display.getSystemColor (SWT.COLOR_INFO_BACKGROUND));
|
||||
GridLayout layout = new GridLayout(1, true);
|
||||
layout.verticalSpacing=0;
|
||||
layout.horizontalSpacing=0;
|
||||
layout.marginWidth = 0;
|
||||
layout.marginHeight = 0;
|
||||
tip.setLayout(layout);
|
||||
boolean visible = provider.createContent(tip, pt);
|
||||
tip.pack();
|
||||
tip.setSize(tip.computeSize(SWT.DEFAULT, SWT.DEFAULT));
|
||||
setHoverLocation(tip, tipPosition);
|
||||
tip.setVisible (visible);
|
||||
if(visible)
|
||||
tipWidget=event.widget;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
control.addListener (SWT.Dispose, listener);
|
||||
control.addListener (SWT.KeyDown, listener);
|
||||
//control.addListener (SWT.MouseMove, listener);
|
||||
control.addListener (SWT.MouseHover, listener);
|
||||
control.addListener (SWT.MouseDown, listener);
|
||||
|
||||
/*
|
||||
* Trap F1 Help to pop up a custom help box
|
||||
*/
|
||||
control.addHelpListener(event -> {
|
||||
if (tipWidget == null) return;
|
||||
ToolTipHelpTextProvider handler = (ToolTipHelpTextProvider)tipWidget.getData(Constants.HELP_PROVIDER_TAG);
|
||||
if (handler == null) return;
|
||||
String text = handler.getHelpText(tipWidget);
|
||||
if (text == null) return;
|
||||
|
||||
if (shell.isVisible()) {
|
||||
shell.setVisible(false);
|
||||
Shell helpShell = new Shell(parentShell, SWT.SHELL_TRIM);
|
||||
helpShell.setLayout(new FillLayout());
|
||||
Label label = new Label(helpShell, SWT.NONE);
|
||||
label.setText(text);
|
||||
helpShell.pack();
|
||||
setHoverLocation(helpShell, tipPosition);
|
||||
helpShell.open();
|
||||
}
|
||||
});
|
||||
// control.addKeyListener(KeyListener.keyPressedAdapter( e-> {
|
||||
// if (e.keyCode == SWT.F2 && shell.isVisible()) {
|
||||
// shell.setFocus();
|
||||
// }
|
||||
// }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the location for a hovering shell
|
||||
* @param shell the object that is to hover
|
||||
* @param position the position of a widget to hover over
|
||||
* @return the top-left location for a hovering box
|
||||
*/
|
||||
private void setHoverLocation(Shell shell, Point position) {
|
||||
Rectangle displayBounds = shell.getDisplay().getBounds();
|
||||
Rectangle shellBounds = shell.getBounds();
|
||||
shellBounds.x = Math.max(Math.min(position.x, displayBounds.width - shellBounds.width), 0);
|
||||
shellBounds.y = Math.max(Math.min(position.y + hoverYOffset, displayBounds.height - shellBounds.height), 0);
|
||||
shell.setBounds(shellBounds);
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*******************************************************************************
|
||||
* 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.Map.Entry;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.GC;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
|
||||
import com.minres.scviewer.database.ui.WaveformColors;
|
||||
|
||||
public class TrackAreaPainter implements IPainter {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final WaveformCanvas waveCanvas;
|
||||
|
||||
TreeMap<Integer, IWaveformPainter> trackVerticalOffset;
|
||||
/**
|
||||
* @param txDisplay
|
||||
*/
|
||||
public TrackAreaPainter(WaveformCanvas waveCanvas) {
|
||||
this.waveCanvas = waveCanvas;
|
||||
this.trackVerticalOffset= new TreeMap<>();
|
||||
}
|
||||
|
||||
public void paintArea(GC gc, Rectangle a) {
|
||||
Rectangle area = new Rectangle(a.x, a.y+waveCanvas.rulerHeight, a.width, a.height-waveCanvas.rulerHeight);
|
||||
gc.setBackground(this.waveCanvas.colors[WaveformColors.TRACK_BG_EVEN.ordinal()]);
|
||||
gc.setFillRule(SWT.FILL_EVEN_ODD);
|
||||
gc.fillRectangle(area);
|
||||
if(trackVerticalOffset.size()>0){
|
||||
Integer firstKey=trackVerticalOffset.floorKey(area.y);
|
||||
if(firstKey==null) firstKey=trackVerticalOffset.firstKey();
|
||||
Integer lastKey = trackVerticalOffset.floorKey(area.y+area.height);
|
||||
Rectangle subArea = new Rectangle(area.x, 0, area.width, 0);
|
||||
if(lastKey==firstKey){
|
||||
subArea.y=firstKey;
|
||||
IWaveformPainter p = trackVerticalOffset.get(firstKey);
|
||||
subArea.height=p.getHeight();
|
||||
p.paintArea(gc, subArea);
|
||||
}else{
|
||||
for(Entry<Integer, IWaveformPainter> entry : trackVerticalOffset.subMap(firstKey, true, lastKey, true).entrySet()){
|
||||
subArea.y=entry.getKey();
|
||||
subArea.height=entry.getValue().getHeight();
|
||||
entry.getValue().paintArea(gc, subArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TreeMap<Integer, IWaveformPainter> getTrackVerticalOffset() {
|
||||
return trackVerticalOffset;
|
||||
}
|
||||
|
||||
public void addTrackPainter(IWaveformPainter trackPainter){
|
||||
trackVerticalOffset.put(trackPainter.getVerticalOffset()+waveCanvas.rulerHeight, trackPainter);
|
||||
|
||||
}
|
||||
|
||||
public int getHeight(){
|
||||
if(trackVerticalOffset.size()==0) return 1;
|
||||
return trackVerticalOffset.lastKey() + trackVerticalOffset.lastEntry().getValue().getHeight();
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*******************************************************************************
|
||||
* 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 com.minres.scviewer.database.ui.TrackEntry;
|
||||
|
||||
public abstract class TrackPainter implements IWaveformPainter {
|
||||
|
||||
protected boolean even;
|
||||
|
||||
protected TrackEntry trackEntry;
|
||||
|
||||
public TrackPainter(TrackEntry trackEntry, boolean even) {
|
||||
this.trackEntry = trackEntry;
|
||||
this.even=even;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return trackEntry.height;
|
||||
}
|
||||
|
||||
public int getVerticalOffset() {
|
||||
return trackEntry.vOffset;
|
||||
}
|
||||
|
||||
public boolean isEven() {
|
||||
return even;
|
||||
}
|
||||
|
||||
public TrackEntry getTrackEntry() {
|
||||
return trackEntry;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,568 @@
|
||||
/*******************************************************************************
|
||||
* 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.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.ControlAdapter;
|
||||
import org.eclipse.swt.events.ControlEvent;
|
||||
import org.eclipse.swt.events.PaintEvent;
|
||||
import org.eclipse.swt.events.PaintListener;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.graphics.Color;
|
||||
import org.eclipse.swt.graphics.GC;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.eclipse.swt.graphics.Rectangle;
|
||||
import org.eclipse.swt.graphics.Transform;
|
||||
import org.eclipse.swt.widgets.Canvas;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.swt.widgets.ScrollBar;
|
||||
import org.eclipse.wb.swt.SWTResourceManager;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.minres.scviewer.database.ITx;
|
||||
import com.minres.scviewer.database.IWaveform;
|
||||
import com.minres.scviewer.database.RelationType;
|
||||
import com.minres.scviewer.database.swt.Constants;
|
||||
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{
|
||||
|
||||
Color[] colors = new Color[WaveformColors.values().length];
|
||||
|
||||
private int trackHeight = 50;
|
||||
|
||||
private long scaleFactor = 1000000L; // 1ns
|
||||
|
||||
String unit="ns";
|
||||
|
||||
private int level = 12;
|
||||
|
||||
private long maxTime;
|
||||
|
||||
protected Point origin; /* original size */
|
||||
|
||||
protected Transform transform;
|
||||
|
||||
protected int rulerHeight=40;
|
||||
|
||||
protected List<IPainter> painterList;
|
||||
|
||||
ITx currentSelection;
|
||||
|
||||
private List<SelectionAdapter> selectionListeners;
|
||||
|
||||
private RulerPainter rulerPainter;
|
||||
|
||||
private TrackAreaPainter trackAreaPainter;
|
||||
|
||||
private ArrowPainter arrowPainter;
|
||||
|
||||
private List<CursorPainter> cursorPainters;
|
||||
|
||||
HashMap<IWaveform, IWaveformPainter> wave2painterMap;
|
||||
/**
|
||||
* Constructor for ScrollableCanvas.
|
||||
*
|
||||
* @param parent
|
||||
* the parent of this control.super(parent, style | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.V_SCROLL | SWT.H_SCROLL);
|
||||
* @param style
|
||||
* the style of this control.
|
||||
*/
|
||||
public WaveformCanvas(final Composite parent, int style) {
|
||||
super(parent, style | SWT.DOUBLE_BUFFERED | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.V_SCROLL | SWT.H_SCROLL);
|
||||
addControlListener(new ControlAdapter() { /* resize listener. */
|
||||
public void controlResized(ControlEvent event) {
|
||||
syncScrollBars();
|
||||
}
|
||||
});
|
||||
addPaintListener(new PaintListener() { /* paint listener. */
|
||||
public void paintControl(final PaintEvent event) {
|
||||
paint(event.gc);
|
||||
}
|
||||
});
|
||||
painterList = new LinkedList<IPainter>();
|
||||
origin = new Point(0, 0);
|
||||
transform = new Transform(getDisplay());
|
||||
selectionListeners = new LinkedList<>();
|
||||
cursorPainters= new ArrayList<>();
|
||||
wave2painterMap=new HashMap<>();
|
||||
|
||||
initScrollBars();
|
||||
initColors(null);
|
||||
// order is important: it is bottom to top
|
||||
trackAreaPainter=new TrackAreaPainter(this);
|
||||
painterList.add(trackAreaPainter);
|
||||
rulerPainter=new RulerPainter(this);
|
||||
painterList.add(rulerPainter);
|
||||
arrowPainter=new ArrowPainter(this, IWaveformViewer.NEXT_PREV_IN_STREAM);
|
||||
painterList.add(arrowPainter);
|
||||
CursorPainter cp = new CursorPainter(this, scaleFactor * 10, cursorPainters.size()-1);
|
||||
painterList.add(cp);
|
||||
cursorPainters.add(cp);
|
||||
CursorPainter marker = new CursorPainter(this, scaleFactor * 100, cursorPainters.size()-1);
|
||||
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 long getXOffset() {
|
||||
return -origin.x;
|
||||
}
|
||||
|
||||
public void addCursoPainter(CursorPainter cursorPainter){
|
||||
painterList.add(cursorPainter);
|
||||
cursorPainters.add(cursorPainter);
|
||||
}
|
||||
|
||||
public void initColors(HashMap<WaveformColors, RGB> colourMap) {
|
||||
Display d = getDisplay();
|
||||
if (colourMap != null) {
|
||||
for (WaveformColors c : WaveformColors.values()) {
|
||||
if (colourMap.containsKey(c))
|
||||
colors[c.ordinal()] = new Color(d, colourMap.get(c));
|
||||
}
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public void setHighliteRelation(RelationType relationType){
|
||||
if(arrowPainter!=null){
|
||||
boolean redraw = arrowPainter.getHighlightType()!=relationType;
|
||||
arrowPainter.setHighlightType(relationType);
|
||||
if(redraw) redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public Point getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return getClientArea().width;
|
||||
}
|
||||
public void setOrigin(Point origin) {
|
||||
setOrigin(origin.x, origin.y);
|
||||
}
|
||||
|
||||
public void setOrigin(int x, int y) {
|
||||
checkWidget();
|
||||
ScrollBar hBar = getHorizontalBar();
|
||||
hBar.setSelection(-x);
|
||||
x = -hBar.getSelection();
|
||||
ScrollBar vBar = getVerticalBar();
|
||||
vBar.setSelection(-y);
|
||||
y = -vBar.getSelection();
|
||||
origin.x = x;
|
||||
origin.y = y;
|
||||
syncScrollBars();
|
||||
}
|
||||
|
||||
public long getMaxTime() {
|
||||
return maxTime;
|
||||
}
|
||||
|
||||
public void setMaxTime(long maxTime) {
|
||||
this.maxTime = maxTime;
|
||||
syncScrollBars();
|
||||
}
|
||||
|
||||
public int getTrackHeight() {
|
||||
return trackHeight;
|
||||
}
|
||||
|
||||
public void setTrackHeight(int trackHeight) {
|
||||
this.trackHeight = trackHeight;
|
||||
syncScrollBars();
|
||||
}
|
||||
|
||||
public int getZoomLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public int getMaxZoomLevel(){
|
||||
return Constants.unitMultiplier.length*Constants.unitString.length-1;
|
||||
}
|
||||
|
||||
public void setZoomLevel(int level) {
|
||||
long tc=cursorPainters.get(0).getTime(); // cursor time
|
||||
setZoomLevel(level, tc);
|
||||
}
|
||||
|
||||
public void setZoomLevel(int level, long centerTime) {
|
||||
long oldScaleFactor=scaleFactor;
|
||||
if(level<0) level = 0;
|
||||
if(level<Constants.unitMultiplier.length*Constants.unitString.length){
|
||||
this.level = level;
|
||||
this.scaleFactor = (long) Math.pow(10, level/2);
|
||||
if(level%2==1) this.scaleFactor*=3;
|
||||
ITx tx = arrowPainter.getTx();
|
||||
arrowPainter.setTx(null);
|
||||
/*
|
||||
* xc = tc/oldScaleFactor
|
||||
* xoffs = xc+origin.x
|
||||
* xcn = tc/newScaleFactor
|
||||
* t0n = (xcn-xoffs)*scaleFactor
|
||||
*/
|
||||
long xc=centerTime/oldScaleFactor; // cursor total x-offset
|
||||
long xoffs=xc+origin.x; // cursor offset relative to left border
|
||||
long xcn=centerTime/scaleFactor; // new total x-offset
|
||||
long originX=xcn-xoffs;
|
||||
if(originX>0) {
|
||||
origin.x=(int) -originX; // new cursor time offset relative to left border
|
||||
}else {
|
||||
origin.x=0;
|
||||
}
|
||||
syncScrollBars();
|
||||
arrowPainter.setTx(tx);
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public long getScaleFactor() {
|
||||
return scaleFactor;
|
||||
}
|
||||
|
||||
public long getScaleFactorPow10() {
|
||||
int scale = level/Constants.unitMultiplier.length;
|
||||
double res = Math.pow(1000, scale);
|
||||
return (long) res;
|
||||
}
|
||||
|
||||
public String getUnitStr(){
|
||||
return Constants.unitString[level/Constants.unitMultiplier.length];
|
||||
}
|
||||
|
||||
public int getUnitMultiplier(){
|
||||
return Constants.unitMultiplier[level%Constants.unitMultiplier.length];
|
||||
}
|
||||
|
||||
public long getTimeForOffset(int xOffset){
|
||||
return (xOffset-origin.x) * scaleFactor;
|
||||
}
|
||||
|
||||
public void addPainter(IPainter painter) {
|
||||
painterList.add(painter);
|
||||
redraw();
|
||||
}
|
||||
|
||||
public void removePainter(IPainter painter) {
|
||||
painterList.remove(painter);
|
||||
redraw();
|
||||
}
|
||||
|
||||
public void clearAllWaveformPainter() {
|
||||
clearAllWaveformPainter(true);
|
||||
}
|
||||
|
||||
void clearAllWaveformPainter(boolean update) {
|
||||
trackAreaPainter.getTrackVerticalOffset().clear();
|
||||
wave2painterMap.clear();
|
||||
if(update) syncScrollBars();
|
||||
}
|
||||
|
||||
public void addWaveformPainter(IWaveformPainter painter) {
|
||||
addWaveformPainter(painter, true);
|
||||
}
|
||||
|
||||
void addWaveformPainter(IWaveformPainter painter, boolean update) {
|
||||
trackAreaPainter.addTrackPainter(painter);
|
||||
wave2painterMap.put(painter.getTrackEntry().waveform, painter);
|
||||
if(update) syncScrollBars();
|
||||
}
|
||||
|
||||
public List<CursorPainter> getCursorPainters() {
|
||||
return cursorPainters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispose the garbage here
|
||||
*/
|
||||
public void dispose() {
|
||||
transform.dispose();
|
||||
for (WaveformColors c : WaveformColors.values())
|
||||
colors[c.ordinal()].dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/* Initialize the scrollbar and register listeners. */
|
||||
private void initScrollBars() {
|
||||
ScrollBar horizontal = getHorizontalBar();
|
||||
horizontal.setEnabled(false);
|
||||
horizontal.setVisible(true);
|
||||
horizontal.addSelectionListener(new SelectionAdapter() {
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
if (painterList.size() == 0)
|
||||
return;
|
||||
setOrigin(-((ScrollBar) event.widget).getSelection(), origin.y);
|
||||
}
|
||||
});
|
||||
ScrollBar vertical = getVerticalBar();
|
||||
vertical.setEnabled(false);
|
||||
vertical.setVisible(true);
|
||||
vertical.addSelectionListener(new SelectionAdapter() {
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
if (painterList.size() == 0)
|
||||
return;
|
||||
setOrigin(origin.x, -((ScrollBar) event.widget).getSelection());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize the scrollbar with the image. If the transform is out of
|
||||
* range, it will correct it. This function considers only following factors
|
||||
* :<b> transform, image size, client area</b>.
|
||||
*/
|
||||
public void syncScrollBars() {
|
||||
if (painterList.size() == 0) {
|
||||
redraw();
|
||||
return;
|
||||
}
|
||||
int height = trackAreaPainter.getHeight(); // incl. Ruler
|
||||
long width = maxTime / scaleFactor;
|
||||
Rectangle clientArea=getClientArea();
|
||||
ScrollBar horizontal = getHorizontalBar();
|
||||
horizontal.setIncrement((int) (getClientArea().width / 100));
|
||||
horizontal.setPageIncrement(getClientArea().width);
|
||||
int clientWidthw = clientArea.width;
|
||||
if (width > clientWidthw) { /* image is wider than client area */
|
||||
horizontal.setMinimum(0);
|
||||
horizontal.setMaximum((int)width);
|
||||
horizontal.setEnabled(true);
|
||||
if (((int) -origin.x) > horizontal.getMaximum() - clientWidthw) {
|
||||
origin.x = -horizontal.getMaximum() + clientWidthw;
|
||||
}
|
||||
} else { /* image is narrower than client area */
|
||||
horizontal.setEnabled(false);
|
||||
}
|
||||
horizontal.setThumb(clientWidthw);
|
||||
horizontal.setSelection(-origin.x);
|
||||
|
||||
ScrollBar vertical = getVerticalBar();
|
||||
vertical.setIncrement((int) (getClientArea().height / 100));
|
||||
vertical.setPageIncrement((int) (getClientArea().height));
|
||||
int clientHeighth = clientArea.height;
|
||||
if (height > clientHeighth) { /* image is higher than client area */
|
||||
vertical.setMinimum(0);
|
||||
vertical.setMaximum(height);
|
||||
vertical.setEnabled(true);
|
||||
if (((int) -origin.y) > vertical.getMaximum() - clientHeighth) {
|
||||
origin.y = -vertical.getMaximum() + clientHeighth;
|
||||
}
|
||||
} else { /* image is less higher than client area */
|
||||
vertical.setMaximum((int) (clientHeighth));
|
||||
vertical.setEnabled(false);
|
||||
}
|
||||
vertical.setThumb(clientHeighth);
|
||||
vertical.setSelection(-origin.y);
|
||||
redraw();
|
||||
fireSelectionEvent();
|
||||
|
||||
}
|
||||
|
||||
/* Paint function */
|
||||
private void paint(GC gc) {
|
||||
Rectangle clientRect = getClientArea(); /* Canvas' painting area */
|
||||
// clientRect.x = -origin.x;
|
||||
clientRect.y = -origin.y;
|
||||
// reset the transform
|
||||
transform.identity();
|
||||
// shift the content
|
||||
// DO NOT SHIFT HORIZONTALLY, the range is WAY TOO BIG for float!!!
|
||||
transform.translate(0, origin.y);
|
||||
gc.setTransform(transform);
|
||||
gc.setClipping(clientRect);
|
||||
if (painterList.size() > 0 ) {
|
||||
for (IPainter painter : painterList)
|
||||
painter.paintArea(gc, clientRect);
|
||||
} else {
|
||||
gc.fillRectangle(clientRect);
|
||||
initScrollBars();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Object> getElementsAt(Point point) {
|
||||
LinkedList<Object> result=new LinkedList<>();
|
||||
for (IPainter p : Lists.reverse(painterList)) {
|
||||
if (p instanceof TrackAreaPainter) {
|
||||
int y = point.y - origin.y;
|
||||
int x = point.x - origin.x;
|
||||
Entry<Integer, IWaveformPainter> entry = trackAreaPainter.getTrackVerticalOffset().floorEntry(y);
|
||||
if (entry != null) {
|
||||
if (entry.getValue() instanceof StreamPainter) {
|
||||
ITx tx = ((StreamPainter) entry.getValue()).getClicked(new Point(x, y - entry.getKey()));
|
||||
if(tx!=null)
|
||||
result.add(tx);
|
||||
}
|
||||
result.add(entry.getValue().getTrackEntry());
|
||||
}
|
||||
} else if (p instanceof CursorPainter) {
|
||||
if (Math.abs(point.x - origin.x - ((CursorPainter) p).getTime()/scaleFactor) < 2) {
|
||||
result.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Object> getEntriesAtPosition(IWaveform iWaveform, int i) {
|
||||
LinkedList<Object> result=new LinkedList<>();
|
||||
int x = i - origin.x;
|
||||
for(IPainter p: wave2painterMap.values()){
|
||||
if (p instanceof StreamPainter && ((StreamPainter)p).getStream()==iWaveform) {
|
||||
result.add(((StreamPainter) p).getClicked(new Point(x, trackHeight/2)));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setSelected(ITx currentSelection) {
|
||||
this.currentSelection = currentSelection;
|
||||
if (currentSelection != null)
|
||||
reveal(currentSelection);
|
||||
arrowPainter.setTx(currentSelection);
|
||||
redraw();
|
||||
}
|
||||
|
||||
public void reveal(ITx tx) {
|
||||
int lower = (int) (tx.getBeginTime() / scaleFactor);
|
||||
int higher = (int) (tx.getEndTime() / scaleFactor);
|
||||
Point size = getSize();
|
||||
size.x -= getVerticalBar().getSize().x + 2;
|
||||
size.y -= getHorizontalBar().getSize().y;
|
||||
if (lower < -origin.x) {
|
||||
setOrigin(-lower, origin.y);
|
||||
} else if (higher > (size.x - origin.x)) {
|
||||
setOrigin(size.x - higher, origin.y);
|
||||
}
|
||||
for (IWaveformPainter painter : wave2painterMap.values()) {
|
||||
if (painter instanceof StreamPainter && ((StreamPainter) painter).getStream() == tx.getStream()) {
|
||||
int top = painter.getVerticalOffset() + trackHeight * tx.getConcurrencyIndex();
|
||||
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(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();
|
||||
size.x -= getVerticalBar().getSize().x + 2;
|
||||
size.y -= getHorizontalBar().getSize().y;
|
||||
if (scaledTime < -origin.x) {
|
||||
setOrigin(-scaledTime+10, origin.y);
|
||||
} else if (scaledTime > (size.x - origin.x)) {
|
||||
setOrigin(size.x - scaledTime-30, origin.y);
|
||||
}
|
||||
}
|
||||
|
||||
public int getRulerHeight() {
|
||||
return rulerHeight;
|
||||
}
|
||||
|
||||
public void setRulerHeight(int rulerHeight) {
|
||||
this.rulerHeight = rulerHeight;
|
||||
}
|
||||
|
||||
public void addSelectionListener(SelectionAdapter selectionAdapter) {
|
||||
selectionListeners.add(selectionAdapter);
|
||||
}
|
||||
|
||||
public void removeSelectionListener(SelectionAdapter selectionAdapter) {
|
||||
selectionListeners.remove(selectionAdapter);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected void fireSelectionEvent() {
|
||||
Event e = new Event();
|
||||
e.widget = this;
|
||||
e.detail=SWT.SELECTED;
|
||||
e.type=SWT.Selection;
|
||||
SelectionEvent ev = new SelectionEvent(e);
|
||||
ev.x = origin.x;
|
||||
ev.y = origin.y;
|
||||
for (SelectionAdapter a : selectionListeners) {
|
||||
a.widgetSelected(ev);
|
||||
}
|
||||
}
|
||||
|
||||
long getMaxVisibleTime() {
|
||||
return (getClientArea().width+origin.x)*scaleFactor;
|
||||
}
|
||||
|
||||
long getMinVisibleTime() {
|
||||
return origin.x * scaleFactor;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user