package timeflow.vis.timeline;
|
|
import timeflow.data.db.*;
|
import timeflow.data.time.*;
|
import timeflow.model.*;
|
import timeflow.vis.Mouseover;
|
import timeflow.vis.MouseoverLabel;
|
import timeflow.vis.VisualAct;
|
|
import timeflow.util.*;
|
|
import java.awt.*;
|
import java.awt.geom.AffineTransform;
|
import java.util.*;
|
import java.util.List;
|
|
public class TimelineRenderer
|
{
|
|
private TimelineVisuals visuals;
|
private int dy;
|
|
public TimelineRenderer(TimelineVisuals visuals)
|
{
|
this.visuals = visuals;
|
}
|
|
public void setDY(int dy)
|
{
|
this.dy = dy;
|
}
|
|
public void render(Graphics2D g, Collection<Mouseover> objectLocations)
|
{
|
AffineTransform old = g.getTransform();
|
g.setTransform(AffineTransform.getTranslateInstance(0, -dy));
|
|
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
TFModel model = visuals.getModel();
|
Display display = model.getDisplay();
|
ActDB db = model.getDB();
|
|
if (display.emptyMessage(g, model))
|
{
|
return;
|
}
|
|
// need to check this, because resize events don't (and shouldn't) register with central TFModel.
|
visuals.layoutIfChanged();
|
|
java.util.List<VisualAct> visualActs = visuals.getVisualActs();
|
|
if (visualActs == null || visualActs.size() == 0)
|
{
|
g.drawString("No data", 10, 30);
|
return;
|
}
|
|
Rectangle bounds = visuals.getBounds();
|
boolean colorTrackLabels = db.getField(VirtualField.COLOR) == null || db.getField(VirtualField.COLOR).equals(db.getField(VirtualField.TRACK));
|
|
// draw tracks, if more than 1.
|
if (visuals.trackList.size() > 1)
|
{
|
boolean zebra = true;
|
|
for (TimelineTrack t : visuals.trackList)
|
{
|
if (zebra)
|
{
|
g.setColor(display.getColor("timeline.zebra"));
|
g.fillRect(bounds.x, t.y0, bounds.width, t.y1 - t.y0);
|
}
|
zebra = !zebra;
|
g.setColor(display.getColor("timeline.grid"));
|
g.drawLine(bounds.x, t.y0, bounds.x + bounds.width, t.y0);
|
}
|
}
|
|
Interval screenInterval = visuals.getViewInterval().subinterval(-.5, 1.5);
|
AxisTicMarks tics = AxisTicMarks.histoTics(screenInterval.start, screenInterval.end);
|
for (TimelineTrack t : visuals.trackList)
|
{
|
// now... if not in graph mode, just draw items
|
if (visuals.getLayoutStyle() != TimelineVisuals.Layout.GRAPH)//max<(t.y1-t.y0)/20)
|
{
|
for (VisualAct v : t.visualActs)
|
{
|
Mouseover o = v.draw(g, null, bounds, display, true, true);
|
if (o != null)
|
{
|
o.y -= dy;
|
objectLocations.add(o);
|
}
|
}
|
continue;
|
}
|
|
if (true) continue;
|
|
// draw bars. to do so, we make a histogram of visible items.
|
t.histogram = new DoubleBag<Long>();
|
for (VisualAct v : t.visualActs)
|
{
|
long time = v.getStart().getTime();
|
if (screenInterval.contains(time))
|
{
|
t.histogram.add(tics.unit.roundDown(v.getStart().getTime()).getTime(), 1);//v.getSize());
|
}
|
}
|
|
// get max of items.
|
double max = t.histogram.getMax();
|
|
// now draw bars on screen.
|
Color fg = colorTrackLabels ? model.getDisplay().makeColor(t.label) : Color.gray;
|
if (visuals.trackList.size() < 2)
|
{
|
fg = Color.gray;
|
}
|
|
List<Long> keys = t.histogram.unordered();
|
Collections.sort(keys);
|
for (Long r : keys)
|
{
|
double num = t.histogram.num(r);
|
int x1 = visuals.getTimeScale().toInt(r);
|
int x2 = visuals.getTimeScale().toInt(tics.unit.roundUp(r + 1).getTime());
|
int barY = t.y1 - (int) (.9 * ((t.y1 - t.y0) * num) / max);
|
g.setColor(new Color(230, 230, 230));
|
int m = 12;
|
g.fillRoundRect(x1 + 3, barY + 3, x2 - x1 - 1, t.y1 - barY, m, m);
|
|
g.setColor(fg);
|
g.fillRoundRect(x1, barY, x2 - x1 - 1, t.y1 - barY, m, m);
|
|
MouseoverLabel mouse = new MouseoverLabel("" + Math.round(num), "items", x1, barY, x2 - x1 - 1, t.y1 - barY);
|
objectLocations.add(mouse);
|
}
|
}
|
|
// finally label the tracks. we do this last so that the labels go on top of the data.
|
|
if (visuals.trackList.size() > 1)
|
{
|
boolean zebra = false;
|
FontMetrics hugeFm = display.hugeFontMetrics();
|
for (TimelineTrack t : visuals.trackList)
|
{
|
|
// now label the track.
|
//if (t.y1 - t.y0 > 23)
|
{
|
Color fg = colorTrackLabels ? model.getDisplay().makeColor(t.label) : Color.darkGray;
|
Color bg = zebra ? display.getColor("timeline.zebra") : Color.white;
|
|
String label = t.label;
|
if (label.equals(Display.MISC_CODE))
|
{
|
label = display.getMiscLabel();
|
} else if (label.length() == 0)
|
{
|
label = display.getNullLabel();
|
} else
|
{
|
label = display.format(label, 20, false);
|
}
|
|
// draw background.
|
g.setColor(bg);
|
int sw = hugeFm.stringWidth(label);
|
g.fillRect(0, t.y1 - 20, sw + 8, 19);
|
|
// draw foreground (actual label)
|
g.setFont(display.huge());
|
g.setColor(fg);
|
g.drawString(label, 2, t.y1); // - 5);
|
}
|
zebra = !zebra;
|
}
|
}
|
g.setTransform(old);
|
}
|
}
|