1 /* MouseEvent.java -- a mouse event 2 Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package java.awt.event; 40 41 import gnu.java.awt.EventModifier; 42 43 import java.awt.Component; 44 import java.awt.Point; 45 import java.awt.PopupMenu; 46 import java.io.IOException; 47 import java.io.ObjectInputStream; 48 49 /** 50 * This event is generated for a mouse event. There are three main categories 51 * of mouse events: Regular events include pressing, releasing, and clicking 52 * buttons, as well as moving over the boundary of the unobscured portion of 53 * a component. Motion events include movement and dragging. Wheel events are 54 * covered separately by the subclass MouseWheelEvent. 55 * 56 * <p>A mouse event is tied to the unobstructed visible component that the 57 * mouse cursor was over at the time of the action. The button that was 58 * most recently pressed is the only one that shows up in 59 * <code>getModifiers</code>, and is returned by <code>getButton</code>, 60 * while all buttons that are down show up in <code>getModifiersEx</code>. 61 * 62 * <p>Drag events may be cut short if native drag-and-drop operations steal 63 * the event. Likewise, if a mouse drag exceeds the bounds of a window or 64 * virtual device, some platforms may clip the path to fit in the bounds of 65 * the component. 66 * 67 * @author Aaron M. Renn (arenn@urbanophile.com) 68 * @author Eric Blake (ebb9@email.byu.edu) 69 * @see MouseAdapter 70 * @see MouseListener 71 * @see MouseMotionAdapter 72 * @see MouseMotionListener 73 * @see MouseWheelListener 74 * @since 1.1 75 * @status updated to 1.4 76 */ 77 public class MouseEvent extends InputEvent 78 { 79 /** 80 * Compatible with JDK 1.1+. 81 */ 82 private static final long serialVersionUID = -991214153494842848L; 83 84 /** This is the first id in the range of event ids used by this class. */ 85 public static final int MOUSE_FIRST = 500; 86 87 /** This is the last id in the range of event ids used by this class. */ 88 public static final int MOUSE_LAST = 507; 89 90 /** This event id indicates that the mouse was clicked. */ 91 public static final int MOUSE_CLICKED = 500; 92 93 /** This event id indicates that the mouse was pressed. */ 94 public static final int MOUSE_PRESSED = 501; 95 96 /** This event id indicates that the mouse was released. */ 97 public static final int MOUSE_RELEASED = 502; 98 99 /** This event id indicates that the mouse was moved. */ 100 public static final int MOUSE_MOVED = 503; 101 102 /** This event id indicates that the mouse entered a component. */ 103 public static final int MOUSE_ENTERED = 504; 104 105 /** This event id indicates that the mouse exited a component. */ 106 public static final int MOUSE_EXITED = 505; 107 108 /** 109 * This indicates that no button changed state. 110 * 111 * @see #getButton() 112 * @since 1.4 113 */ 114 public static final int NOBUTTON = 0; 115 116 /** 117 * This indicates that button 1 changed state. 118 * 119 * @see #getButton() 120 * @since 1.4 121 */ 122 public static final int BUTTON1 = 1; 123 124 /** 125 * This indicates that button 2 changed state. 126 * 127 * @see #getButton() 128 * @since 1.4 129 */ 130 public static final int BUTTON2 = 2; 131 132 /** 133 * This indicates that button 3 changed state. 134 * 135 * @see #getButton() 136 * @since 1.4 137 */ 138 public static final int BUTTON3 = 3; 139 140 /** This event id indicates that the mouse was dragged over a component. */ 141 public static final int MOUSE_DRAGGED = 506; 142 143 /** 144 * This event id indicates that the mouse wheel was rotated. 145 * 146 * @since 1.4 147 */ 148 public static final int MOUSE_WHEEL = 507; 149 150 /** 151 * The X coordinate of the mouse cursor at the time of the event. 152 * 153 * @see #getX() 154 * @serial the x coordinate 155 */ 156 private int x; 157 158 /** 159 * The Y coordinate of the mouse cursor at the time of the event. 160 * 161 * @see #getY() 162 * @serial the y coordinate 163 */ 164 private int y; 165 166 /** 167 * The number of clicks that took place. For MOUSE_CLICKED, MOUSE_PRESSED, 168 * and MOUSE_RELEASED, this will be at least 1; otherwise it is 0. 169 * 170 * see #getClickCount() 171 * @serial the number of clicks 172 */ 173 private final int clickCount; 174 175 /** 176 * Indicates which mouse button changed state. Can only be one of 177 * {@link #NOBUTTON}, {@link #BUTTON1}, {@link #BUTTON2}, or 178 * {@link #BUTTON3}. 179 * 180 * @see #getButton() 181 * @since 1.4 182 */ 183 private int button; 184 185 /** 186 * Whether or not this event should trigger a popup menu. 187 * 188 * @see PopupMenu 189 * @see #isPopupTrigger() 190 * @serial true if this is a popup trigger 191 */ 192 private final boolean popupTrigger; 193 194 /** 195 * Initializes a new instance of <code>MouseEvent</code> with the specified 196 * information. Note that an invalid id leads to unspecified results. 197 * 198 * @param source the source of the event 199 * @param id the event id 200 * @param when the timestamp of when the event occurred 201 * @param modifiers the modifier keys during the event, in old or new style 202 * @param x the X coordinate of the mouse point 203 * @param y the Y coordinate of the mouse point 204 * @param clickCount the number of mouse clicks for this event 205 * @param popupTrigger true if this event triggers a popup menu 206 * @param button the most recent mouse button to change state 207 * @throws IllegalArgumentException if source is null or button is invalid 208 * @since 1.4 209 */ MouseEvent(Component source, int id, long when, int modifiers, int x, int y, int clickCount, boolean popupTrigger, int button)210 public MouseEvent(Component source, int id, long when, int modifiers, 211 int x, int y, int clickCount, boolean popupTrigger, 212 int button) 213 { 214 super(source, id, when, modifiers); 215 this.x = x; 216 this.y = y; 217 this.clickCount = clickCount; 218 this.popupTrigger = popupTrigger; 219 this.button = button; 220 if (button < NOBUTTON || button > BUTTON3) 221 throw new IllegalArgumentException(); 222 if ((modifiers & EventModifier.OLD_MASK) != 0) 223 { 224 if ((modifiers & BUTTON1_MASK) != 0) 225 this.button = BUTTON1; 226 else if ((modifiers & BUTTON2_MASK) != 0) 227 this.button = BUTTON2; 228 else if ((modifiers & BUTTON3_MASK) != 0) 229 this.button = BUTTON3; 230 } 231 // clear the mouse button modifier masks if this is a button 232 // release event. 233 if (id == MOUSE_RELEASED) 234 this.modifiersEx &= ~(BUTTON1_DOWN_MASK 235 | BUTTON2_DOWN_MASK 236 | BUTTON3_DOWN_MASK); 237 } 238 239 /** 240 * Initializes a new instance of <code>MouseEvent</code> with the specified 241 * information. Note that an invalid id leads to unspecified results. 242 * 243 * @param source the source of the event 244 * @param id the event id 245 * @param when the timestamp of when the event occurred 246 * @param modifiers the modifier keys during the event, in old or new style 247 * @param x the X coordinate of the mouse point 248 * @param y the Y coordinate of the mouse point 249 * @param clickCount the number of mouse clicks for this event 250 * @param popupTrigger true if this event triggers a popup menu 251 * @throws IllegalArgumentException if source is null 252 */ MouseEvent(Component source, int id, long when, int modifiers, int x, int y, int clickCount, boolean popupTrigger)253 public MouseEvent(Component source, int id, long when, int modifiers, 254 int x, int y, int clickCount, boolean popupTrigger) 255 { 256 this(source, id, when, modifiers, x, y, clickCount, popupTrigger, 257 NOBUTTON); 258 } 259 260 /** 261 * This method returns the X coordinate of the mouse position. This is 262 * relative to the source component. 263 * 264 * @return the x coordinate 265 */ getX()266 public int getX() 267 { 268 return x; 269 } 270 271 /** 272 * This method returns the Y coordinate of the mouse position. This is 273 * relative to the source component. 274 * 275 * @return the y coordinate 276 */ getY()277 public int getY() 278 { 279 return y; 280 } 281 282 /** 283 * This method returns a <code>Point</code> for the x,y position of 284 * the mouse pointer. This is relative to the source component. 285 * 286 * @return a <code>Point</code> for the event position 287 */ getPoint()288 public Point getPoint() 289 { 290 return new Point(x, y); 291 } 292 293 /** 294 * Translates the event coordinates by the specified x and y offsets. 295 * 296 * @param dx the value to add to the X coordinate of this event 297 * @param dy the value to add to the Y coordiante of this event 298 */ translatePoint(int dx, int dy)299 public void translatePoint(int dx, int dy) 300 { 301 x += dx; 302 y += dy; 303 } 304 305 /** 306 * This method returns the number of mouse clicks associated with this 307 * event. 308 * 309 * @return the number of mouse clicks for this event 310 */ getClickCount()311 public int getClickCount() 312 { 313 return clickCount; 314 } 315 316 /** 317 * Returns which button, if any, was the most recent to change state. This 318 * will be one of {@link #NOBUTTON}, {@link #BUTTON1}, {@link #BUTTON2}, or 319 * {@link #BUTTON3}. 320 * 321 * @return the button that changed state 322 * @since 1.4 323 */ getButton()324 public int getButton() 325 { 326 return button; 327 } 328 329 /** 330 * This method tests whether or not the event is a popup menu trigger. This 331 * should be checked in both MousePressed and MouseReleased to be 332 * cross-platform compatible, as different systems have different popup 333 * triggers. 334 * 335 * @return true if the event is a popup menu trigger 336 */ isPopupTrigger()337 public boolean isPopupTrigger() 338 { 339 return popupTrigger; 340 } 341 342 /** 343 * Returns a string describing the modifiers, such as "Shift" or 344 * "Ctrl+Button1". 345 * 346 * XXX Sun claims this can be localized via the awt.properties file - how 347 * do we implement that? 348 * 349 * @param modifiers the old-style modifiers to convert to text 350 * @return a string representation of the modifiers in this bitmask 351 */ getMouseModifiersText(int modifiers)352 public static String getMouseModifiersText(int modifiers) 353 { 354 modifiers &= EventModifier.OLD_MASK; 355 if ((modifiers & BUTTON2_MASK) != 0) 356 modifiers |= BUTTON2_DOWN_MASK; 357 if ((modifiers & BUTTON3_MASK) != 0) 358 modifiers |= BUTTON3_DOWN_MASK; 359 return getModifiersExText(EventModifier.extend(modifiers)); 360 } 361 362 /** 363 * Returns a string identifying this event. This is formatted as the field 364 * name of the id type, followed by the (x,y) point, the most recent button 365 * changed, modifiers (if any), extModifiers (if any), and clickCount. 366 * 367 * @return a string identifying this event 368 */ paramString()369 public String paramString() 370 { 371 StringBuffer s = new StringBuffer(); 372 switch (id) 373 { 374 case MOUSE_CLICKED: 375 s.append("MOUSE_CLICKED,("); 376 break; 377 case MOUSE_PRESSED: 378 s.append("MOUSE_PRESSED,("); 379 break; 380 case MOUSE_RELEASED: 381 s.append("MOUSE_RELEASED,("); 382 break; 383 case MOUSE_MOVED: 384 s.append("MOUSE_MOVED,("); 385 break; 386 case MOUSE_ENTERED: 387 s.append("MOUSE_ENTERED,("); 388 break; 389 case MOUSE_EXITED: 390 s.append("MOUSE_EXITED,("); 391 break; 392 case MOUSE_DRAGGED: 393 s.append("MOUSE_DRAGGED,("); 394 break; 395 case MOUSE_WHEEL: 396 s.append("MOUSE_WHEEL,("); 397 break; 398 default: 399 s.append("unknown type,("); 400 } 401 s.append(x).append(',').append(y).append("),button=").append(button); 402 // FIXME: need a mauve test for this method 403 if (modifiersEx != 0) 404 s.append(",extModifiers=").append(getModifiersExText(modifiersEx)); 405 return s.append(",clickCount=").append(clickCount).toString(); 406 } 407 408 /** 409 * Reads in the object from a serial stream. 410 * 411 * @param s the stream to read from 412 * @throws IOException if deserialization fails 413 * @throws ClassNotFoundException if deserialization fails 414 * @serialData default, except that the modifiers are converted to new style 415 */ readObject(ObjectInputStream s)416 private void readObject(ObjectInputStream s) 417 throws IOException, ClassNotFoundException 418 { 419 s.defaultReadObject(); 420 if ((modifiers & EventModifier.OLD_MASK) != 0) 421 { 422 if ((modifiers & BUTTON1_MASK) != 0) 423 button = BUTTON1; 424 else if ((modifiers & BUTTON2_MASK) != 0) 425 button = BUTTON2; 426 else if ((modifiers & BUTTON3_MASK) != 0) 427 button = BUTTON3; 428 modifiersEx = EventModifier.extend(modifiers) & EventModifier.NEW_MASK; 429 } 430 } 431 } // class MouseEvent 432