package automenta.vivisect.timeline;
import automenta.vivisect.Vis;
import com.google.common.collect.Lists;
import java.awt.Graphics2D;
import java.util.Collection;
import java.util.List;
import static processing.core.PConstants.HSB;
import processing.core.PGraphics;
import processing.core.PGraphicsJava2D;
/**
* Timeline view of an inference trace. Focuses on a specific window and certain
* features which can be adjusted dynamically. Can either analyze a trace while
* a NAR runs, or after it finishes.
*/
public class TimelineVis implements Vis {
float camScale = 1f;
float scaleSpeed = 4f;
private float lastMousePressY = Float.NaN;
private float lastMousePressX = Float.NaN;
final int defaultFrameRate = 25;
boolean updating = true;
float minLabelScale = 10f;
float minYScale = 0.5f;
float minTimeScale = 0.5f;
float maxYScale = 1000f;
float maxTimeScale = 1000f;
float drawnTextScale = 0;
//display options to extract to a parameter class ----------------------------------------
boolean showItemLabels = true;
float textScale = 0.1f;
int cycleStart = 0;
int cycleEnd = 0;
public PGraphics g;
public Graphics2D g2; //for direct Swing control
public static class Camera {
public float camX = 0f;
public float camY = 0f;
public float timeScale = 32f;
public float yScale = 32f;
public long lastUpdate = 0;
}
public final Camera camera;
long lastUpdate = System.nanoTime();
long lastCameraUpdate = 0;
public final List<Chart> charts;
//display options ----------------------------------------
public TimelineVis(List<Chart> charts) {
this(new Camera(), charts);
}
public TimelineVis(Camera camera, List<Chart> charts) {
super();
this.camera = camera;
this.charts = charts;
}
public TimelineVis(Chart... charts) {
this(new Camera(), charts);
}
public TimelineVis(Camera camera, Chart... charts) {
this(camera, Lists.newCopyOnWriteArrayList(Lists.newArrayList(charts)));
}
public void view(long start, long end) {
//TODO calculate timeScale and camX to view the cycle range
}
public void clearCharts() {
charts.clear();
}
public void setCharts(Collection<Chart> newChartList) {
clearCharts();
charts.addAll(newChartList);
}
public void addChart(Chart c) {
charts.add(c);
}
public long getStart() {
return cycleStart;
}
public long getEnd() {
return cycleEnd;
}
// @Override
// public void mouseWheelMoved(MouseWheelEvent e) {
// super.mouseWheelMoved(e);
// /*int wr = e.getWheelRotation();
// camScale += wr * dScale;
// if (wr != 0)
// updateNext();*/
// }
//
// @Override
// public void keyPressed(KeyEvent event) {
// super.keyPressed(event);
// if (event.getKey() == 'l') {
// showItemLabels = !showItemLabels;
// updateNext();
// }
//
// }
// @Override
// public void mouseMoved() {
// updateMouse();
// }
//
//
// @Override
// public void mouseReleased() {
// updateMouse();
// }
//
// protected void updateMouse() {
//
// boolean changed = false;
//
//
// //scale limits
// if (mouseButton > 0) {
// long now = System.nanoTime();
//
// if (Float.isFinite(lastMousePressX)) {
// float dt = (now - lastUpdate)/1e9f;
//
//
// //float dx = (mouseX - lastMousePressX);
// //float dy = (mouseY - lastMousePressY);
// float dx = mouseX - pmouseX;
// float dy = mouseY - pmouseY;
//
// if (mouseButton == 37) {
// //left mouse button
// if ((dx != 0) || (dy != 0)) {
// camera.camX -= dx;
// camera.camY -= dy;
// changed = true;
// }
// } else if (mouseButton == 39) {
// //right mouse button
//
//
// float sx = dx * scaleSpeed * dt;
// float sy = dy * scaleSpeed * dt;
//
// camera.camX += sx / camera.timeScale;
// camera.camY += sy / camera.yScale;
//
// camera.timeScale += sx;
// camera.yScale += sy;
//
// changed = true;
// //System.out.println(camX + " " + camY + " " + sx + " " + sy);
// }
// else {
// lastMousePressX = Float.NaN;
// }
//// else if (mouseButton == 3) {
//// //middle mouse button (wheel)
//// rotZ -= dx * rotSpeed;
//// }
// }
//
// lastMousePressX = mouseX;
// lastMousePressY = mouseY;
//
// lastUpdate = now;
//
// } else {
// lastMousePressX = Float.NaN;
// }
//
//
// if (changed) {
// camera.lastUpdate = System.currentTimeMillis();
// updateNext();
// }
//
// }
//
// protected void updateCamera() {
//
// if (camera.yScale < minYScale) camera.yScale = minYScale;
// if (camera.yScale > maxYScale) camera.yScale = maxYScale;
// if (camera.timeScale < minTimeScale) camera.timeScale = minTimeScale;
// if (camera.timeScale > maxTimeScale) camera.timeScale = maxTimeScale;
//
// translate(-camera.camX + width / 2, -camera.camY + height / 2);
//
// cycleStart = (int) (Math.floor((camera.camX - width / 2) / camera.timeScale) - 1);
// cycleStart = Math.max(0, cycleStart);
// cycleEnd = (int) (Math.ceil((camera.camX + width / 2) / camera.timeScale) + 1);
//
// if (cycleEnd < cycleStart) cycleEnd = cycleStart;
//
// drawnTextScale = Math.min(camera.yScale, camera.timeScale) * textScale;
//
// if (camera.lastUpdate > lastCameraUpdate) {
// updating = true;
// }
//
//
//
// }
public void updateNext() {
if (!updating) {
for (Chart c : charts) {
float h = c.height * camera.yScale;
c.update(this, camera.timeScale, camera.yScale);
}
}
updating = true;
}
@Override
public boolean draw(PGraphics g) {
this.g = g;
this.g2 = ((PGraphicsJava2D)g).g2;
int originalColorMode = g.colorMode;
g.colorMode(HSB);
//updateMouse();
/*if (!isDisplayable() || !isVisible())
return true;*/
//updateCamera();
/*if (!updating) {
return true;
}
updating = false;*/
lastCameraUpdate = camera.lastUpdate;
//background(0);
float y = 0;
float yMargin = camera.yScale * 0.1f;
cycleStart = Integer.MAX_VALUE;
cycleEnd = 0;
for (Chart c : charts) {
int cstart = c.getStart();
int cend = c.getEnd();
if (cstart < cycleStart) cycleStart = cstart;
if (cend > cycleEnd) cycleEnd = cend;
}
for (Chart c : charts) {
float h = c.height * camera.yScale;
c.draw(this, y, camera.timeScale, camera.yScale);
y += (h + yMargin);
}
g.colorMode(originalColorMode);
return true;
}
public boolean isShowingItemLabels() {
return showItemLabels;
}
public float getMinLabelScale() {
return minLabelScale;
}
/*
import picking.*;
Picker picker;
float a = 0.0;
void setup() {
size(200, 150, P3D);
picker = new Picker(this);
}
void draw() {
a += 0.01;
background(255);
picker.start(0);
drawBox(80, 75, 50, #ff8800);
picker.start(1);
drawBox(140, 75, 20, #eeee00);
picker.stop();
color c = 0;
int id = picker.get(mouseX, mouseY);
switch (id) {
case 0:
c = #ff8800;
break;
case 1:
c = #eeee00;
break;
}
drawBorder(10, c);
}
void drawBox(int x, int y, int w, color c) {
stroke(0);
fill(c);
pushMatrix();
translate(x, y);
rotateX(a); rotateY(a);
box(w);
popMatrix();
}
void drawBorder(int w, color c) {
noStroke();
fill(c);
rect(0, 0, width, w);
rect(0, height - w, width, w);
rect(0, 0, w, height);
rect(width - w, 0, w, height);
}
*/
public float getDrawnTextScale() {
return drawnTextScale;
}
}