package render;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import javax.swing.JPanel;
import javax.swing.Timer;
import env.Space;
public class SpaceViewPanel extends JPanel {
private static final long serialVersionUID = 1L;
private Space space;
private OverlayManager overlays;
private Viewport vp;
private RenderNode rootWindow;
public RenderPreferences prefs;
public boolean lockPosition;
private Timer timer;
public SpaceViewPanel(Space sp) {
super(new BorderLayout());
prefs = new StandardPrefs();
overlays = new OverlayManager();
space = sp;
vp = new Viewport(0, 0, 0, 1d);
ViewportMouseDrag md = new ViewportMouseDrag();
this.addMouseMotionListener(md);
this.addMouseListener(md);
this.addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(MouseWheelEvent e) {
vp.zoom(-e.getPreciseWheelRotation(), e.getX(), -e.getY());
}
});
rootWindow = new XYTRenderNode(0,0,0);
rootWindow.addChild(vp);
rootWindow.addChild(overlays);
timer = new Timer(15, new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
repaint();
}
});
timer.start();
this.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
AffineTransform cart = new AffineTransform();
cart.scale(1, -1);
space.blockRunning(true);
rootWindow.interaction(cart, e, MouseEventType.MOUSE_RELEASE);
space.blockRunning(false);
}
public void mousePressed(MouseEvent e) {
}
});
this.addKeyListener(overlays);
this.setFocusable(true);
}
public void paint(Graphics g) {
update(g);
}
public void update(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g.setColor(prefs.spaceColor());
g.fillRect(0, 0, getWidth(), getHeight());
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
AffineTransform cart = new AffineTransform();
cart.scale(1, -1);
overlays.setWindowDimensions(this.getSize());
space.blockRunning(true);
rootWindow.render(g2,cart, prefs);
space.blockRunning(false);
}
public class Viewport extends XYTRenderNode {
private double zoom;
public Viewport(double x, double y, double theta, double zoom) {
super(x, y, theta);
this.children = space.rendities();
this.zoom = zoom;
}
public void transform(AffineTransform at) {
super.transform(at);
at.translate(getWidth()/2, -getHeight()/2);
at.scale(zoom, zoom);
}
public void zoom(double amt, double x, double y) {
amt = amt/Math.abs(amt);
double oldworldx = (x-this.x-getWidth()/2)/zoom;
double oldworldy = (y-this.y+getHeight()/2)/zoom;
zoom += amt * (zoom/10);
double newworldx = (x-this.x-getWidth()/2)/zoom;
double newworldy = (y-this.y+getHeight()/2)/zoom;
this.x -= (oldworldx-newworldx)*zoom;
this.y -= (oldworldy-newworldy)*zoom;
}
public void moveCenter(double x, double y) {
if (!lockPosition) {
this.x -= x;
this.y -= y;
}
}
}
private class ViewportMouseDrag extends MouseAdapter {
int lx, ly;
int sx, sy;
public ViewportMouseDrag() {
lx = ly = -1;
}
public void mouseDragged(MouseEvent e) {
boolean interacted = false;
sx = sy = -1;
AffineTransform cart = new AffineTransform();
cart.scale(1, -1);
if (lx==-1) {
space.blockRunning(true);
interacted = rootWindow.interaction(cart, e, MouseEventType.MOUSE_DRAG);
space.blockRunning(false);
}
if (interacted) {
return;
}
if (lx!=-1) {
vp.moveCenter(lx-e.getX(), ly+e.getY());
lx = e.getX();
ly = -e.getY();
}
}
public void mousePressed(MouseEvent e) {
AffineTransform cart = new AffineTransform();
cart.scale(1, -1);
space.blockRunning(true);
boolean interacted = rootWindow.interaction(cart, e, MouseEventType.MOUSE_PRESS);
space.blockRunning(false);
if (interacted) {
sx = sy = -1;
overlays.lowPriorityInteraction = null;
return;
}
if (overlays.lowPriorityInteraction != null) {
space.blockRunning(true);
overlays.lowPriorityInteraction.run();
overlays.lowPriorityInteraction = null;
sx = sy = -1;
space.blockRunning(false);
return;
}
if (e.getButton() == MouseEvent.BUTTON1) {
sx=lx = e.getX();
sy=ly = -e.getY();
}
}
public void mouseReleased(MouseEvent e) {
if (sx==e.getX() && sy==-e.getY()) {
if (overlays.nonproductiveClick != null) {
space.blockRunning(true);
overlays.nonproductiveClick.run();
space.blockRunning(false);
}
}
sx = sy = ly = lx = -1;
}
}
public OverlayManager overlays() {
return overlays;
}
public void stop() {
timer.stop();
}
}