/*******************************************************************************
* 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;
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.util.ArrayList;
import java.util.Collections;
import org.andrewberman.ui.camera.Camera;
import org.andrewberman.ui.ifaces.UIObject;
import org.andrewberman.ui.menu.MenuItem;
import org.andrewberman.ui.menu.MenuItem.ZDepthComparator;
import org.andrewberman.ui.tools.ToolManager;
import processing.core.PApplet;
/**
* The <code>EventManager</code> class, along with <code>FocusManager</code>,
* is a fundamental part of this package. <code>EventManager's</code> job is
* to keep track of all the UI objects currently on the screen and dispatch
* <code>Event</code> objects accordingly.
* <p>
* The <code>UIObject</code> interface is used in order to ensure that all
* objects wishing to register with the <code>EventManager</code> are capable
* of receiving mouse, keyboard, focus, and draw events.
* <p>
* Every UI object wishing to be controlled by the EventManager object should do
* the following in its constructor:
* <ul>
* <li>Call the static method <code>UIUtils.lazyLoad</code>. This causes all
* "singlet" objects to load up their instances if they haven't done so already.</li>
* <li>Call <code>p.event().add(this)</code>. This causes the
* EventManager to begin managing this UIObject. This consists of: calling the
* draw() method every frame, and if the FocusManager allows it, calling the
* mouseEvent, keyEvent, and focusEvent methods accordingly.</li>
* </ul>
*
* @author Greg
* @see org.andrewberman.ui.ifaces.UIObject
* @see org.andrewberman.ui.FocusManager
* @see org.andrewberman.ui.ShortcutManager
* @see org.andrewberman.ui.UIUtils
*/
public final class EventManager implements MouseListener, MouseMotionListener,
MouseWheelListener, KeyListener
{
private PApplet p;
private UIContext c;
private ArrayList delegates = new ArrayList(5);
private ToolManager toolManager;
public Camera toolCamera;
boolean disableInput = false;
Point screen = new Point(0, 0);
Point model = new Point(0, 0);
public EventManager(UIContext c)
{
this.p = c.getApplet();
this.c = c;
setup();
}
public void setup()
{
if (p.g.getClass().getName().equals(PApplet.OPENGL))
{
// PGraphicsOpenGL gl = (PGraphicsOpenGL) p.g;
// gl.canvas.addMouseListener(this);
// gl.canvas.addMouseMotionListener(this);
// gl.canvas.addKeyListener(this);
// gl.canvas.addMouseWheelListener(this);
} else
{
p.addMouseListener(this);
p.addMouseMotionListener(this);
p.addMouseWheelListener(this);
p.addKeyListener(this);
}
/*
* Register ourselves with the PApplet to be drawn every frame.
*/
p.registerDraw(this);
}
public void setDisabled(boolean disable)
{
this.disableInput = disable;
}
ArrayList<UIObject> delegatesToAdd = new ArrayList();
public void add(UIObject o)
{
synchronized (delegates)
{
delegates.add(o);
}
// delegatesToAdd.add(o);
}
public void setToolManager(ToolManager t)
{
toolManager = t;
}
public ToolManager getToolManager()
{
return toolManager;
}
public void setCamera(Camera c)
{
toolCamera = c;
}
public void remove(UIObject o)
{
delegates.remove(o);
}
public void draw()
{
// if (disabled)
// return;
// UIUtils.setMatrix(p);
synchronized (delegates)
{
for (int i = 0; i < delegates.size(); i++)
{
UIObject o = (UIObject) delegates.get(i);
o.draw();
}
}
/*
* Do any drawing of the current tool.
*/
if (toolManager != null)
toolManager.draw();
// for (int i = 0; i < delegatesToAdd.size(); i++)
// {
// UIObject o = delegatesToAdd.get(i);
// delegatesToAdd.remove(i);
// delegates.add(o);
// }
}
public void mouseEvent(MouseEvent e)
{
if (disableInput)
return;
screen.setLocation(e.getX(), e.getY());
model.setLocation(screen.x, screen.y);
UIUtils.screenToModel(model);
if (c.focus() != null)
{
/*
* First, send the event directly to the focused object.
*/
if (c.focus().getFocusedObject() instanceof UIObject)
{
UIObject o = (UIObject) c.focus().getFocusedObject();
// System.out.println(c.focus().getFocusedObject());
o.mouseEvent(e, screen, model);
}
/*
* If the FocusManager is in a modal state, return without further
* dispatching.
*/
if (c.focus().isModal())
return;
}
/*
* Now, send it to the ToolManager.
*/
if (!e.isConsumed())
{
if (toolManager != null)
toolManager.mouseEvent(e, screen, model);
}
/*
* Then, if the focus isn't modal and the object wasn't consumed,
* continue sending the mouse event to the other uiobjects.
*/
synchronized (delegates)
{
for (int i = delegates.size() - 1; i >= 0; i--)
{
if (e.isConsumed())
break;
UIObject ui = (UIObject) delegates.get(i);
if (ui == c.focus().getFocusedObject())
continue;
ui.mouseEvent(e, screen, model);
}
}
}
public void keyEvent(KeyEvent e)
{
if (disableInput)
return;
/*
* We only send keyboard events to the focused object.
*/
if (c.focus().getFocusedObject() instanceof UIObject)
((UIObject) c.focus().getFocusedObject()).keyEvent(e);
/*
* Lastly, dispatch to the tool manager if not consumed.
*/
if (c.focus().getFocusedObject() == null)
{
if (toolManager != null)
toolManager.keyEvent(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);
}
public void mouseDragged(MouseEvent e)
{
mouseEvent(e);
}
public void mouseMoved(MouseEvent e)
{
mouseEvent(e);
}
public void mouseWheelMoved(MouseWheelEvent e)
{
mouseEvent(e);
}
public void keyPressed(KeyEvent e)
{
keyEvent(e);
}
public void keyReleased(KeyEvent e)
{
keyEvent(e);
}
public void keyTyped(KeyEvent e)
{
keyEvent(e);
}
}