View Javadoc

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