Restructured plugins
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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,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();
|
||||
|
||||
}
|
@ -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,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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user