Restructured plugins

This commit is contained in:
2015-11-03 22:29:42 +01:00
parent 83fd7877f2
commit 7d3c37e989
48 changed files with 472 additions and 162 deletions

View File

@ -0,0 +1,75 @@
/*******************************************************************************
* 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;
public class CursorPainter implements IPainter {
/**
*
*/
private final WaveformCanvas waveCanvas;
private long time;
private boolean isDragging;
public final int id;
/**
* @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.streams.size()>0){
long scaleFactor=waveCanvas.getScaleFactor();
int x = (int) (time/scaleFactor);
int top = id<0?area.y:area.y+15;
Color drawColor=waveCanvas.colors[id<0?WaveformCanvas.Colors.CURSOR.ordinal():WaveformCanvas.Colors.MARKER.ordinal()];
Color dragColor = waveCanvas.colors[WaveformCanvas.Colors.CURSOR_DRAG.ordinal()];
Color textColor=waveCanvas.colors[id<0?WaveformCanvas.Colors.CURSOR_TEXT.ordinal():WaveformCanvas.Colors.MARKER_TEXT.ordinal()];
if(x>=area.x && x<=(area.x+area.width)){
gc.setForeground(isDragging?dragColor:drawColor);
gc.drawLine(x, top, x, area.y+area.height);
gc.setBackground(drawColor);
gc.setForeground(textColor);
Double dTime=new Double(time);
gc.drawText((dTime/waveCanvas.getScaleFactorPow10())+waveCanvas.getUnitStr(), x+1, top);
}
}
}
}

View File

@ -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);
}

View File

@ -0,0 +1,18 @@
/*******************************************************************************
* 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;
public interface IWaveformPainter extends IPainter {
public int getMinHeight();
}

View File

@ -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;
}
}
}

View File

@ -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 org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
public class RulerPainter implements IPainter {
protected WaveformCanvas waveCanvas;
static final int rulerTickMinorC = 10;
static final int rulerTickMajorC = 100;
private Color headerBgColor;
private Color headerFgColor;
public RulerPainter(WaveformCanvas waveCanvas, Color headerFgColor, Color headerBgColor) {
this.waveCanvas=waveCanvas;
this.headerBgColor=headerBgColor;
this.headerFgColor=headerFgColor;
}
@Override
public void paintArea(GC gc, Rectangle area) {
String unit=waveCanvas.getUnitStr();
int unitMultiplier=waveCanvas.getUnitMultiplier();
long scaleFactor=waveCanvas.getScaleFactor();
long zoomLevel = waveCanvas.getZoomLevel();
long start=area.x*scaleFactor;
long end=start+area.width*scaleFactor;
long rulerTickMinor = rulerTickMinorC*scaleFactor;
long rulerTickMajor = rulerTickMajorC*scaleFactor;
if(zoomLevel%3==1){
rulerTickMinor/=3;
rulerTickMajor/=3;
}
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 startMinorIncr = start;
long modulo = start % rulerTickMinor;
startMinorIncr+=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 tick = startMinorIncr; tick < end; tick += rulerTickMinor) {
int x0 = (int) (tick/scaleFactor);
if ((tick % rulerTickMajor) == 0) {
gc.drawText(Double.toString(tick/scaleFactor*unitMultiplier)+unit, x0, area.y+textY);
gc.drawLine(x0, area.y+majorTickY, x0,area.y+ bottom);
} else {
gc.drawLine(x0, area.y+minorTickY, x0, area.y+bottom);
}
}
}
}

View File

@ -0,0 +1,151 @@
/*******************************************************************************
* 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.NavigableMap;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import com.minres.scviewer.database.ISignal;
import com.minres.scviewer.database.ISignalChange;
import com.minres.scviewer.database.IWaveformEvent;
import com.minres.scviewer.database.ISignalChangeMulti;
import com.minres.scviewer.database.ISignalChangeSingle;
public class SignalPainter implements IWaveformPainter {
/**
*
*/
private final WaveformCanvas waveCanvas;
private ISignal<? extends ISignalChange> signal;
private int height;
private boolean even;
public SignalPainter(WaveformCanvas txDisplay, boolean even, int height, ISignal<? extends IWaveformEvent> signal) {
this.waveCanvas = txDisplay;
this.signal=signal;
this.height=height;
this.even=even;
}
public void paintArea(GC gc, Rectangle area) {
if(waveCanvas.currentWaveformSelection!=null && waveCanvas.currentWaveformSelection.equals(signal))
gc.setBackground(this.waveCanvas.colors[WaveformCanvas.Colors.TRACK_BG_HIGHLITE.ordinal()]);
else
gc.setBackground(this.waveCanvas.colors[even?WaveformCanvas.Colors.TRACK_BG_EVEN.ordinal():WaveformCanvas.Colors.TRACK_BG_ODD.ordinal()]);
gc.setFillRule(SWT.FILL_EVEN_ODD);
gc.fillRectangle(area);
Entry<Long, ? extends ISignalChange> firstChange=signal.getEvents().floorEntry(area.x*this.waveCanvas.getScaleFactor());
Entry<Long, ? extends ISignalChange> lastTx=signal.getEvents().ceilingEntry((area.x+area.width)*this.waveCanvas.getScaleFactor());
if(firstChange==null){
if(lastTx==null) return;
firstChange = signal.getEvents().firstEntry();
} else if(lastTx==null){
lastTx=signal.getEvents().lastEntry();
}
gc.setForeground(this.waveCanvas.colors[WaveformCanvas.Colors.LINE.ordinal()]);
gc.setLineStyle(SWT.LINE_SOLID);
gc.setLineWidth(1);
Entry<Long, ? extends ISignalChange> left=firstChange;
if(left.getValue() instanceof ISignalChangeSingle){
NavigableMap<Long, ? extends ISignalChange> entries=signal.getEvents().subMap(firstChange.getKey(), false, lastTx.getKey(), true);
for(Entry<Long, ? extends ISignalChange> right:entries.entrySet()){
int xEnd= (int)(right.getKey()/this.waveCanvas.getScaleFactor());
int xBegin= (int)(left.getKey()/this.waveCanvas.getScaleFactor());
if(xEnd>xBegin){
int yOffset = this.waveCanvas.getTrackHeight()/2;
Color color = this.waveCanvas.colors[WaveformCanvas.Colors.SIGNALX.ordinal()];
switch(((ISignalChangeSingle) left.getValue()).getValue()){
case '1':
color=this.waveCanvas.colors[WaveformCanvas.Colors.SIGNAL1.ordinal()];
yOffset = this.waveCanvas.getTrackHeight()/5;
break;
case '0':
color=this.waveCanvas.colors[WaveformCanvas.Colors.SIGNAL0.ordinal()];
yOffset = 4*this.waveCanvas.getTrackHeight()/5;
break;
case 'Z':
color=this.waveCanvas.colors[WaveformCanvas.Colors.SIGNALZ.ordinal()];
break;
default:
}
yOffset+=area.y;
gc.setForeground(color);
gc.drawLine(xBegin, yOffset, xEnd, yOffset);
int yNext = this.waveCanvas.getTrackHeight()/2;
switch(((ISignalChangeSingle) right.getValue()).getValue()){
case '1':
yNext = this.waveCanvas.getTrackHeight()/5+area.y;
break;
case '0':
yNext = 4*this.waveCanvas.getTrackHeight()/5+area.y;
break;
default:
}
gc.drawLine(xEnd, yOffset, xEnd, yNext);
}
left=right;
}
} else if(left.getValue() instanceof ISignalChangeMulti){
NavigableMap<Long,? extends ISignalChange> entries=signal.getEvents().subMap(firstChange.getKey(), false, lastTx.getKey(), true);
for(Entry<Long, ? extends ISignalChange> right:entries.entrySet()){
int yOffsetT = this.waveCanvas.getTrackHeight()/5+area.y;
int yOffsetM = this.waveCanvas.getTrackHeight()/2+area.y;
int yOffsetB = 4*this.waveCanvas.getTrackHeight()/5+area.y;
Color colorBorder = this.waveCanvas.colors[WaveformCanvas.Colors.SIGNAL0.ordinal()];
ISignalChangeMulti last = (ISignalChangeMulti) left.getValue();
if(last.getValue().toString().contains("X")){
colorBorder=this.waveCanvas.colors[WaveformCanvas.Colors.SIGNALX.ordinal()];
}else if(last.getValue().toString().contains("Z")){
colorBorder=this.waveCanvas.colors[WaveformCanvas.Colors.SIGNALZ.ordinal()];
}
int beginTime= (int)(left.getKey()/this.waveCanvas.getScaleFactor());
int endTime= (int)(right.getKey()/this.waveCanvas.getScaleFactor());
int[] points = {
beginTime,yOffsetM,
beginTime+1,yOffsetT,
endTime-1,yOffsetT,
endTime,yOffsetM,
endTime-1,yOffsetB,
beginTime+1,yOffsetB
};
gc.setForeground(colorBorder);
gc.drawPolygon(points);
gc.setForeground(this.waveCanvas.colors[WaveformCanvas.Colors.SIGNAL_TEXT.ordinal()]);
int size = gc.getDevice().getDPI().y * gc.getFont().getFontData()[0].getHeight()/72;
if(beginTime<area.x) beginTime=area.x;
int width=endTime-beginTime;
if(width>6) {
Rectangle old = gc.getClipping();
gc.setClipping(beginTime+3, yOffsetT, endTime-beginTime-5, yOffsetB-yOffsetT);
gc.drawText("h'"+last.getValue().toHexString(), beginTime+3, yOffsetM-size/2-1);
gc.setClipping(old);
}
left=right;
}
}
}
@Override
public int getMinHeight() {
return height;
}
public ISignal<? extends ISignalChange> getSignal() {
return signal;
}
}

