/*******************************************************************************
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package hr.fer.zemris.vhdllab.applets.editor.newtb.view.components2;
import hr.fer.zemris.vhdllab.applets.editor.newtb.enums.ChangeStateEdge;
import hr.fer.zemris.vhdllab.applets.editor.newtb.enums.Radix;
import hr.fer.zemris.vhdllab.applets.editor.newtb.enums.TimeScale;
import hr.fer.zemris.vhdllab.applets.editor.newtb.enums.VectorDirection;
import hr.fer.zemris.vhdllab.applets.editor.newtb.model.CombinatorialTestbench;
import hr.fer.zemris.vhdllab.applets.editor.newtb.model.SingleClockTestbench;
import hr.fer.zemris.vhdllab.applets.editor.newtb.model.Testbench;
import hr.fer.zemris.vhdllab.applets.editor.newtb.model.signals.ClockSignal;
import hr.fer.zemris.vhdllab.applets.editor.newtb.model.signals.ScalarSignal;
import hr.fer.zemris.vhdllab.applets.editor.newtb.model.signals.Signal;
import hr.fer.zemris.vhdllab.applets.editor.newtb.model.signals.SignalChange;
import hr.fer.zemris.vhdllab.applets.editor.newtb.model.signals.VectorSignal;
import hr.fer.zemris.vhdllab.applets.editor.newtb.util.RadixConverter;
import hr.fer.zemris.vhdllab.applets.editor.newtb.view.components2.JTestbench.Communicator;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.swing.JComponent;
/**
*
* @author Nikola Santic
*
*/
public class JDrawArea extends JComponent {
private static final long serialVersionUID = 1L;
private static final int timeLineHeight = 40;
private static final int trackHeight = 40;
private static final int headerLength = 80;
private static final int markerHeight = 15;
private static final int markerWidth = 20;
private static final int vExpandX = 10;
private static final int vExpandY = 15;
private static final int vExpandSize = 10;
private static final int signalPad = 5;
private static final int vectorPad = 8;
protected int screenWidth;
private int newReference = timeLineHeight;
private long testBenchLength;
protected long testBenchLengthScaled;
protected long begin;
protected long beginScaled;
protected long length;
protected long lengthScaled;
protected long multiplier = 1;
private long inputSetupTime = -1;
private long checkOutputsTime = -1;
private ChangeStateEdge changeStateEdge;
private Radix radix;
protected boolean isClockTestbench;
private long clockUpTime = 0;
private long periodLength;
protected boolean markerCaught = false;
protected int beginIndex;
private List<Signal> signalList;
private ClockSignal clockSignal;
protected Marker marker;
private List<VectorSignal> expanded = new ArrayList<VectorSignal>();
private HashMap<VectorSignal, Rectangle> vExpandList = new HashMap<VectorSignal, Rectangle>();
protected HashMap<Integer, Signal> indexSignalMap = new HashMap<Integer, Signal>();
protected Scale scale;
public JDrawArea(Testbench testbench) {
this.signalList = new ArrayList<Signal>();
this.initSignalList(testbench);
marker = new Marker(testbench.getSimulationLength());
if (testbench.getClass() == SingleClockTestbench.class) {
isClockTestbench = true;
changeStateEdge = ((SingleClockTestbench) testbench).getChangeStateEdge();
if (changeStateEdge == ChangeStateEdge.rising)
clockUpTime = ((SingleClockTestbench) testbench).getClockTimeHigh();
inputSetupTime = ((SingleClockTestbench) testbench).getInputSetupTime();
} else {
isClockTestbench = false;
checkOutputsTime = ((CombinatorialTestbench) testbench)
.getCheckOutputsTime();
}
periodLength = testbench.getPeriodLength();
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
int reference = timeLineHeight + (isClockTestbench ? trackHeight : 0);
if (marker.contains(e.getX(), e.getY())
&& e.getButton() == MouseEvent.BUTTON1) {
markerCaught = true;
} else if (e.getY() > reference
&& e.getButton() == MouseEvent.BUTTON1) {
int y = (e.getY() - reference) / trackHeight;
Signal s = indexSignalMap.get(beginIndex + y);
if (s != null)
clickSignal(s, e.getX(), e.getY());
}
}
});
addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
if (markerCaught) {
int x = e.getX();
if (x >= headerLength && x < screenWidth) {
if (x > headerLength + scale.toPixel(testBenchLengthScaled - beginScaled))
x = headerLength + scale.toPixel(testBenchLengthScaled - beginScaled);
moveMarker(x - headerLength);
}
}
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
if (markerCaught) {
changeSimLength();
markerCaught = false;
}
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getY() < timeLineHeight) {
int x = e.getX();
if (x >= headerLength
&& x <= screenWidth
&& e.getClickCount() >= 2
&& x <= headerLength + scale.toPixel(testBenchLengthScaled - beginScaled))
moveMarker(x - headerLength);
changeSimLength();
}
}
});
}
private void initSignalList(Testbench tb) {
int i = 0;
if (tb.getClass() == SingleClockTestbench.class) {
ClockSignal cs = ((SingleClockTestbench) tb).getClockSignal();
clockSignal = cs;
}
for (Signal s : tb) {
if (s.getClass() == VectorSignal.class){
vExpandList.put((VectorSignal) s, new Rectangle(vExpandSize, vExpandSize));
this.signalList.add(s);
indexSignalMap.put(i, s);
i++;
}
else if(s.getClass() == ScalarSignal.class) {
this.signalList.add(s);
indexSignalMap.put(i, s);
i++;
}
}
}
protected void clickSignal(Signal s, int x, int y) {
if (x < headerLength && s.getClass() == VectorSignal.class) {
if (vExpandList.get(s).contains(x, y))
expandSignal((VectorSignal) s);
} else if (x > headerLength) {
changeSignal(s, x, y);
}
}
private void changeSignal(Signal s, int x, int y) {
if (s.getClass() == ClockSignal.class)
return;
int reference = timeLineHeight + (isClockTestbench ? trackHeight : 0);
x = x - headerLength;
long time = begin + scale.toTime(x) * multiplier;
if (time >= testBenchLength)
return;
if (s.getClass() == ScalarSignal.class) {
this.getParentJTestbench().setSignalChange(s.getName(), 0, time);
} else if (s.getClass() == VectorSignal.class) {
if (!expanded.contains(s)) {
} else {
int top = getVectorBegin((y - reference) / trackHeight + beginIndex);
int sel = (y - reference) / trackHeight + beginIndex;
if (sel - top == 0 || sel - top > s.getDimension()) {
//System.out
// .println(s.getName()
// + " je vektor, otvoren, ali tko smo mi da pravimo razliku?");
//
// NAPOMENA : Provjeri ovaj time koji mi saljes, cini mi se da u jednom trenutku kad testbench postane velik,
// posaljes mi negativan broj zbog overflowa
//
this.getParentJTestbench().clearSelectedSignal();
this.getParentJTestbench().openSetSignalDialog(s.getName(),
time);
} else {
// DOBRO PRIPAZI OVDIJE!!!
// Zbog potrebnih prilagodbi na xilinix, promjenio sam ovaj
// red (Davor)
// this.getParentJTestbench().setSignalChange(s.getName(),
// s.getDimension() - i, time);
this.getParentJTestbench().setSignalChange(s.getName(),
sel - top - 1, time);
//System.out.println(s.getName() + " je vektorova komponenta " + (i - 1));
}
}
}
}
Communicator getClickInformation(int x, int y) {
Communicator com = new Communicator();
com.isSignalRenderArea = x > headerLength;
x = x - headerLength;
com.time = begin + scale.toTime(x) * multiplier;
Signal s = null;
int reference = timeLineHeight + (isClockTestbench ? trackHeight : 0);
if (y > reference) {
y = (y - reference) / trackHeight;
s = indexSignalMap.get(beginIndex + y);
}
int top = getVectorBegin(beginIndex + y);
com.signal = s;
com.componentIndex = y - top - 1;
return com;
}
private void expandSignal(VectorSignal s) {
if (expanded.contains(s))
expanded.remove(s);
else
expanded.add(s);
indexSignalMap.clear();
int i = 0;
for (Signal signal : signalList) {
if (signal.getClass() == VectorSignal.class && expanded.contains(signal)) {
for (int j = 0; j <= signal.getDimension(); j++) {
indexSignalMap.put(i + j, signal);
}
i += signal.getDimension() + 1;
} else {
indexSignalMap.put(i , signal);
i++;
}
}
// U izradi
// this.setSize(new Dimension(super.getSize().width, timeLineHeight +
// trackHeight*positionMap.size() + 10));
this.getParentJTestbench().setNOfSignalComponents(indexSignalMap.size());
this.getParentJTestbench().repaint();
}
protected void moveMarker(int x) {
repaint(marker.position - markerWidth, trackHeight - markerHeight - 2,
2 * markerWidth, markerHeight + 2);
marker.moveForPixels(x);
repaint(marker.position - markerWidth, trackHeight - markerHeight - 2,
2 * markerWidth, markerHeight + 2);
}
protected void moveMarker(long time) {
repaint(marker.position - markerWidth, trackHeight - markerHeight - 2,
2 * markerWidth, markerHeight + 2);
marker.moveForTime(time);
repaint(marker.position - markerWidth, trackHeight - markerHeight - 2,
2 * markerWidth, markerHeight + 2);
}
protected void changeSimLength() {
this.getParentJTestbench().setSimulationLength(marker.markedTime);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(super.getSize().width, timeLineHeight
+ trackHeight * indexSignalMap.size() + 10);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponents(g);
//System.out.println("JDrawArea paintComponent: " + this.getSize());
multiplier = TimeScale.getMultiplier(this.getParentJTestbench().model
.getTestbench().getTimeScale());
testBenchLength = this.getParentJTestbench().model.getTestbench()
.getTestBenchLength();
begin = this.getParentJTestbench().renderBeginTime;
length = this.getParentJTestbench().renderLength;
beginScaled = begin / multiplier;
lengthScaled = length / multiplier;
testBenchLengthScaled = testBenchLength / multiplier;
Dimension size = this.getSize();
screenWidth = size.width;
scale = new Scale(screenWidth);
radix = this.getParentJTestbench().getTestbenchRadix();
paintTimeLine(g);
newReference = timeLineHeight;
if(isClockTestbench){
paintScalarSignal(g, clockSignal);
}
// for (Signal signal : signalList) {
// paintSignal(g, signal);
// }
beginIndex = this.getParentJTestbench().getBeginSignalIndex();
int endIndex = beginIndex + (screenWidth - newReference) / trackHeight;
for(int i = beginIndex ; newReference <= screenWidth - trackHeight && i < indexSignalMap.size(); i++ ){
Signal s = indexSignalMap.get(i);
if (s.getClass() == VectorSignal.class && expanded.contains(s)) {
int start = i;
Signal comp = null;
do {
i++;
comp = indexSignalMap.get(i);
} while (comp == s && i < endIndex);
if(comp != s)
paintVectorSignal(g, (VectorSignal) s, s.getDimension() + 1 - (i - start), s.getDimension());
else if(indexSignalMap.get(start - 1) == s){
int beg = getVectorBegin(start - 1);
paintVectorSignal(g, (VectorSignal) s, start - beg, i - beg);
}
else
paintVectorSignal(g, (VectorSignal) s, 0, i - start);
i--;
}
else if(s.getClass() == VectorSignal.class){
paintVectorMain(g, (VectorSignal) s);
}
else
paintScalarSignal(g, s);
}
g.setColor(getBackground());
g.fillRect(0, newReference + 1, getWidth(), getHeight() - newReference - 1);
}
private int getVectorBegin (int position){
Signal vs = indexSignalMap.get(position);
do{
position--;
} while(vs == indexSignalMap.get(position));
return position + 1;
}
private void paintTimeLine(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
String timeScaleName = getParentJTestbench().model.getTestbench()
.getTimeScale().toString();
marker.init();
g2.setStroke(new BasicStroke(2));
g2.setColor(this.getBackground());
g2.fillRect(0, 0, getWidth(), timeLineHeight);
g2.setColor(this.getForeground());
g2.drawRect(0, 0, getWidth(), timeLineHeight);
g2.drawRect(0, 0, headerLength, timeLineHeight);
g2.drawString(timeScaleName, headerLength / 2, timeLineHeight * 3 / 5);
g2.setStroke(new BasicStroke(1));
for (long i = beginScaled; i <= testBenchLengthScaled
&& i <= beginScaled + lengthScaled; i += scale.scaleT) {
if ((i - beginScaled) % (5 * scale.scaleT) == 0) {
int ilength = Long.toString(i).length();
g2.drawLine(headerLength + scale.toPixel(i - beginScaled),
timeLineHeight / 2, headerLength
+ scale.toPixel(i - beginScaled),
timeLineHeight);
if (i != beginScaled)
g2.drawString(String.valueOf(i), headerLength
+ scale.toPixel(i - beginScaled) - 6 * ilength / 2,
timeLineHeight / 3);
} else {
g2.drawLine(headerLength + scale.toPixel(i - beginScaled),
timeLineHeight, headerLength
+ scale.toPixel(i - beginScaled),
3 * timeLineHeight / 4);
}
}
if (marker.showing)
marker.paint(g2);
}
private void paintVectorSignal(Graphics g, VectorSignal signal, int startIndex, int endIndex) {
if(startIndex == 0){
paintVectorMain(g, signal);
startIndex++;
}
if (expanded.contains(signal)) {
Signal[] scalarSignals = null;
try {
scalarSignals = signal.getSignalComponents();
} catch (Exception e) {
e.printStackTrace();
}
for (int i = startIndex - 1; i <= endIndex - 1; i++) {
paintScalarSignal(g, scalarSignals[i]);
}
}
}
private void paintVectorMain(Graphics g, VectorSignal signal) {
paintSignalHeader(g, signal);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(2));
List<SignalChange> changes = signal.getSignalChangeList(begin, begin
+ length);
g2.setColor(Color.white);
g2.fillRect(headerLength + 1, newReference, getWidth() - headerLength,
trackHeight);
g2.setColor(getForeground());
g2.drawRect(headerLength, newReference, getWidth() - headerLength,
trackHeight);
int fromPix = 0;
String sigVal = RadixConverter.binToOtherString(
signal.getSignalChange(begin).getSignalValue(),
Radix.toInt(radix),
signal.getDimension(),
true);
for (SignalChange signalChange : changes) {
long toTime = signalChange.getTime();
int toPix = (int) ((toTime - begin) / multiplier) * scale.scaleX
/ scale.scaleT;
if (fromPix == 0 && signal.getSignalChange(begin).getTime() < begin)
paintVectorValueRight(g2, toPix, sigVal);
else
paintVectorValueWhole(g2, fromPix, toPix, sigVal);
fromPix = toPix;
sigVal = RadixConverter.binToOtherString(
signalChange.getSignalValue(),
Radix.toInt(radix),
signal.getDimension(),
true);
}
/* Zadnji dio */
/* Ako nema prijelaza */
if (changes.isEmpty() && begin + length < testBenchLength) {
int toPix = scale.toPixel(length / multiplier);
paintVectorValueMiddle(g2, toPix, sigVal);
}
/* Ako je cijeli vektor na ekranu */
else if (begin + length >= testBenchLength && begin == 0) {
int toPix = scale.toPixel((testBenchLength - begin) / multiplier);
paintVectorValueWhole(g2, fromPix, toPix, sigVal);
}
/* Ako zadnji vektor zavrsava */
else if (begin + length >= testBenchLength && begin > 0
&& changes.isEmpty()) {
int toPix = scale.toPixel((testBenchLength - begin) / multiplier);
paintVectorValueRight(g2, toPix, sigVal);
}
/* Ako zadnji, cjelokupno prisutan vektor zavrsava */
else if (begin + length >= testBenchLength && begin > 0) {
int toPix = scale.toPixel((testBenchLength - begin) / multiplier);
paintVectorValueWhole(g2, fromPix, toPix, sigVal);
}
/* Ako je nesto drugo, nadam se ,normalno */
else {
int toPix = scale.toPixel((length) / multiplier);
paintVectorValueLeft(g2, fromPix, toPix, sigVal);
}
newReference += trackHeight;
}
private void paintVectorValueMiddle(Graphics2D g2, int toPix,
String sigValue) {
int[] x = { headerLength + vectorPad, headerLength + toPix,
headerLength + toPix, headerLength + vectorPad };
int[] y = { newReference + trackHeight - signalPad,
newReference + trackHeight - signalPad,
newReference + signalPad, newReference + signalPad };
Polygon pol = new Polygon(x, y, 4);
paintVectorShape(g2, 0, toPix, sigValue, pol);
}
private void paintVectorValueLeft(Graphics2D g2, int fromPix, int toPix,
String sigValue) {
if ((toPix - fromPix) < 16) return;
int[] x = { headerLength + fromPix, headerLength + fromPix + vectorPad,
headerLength + toPix, headerLength + toPix,
headerLength + fromPix + vectorPad };
int[] y = { newReference + trackHeight / 2,
newReference + trackHeight - signalPad,
newReference + trackHeight - signalPad,
newReference + signalPad, newReference + signalPad };
Polygon pol = new Polygon(x, y, 5);
paintVectorShape(g2, fromPix, toPix, sigValue, pol);
}
private void paintVectorValueRight(Graphics2D g2, int toPix,
String sigValue) {
if (toPix < 16) return;
int[] x = { headerLength + vectorPad, headerLength + toPix - vectorPad,
headerLength + toPix, headerLength + toPix - vectorPad,
headerLength + vectorPad };
int[] y = { newReference + trackHeight - signalPad,
newReference + trackHeight - signalPad,
newReference + trackHeight / 2, newReference + signalPad,
newReference + signalPad };
Polygon pol = new Polygon(x, y, 5);
paintVectorShape(g2, 0, toPix, sigValue, pol);
}
private void paintVectorValueWhole(Graphics2D g2, int fromPix, int toPix,
String sigValue) {
if ((toPix - fromPix) < 16) return;
int[] x = { headerLength + fromPix, headerLength + fromPix + vectorPad,
headerLength + toPix - vectorPad, headerLength + toPix,
headerLength + toPix - vectorPad,
headerLength + fromPix + vectorPad };
int[] y = { newReference + trackHeight / 2,
newReference + trackHeight - signalPad,
newReference + trackHeight - signalPad,
newReference + trackHeight / 2, newReference + signalPad,
newReference + signalPad };
Polygon pol = new Polygon(x, y, 6);
paintVectorShape(g2, fromPix, toPix, sigValue, pol);
}
private void paintVectorShape(Graphics2D g2, int fromPix, int toPix,
String sigValue, Polygon pol) {
if (fromPix == toPix)
return;
g2.setStroke(new BasicStroke(1));
g2.setColor(Color.orange);
g2.fill(pol);
g2.setColor(getForeground());
g2.draw(pol);
if (toPix - fromPix > sigValue.length() * 6)
g2.drawString(sigValue, headerLength + (toPix + fromPix) / 2
- sigValue.length() * 3, newReference + trackHeight * 3 / 5);
}
private void paintScalarSignal(Graphics g, Signal signal) {
paintSignalHeader(g, signal);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(2));
List<SignalChange> changes = signal.getSignalChangeList(begin, begin
+ length);
g2.setColor(Color.white);
g2.fillRect(headerLength + 1, newReference, getWidth() - headerLength,
trackHeight);
g2.setColor(getForeground());
g2.drawRect(headerLength, newReference, getWidth() - headerLength,
trackHeight);
g2.setColor(new Color(250, 250, 100));
if (signal.getClass() != ClockSignal.class && inputSetupTime > 0) {
int perLength = scale.toPixel(periodLength / multiplier);
int inpLength = scale.toPixel(inputSetupTime / multiplier);
int tbLength = scale.toPixel(testBenchLengthScaled) + headerLength;
int upLength = scale.toPixel(clockUpTime / multiplier);
for (int i = headerLength + perLength - upLength; i < getWidth()
&& i <= tbLength; i += perLength) {
g2.fillRect(i - inpLength + 3, newReference + signalPad + 5,
inpLength - 6, trackHeight - 2 * signalPad - 10);
}
} else if (checkOutputsTime > 0) {
int perLength = scale.toPixel(periodLength / multiplier);
int checkOLength = scale.toPixel(checkOutputsTime / multiplier);
int tbLength = scale.toPixel(testBenchLengthScaled) + headerLength;
for (int i = headerLength + perLength + checkOLength; i < getWidth()
&& i <= tbLength; i += perLength) {
g2.fillRect(i - checkOLength + 3, newReference + signalPad + 5,
checkOLength - 6, trackHeight - 2 * signalPad - 10);
}
}
g2.setColor(getForeground());
g2.setStroke(new BasicStroke(1));
int fromPix = 0;
int i = 0;
String sigVal = signal.getSignalChange(begin).getSignalValue();
for (SignalChange signalChange : changes) {
long toTime = signalChange.getTime();
int toPix = scale.toPixel((toTime - begin) / multiplier);
// Horizontal Line
g2.drawLine(headerLength + fromPix, newReference
+ signalValue(sigVal), headerLength + toPix, newReference
+ signalValue(sigVal));
fromPix = toPix;
// Vertical Line
if(signal.getClass() == ClockSignal.class && (
(changeStateEdge == ChangeStateEdge.falling && i % 2 == 0 && i != 0) ||
(changeStateEdge == ChangeStateEdge.rising && i % 2 == 1))){
g2.setColor(Color.red);
g2.setStroke(new BasicStroke(2));
g2.drawLine(headerLength + fromPix, newReference + signalPad + 1,
headerLength + fromPix, newReference + trackHeight
- signalPad);
}
else
g2.drawLine(headerLength + fromPix, newReference + signalPad,
headerLength + fromPix, newReference + trackHeight
- signalPad);
sigVal = signal.getSignalChange(toTime).getSignalValue();
g2.setColor(getForeground());
g2.setStroke(new BasicStroke(1));
i++;
}
sigVal = signal.getSignalChange(begin + length).getSignalValue();
// int toEnd = (int)((begin + length)/multiplier) * scale.scaleX /
// scale.scaleT;
// POPRAVI!
g2.drawLine(headerLength + fromPix, newReference + signalValue(sigVal),
getWidth(), newReference + signalValue(sigVal));
newReference += trackHeight;
}
private void paintSignalHeader(Graphics g, Signal signal) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(getBackground());
g2.fillRect(0, newReference, headerLength, trackHeight);
g2.setColor(getForeground());
g2.setStroke(new BasicStroke(2));
g2.drawRect(1, newReference, headerLength - 1, trackHeight);
String name = signal.getName();
if (signal.getClass() == VectorSignal.class) {
VectorSignal vs = (VectorSignal) signal;
if (vs.getDirection() == VectorDirection.to)
name += " [0:" + (vs.getDimension() - 1) + "]";
else
name += " [" + (vs.getDimension() - 1) + ":0]";
Rectangle vExpand = vExpandList.get(vs);
vExpand.setLocation(vExpandX, newReference + vExpandY);
vExpandList.put(vs, vExpand);
g2.setStroke(new BasicStroke(1));
g2.setColor(Color.white);
g2.fill(vExpand);
g2.setColor(Color.black);
g2.draw(vExpand);
g2.drawLine(vExpandX + 2,
newReference + vExpandY + vExpandSize / 2, vExpandX
+ vExpandSize - 2, newReference + vExpandY
+ vExpandSize / 2);
if (!expanded.contains(vs))
g2.drawLine(vExpandX + vExpandSize / 2, newReference + vExpandY
+ 2, vExpandX + vExpandSize / 2, newReference
+ vExpandY + vExpandSize - 2);
}
g2.drawString(name, headerLength / 3, newReference + trackHeight * 3
/ 5);
}
private int signalValue(String sigVal) {
if ("1".equals(sigVal))
return signalPad;
else if ("0".equals(sigVal))
return trackHeight - signalPad;
else
return trackHeight / 2;
}
@Override
public void validate() {
super.validate();
}
protected JTestbench getParentJTestbench() {
Container c = this;
for (int i = 0; i < 5; i++) {
if (c == null) {
return null;
}
if (c.getClass() == JTestbench.class) {
return (JTestbench) c;
}
c = c.getParent();
}
return null;
}
private class Marker {
private Polygon polygon;
protected int position;
protected long markedTime;
protected boolean showing;
public Marker(long markedTime) {
this.markedTime = markedTime;
this.position = headerLength;
int[] x = { headerLength - markerWidth / 2, headerLength,
headerLength + markerWidth / 2 };
int[] y = { timeLineHeight - markerHeight, timeLineHeight,
timeLineHeight - markerHeight };
polygon = new Polygon(x, y, 3);
}
public void init() {
showing = (begin <= markedTime && markedTime <= begin + length);
if (!showing)
return;
int newPos = headerLength
+ scale.toPixel((markedTime - begin) / multiplier);
polygon.translate(newPos - position, 0);
position = newPos;
}
public void moveForPixels(int pos) {
long newTime = begin + scale.toTime(pos) * multiplier;
moveForTime(newTime);
}
public void moveForTime(long time){
int left = (int)(time / multiplier) /scale.scaleT * scale.scaleT;
int right = left + scale.scaleT;
if((int)(time / multiplier) < (right+left) / 2)
markedTime = left * multiplier;
else
markedTime = right * multiplier;
}
public boolean contains(int x, int y) {
if (!showing)
return false;
return polygon.contains(x, y);
}
public void paint(Graphics2D g2) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(Color.lightGray);
g2.fill(polygon);
g2.setPaint(Color.black);
g2.setStroke(new BasicStroke(2));
g2.draw(polygon);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_OFF);
}
}
private class Scale {
protected int scaleT;
protected int scaleX;
public Scale(int width) {
width = width - headerLength;
if (lengthScaled <= 100)
scaleT = 2;
else if (lengthScaled <= 100)
scaleT = 2;
else if (lengthScaled <= 500)
scaleT = 10;
else if (lengthScaled <= 1000)
scaleT = 20;
else if (lengthScaled <= 5000)
scaleT = 100;
else if (lengthScaled <= 10000)
scaleT = 200;
else
scaleT = 1000;
scaleX = scaleT * width / (int) lengthScaled;
if (scaleX < 10)
scaleX = 10;
}
int toPixel(long time){
return (int) (time * scale.scaleX
/ scale.scaleT);
}
int toTime(int pixel){
return pixel * scale.scaleT / scale.scaleX;
}
}
}