/*******************************************************************************
* Copyright (c) 2007, 2008 Gregory Jordan
*
* This file is part of PhyloWidget.
*
* PhyloWidget is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, either version 2 of the License, or (at your option) any later
* version.
*
* PhyloWidget is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* PhyloWidget. If not, see <http://www.gnu.org/licenses/>.
*/
package org.andrewberman.ui.camera;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Point2D;
//import org.andrewberman.ui.FocusManager;
import processing.core.PApplet;
public class MovableCamera extends Camera implements MouseWheelListener,
KeyListener, MouseMotionListener, MouseListener
{
Point2D.Float pt = new Point2D.Float(0, 0);
protected int NUDGE_DISTANCE;
protected float NUDGE_SCALE;
protected boolean mouseInside = false;
/**
* If set to true, then this camera will start scrolling when the mouse is
* close to the edge of the screen.
*/
public boolean enableSideScrolling = false;
public boolean respondToKeyboard = false;
public void setRespondToKeyboard(boolean respondToKeyboard)
{
this.respondToKeyboard = respondToKeyboard;
}
public MovableCamera(PApplet p)
{
super(p);
this.p = p;
makeResponsive();
NUDGE_DISTANCE = p.width / 5;
NUDGE_SCALE = 10f / (float) NUDGE_DISTANCE;
}
public void makeResponsive()
{
p.addMouseListener(this);
p.addMouseMotionListener(this);
p.addMouseWheelListener(this);
p.addKeyListener(this);
}
public void makeUnresponsive()
{
p.removeMouseListener(this);
p.removeMouseMotionListener(this);
p.removeMouseWheelListener(this);
p.removeKeyListener(this);
}
public void update()
{
// System.out.println(getX()+" "+getY());
xTween.update();
yTween.update();
zTween.update();
scroll();
applyTransformations();
}
public void scroll()
{
/*
* Handle the edge scrolling.
*/
if (mouseInside && enableSideScrolling)
{
pt.setLocation(p.mouseX, p.mouseY);
float zoomMultiplier = NUDGE_SCALE / getZ();
float dy = 0;
float dx = 0;
if (pt.y > p.height - NUDGE_DISTANCE)
{
dy = NUDGE_DISTANCE - (p.height - pt.y);
} else if (pt.y < NUDGE_DISTANCE)
{
dy = -(NUDGE_DISTANCE - pt.y);
}
if (pt.x > p.width - NUDGE_DISTANCE)
{
dx = NUDGE_DISTANCE - (p.width - pt.x);
} else if (pt.x < NUDGE_DISTANCE)
{
dx = -(NUDGE_DISTANCE - pt.x);
}
if (dy != 0 || dx != 0)
{
this.nudge(dx * zoomMultiplier, dy * zoomMultiplier);
}
}
}
public float getStageWidth()
{
return p.width;
}
public float getStageHeight()
{
return p.height;
}
public void mouseWheelMoved(MouseWheelEvent e)
{
this.zTween.stop();
// float rotVal = (float) Math.abs(e.getWheelRotation());
// rotVal = Math.min(rotVal, 1);
float rotVal = 1.5f;
// System.out.println(rotVal);
// int rotDir = (int) Math.signum(e.getWheelRotation());
int rotDir = (e.getWheelRotation() < 0 ? 1 : -1);
float mult = (float) Math.pow(rotVal, rotDir);
pt.setLocation(e.getX(), e.getY());
float dx = p.width / 2 - pt.x;
float dy = p.height / 2 - pt.y;
// dx = -dx / getZ() / (float)Math.pow(mult, rotDir) * rotDir;
// dy = -dy / getZ() / (float)Math.pow(mult, rotDir) * rotDir;
float destZ = getZ() * mult;
dx = dx / destZ * (1 - mult);
dy = dy / destZ * (1 - mult);
this.zoomBy(mult);
this.nudge(dx, dy);
}
public void keyEvent(KeyEvent e)
{
// Only want keypresses here.
if (e.getID() != KeyEvent.KEY_PRESSED)
return;
if (!respondToKeyboard)
return;
System.out.println(e.getKeyCode());
int code = e.getKeyCode();
float nudgeAmt = 10 * 1f / getZ();
switch (code)
{
case (81): // Q
this.zoomBy(2);
break;
case (87): // W
this.zoomBy(.5f);
break;
case (37): // Left
this.nudge(-nudgeAmt, 0);
break;
case (39): // Right
this.nudge(nudgeAmt, 0);
break;
case (38): // Up(?)
this.nudge(0,-nudgeAmt);
break;
case (40): // Down(?)
this.nudge(0,nudgeAmt);
break;
}
}
public void mouseEvent(MouseEvent e)
{
int type = e.getID();
switch (type)
{
case (MouseEvent.MOUSE_MOVED):
case (MouseEvent.MOUSE_DRAGGED):
break;
case (MouseEvent.MOUSE_EXITED):
mouseInside = false;
break;
case (MouseEvent.MOUSE_ENTERED):
mouseInside = true;
break;
case (MouseEvent.MOUSE_PRESSED):
// Point2D.Float pt = new Point2D.Float(e.getX(), e.getY());
// ProcessingUtils.screenToModel(p, pt);
// System.out.println(pt);
break;
}
}
public void keyPressed(KeyEvent e)
{
keyEvent(e);
}
public void keyReleased(KeyEvent e)
{
keyEvent(e);
}
public void keyTyped(KeyEvent e)
{
keyEvent(e);
}
public void mouseDragged(MouseEvent e)
{
mouseEvent(e);
}
public void mouseMoved(MouseEvent e)
{
mouseEvent(e);
}
public void mouseClicked(MouseEvent e)
{
mouseEvent(e);
}
public void mouseEntered(MouseEvent e)
{
mouseEvent(e);
}
public void mouseExited(MouseEvent e)
{
mouseEvent(e);
}
public void mousePressed(MouseEvent e)
{
mouseEvent(e);
}
public void mouseReleased(MouseEvent e)
{
mouseEvent(e);
}
}