View File

@ -0,0 +1,164 @@
/*******************************************************************************
* 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;
public class StreamPainter implements IWaveformPainter{
/**
*
*/
private final WaveformCanvas waveCanvas;
private ITxStream<? extends ITxEvent> stream;
private int height, upper, txHeight;
private int totalHeight;
private boolean even;
private TreeSet<ITx> seenTx;
public StreamPainter(WaveformCanvas txDisplay, boolean even, int height, ITxStream<? extends ITxEvent> stream) {
this.waveCanvas = txDisplay;
this.stream=stream;
this.height=height;
this.upper=this.waveCanvas.getTrackHeight()/5;
this.txHeight=3*this.waveCanvas.getTrackHeight()/5;
this.totalHeight=stream.getMaxConcurrency()*this.waveCanvas.getTrackHeight();
this.even=even;
this.seenTx=new TreeSet<ITx>();
}
@SuppressWarnings("unchecked")
public void paintArea(GC gc, Rectangle area) {
if(stream.getEvents().size()==0) return;
if(waveCanvas.currentWaveformSelection!=null && waveCanvas.currentWaveformSelection.equals(stream))
gc.setBackground(this.waveCanvas.colors[WaveformCanvas.Colors.TRACK_BG_HIGHLITE.ordinal()]);
else
gc.setBackground(this.waveCanvas.colors[even?WaveformCanvas.Colors.TRACK_BG_EVEN.ordinal():WaveformCanvas.Colors.TRACK_BG_ODD.ordinal()]);
gc.setFillRule(SWT.FILL_EVEN_ODD);
gc.fillRectangle(area);
Entry<Long, ?> firstTx=stream.getEvents().floorEntry(area.x*waveCanvas.getScaleFactor());
Entry<Long, ?> lastTx=stream.getEvents().ceilingEntry((area.x+area.width)*waveCanvas.getScaleFactor());
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[WaveformCanvas.Colors.LINE.ordinal()]);
for(int y1=area.y+this.waveCanvas.getTrackHeight()/2; y1<area.y+totalHeight; y1+=this.waveCanvas.getTrackHeight())
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());
else{
seenTx.clear();
NavigableMap<Long,?> entries = stream.getEvents().subMap(firstTx.getKey(), true, lastTx.getKey(), true);
boolean highlighed=false;
gc.setForeground(this.waveCanvas.colors[WaveformCanvas.Colors.LINE.ordinal()]);
gc.setBackground(this.waveCanvas.colors[WaveformCanvas.Colors.TX_BG.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);
seenTx.remove(tx);
}
}
for(ITx tx:seenTx){
drawTx(gc, area, tx);
}
if(highlighed){
gc.setForeground(this.waveCanvas.colors[WaveformCanvas.Colors.LINE_HIGHLITE.ordinal()]);
gc.setBackground(this.waveCanvas.colors[WaveformCanvas.Colors.TX_BG_HIGHLITE.ordinal()]);
drawTx(gc, area, waveCanvas.currentSelection);
}
}
}
protected void drawTx(GC gc, Rectangle area, ITx tx) {
int offset = tx.getConcurrencyIndex()*this.waveCanvas.getTrackHeight();
Rectangle bb = new Rectangle(
(int)(tx.getBeginTime()/this.waveCanvas.getScaleFactor()), area.y+offset+upper,
(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 {
gc.fillRoundRectangle(bb.x, bb.y, bb.width, bb.height, 5, 5);
gc.drawRoundRectangle(bb.x, bb.y, bb.width, bb.height, 5, 5);
}
}
@Override
public int getMinHeight() {
return height;
}
public Object 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 stream;
}
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;
}
}

