1 /*
2 * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package java.awt.event;
27
28 import java.awt.Component;
29 import java.awt.GraphicsEnvironment;
30 import java.awt.Point;
31 import java.awt.Toolkit;
32 import java.io.IOException;
33 import java.io.ObjectInputStream;
34 import java.awt.IllegalComponentStateException;
35
36 /**
37 * An event which indicates that a mouse action occurred in a component.
38 * A mouse action is considered to occur in a particular component if and only
39 * if the mouse cursor is over the unobscured part of the component's bounds
40 * when the action happens.
41 * For lightweight components, such as Swing's components, mouse events
42 * are only dispatched to the component if the mouse event type has been
43 * enabled on the component. A mouse event type is enabled by adding the
44 * appropriate mouse-based {@code EventListener} to the component
45 * ({@link MouseListener} or {@link MouseMotionListener}), or by invoking
46 * {@link Component#enableEvents(long)} with the appropriate mask parameter
47 * ({@code AWTEvent.MOUSE_EVENT_MASK} or {@code AWTEvent.MOUSE_MOTION_EVENT_MASK}).
48 * If the mouse event type has not been enabled on the component, the
49 * corresponding mouse events are dispatched to the first ancestor that
50 * has enabled the mouse event type.
51 *<p>
52 * For example, if a {@code MouseListener} has been added to a component, or
53 * {@code enableEvents(AWTEvent.MOUSE_EVENT_MASK)} has been invoked, then all
54 * the events defined by {@code MouseListener} are dispatched to the component.
55 * On the other hand, if a {@code MouseMotionListener} has not been added and
56 * {@code enableEvents} has not been invoked with
57 * {@code AWTEvent.MOUSE_MOTION_EVENT_MASK}, then mouse motion events are not
58 * dispatched to the component. Instead the mouse motion events are
59 * dispatched to the first ancestors that has enabled mouse motion
60 * events.
61 * <P>
62 * This low-level event is generated by a component object for:
63 * <ul>
64 * <li>Mouse Events
65 * <ul>
66 * <li>a mouse button is pressed
67 * <li>a mouse button is released
68 * <li>a mouse button is clicked (pressed and released)
69 * <li>the mouse cursor enters the unobscured part of component's geometry
70 * <li>the mouse cursor exits the unobscured part of component's geometry
71 * </ul>
72 * <li> Mouse Motion Events
73 * <ul>
74 * <li>the mouse is moved
75 * <li>the mouse is dragged
76 * </ul>
77 * </ul>
78 * <P>
79 * A <code>MouseEvent</code> object is passed to every
80 * <code>MouseListener</code>
81 * or <code>MouseAdapter</code> object which is registered to receive
82 * the "interesting" mouse events using the component's
83 * <code>addMouseListener</code> method.
84 * (<code>MouseAdapter</code> objects implement the
85 * <code>MouseListener</code> interface.) Each such listener object
86 * gets a <code>MouseEvent</code> containing the mouse event.
87 * <P>
88 * A <code>MouseEvent</code> object is also passed to every
89 * <code>MouseMotionListener</code> or
90 * <code>MouseMotionAdapter</code> object which is registered to receive
91 * mouse motion events using the component's
92 * <code>addMouseMotionListener</code>
93 * method. (<code>MouseMotionAdapter</code> objects implement the
94 * <code>MouseMotionListener</code> interface.) Each such listener object
95 * gets a <code>MouseEvent</code> containing the mouse motion event.
96 * <P>
97 * When a mouse button is clicked, events are generated and sent to the
98 * registered <code>MouseListener</code>s.
99 * The state of modal keys can be retrieved using {@link InputEvent#getModifiers}
100 * and {@link InputEvent#getModifiersEx}.
101 * The button mask returned by {@link InputEvent#getModifiers} reflects
102 * only the button that changed state, not the current state of all buttons.
103 * (Note: Due to overlap in the values of ALT_MASK/BUTTON2_MASK and
104 * META_MASK/BUTTON3_MASK, this is not always true for mouse events involving
105 * modifier keys).
106 * To get the state of all buttons and modifier keys, use
107 * {@link InputEvent#getModifiersEx}.
108 * The button which has changed state is returned by {@link MouseEvent#getButton}
109 * <P>
110 * For example, if the first mouse button is pressed, events are sent in the
111 * following order:
112 * <PRE>
113 * <b >id </b > <b >modifiers </b > <b >button </b >
114 * <code>MOUSE_PRESSED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
115 * <code>MOUSE_RELEASED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
116 * <code>MOUSE_CLICKED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
117 * </PRE>
118 * When multiple mouse buttons are pressed, each press, release, and click
119 * results in a separate event.
120 * <P>
121 * For example, if the user presses <b>button 1</b> followed by
122 * <b>button 2</b>, and then releases them in the same order,
123 * the following sequence of events is generated:
124 * <PRE>
125 * <b >id </b > <b >modifiers </b > <b >button </b >
126 * <code>MOUSE_PRESSED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
127 * <code>MOUSE_PRESSED</code>: <code>BUTTON2_MASK</code> <code>BUTTON2</code>
128 * <code>MOUSE_RELEASED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
129 * <code>MOUSE_CLICKED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
130 * <code>MOUSE_RELEASED</code>: <code>BUTTON2_MASK</code> <code>BUTTON2</code>
131 * <code>MOUSE_CLICKED</code>: <code>BUTTON2_MASK</code> <code>BUTTON2</code>
132 * </PRE>
133 * If <b>button 2</b> is released first, the
134 * <code>MOUSE_RELEASED</code>/<code>MOUSE_CLICKED</code> pair
135 * for <code>BUTTON2_MASK</code> arrives first,
136 * followed by the pair for <code>BUTTON1_MASK</code>.
137 * <p>
138 *
139 * <code>MOUSE_DRAGGED</code> events are delivered to the <code>Component</code>
140 * in which the mouse button was pressed until the mouse button is released
141 * (regardless of whether the mouse position is within the bounds of the
142 * <code>Component</code>). Due to platform-dependent Drag&Drop implementations,
143 * <code>MOUSE_DRAGGED</code> events may not be delivered during a native
144 * Drag&Drop operation.
145 *
146 * In a multi-screen environment mouse drag events are delivered to the
147 * <code>Component</code> even if the mouse position is outside the bounds of the
148 * <code>GraphicsConfiguration</code> associated with that
149 * <code>Component</code>. However, the reported position for mouse drag events
150 * in this case may differ from the actual mouse position:
151 * <ul>
152 * <li>In a multi-screen environment without a virtual device:
153 * <br>
154 * The reported coordinates for mouse drag events are clipped to fit within the
155 * bounds of the <code>GraphicsConfiguration</code> associated with
156 * the <code>Component</code>.
157 * <li>In a multi-screen environment with a virtual device:
158 * <br>
159 * The reported coordinates for mouse drag events are clipped to fit within the
160 * bounds of the virtual device associated with the <code>Component</code>.
161 * </ul>
162 * <p>
163 * An unspecified behavior will be caused if the {@code id} parameter
164 * of any particular {@code MouseEvent} instance is not
165 * in the range from {@code MOUSE_FIRST} to {@code MOUSE_LAST}-1
166 * ({@code MOUSE_WHEEL} is not acceptable).
167 *
168 * @author Carl Quinn
169 *
170 * @see MouseAdapter
171 * @see MouseListener
172 * @see MouseMotionAdapter
173 * @see MouseMotionListener
174 * @see MouseWheelListener
175 * @see <a href="http://java.sun.com/docs/books/tutorial/post1.0/ui/mouselistener.html">Tutorial: Writing a Mouse Listener</a>
176 * @see <a href="http://java.sun.com/docs/books/tutorial/post1.0/ui/mousemotionlistener.html">Tutorial: Writing a Mouse Motion Listener</a>
177 *
178 * @since 1.1
179 */
180 public class MouseEvent extends InputEvent {
181
182 /**
183 * The first number in the range of ids used for mouse events.
184 */
185 public static final int MOUSE_FIRST = 500;
186
187 /**
188 * The last number in the range of ids used for mouse events.
189 */
190 public static final int MOUSE_LAST = 507;
191
192 /**
193 * The "mouse clicked" event. This <code>MouseEvent</code>
194 * occurs when a mouse button is pressed and released.
195 */
196 public static final int MOUSE_CLICKED = MOUSE_FIRST;
197
198 /**
199 * The "mouse pressed" event. This <code>MouseEvent</code>
200 * occurs when a mouse button is pushed down.
201 */
202 public static final int MOUSE_PRESSED = 1 + MOUSE_FIRST; //Event.MOUSE_DOWN
203
204 /**
205 * The "mouse released" event. This <code>MouseEvent</code>
206 * occurs when a mouse button is let up.
207 */
208 public static final int MOUSE_RELEASED = 2 + MOUSE_FIRST; //Event.MOUSE_UP
209
210 /**
211 * The "mouse moved" event. This <code>MouseEvent</code>
212 * occurs when the mouse position changes.
213 */
214 public static final int MOUSE_MOVED = 3 + MOUSE_FIRST; //Event.MOUSE_MOVE
215
216 /**
217 * The "mouse entered" event. This <code>MouseEvent</code>
218 * occurs when the mouse cursor enters the unobscured part of component's
219 * geometry.
220 */
221 public static final int MOUSE_ENTERED = 4 + MOUSE_FIRST; //Event.MOUSE_ENTER
222
223 /**
224 * The "mouse exited" event. This <code>MouseEvent</code>
225 * occurs when the mouse cursor exits the unobscured part of component's
226 * geometry.
227 */
228 public static final int MOUSE_EXITED = 5 + MOUSE_FIRST; //Event.MOUSE_EXIT
229
230 /**
231 * The "mouse dragged" event. This <code>MouseEvent</code>
232 * occurs when the mouse position changes while a mouse button is pressed.
233 */
234 public static final int MOUSE_DRAGGED = 6 + MOUSE_FIRST; //Event.MOUSE_DRAG
235
236 /**
237 * The "mouse wheel" event. This is the only <code>MouseWheelEvent</code>.
238 * It occurs when a mouse equipped with a wheel has its wheel rotated.
239 * @since 1.4
240 */
241 public static final int MOUSE_WHEEL = 7 + MOUSE_FIRST;
242
243 /**
244 * Indicates no mouse buttons; used by {@link #getButton}.
245 * @since 1.4
246 */
247 public static final int NOBUTTON = 0;
248
249 /**
250 * Indicates mouse button #1; used by {@link #getButton}.
251 * @since 1.4
252 */
253 public static final int BUTTON1 = 1;
254
255 /**
256 * Indicates mouse button #2; used by {@link #getButton}.
257 * @since 1.4
258 */
259 public static final int BUTTON2 = 2;
260
261 /**
262 * Indicates mouse button #3; used by {@link #getButton}.
263 * @since 1.4
264 */
265 public static final int BUTTON3 = 3;
266
267 /**
268 * The mouse event's x coordinate.
269 * The x value is relative to the component that fired the event.
270 *
271 * @serial
272 * @see #getX()
273 */
274 int x;
275
276 /**
277 * The mouse event's y coordinate.
278 * The y value is relative to the component that fired the event.
279 *
280 * @serial
281 * @see #getY()
282 */
283 int y;
284
285 /**
286 * The mouse event's x absolute coordinate.
287 * In a virtual device multi-screen environment in which the
288 * desktop area could span multiple physical screen devices,
289 * this coordinate is relative to the virtual coordinate system.
290 * Otherwise, this coordinate is relative to the coordinate system
291 * associated with the Component's GraphicsConfiguration.
292 *
293 * @serial
294 */
295 private int xAbs;
296
297 /**
298 * The mouse event's y absolute coordinate.
299 * In a virtual device multi-screen environment in which the
300 * desktop area could span multiple physical screen devices,
301 * this coordinate is relative to the virtual coordinate system.
302 * Otherwise, this coordinate is relative to the coordinate system
303 * associated with the Component's GraphicsConfiguration.
304 *
305 * @serial
306 */
307 private int yAbs;
308
309 /**
310 * Indicates the number of quick consecutive clicks of
311 * a mouse button.
312 * clickCount will be valid for only three mouse events :<BR>
313 * <code>MOUSE_CLICKED</code>,
314 * <code>MOUSE_PRESSED</code> and
315 * <code>MOUSE_RELEASED</code>.
316 * For the above, the <code>clickCount</code> will be at least 1.
317 * For all other events the count will be 0.
318 *
319 * @serial
320 * @see #getClickCount().
321 */
322 int clickCount;
323
324 /**
325 * Indicates which, if any, of the mouse buttons has changed state.
326 *
327 * The only legal values are the following constants:
328 * <code>NOBUTTON</code>,
329 * <code>BUTTON1</code>,
330 * <code>BUTTON2</code> or
331 * <code>BUTTON3</code>.
332 * @serial
333 * @see #getButton().
334 */
335 int button;
336
337 /**
338 * A property used to indicate whether a Popup Menu
339 * should appear with a certain gestures.
340 * If <code>popupTrigger</code> = <code>false</code>,
341 * no popup menu should appear. If it is <code>true</code>
342 * then a popup menu should appear.
343 *
344 * @serial
345 * @see java.awt.PopupMenu
346 * @see #isPopupTrigger()
347 */
348 boolean popupTrigger = false;
349
350 /*
351 * JDK 1.1 serialVersionUID
352 */
353 private static final long serialVersionUID = -991214153494842848L;
354
355 static {
356 /* ensure that the necessary native libraries are loaded */
357 NativeLibLoader.loadLibraries();
358 if (!GraphicsEnvironment.isHeadless()) {
359 initIDs();
360 }
361 }
362
363 /**
364 * Initialize JNI field and method IDs for fields that may be
365 accessed from C.
366 */
367 private static native void initIDs();
368
369 /**
370 * Returns the absolute x, y position of the event.
371 * In a virtual device multi-screen environment in which the
372 * desktop area could span multiple physical screen devices,
373 * these coordinates are relative to the virtual coordinate system.
374 * Otherwise, these coordinates are relative to the coordinate system
375 * associated with the Component's GraphicsConfiguration.
376 *
377 * @return a <code>Point</code> object containing the absolute x
378 * and y coordinates.
379 *
380 * @see java.awt.GraphicsConfiguration
381 * @since 1.6
382 */
383 public Point getLocationOnScreen(){
384 return new Point(xAbs, yAbs);
385 }
386
387 /**
388 * Returns the absolute horizontal x position of the event.
389 * In a virtual device multi-screen environment in which the
390 * desktop area could span multiple physical screen devices,
391 * this coordinate is relative to the virtual coordinate system.
392 * Otherwise, this coordinate is relative to the coordinate system
393 * associated with the Component's GraphicsConfiguration.
394 *
395 * @return x an integer indicating absolute horizontal position.
396 *
397 * @see java.awt.GraphicsConfiguration
398 * @since 1.6
399 */
400 public int getXOnScreen() {
401 return xAbs;
402 }
403
404 /**
405 * Returns the absolute vertical y position of the event.
406 * In a virtual device multi-screen environment in which the
407 * desktop area could span multiple physical screen devices,
408 * this coordinate is relative to the virtual coordinate system.
409 * Otherwise, this coordinate is relative to the coordinate system
410 * associated with the Component's GraphicsConfiguration.
411 *
412 * @return y an integer indicating absolute vertical position.
413 *
414 * @see java.awt.GraphicsConfiguration
415 * @since 1.6
416 */
417 public int getYOnScreen() {
418 return yAbs;
419 }
420
421 /**
422 * Constructs a <code>MouseEvent</code> object with the
423 * specified source component,
424 * type, modifiers, coordinates, and click count.
425 * <p>
426 * Creating an invalid event (such
427 * as by using more than one of the old _MASKs, or modifier/button
428 * values which don't match) results in unspecified behavior.
429 * An invocation of the form
430 * <tt>MouseEvent(source, id, when, modifiers, x, y, clickCount, popupTrigger, button)</tt>
431 * behaves in exactly the same way as the invocation
432 * <tt> {@link #MouseEvent(Component, int, long, int, int, int,
433 * int, int, int, boolean, int) MouseEvent}(source, id, when, modifiers,
434 * x, y, xAbs, yAbs, clickCount, popupTrigger, button)</tt>
435 * where xAbs and yAbs defines as source's location on screen plus
436 * relative coordinates x and y.
437 * xAbs and yAbs are set to zero if the source is not showing.
438 * This method throws an
439 * <code>IllegalArgumentException</code> if <code>source</code>
440 * is <code>null</code>.
441 *
442 * @param source The <code>Component</code> that originated the event
443 * @param id An integer indicating the type of event.
444 * For information on allowable values, see
445 * the class description for {@link MouseEvent}
446 * @param when A long integer that gives the time the event occurred.
447 * Passing negative or zero value
448 * is not recommended
449 * @param modifiers The modifier keys down during event (e.g. shift, ctrl,
450 * alt, meta)
451 * Passing negative parameter
452 * is not recommended.
453 * Zero value means that no modifiers were passed.
454 * Use either an extended _DOWN_MASK or old _MASK modifiers,
455 * however do not mix models in the one event.
456 * The extended modifiers are preferred for using
457 * @param x The horizontal x coordinate for the mouse location.
458 * It is allowed to pass negative values
459 * @param y The vertical y coordinate for the mouse location.
460 * It is allowed to pass negative values
461 * @param clickCount The number of mouse clicks associated with event.
462 * Passing negative value
463 * is not recommended
464 * @param popupTrigger A boolean that equals {@code true} if this event
465 * is a trigger for a popup menu
466 * @param button An integer that indicates, which of the mouse buttons has
467 * changed its state
468 * @throws IllegalArgumentException if an invalid <code>button</code>
469 * value is passed in
470 * @throws IllegalArgumentException if <code>source</code> is null
471 * @see #getSource()
472 * @see #getID()
473 * @see #getWhen()
474 * @see #getModifiers()
475 * @see #getX()
476 * @see #getY()
477 * @see #getClickCount()
478 * @see #isPopupTrigger()
479 * @see #getButton()
480 * @since 1.4
481 */
482 public MouseEvent(Component source, int id, long when, int modifiers,
483 int x, int y, int clickCount, boolean popupTrigger,
484 int button)
485 {
486 this(source, id, when, modifiers, x, y, 0, 0, clickCount, popupTrigger, button);
487 Point eventLocationOnScreen = new Point(0, 0);
488 try {
489 eventLocationOnScreen = source.getLocationOnScreen();
490 this.xAbs = eventLocationOnScreen.x + x;
491 this.yAbs = eventLocationOnScreen.y + y;
492 } catch (IllegalComponentStateException e){
493 this.xAbs = 0;
494 this.yAbs = 0;
495 }
496 }
497
498 /**
499 * Constructs a <code>MouseEvent</code> object with the
500 * specified source component,
501 * type, modifiers, coordinates, and click count.
502 * An invocation of the form
503 * <tt>MouseEvent(source, id, when, modifiers, x, y, clickCount, popupTrigger)</tt>
504 * behaves in exactly the same way as the invocation
505 * <tt> {@link #MouseEvent(Component, int, long, int, int, int,
506 * int, int, int, boolean, int) MouseEvent}(source, id, when, modifiers,
507 * x, y, xAbs, yAbs, clickCount, popupTrigger, MouseEvent.NOBUTTON)</tt>
508 * where xAbs and yAbs defines as source's location on screen plus
509 * relative coordinates x and y.
510 * xAbs and yAbs are set to zero if the source is not showing.
511 * This method throws an <code>IllegalArgumentException</code>
512 * if <code>source</code> is <code>null</code>.
513 *
514 * @param source The <code>Component</code> that originated the event
515 * @param id An integer indicating the type of event.
516 * For information on allowable values, see
517 * the class description for {@link MouseEvent}
518 * @param when A long integer that gives the time the event occurred.
519 * Passing negative or zero value
520 * is not recommended
521 * @param modifiers The modifier keys down during event (e.g. shift, ctrl,
522 * alt, meta)
523 * Passing negative parameter
524 * is not recommended.
525 * Zero value means that no modifiers were passed.
526 * Use either an extended _DOWN_MASK or old _MASK modifiers,
527 * however do not mix models in the one event.
528 * The extended modifiers are preferred for using
529 * @param x The horizontal x coordinate for the mouse location.
530 * It is allowed to pass negative values
531 * @param y The vertical y coordinate for the mouse location.
532 * It is allowed to pass negative values
533 * @param clickCount The number of mouse clicks associated with event.
534 * Passing negative value
535 * is not recommended
536 * @param popupTrigger A boolean that equals {@code true} if this event
537 * is a trigger for a popup menu
538 * @throws IllegalArgumentException if <code>source</code> is null
539 * @see #getSource()
540 * @see #getID()
541 * @see #getWhen()
542 * @see #getModifiers()
543 * @see #getX()
544 * @see #getY()
545 * @see #getClickCount()
546 * @see #isPopupTrigger()
547 */
548 public MouseEvent(Component source, int id, long when, int modifiers,
549 int x, int y, int clickCount, boolean popupTrigger) {
550 this(source, id, when, modifiers, x, y, clickCount, popupTrigger, NOBUTTON);
551 }
552
553
554 /**
555 * Constructs a <code>MouseEvent</code> object with the
556 * specified source component,
557 * type, modifiers, coordinates, absolute coordinates, and click count.
558 * <p>
559 * Creating an invalid event (such
560 * as by using more than one of the old _MASKs, or modifier/button
561 * values which don't match) results in unspecified behavior.
562 * Even if inconsistent values for relative and absolute coordinates are
563 * passed to the constructor, the mouse event instance is still
564 * created and no exception is thrown.
565 * This method throws an
566 * <code>IllegalArgumentException</code> if <code>source</code>
567 * is <code>null</code>.
568 *
569 * @param source The <code>Component</code> that originated the event
570 * @param id An integer indicating the type of event.
571 * For information on allowable values, see
572 * the class description for {@link MouseEvent}
573 * @param when A long integer that gives the time the event occurred.
574 * Passing negative or zero value
575 * is not recommended
576 * @param modifiers The modifier keys down during event (e.g. shift, ctrl,
577 * alt, meta)
578 * Passing negative parameter
579 * is not recommended.
580 * Zero value means that no modifiers were passed.
581 * Use either an extended _DOWN_MASK or old _MASK modifiers,
582 * however do not mix models in the one event.
583 * The extended modifiers are preferred for using
584 * @param x The horizontal x coordinate for the mouse location.
585 * It is allowed to pass negative values
586 * @param y The vertical y coordinate for the mouse location.
587 * It is allowed to pass negative values
588 * @param xAbs The absolute horizontal x coordinate for the mouse location
589 * It is allowed to pass negative values
590 * @param yAbs The absolute vertical y coordinate for the mouse location
591 * It is allowed to pass negative values
592 * @param clickCount The number of mouse clicks associated with event.
593 * Passing negative value
594 * is not recommended
595 * @param popupTrigger A boolean that equals {@code true} if this event
596 * is a trigger for a popup menu
597 * @param button An integer that indicates, which of the mouse buttons has
598 * changed its state
599 * @throws IllegalArgumentException if an invalid <code>button</code>
600 * value is passed in
601 * @throws IllegalArgumentException if <code>source</code> is null
602 * @see #getSource()
603 * @see #getID()
604 * @see #getWhen()
605 * @see #getModifiers()
606 * @see #getX()
607 * @see #getY()
608 * @see #getXOnScreen()
609 * @see #getYOnScreen()
610 * @see #getClickCount()
611 * @see #isPopupTrigger()
612 * @see #getButton()
613 * @since 1.6
614 */
615 public MouseEvent(Component source, int id, long when, int modifiers,
616 int x, int y, int xAbs, int yAbs,
617 int clickCount, boolean popupTrigger, int button)
618 {
619 super(source, id, when, modifiers);
620 this.x = x;
621 this.y = y;
622 this.xAbs = xAbs;
623 this.yAbs = yAbs;
624 this.clickCount = clickCount;
625 this.popupTrigger = popupTrigger;
626 if (button < NOBUTTON || button >BUTTON3) {
627 throw new IllegalArgumentException("Invalid button value");
628 }
629 this.button = button;
630 if ((getModifiers() != 0) && (getModifiersEx() == 0)) {
631 setNewModifiers();
632 } else if ((getModifiers() == 0) &&
633 (getModifiersEx() != 0 || button != NOBUTTON))
634 {
635 setOldModifiers();
636 }
637 }
638
639 /**
640 * Returns the horizontal x position of the event relative to the
641 * source component.
642 *
643 * @return x an integer indicating horizontal position relative to
644 * the component
645 */
646 public int getX() {
647 return x;
648 }
649
650 /**
651 * Returns the vertical y position of the event relative to the
652 * source component.
653 *
654 * @return y an integer indicating vertical position relative to
655 * the component
656 */
657 public int getY() {
658 return y;
659 }
660
661 /**
662 * Returns the x,y position of the event relative to the source component.
663 *
664 * @return a <code>Point</code> object containing the x and y coordinates
665 * relative to the source component
666 *
667 */
668 public Point getPoint() {
669 int x;
670 int y;
671 synchronized (this) {
672 x = this.x;
673 y = this.y;
674 }
675 return new Point(x, y);
676 }
677
678 /**
679 * Translates the event's coordinates to a new position
680 * by adding specified <code>x</code> (horizontal) and <code>y</code>
681 * (vertical) offsets.
682 *
683 * @param x the horizontal x value to add to the current x
684 * coordinate position
685 * @param y the vertical y value to add to the current y
686 coordinate position
687 */
688 public synchronized void translatePoint(int x, int y) {
689 this.x += x;
690 this.y += y;
691 }
692
693 /**
694 * Returns the number of mouse clicks associated with this event.
695 *
696 * @return integer value for the number of clicks
697 */
698 public int getClickCount() {
699 return clickCount;
700 }
701
702 /**
703 * Returns which, if any, of the mouse buttons has changed state.
704 *
705 * @return one of the following constants:
706 * <code>NOBUTTON</code>,
707 * <code>BUTTON1</code>,
708 * <code>BUTTON2</code> or
709 * <code>BUTTON3</code>.
710 * @since 1.4
711 */
712 public int getButton() {
713 return button;
714 }
715
716 /**
717 * Returns whether or not this mouse event is the popup menu
718 * trigger event for the platform.
719 * <p><b>Note</b>: Popup menus are triggered differently
720 * on different systems. Therefore, <code>isPopupTrigger</code>
721 * should be checked in both <code>mousePressed</code>
722 * and <code>mouseReleased</code>
723 * for proper cross-platform functionality.
724 *
725 * @return boolean, true if this event is the popup menu trigger
726 * for this platform
727 */
728 public boolean isPopupTrigger() {
729 return popupTrigger;
730 }
731
732 /**
733 * Returns a <code>String</code> instance describing the modifier keys and
734 * mouse buttons that were down during the event, such as "Shift",
735 * or "Ctrl+Shift". These strings can be localized by changing
736 * the <code>awt.properties</code> file.
737 * <p>
738 * Note that the <code>InputEvent.ALT_MASK</code> and
739 * <code>InputEvent.BUTTON2_MASK</code> have equal values,
740 * so the "Alt" string is returned for both modifiers. Likewise,
741 * the <code>InputEvent.META_MASK</code> and
742 * <code>InputEvent.BUTTON3_MASK</code> have equal values,
743 * so the "Meta" string is returned for both modifiers.
744 * <p>
745 * Note that passing negative parameter is incorrect,
746 * and will cause the returning an unspecified string.
747 * Zero parameter means that no modifiers were passed and will
748 * cause the returning an empty string.
749 *
750 * @param modifiers A modifier mask describing the modifier keys and
751 * mouse buttons that were down during the event
752 * @return string string text description of the combination of modifier
753 * keys and mouse buttons that were down during the event
754 * @see InputEvent#getModifiersExText(int)
755 * @since 1.4
756 */
757 public static String getMouseModifiersText(int modifiers) {
758 StringBuilder buf = new StringBuilder();
759 if ((modifiers & InputEvent.ALT_MASK) != 0) {
760 buf.append(Toolkit.getProperty("AWT.alt", "Alt"));
761 buf.append("+");
762 }
763 if ((modifiers & InputEvent.META_MASK) != 0) {
764 buf.append(Toolkit.getProperty("AWT.meta", "Meta"));
765 buf.append("+");
766 }
767 if ((modifiers & InputEvent.CTRL_MASK) != 0) {
768 buf.append(Toolkit.getProperty("AWT.control", "Ctrl"));
769 buf.append("+");
770 }
771 if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
772 buf.append(Toolkit.getProperty("AWT.shift", "Shift"));
773 buf.append("+");
774 }
775 if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
776 buf.append(Toolkit.getProperty("AWT.altGraph", "Alt Graph"));
777 buf.append("+");
778 }
779 if ((modifiers & InputEvent.BUTTON1_MASK) != 0) {
780 buf.append(Toolkit.getProperty("AWT.button1", "Button1"));
781 buf.append("+");
782 }
783 if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
784 buf.append(Toolkit.getProperty("AWT.button2", "Button2"));
785 buf.append("+");
786 }
787 if ((modifiers & InputEvent.BUTTON3_MASK) != 0) {
788 buf.append(Toolkit.getProperty("AWT.button3", "Button3"));
789 buf.append("+");
790 }
791 if (buf.length() > 0) {
792 buf.setLength(buf.length()-1); // remove trailing '+'
793 }
794 return buf.toString();
795 }
796
797 /**
798 * Returns a parameter string identifying this event.
799 * This method is useful for event-logging and for debugging.
800 *
801 * @return a string identifying the event and its attributes
802 */
803 public String paramString() {
804 StringBuilder str = new StringBuilder(80);
805
806 switch(id) {
807 case MOUSE_PRESSED:
808 str.append("MOUSE_PRESSED");
809 break;
810 case MOUSE_RELEASED:
811 str.append("MOUSE_RELEASED");
812 break;
813 case MOUSE_CLICKED:
814 str.append("MOUSE_CLICKED");
815 break;
816 case MOUSE_ENTERED:
817 str.append("MOUSE_ENTERED");
818 break;
819 case MOUSE_EXITED:
820 str.append("MOUSE_EXITED");
821 break;
822 case MOUSE_MOVED:
823 str.append("MOUSE_MOVED");
824 break;
825 case MOUSE_DRAGGED:
826 str.append("MOUSE_DRAGGED");
827 break;
828 case MOUSE_WHEEL:
829 str.append("MOUSE_WHEEL");
830 break;
831 default:
832 str.append("unknown type");
833 }
834
835 // (x,y) coordinates
836 str.append(",(").append(x).append(",").append(y).append(")");
837 str.append(",absolute(").append(xAbs).append(",").append(yAbs).append(")");
838
839 str.append(",button=").append(getButton());
840
841 if (getModifiers() != 0) {
842 str.append(",modifiers=").append(getMouseModifiersText(modifiers));
843 }
844
845 if (getModifiersEx() != 0) {
846 str.append(",extModifiers=").append(getModifiersExText(modifiers));
847 }
848
849 str.append(",clickCount=").append(clickCount);
850
851 return str.toString();
852 }
853
854 /**
855 * Sets new modifiers by the old ones.
856 * Also sets button.
857 */
858 private void setNewModifiers() {
859 if ((modifiers & BUTTON1_MASK) != 0) {
860 modifiers |= BUTTON1_DOWN_MASK;
861 }
862 if ((modifiers & BUTTON2_MASK) != 0) {
863 modifiers |= BUTTON2_DOWN_MASK;
864 }
865 if ((modifiers & BUTTON3_MASK) != 0) {
866 modifiers |= BUTTON3_DOWN_MASK;
867 }
868 if (id == MOUSE_PRESSED
869 || id == MOUSE_RELEASED
870 || id == MOUSE_CLICKED)
871 {
872 if ((modifiers & BUTTON1_MASK) != 0) {
873 button = BUTTON1;
874 modifiers &= ~BUTTON2_MASK & ~BUTTON3_MASK;
875 if (id != MOUSE_PRESSED) {
876 modifiers &= ~BUTTON1_DOWN_MASK;
877 }
878 } else if ((modifiers & BUTTON2_MASK) != 0) {
879 button = BUTTON2;
880 modifiers &= ~BUTTON1_MASK & ~BUTTON3_MASK;
881 if (id != MOUSE_PRESSED) {
882 modifiers &= ~BUTTON2_DOWN_MASK;
883 }
884 } else if ((modifiers & BUTTON3_MASK) != 0) {
885 button = BUTTON3;
886 modifiers &= ~BUTTON1_MASK & ~BUTTON2_MASK;
887 if (id != MOUSE_PRESSED) {
888 modifiers &= ~BUTTON3_DOWN_MASK;
889 }
890 }
891 }
892 if ((modifiers & InputEvent.ALT_MASK) != 0) {
893 modifiers |= InputEvent.ALT_DOWN_MASK;
894 }
895 if ((modifiers & InputEvent.META_MASK) != 0) {
896 modifiers |= InputEvent.META_DOWN_MASK;
897 }
898 if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
899 modifiers |= InputEvent.SHIFT_DOWN_MASK;
900 }
901 if ((modifiers & InputEvent.CTRL_MASK) != 0) {
902 modifiers |= InputEvent.CTRL_DOWN_MASK;
903 }
904 if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
905 modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
906 }
907 }
908
909 /**
910 * Sets old modifiers by the new ones.
911 */
912 private void setOldModifiers() {
913 if (id == MOUSE_PRESSED
914 || id == MOUSE_RELEASED
915 || id == MOUSE_CLICKED)
916 {
917 switch(button) {
918 case BUTTON1:
919 modifiers |= BUTTON1_MASK;
920 break;
921 case BUTTON2:
922 modifiers |= BUTTON2_MASK;
923 break;
924 case BUTTON3:
925 modifiers |= BUTTON3_MASK;
926 break;
927 }
928 } else {
929 if ((modifiers & BUTTON1_DOWN_MASK) != 0) {
930 modifiers |= BUTTON1_MASK;
931 }
932 if ((modifiers & BUTTON2_DOWN_MASK) != 0) {
933 modifiers |= BUTTON2_MASK;
934 }
935 if ((modifiers & BUTTON3_DOWN_MASK) != 0) {
936 modifiers |= BUTTON3_MASK;
937 }
938 }
939 if ((modifiers & ALT_DOWN_MASK) != 0) {
940 modifiers |= ALT_MASK;
941 }
942 if ((modifiers & META_DOWN_MASK) != 0) {
943 modifiers |= META_MASK;
944 }
945 if ((modifiers & SHIFT_DOWN_MASK) != 0) {
946 modifiers |= SHIFT_MASK;
947 }
948 if ((modifiers & CTRL_DOWN_MASK) != 0) {
949 modifiers |= CTRL_MASK;
950 }
951 if ((modifiers & ALT_GRAPH_DOWN_MASK) != 0) {
952 modifiers |= ALT_GRAPH_MASK;
953 }
954 }
955
956 /**
957 * Sets new modifiers by the old ones.
958 * @serial
959 */
960 private void readObject(ObjectInputStream s)
961 throws IOException, ClassNotFoundException {
962 s.defaultReadObject();
963 if (getModifiers() != 0 && getModifiersEx() == 0) {
964 setNewModifiers();
965 }
966 }
967 }