View Javadoc

1   /*
2    * @(#) InputListener.java Mar 2, 2004
3    * 
4    * Copyright (c) 2002-2005 Delft University of Technology Jaffalaan 5, 2628 BX
5    * Delft, the Netherlands. All rights reserved.
6    * 
7    * This software is proprietary information of Delft University of Technology
8    * The code is published under the Lesser General Public License
9    */
10  package nl.tudelft.simulation.dsol.gui.animation2D.mouse;
11  
12  import java.awt.event.ActionEvent;
13  import java.awt.event.KeyEvent;
14  import java.awt.event.KeyListener;
15  import java.awt.event.MouseEvent;
16  import java.awt.event.MouseListener;
17  import java.awt.event.MouseMotionListener;
18  import java.awt.event.MouseWheelEvent;
19  import java.awt.event.MouseWheelListener;
20  import java.awt.geom.Point2D;
21  import java.awt.geom.Rectangle2D;
22  import java.rmi.RemoteException;
23  import java.text.NumberFormat;
24  import java.util.ArrayList;
25  import java.util.Iterator;
26  import java.util.List;
27  
28  import javax.swing.JPopupMenu;
29  import javax.swing.JSeparator;
30  import javax.vecmath.Point4i;
31  
32  import nl.tudelft.simulation.dsol.animation.LocatableInterface;
33  import nl.tudelft.simulation.dsol.animation.D2.Renderable2DInterface;
34  import nl.tudelft.simulation.dsol.gui.DSOLApplicationInterface;
35  import nl.tudelft.simulation.dsol.gui.animation2D.AnimationPanel;
36  import nl.tudelft.simulation.dsol.gui.animation2D.GridPanel;
37  import nl.tudelft.simulation.dsol.gui.animation2D.actions.IntrospectionAction;
38  import nl.tudelft.simulation.dsol.gui.animation2D.actions.PanDownAction;
39  import nl.tudelft.simulation.dsol.gui.animation2D.actions.PanLeftAction;
40  import nl.tudelft.simulation.dsol.gui.animation2D.actions.PanRightAction;
41  import nl.tudelft.simulation.dsol.gui.animation2D.actions.PanUpAction;
42  import nl.tudelft.simulation.dsol.gui.animation2D.actions.ZoomInAction;
43  import nl.tudelft.simulation.dsol.gui.animation2D.actions.ZoomOutAction;
44  import nl.tudelft.simulation.introspection.gui.IntroSpectionDialog;
45  import nl.tudelft.simulation.logger.Logger;
46  
47  /***
48   * A InputListener <br>
49   * (c) copyright 2002-2005 <a href="http://www.simulation.tudelft.nl">Delft
50   * University of Technology </a>, the Netherlands. <br>
51   * See for project information <a
52   * href="http://www.simulation.tudelft.nl">www.simulation.tudelft.nl </a> <br>
53   * License of use: <a href="http://www.gnu.org/copyleft/lesser.html">Lesser
54   * General Public License (LGPL) </a>, no warranty.
55   * 
56   * @version $Revision$ $Date$
57   * @author <a href="http://www.tbm.tudelft.nl/webstaf/peterja">Peter Jacobs </a>
58   */
59  public class InputListener implements MouseListener, MouseWheelListener,
60  		MouseMotionListener, KeyListener
61  {
62  	/*** the simulator to control */
63  	protected DSOLApplicationInterface application;
64  
65  	/*** the panel to use */
66  	protected AnimationPanel panel;
67  
68  	/*** the mouseClicked point in screen coordinates */
69  	protected Point2D mouseClicked = null;
70  
71  	/*** the formatter */
72  	private NumberFormat formatter = NumberFormat.getInstance();
73  
74  	/***
75  	 * constructs a new InputListener
76  	 * 
77  	 * @param application the application
78  	 * @param panel the panel
79  	 */
80  	public InputListener(final DSOLApplicationInterface application,
81  			final AnimationPanel panel)
82  	{
83  		super();
84  		this.application = application;
85  		this.panel = panel;
86  	}
87  
88  	/***
89  	 * @see java.awt.event.MouseListener
90  	 *      #mouseClicked(java.awt.event.MouseEvent)
91  	 */
92  	public void mouseClicked(final MouseEvent e)
93  	{
94  		this.panel.requestFocus();
95  		this.mouseClicked = e.getPoint();
96  		if (!e.isPopupTrigger())
97  		{
98  			Object selected = this.getSelectedObject(this.getSelectedObjects(e
99  					.getPoint()));
100 			if (selected != null)
101 			{
102 				new IntroSpectionDialog(selected);
103 			}
104 		}
105 	}
106 
107 	/***
108 	 * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
109 	 */
110 	public void mousePressed(final MouseEvent e)
111 	{
112 		this.panel.requestFocus();
113 		this.mouseClicked = e.getPoint();
114 		if (e.isPopupTrigger())
115 		{
116 			this.popup(e);
117 			return;
118 		}
119 	}
120 
121 	/***
122 	 * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
123 	 */
124 	public void mouseReleased(final MouseEvent e)
125 	{
126 		if (e.isPopupTrigger())
127 		{
128 			this.popup(e);
129 		} else
130 		{
131 			// Pan if either shift is down or the middle mouse button is used.
132 			if ((e.isShiftDown()) || (e.getButton() == MouseEvent.BUTTON2))
133 			{
134 				this.pan(this.mouseClicked, e.getPoint());
135 				this.panel.repaint();
136 			}
137 		}
138 	}
139 
140 	/***
141 	 * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
142 	 */
143 	public void mouseEntered(final MouseEvent e)
144 	{
145 		// Nothing to be done.
146 	}
147 
148 	/***
149 	 * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
150 	 */
151 	public void mouseExited(final MouseEvent e)
152 	{
153 		// Nothing to be done
154 	}
155 
156 	/***
157 	 * @see java.awt.event.MouseWheelListener#mouseWheelMoved(java.awt.event.MouseWheelEvent)
158 	 */
159 	public void mouseWheelMoved(final MouseWheelEvent e)
160 	{
161 		// Use mouse wheel to zoom
162 		int amount = e.getUnitsToScroll();
163 		if (amount > 0)
164 		{
165 			this.panel.zoom(GridPanel.IN, 0.95 * amount);
166 		} else if (amount < 0)
167 		{
168 			this.panel.zoom(GridPanel.OUT, 0.95 * -amount);
169 		}
170 	}
171 
172 	/***
173 	 * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
174 	 */
175 	public void mouseDragged(final MouseEvent e)
176 	{
177 		if (e.isShiftDown())
178 		{
179 			this.setDragLine(e.getPoint());
180 		}
181 		this.panel.repaint();
182 	}
183 
184 	/***
185 	 * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
186 	 */
187 	public void mouseMoved(final MouseEvent mouseEvent)
188 	{
189 		Point2D point = Renderable2DInterface.Util.getWorldCoordinates(
190 				mouseEvent.getPoint(), this.panel.getExtent(), this.panel
191 						.getSize());
192 		String worldPoint = "null";
193 		if (point != null)
194 		{
195 			worldPoint = "world(x=" + this.formatter.format(point.getX())
196 					+ " ; y=" + this.formatter.format(point.getY()) + ")";
197 		}
198 		String mousePoint = "screen(x="
199 				+ this.formatter.format(mouseEvent.getPoint().getX()) + " ; y="
200 				+ this.formatter.format(mouseEvent.getPoint().getY()) + ")";
201 		this.panel.setToolTipText(worldPoint + "  " + mousePoint);
202 	}
203 
204 	/***
205 	 * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)
206 	 */
207 	public void keyPressed(final KeyEvent e)
208 	{
209 		switch (e.getKeyCode())
210 		{
211 			case KeyEvent.VK_LEFT :
212 				new PanLeftAction(this.panel).actionPerformed(new ActionEvent(
213 						this, 0, "LEFT"));
214 				break;
215 			case KeyEvent.VK_RIGHT :
216 				new PanRightAction(this.panel).actionPerformed(new ActionEvent(
217 						this, 0, "RIGHT"));
218 				break;
219 			case KeyEvent.VK_UP :
220 				new PanUpAction(this.panel).actionPerformed(new ActionEvent(
221 						this, 0, "UP"));
222 				break;
223 			case KeyEvent.VK_DOWN :
224 				new PanDownAction(this.panel).actionPerformed(new ActionEvent(
225 						this, 0, "DOWN"));
226 				break;
227 			case KeyEvent.VK_MINUS :
228 				new ZoomOutAction(this.panel).actionPerformed(new ActionEvent(
229 						this, 0, "OUT"));
230 				break;
231 			case KeyEvent.VK_EQUALS :
232 				new ZoomInAction(this.panel).actionPerformed(new ActionEvent(
233 						this, 0, "IN"));
234 				break;
235 			default :
236 		}
237 	}
238 
239 	/***
240 	 * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)
241 	 */
242 	public void keyReleased(final KeyEvent e)
243 	{
244 		// nothing to be done
245 	}
246 
247 	/***
248 	 * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)
249 	 */
250 	public void keyTyped(final KeyEvent e)
251 	{
252 		// nothing to be done
253 	}
254 
255 	/***
256 	 * What to do if the middle mouse button was released
257 	 * 
258 	 * @param mouseClickedPoint the point where the mouse was clicked
259 	 * @param mouseReleasedPoint the point where the mouse was released
260 	 */
261 	protected void pan(final Point2D mouseClickedPoint,
262 			final Point2D mouseReleasedPoint)
263 	{
264 		// Drag extend to new location
265 		double dx = mouseReleasedPoint.getX() - mouseClickedPoint.getX();
266 		double dy = mouseReleasedPoint.getY() - mouseClickedPoint.getY();
267 		double scale = Renderable2DInterface.Util.getScale(this.panel
268 				.getExtent(), this.panel.getSize());
269 
270 		Rectangle2D.Double extent = (Rectangle2D.Double) this.panel.getExtent();
271 		extent.setRect((extent.getMinX() - dx * scale), (extent.getMinY() + dy
272 				* scale), extent.getWidth(), extent.getHeight());
273 	}
274 
275 	/***
276 	 * returns the list of selected objects at a certain mousePoint
277 	 * 
278 	 * @param mousePoint the mousePoint
279 	 * @return the selected objects
280 	 */
281 	protected List getSelectedObjects(final Point2D mousePoint)
282 	{
283 		List targets = new ArrayList();
284 		try
285 		{
286 			Point2D point = Renderable2DInterface.Util.getWorldCoordinates(
287 					mousePoint, this.panel.getExtent(), this.panel.getSize());
288 			for (Iterator i = this.panel.getElements().iterator(); i.hasNext();)
289 			{
290 				Renderable2DInterface renderable = (Renderable2DInterface) i
291 						.next();
292 				if (renderable.contains(point, this.panel.getExtent(),
293 						this.panel.getSize()))
294 				{
295 					targets.add(renderable.getSource());
296 				}
297 			}
298 		} catch (Exception exception)
299 		{
300 			Logger.warning(this, "getSelectedObjects", exception);
301 		}
302 		return targets;
303 	}
304 
305 	/***
306 	 * popsup on a mouseEvent
307 	 * 
308 	 * @param e the mouseEvent
309 	 */
310 	protected void popup(final MouseEvent e)
311 	{
312 		List targets = this.getSelectedObjects(e.getPoint());
313 		if (targets.size() > 0)
314 		{
315 			JPopupMenu popupMenu = new JPopupMenu();
316 			popupMenu.add("Introspect");
317 			popupMenu.add(new JSeparator());
318 			for (Iterator i = targets.iterator(); i.hasNext();)
319 			{
320 				popupMenu.add(new IntrospectionAction(i.next()));
321 			}
322 			popupMenu.show(this.panel, e.getX(), e.getY());
323 		}
324 	}
325 
326 	/***
327 	 * edits a selected Renderable2D
328 	 * 
329 	 * @param targets which are selected by the mouse.
330 	 * @return the selected Object (e.g. the one with the highest zValue).
331 	 */
332 	protected Object getSelectedObject(final List targets)
333 	{
334 		Object selectedObject = null;
335 		try
336 		{
337 			double zValue = -Double.MAX_VALUE;
338 			for (Iterator i = targets.iterator(); i.hasNext();)
339 			{
340 				LocatableInterface next = (LocatableInterface) i.next();
341 				double z = next.getLocation().z;
342 				if (z > zValue)
343 				{
344 					zValue = z;
345 					selectedObject = next;
346 				}
347 			}
348 		} catch (RemoteException exception)
349 		{
350 			Logger.warning(this, "edit", exception);
351 		}
352 		return selectedObject;
353 	}
354 
355 	/***
356 	 * set the drag line: a line that shows where the user is dragging
357 	 * 
358 	 * @param mousePosition the position of the mouse pointer
359 	 */
360 	private void setDragLine(final Point2D mousePosition)
361 	{
362 		if ((mousePosition != null) && (this.mouseClicked != null))
363 		{
364 			Point4i dragLine = this.panel.getDragLine();
365 			dragLine.w = (int) mousePosition.getX();
366 			dragLine.x = (int) mousePosition.getY();
367 			dragLine.y = (int) this.mouseClicked.getX();
368 			dragLine.z = (int) this.mouseClicked.getY();
369 			this.panel.setDragLineEnabled(true);
370 		}
371 	}
372 }