View File

@ -0,0 +1,59 @@
/*******************************************************************************
* 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;
public class TrackPainter implements IPainter {
/**
*
*/
private final WaveformCanvas waveCanvas;
/**
* @param txDisplay
*/
public TrackPainter(WaveformCanvas waveCanvas) {
this.waveCanvas = waveCanvas;
}
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[WaveformCanvas.Colors.TRACK_BG_EVEN.ordinal()]);
gc.setFillRule(SWT.FILL_EVEN_ODD);
gc.fillRectangle(area);
TreeMap<Integer, IWaveformPainter> offsets = this.waveCanvas.trackVerticalOffset;
if(this.waveCanvas.streams.size()>0){
Integer firstKey=offsets.floorKey(area.y);
if(firstKey==null) firstKey=offsets.firstKey();
Integer lastKey = offsets.floorKey(area.y+area.height);
Rectangle subArea = new Rectangle(area.x, 0, area.width, 0);
if(lastKey==firstKey){
subArea.y=firstKey;
IWaveformPainter p = offsets.get(firstKey);
subArea.height=p.getMinHeight();
p.paintArea(gc, subArea);
}else{
for(Entry<Integer, IWaveformPainter> entry : offsets.subMap(firstKey, true, lastKey, true).entrySet()){
subArea.y=entry.getKey();
subArea.height=entry.getValue().getMinHeight();
entry.getValue().paintArea(gc, subArea);
}
}
}
}
}

