package glug.gui;
import com.madgag.interval.Interval;
import com.madgag.interval.collections.IntervalMap;
import glug.model.SignificantInterval;
import glug.model.ThreadModel;
import glug.model.time.LogInstant;
import glug.model.time.LogInterval;
import java.awt.*;
import java.util.Collection;
import static com.madgag.interval.Bound.MAX;
import static com.madgag.interval.Bound.MIN;
import static com.madgag.interval.SimpleInterval.overlap;
import static com.madgag.interval.SimpleInterval.union;
import static java.lang.Math.round;
public class ThreadPainter {
private final UILogTimeScale uiLogTimeScale;
private final UIThreadScale uiThreadScale;
public ThreadPainter(UILogTimeScale uiLogTimeScale, UIThreadScale uiThreadScale) {
this.uiLogTimeScale = uiLogTimeScale;
this.uiThreadScale = uiThreadScale;
}
public void paintThread(ThreadModel threadModel, int threadIndex, LogInterval visibleInterval, Graphics2D g) {
int durationFor1Pixel = (int) round(uiLogTimeScale.getMillisecondsPerPixel());
int threadGraphicsY = uiThreadScale.modelThreadIndexToView(threadIndex);
int threadGraphicsHeight = uiThreadScale.modelThreadIndexToView(threadIndex+1) - threadGraphicsY;
for (Object intervalTypeDescriptor : threadModel.getIntervalTypes()) {
plotIntervalsOfType(intervalTypeDescriptor, threadModel,
visibleInterval, g, durationFor1Pixel, threadGraphicsY,
threadGraphicsHeight);
}
}
private Color colourFor(Object intervalTypeDescriptor) {
return new Color(intervalTypeDescriptor.hashCode());
}
private void plotIntervalsOfType(
Object intervalTypeDescriptor,
ThreadModel threadModel, LogInterval visibleInterval, Graphics2D g,
int durationFor1Pixel, int threadGraphicsY, int threadGraphicsHeight) {
g.setColor(colourFor(intervalTypeDescriptor));
IntervalMap<LogInstant, SignificantInterval> significantIntervals = threadModel.significantIntervalsFor(intervalTypeDescriptor);
if (significantIntervals==null) {
return;
}
Collection<SignificantInterval> sigInts = significantIntervals.getEventsDuring(visibleInterval);
Interval<LogInstant> visibleIntervalToPlot = null;
for (SignificantInterval significantInterval : sigInts) {
Interval<LogInstant> visibleIntervalOfCurrentSigInt = overlap(significantInterval.getLogInterval(),visibleInterval);
if (visibleIntervalOfCurrentSigInt!=null) {
if (visibleIntervalToPlot==null) {
visibleIntervalToPlot = visibleIntervalOfCurrentSigInt;
} else if (close(visibleIntervalToPlot, durationFor1Pixel, visibleIntervalOfCurrentSigInt)) {
visibleIntervalToPlot = union(visibleIntervalToPlot,visibleIntervalOfCurrentSigInt);
} else {
plotBlock(visibleIntervalToPlot, threadGraphicsY,threadGraphicsHeight, g); // finish with the old block
visibleIntervalToPlot = visibleIntervalOfCurrentSigInt; // start the new block
}
}
}
if (visibleIntervalToPlot != null) {
plotBlock(visibleIntervalToPlot, threadGraphicsY,threadGraphicsHeight, g);
}
}
private boolean close(Interval<LogInstant> visibleIntervalToPlot, int durationFor1Pixel, Interval<LogInstant> visibleIntervalOfCurrentSigInt) {
return (visibleIntervalOfCurrentSigInt.get(MIN).getMillis()-visibleIntervalToPlot.get(MAX).getMillis())<durationFor1Pixel;
}
private void plotBlock(Interval<LogInstant> visibleIntervalOfLine, int threadYStart, int threadGraphicsHeight, Graphics2D g) {
int startX = uiLogTimeScale.modelToView(visibleIntervalOfLine.get(MIN));
int endX = uiLogTimeScale.modelToView(visibleIntervalOfLine.get(MAX));
g.fillRect(startX, threadYStart, endX - startX,threadGraphicsHeight);
}
}