View File

@ -0,0 +1,455 @@
/*******************************************************************************
* 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.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;
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.IWaveformEvent;
public class WaveformCanvas extends Canvas {
public enum Colors {
LINE, LINE_HIGHLITE,
TRACK_BG_EVEN, TRACK_BG_ODD, TRACK_BG_HIGHLITE,
TX_BG, TX_BG_HIGHLITE, TX_BORDER,
SIGNAL0, SIGNAL1, SIGNALZ, SIGNALX, SIGNAL_TEXT,
CURSOR, CURSOR_DRAG, CURSOR_TEXT,
MARKER, MARKER_TEXT
}
Color[] colors = new Color[Colors.values().length];
private int trackHeight = 50;
private long scaleFactor = 1000000L; // 1ns
String unit="ns";
private int level = 12;
public final static String[] unitString={"fs", "ps", "ns", "µs", "ms"};//, "s"};
public final static int[] unitMultiplier={1, 3, 10, 30, 100, 300};
private long maxTime;
protected Point origin; /* original size */
protected Transform transform;
protected int rulerHeight=40;
protected List<IPainter> painterList;
TreeMap<Integer, IWaveformPainter> trackVerticalOffset;
protected List<IWaveform<? extends IWaveformEvent>> streams;
ITx currentSelection;
IWaveform<? extends IWaveformEvent> currentWaveformSelection;
private List<SelectionAdapter> selectionListeners;
/**
* Constructor for ScrollableCanvas.
*
* @param parent
* the parent of this control.
* @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());
trackVerticalOffset = new TreeMap<Integer, IWaveformPainter>();
selectionListeners = new LinkedList<>();
initScrollBars();
initColors(null);
}
private void initColors(HashMap<Colors, RGB> colourMap) {
Display d = getDisplay();
if (colourMap != null) {
for (Colors c : Colors.values()) {
if (colourMap.containsKey(c)) {
colors[c.ordinal()].dispose();
colors[c.ordinal()] = new Color(d, colourMap.get(c));
}
}
} else {
colors[Colors.LINE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED);
colors[Colors.LINE_HIGHLITE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_CYAN);
colors[Colors.TRACK_BG_EVEN.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_BLACK);
colors[Colors.TRACK_BG_ODD.ordinal()] = SWTResourceManager.getColor(40, 40, 40);
colors[Colors.TRACK_BG_HIGHLITE.ordinal()] = SWTResourceManager.getColor(40, 40, 80);
colors[Colors.TX_BG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GREEN);
colors[Colors.TX_BG_HIGHLITE.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN);
colors[Colors.TX_BORDER.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED);
colors[Colors.SIGNAL0.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN);
colors[Colors.SIGNAL1.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GREEN);
colors[Colors.SIGNALZ.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GRAY);
colors[Colors.SIGNALX.ordinal()] = SWTResourceManager.getColor(255, 128, 182);
colors[Colors.SIGNAL_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE);
colors[Colors.CURSOR.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_RED);
colors[Colors.CURSOR_DRAG.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_GRAY);
colors[Colors.CURSOR_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE);
colors[Colors.MARKER.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_DARK_GRAY);
colors[Colors.MARKER_TEXT.ordinal()] = SWTResourceManager.getColor(SWT.COLOR_WHITE);
}
}
public List<IWaveform<? extends IWaveformEvent>> getStreams() {
return streams;
}
public void setStreams(List<IWaveform<? extends IWaveformEvent>> streams) {
this.streams = streams;
}
public Point getOrigin() {
return origin;
}
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 unitMultiplier.length*unitString.length-1;
}
public void setZoomLevel(int level) {
if(level<unitMultiplier.length*unitString.length){
this.level = level;
this.scaleFactor = (long) Math.pow(10, level/2);
if(level%2==1) this.scaleFactor*=3;
syncScrollBars();
}
}
public long getScaleFactor() {
return scaleFactor;
}
public long getScaleFactorPow10() {
int scale = level/unitMultiplier.length;
double res = Math.pow(1000, scale);
return (long) res;
}
public String getUnitStr(){
return unitString[level/unitMultiplier.length];
}
public int getUnitMultiplier(){
return unitMultiplier[level%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 clearAllWavefromPainter() {
trackVerticalOffset.clear();
syncScrollBars();
}
public void addWavefromPainter(int yoffs, IWaveformPainter painter) {
trackVerticalOffset.put(yoffs+rulerHeight, painter);
syncScrollBars();
}
/**
* Dispose the garbage here
*/
public void dispose() {
transform.dispose();
for (Colors c : Colors.values())
colors[c.ordinal()].dispose();
super.dispose();
}
/* Initalize 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>.
*/
private void syncScrollBars() {
if (painterList.size() == 0) {
redraw();
return;
}
int height = 1;
if (trackVerticalOffset.size() > 0)
height = trackVerticalOffset.lastKey() + trackVerticalOffset.lastEntry().getValue().getMinHeight();
int width = (int) (maxTime / scaleFactor);
ScrollBar horizontal = getHorizontalBar();
horizontal.setIncrement((int) (getClientArea().width / 100));
horizontal.setPageIncrement(getClientArea().width);
int cw = getClientArea().width;
if (width > cw) { /* image is wider than client area */
horizontal.setMaximum(width);
horizontal.setEnabled(true);
if (((int) -origin.x) > horizontal.getMaximum() - cw)
origin.x = -horizontal.getMaximum() + cw;
} else { /* image is narrower than client area */
horizontal.setEnabled(false);
}
horizontal.setSelection(-origin.x);
horizontal.setThumb(cw);
ScrollBar vertical = getVerticalBar();
vertical.setIncrement((int) (getClientArea().height / 100));
vertical.setPageIncrement((int) (getClientArea().height));
int ch = getClientArea().height;
if (height > ch) { /* image is higher than client area */
vertical.setMaximum(height);
vertical.setEnabled(true);
if (((int) -origin.y) > vertical.getMaximum() - ch)
origin.y = -vertical.getMaximum() + ch;
} else { /* image is less higher than client area */
vertical.setMaximum((int) (ch));
vertical.setEnabled(false);
}
vertical.setSelection(-origin.y);
vertical.setThumb(ch);
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
transform.translate(origin.x, origin.y);
gc.setTransform(transform);
gc.setClipping(clientRect);
if (painterList.size() > 0 && trackVerticalOffset.size() > 0) {
for (IPainter painter : painterList)
painter.paintArea(gc, clientRect);
} else {
gc.fillRectangle(clientRect);
initScrollBars();
}
}
public List<Object> getClicked(Point point) {
LinkedList<Object> result=new LinkedList<>();
for (IPainter p : Lists.reverse(painterList)) {
if (p instanceof TrackPainter) {
int y = point.y - origin.y;
int x = point.x - origin.x;
Entry<Integer, IWaveformPainter> entry = trackVerticalOffset.floorEntry(y);
if (entry != null) {
if (entry.getValue() instanceof StreamPainter) {
result.add(((StreamPainter) entry.getValue()).getClicked(new Point(x, y - entry.getKey())));
} else if (entry.getValue() instanceof SignalPainter)
result.add(((SignalPainter) entry.getValue()).getSignal());
}
} 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<? extends IWaveformEvent> iWaveform, int i) {
LinkedList<Object> result=new LinkedList<>();
int x = i - origin.x;
for(IPainter p: trackVerticalOffset.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, IWaveform<? extends IWaveformEvent> currentWaveformSelection) {
this.currentSelection = currentSelection;
this.currentWaveformSelection = currentWaveformSelection;
if (currentSelection != null)
reveal(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 (Entry<Integer, IWaveformPainter> entry : trackVerticalOffset.entrySet()) {
if (entry.getValue() instanceof StreamPainter && ((StreamPainter) entry.getValue()).getStream() == tx.getStream()) {
int top = entry.getKey() + 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(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);
}
}
}

View File

@ -0,0 +1,447 @@
/*******************************************************************************
* Copyright (c) 2011 Google, Inc.
* 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:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.wb.swt;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
/**
* Utility class for managing OS resources associated with SWT controls such as colors, fonts, images, etc.
* <p>
* !!! IMPORTANT !!! Application code must explicitly invoke the <code>dispose()</code> method to release the
* operating system resources managed by cached objects when those objects and OS resources are no longer
* needed (e.g. on application shutdown)
* <p>
* This class may be freely distributed as part of any application or plugin.
* <p>
* @author scheglov_ke
* @author Dan Rubel
*/
public class SWTResourceManager {
////////////////////////////////////////////////////////////////////////////
//
// Color
//
////////////////////////////////////////////////////////////////////////////
private static Map<RGB, Color> m_colorMap = new HashMap<RGB, Color>();
/**
* Returns the system {@link Color} matching the specific ID.
*
* @param systemColorID
* the ID value for the color
* @return the system {@link Color} matching the specific ID
*/
public static Color getColor(int systemColorID) {
Display display = Display.getCurrent();
return display.getSystemColor(systemColorID);
}
/**
* Returns a {@link Color} given its red, green and blue component values.
*
* @param r
* the red component of the color
* @param g
* the green component of the color
* @param b
* the blue component of the color
* @return the {@link Color} matching the given red, green and blue component values
*/
public static Color getColor(int r, int g, int b) {
return getColor(new RGB(r, g, b));
}
/**
* Returns a {@link Color} given its RGB value.
*
* @param rgb
* the {@link RGB} value of the color
* @return the {@link Color} matching the RGB value
*/
public static Color getColor(RGB rgb) {
Color color = m_colorMap.get(rgb);
if (color == null) {
Display display = Display.getCurrent();
color = new Color(display, rgb);
m_colorMap.put(rgb, color);
}
return color;
}
/**
* Dispose of all the cached {@link Color}'s.
*/
public static void disposeColors() {
for (Color color : m_colorMap.values()) {
color.dispose();
}
m_colorMap.clear();
}
////////////////////////////////////////////////////////////////////////////
//
// Image
//
////////////////////////////////////////////////////////////////////////////
/**
* Maps image paths to images.
*/
private static Map<String, Image> m_imageMap = new HashMap<String, Image>();
/**
* Returns an {@link Image} encoded by the specified {@link InputStream}.
*
* @param stream
* the {@link InputStream} encoding the image data
* @return the {@link Image} encoded by the specified input stream
*/
protected static Image getImage(InputStream stream) throws IOException {
try {
Display display = Display.getCurrent();
ImageData data = new ImageData(stream);
if (data.transparentPixel > 0) {
return new Image(display, data, data.getTransparencyMask());
}
return new Image(display, data);
} finally {
stream.close();
}
}
/**
* Returns an {@link Image} stored in the file at the specified path.
*
* @param path
* the path to the image file
* @return the {@link Image} stored in the file at the specified path
*/
public static Image getImage(String path) {
Image image = m_imageMap.get(path);
if (image == null) {
try {
image = getImage(new FileInputStream(path));
m_imageMap.put(path, image);
} catch (Exception e) {
image = getMissingImage();
m_imageMap.put(path, image);
}
}
return image;
}
/**
* Returns an {@link Image} stored in the file at the specified path relative to the specified class.
*
* @param clazz
* the {@link Class} relative to which to find the image
* @param path
* the path to the image file, if starts with <code>'/'</code>
* @return the {@link Image} stored in the file at the specified path
*/
public static Image getImage(Class<?> clazz, String path) {
String key = clazz.getName() + '|' + path;
Image image = m_imageMap.get(key);
if (image == null) {
try {
image = getImage(clazz.getResourceAsStream(path));
m_imageMap.put(key, image);
} catch (Exception e) {
image = getMissingImage();
m_imageMap.put(key, image);
}
}
return image;
}
private static final int MISSING_IMAGE_SIZE = 10;
/**
* @return the small {@link Image} that can be used as placeholder for missing image.
*/
private static Image getMissingImage() {
Image image = new Image(Display.getCurrent(), MISSING_IMAGE_SIZE, MISSING_IMAGE_SIZE);
//
GC gc = new GC(image);
gc.setBackground(getColor(SWT.COLOR_RED));
gc.fillRectangle(0, 0, MISSING_IMAGE_SIZE, MISSING_IMAGE_SIZE);
gc.dispose();
//
return image;
}
/**
* Style constant for placing decorator image in top left corner of base image.
*/
public static final int TOP_LEFT = 1;
/**
* Style constant for placing decorator image in top right corner of base image.
*/
public static final int TOP_RIGHT = 2;
/**
* Style constant for placing decorator image in bottom left corner of base image.
*/
public static final int BOTTOM_LEFT = 3;
/**
* Style constant for placing decorator image in bottom right corner of base image.
*/
public static final int BOTTOM_RIGHT = 4;
/**
* Internal value.
*/
protected static final int LAST_CORNER_KEY = 5;
/**
* Maps images to decorated images.
*/
@SuppressWarnings("unchecked")
private static Map<Image, Map<Image, Image>>[] m_decoratedImageMap = new Map[LAST_CORNER_KEY];
/**
* Returns an {@link Image} composed of a base image decorated by another image.
*
* @param baseImage
* the base {@link Image} that should be decorated
* @param decorator
* the {@link Image} to decorate the base image
* @return {@link Image} The resulting decorated image
*/
public static Image decorateImage(Image baseImage, Image decorator) {
return decorateImage(baseImage, decorator, BOTTOM_RIGHT);
}
/**
* Returns an {@link Image} composed of a base image decorated by another image.
*
* @param baseImage
* the base {@link Image} that should be decorated
* @param decorator
* the {@link Image} to decorate the base image
* @param corner
* the corner to place decorator image
* @return the resulting decorated {@link Image}
*/
public static Image decorateImage(final Image baseImage, final Image decorator, final int corner) {
if (corner <= 0 || corner >= LAST_CORNER_KEY) {
throw new IllegalArgumentException("Wrong decorate corner");
}
Map<Image, Map<Image, Image>> cornerDecoratedImageMap = m_decoratedImageMap[corner];
if (cornerDecoratedImageMap == null) {
cornerDecoratedImageMap = new HashMap<Image, Map<Image, Image>>();
m_decoratedImageMap[corner] = cornerDecoratedImageMap;
}
Map<Image, Image> decoratedMap = cornerDecoratedImageMap.get(baseImage);
if (decoratedMap == null) {
decoratedMap = new HashMap<Image, Image>();
cornerDecoratedImageMap.put(baseImage, decoratedMap);
}
//
Image result = decoratedMap.get(decorator);
if (result == null) {
Rectangle bib = baseImage.getBounds();
Rectangle dib = decorator.getBounds();
//
result = new Image(Display.getCurrent(), bib.width, bib.height);
//
GC gc = new GC(result);
gc.drawImage(baseImage, 0, 0);
if (corner == TOP_LEFT) {
gc.drawImage(decorator, 0, 0);
} else if (corner == TOP_RIGHT) {
gc.drawImage(decorator, bib.width - dib.width, 0);
} else if (corner == BOTTOM_LEFT) {
gc.drawImage(decorator, 0, bib.height - dib.height);
} else if (corner == BOTTOM_RIGHT) {
gc.drawImage(decorator, bib.width - dib.width, bib.height - dib.height);
}
gc.dispose();
//
decoratedMap.put(decorator, result);
}
return result;
}
/**
* Dispose all of the cached {@link Image}'s.
*/
public static void disposeImages() {
// dispose loaded images
{
for (Image image : m_imageMap.values()) {
image.dispose();
}
m_imageMap.clear();
}
// dispose decorated images
for (int i = 0; i < m_decoratedImageMap.length; i++) {
Map<Image, Map<Image, Image>> cornerDecoratedImageMap = m_decoratedImageMap[i];
if (cornerDecoratedImageMap != null) {
for (Map<Image, Image> decoratedMap : cornerDecoratedImageMap.values()) {
for (Image image : decoratedMap.values()) {
image.dispose();
}
decoratedMap.clear();
}
cornerDecoratedImageMap.clear();
}
}
}
////////////////////////////////////////////////////////////////////////////
//
// Font
//
////////////////////////////////////////////////////////////////////////////
/**
* Maps font names to fonts.
*/
private static Map<String, Font> m_fontMap = new HashMap<String, Font>();
/**
* Maps fonts to their bold versions.
*/
private static Map<Font, Font> m_fontToBoldFontMap = new HashMap<Font, Font>();
/**
* Returns a {@link Font} based on its name, height and style.
*
* @param name
* the name of the font
* @param height
* the height of the font
* @param style
* the style of the font
* @return {@link Font} The font matching the name, height and style
*/
public static Font getFont(String name, int height, int style) {
return getFont(name, height, style, false, false);
}
/**
* Returns a {@link Font} based on its name, height and style. Windows-specific strikeout and underline
* flags are also supported.
*
* @param name
* the name of the font
* @param size
* the size of the font
* @param style
* the style of the font
* @param strikeout
* the strikeout flag (warning: Windows only)
* @param underline
* the underline flag (warning: Windows only)
* @return {@link Font} The font matching the name, height, style, strikeout and underline
*/
public static Font getFont(String name, int size, int style, boolean strikeout, boolean underline) {
String fontName = name + '|' + size + '|' + style + '|' + strikeout + '|' + underline;
Font font = m_fontMap.get(fontName);
if (font == null) {
FontData fontData = new FontData(name, size, style);
if (strikeout || underline) {
try {
Class<?> logFontClass = Class.forName("org.eclipse.swt.internal.win32.LOGFONT"); //$NON-NLS-1$
Object logFont = FontData.class.getField("data").get(fontData); //$NON-NLS-1$
if (logFont != null && logFontClass != null) {
if (strikeout) {
logFontClass.getField("lfStrikeOut").set(logFont, Byte.valueOf((byte) 1)); //$NON-NLS-1$
}
if (underline) {
logFontClass.getField("lfUnderline").set(logFont, Byte.valueOf((byte) 1)); //$NON-NLS-1$
}
}
} catch (Throwable e) {
System.err.println("Unable to set underline or strikeout" + " (probably on a non-Windows platform). " + e); //$NON-NLS-1$ //$NON-NLS-2$
}
}
font = new Font(Display.getCurrent(), fontData);
m_fontMap.put(fontName, font);
}
return font;
}
/**
* Returns a bold version of the given {@link Font}.
*
* @param baseFont
* the {@link Font} for which a bold version is desired
* @return the bold version of the given {@link Font}
*/
public static Font getBoldFont(Font baseFont) {
Font font = m_fontToBoldFontMap.get(baseFont);
if (font == null) {
FontData fontDatas[] = baseFont.getFontData();
FontData data = fontDatas[0];
font = new Font(Display.getCurrent(), data.getName(), data.getHeight(), SWT.BOLD);
m_fontToBoldFontMap.put(baseFont, font);
}
return font;
}
/**
* Dispose all of the cached {@link Font}'s.
*/
public static void disposeFonts() {
// clear fonts
for (Font font : m_fontMap.values()) {
font.dispose();
}
m_fontMap.clear();
// clear bold fonts
for (Font font : m_fontToBoldFontMap.values()) {
font.dispose();
}
m_fontToBoldFontMap.clear();
}
////////////////////////////////////////////////////////////////////////////
//
// Cursor
//
////////////////////////////////////////////////////////////////////////////
/**
* Maps IDs to cursors.
*/
private static Map<Integer, Cursor> m_idToCursorMap = new HashMap<Integer, Cursor>();
/**
* Returns the system cursor matching the specific ID.
*
* @param id
* int The ID value for the cursor
* @return Cursor The system cursor matching the specific ID
*/
public static Cursor getCursor(int id) {
Integer key = Integer.valueOf(id);
Cursor cursor = m_idToCursorMap.get(key);
if (cursor == null) {
cursor = new Cursor(Display.getDefault(), id);
m_idToCursorMap.put(key, cursor);
}
return cursor;
}
/**
* Dispose all of the cached cursors.
*/
public static void disposeCursors() {
for (Cursor cursor : m_idToCursorMap.values()) {
cursor.dispose();
}
m_idToCursorMap.clear();
}
////////////////////////////////////////////////////////////////////////////
//
// General
//
////////////////////////////////////////////////////////////////////////////
/**
* Dispose of cached objects and their underlying OS resources. This should only be called when the cached
* objects are no longer needed (e.g. on application shutdown).
*/
public static void dispose() {
disposeColors();
disposeImages();
disposeFonts();
disposeCursors();
}
}