1 /*
   2  * Copyright (c) 2000, 2008, Oracle and/or its affiliates. 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt.event;
  27 
  28 import java.awt.Component;
  29 
  30 import javax.tools.annotation.GenerateNativeHeader;
  31 
  32 /**
  33  * An event which indicates that the mouse wheel was rotated in a component.
  34  * <P>
  35  * A wheel mouse is a mouse which has a wheel in place of the middle button.
  36  * This wheel can be rotated towards or away from the user.  Mouse wheels are
  37  * most often used for scrolling, though other uses are possible.
  38  * <P>
  39  * A MouseWheelEvent object is passed to every <code>MouseWheelListener</code>
  40  * object which registered to receive the "interesting" mouse events using the
  41  * component's <code>addMouseWheelListener</code> method.  Each such listener
  42  * object gets a <code>MouseEvent</code> containing the mouse event.
  43  * <P>
  44  * Due to the mouse wheel's special relationship to scrolling Components,
  45  * MouseWheelEvents are delivered somewhat differently than other MouseEvents.
  46  * This is because while other MouseEvents usually affect a change on
  47  * the Component directly under the mouse
  48  * cursor (for instance, when clicking a button), MouseWheelEvents often have
  49  * an effect away from the mouse cursor (moving the wheel while
  50  * over a Component inside a ScrollPane should scroll one of the
  51  * Scrollbars on the ScrollPane).
  52  * <P>
  53  * MouseWheelEvents start delivery from the Component underneath the
  54  * mouse cursor.  If MouseWheelEvents are not enabled on the
  55  * Component, the event is delivered to the first ancestor
  56  * Container with MouseWheelEvents enabled.  This will usually be
  57  * a ScrollPane with wheel scrolling enabled.  The source
  58  * Component and x,y coordinates will be relative to the event's
  59  * final destination (the ScrollPane).  This allows a complex
  60  * GUI to be installed without modification into a ScrollPane, and
  61  * for all MouseWheelEvents to be delivered to the ScrollPane for
  62  * scrolling.
  63  * <P>
  64  * Some AWT Components are implemented using native widgets which
  65  * display their own scrollbars and handle their own scrolling.
  66  * The particular Components for which this is true will vary from
  67  * platform to platform.  When the mouse wheel is
  68  * moved over one of these Components, the event is delivered straight to
  69  * the native widget, and not propagated to ancestors.
  70  * <P>
  71  * Platforms offer customization of the amount of scrolling that
  72  * should take place when the mouse wheel is moved.  The two most
  73  * common settings are to scroll a certain number of "units"
  74  * (commonly lines of text in a text-based component) or an entire "block"
  75  * (similar to page-up/page-down).  The MouseWheelEvent offers
  76  * methods for conforming to the underlying platform settings.  These
  77  * platform settings can be changed at any time by the user.  MouseWheelEvents
  78  * reflect the most recent settings.
  79  * <P>
  80  * The <code>MouseWheelEvent</code> class includes methods for
  81  * getting the number of "clicks" by which the mouse wheel is rotated.
  82  * The {@link #getWheelRotation} method returns the integer number
  83  * of "clicks" corresponding to the number of notches by which the wheel was
  84  * rotated. In addition to this method, the <code>MouseWheelEvent</code>
  85  * class provides the {@link #getPreciseWheelRotation} method which returns
  86  * a double number of "clicks" in case a partial rotation occurred.
  87  * The {@link #getPreciseWheelRotation} method is useful if a mouse supports
  88  * a high-resolution wheel, such as a freely rotating wheel with no
  89  * notches. Applications can benefit by using this method to process
  90  * mouse wheel events more precisely, and thus, making visual perception
  91  * smoother.
  92  *
  93  * @author Brent Christian
  94  * @see MouseWheelListener
  95  * @see java.awt.ScrollPane
  96  * @see java.awt.ScrollPane#setWheelScrollingEnabled(boolean)
  97  * @see javax.swing.JScrollPane
  98  * @see javax.swing.JScrollPane#setWheelScrollingEnabled(boolean)
  99  * @since 1.4
 100  */
 101 
 102 /* No native methods here, but the constants are needed in the supporting JNI code */
 103 @GenerateNativeHeader
 104 public class MouseWheelEvent extends MouseEvent {
 105 
 106     /**
 107      * Constant representing scrolling by "units" (like scrolling with the
 108      * arrow keys)
 109      *
 110      * @see #getScrollType
 111      */
 112     public static final int WHEEL_UNIT_SCROLL = 0;
 113 
 114     /**
 115      * Constant representing scrolling by a "block" (like scrolling
 116      * with page-up, page-down keys)
 117      *
 118      * @see #getScrollType
 119      */
 120     public static final int WHEEL_BLOCK_SCROLL = 1;
 121 
 122     /**
 123      * Indicates what sort of scrolling should take place in response to this
 124      * event, based on platform settings.  Legal values are:
 125      * <ul>
 126      * <li> WHEEL_UNIT_SCROLL
 127      * <li> WHEEL_BLOCK_SCROLL
 128      * </ul>
 129      *
 130      * @see #getScrollType
 131      */
 132     int scrollType;
 133 
 134     /**
 135      * Only valid for scrollType WHEEL_UNIT_SCROLL.
 136      * Indicates number of units that should be scrolled per
 137      * click of mouse wheel rotation, based on platform settings.
 138      *
 139      * @see #getScrollAmount
 140      * @see #getScrollType
 141      */
 142     int scrollAmount;
 143 
 144     /**
 145      * Indicates how far the mouse wheel was rotated.
 146      *
 147      * @see #getWheelRotation
 148      */
 149     int wheelRotation;
 150 
 151     /**
 152      * Indicates how far the mouse wheel was rotated.
 153      *
 154      * @see #getPreciseWheelRotation
 155      */
 156     double preciseWheelRotation;
 157 
 158     /*
 159      * serialVersionUID
 160      */
 161 
 162     private static final long serialVersionUID = 6459879390515399677L;
 163 
 164     /**
 165      * Constructs a <code>MouseWheelEvent</code> object with the
 166      * specified source component, type, modifiers, coordinates,
 167      * scroll type, scroll amount, and wheel rotation.
 168      * <p>Absolute coordinates xAbs and yAbs are set to source's location on screen plus
 169      * relative coordinates x and y. xAbs and yAbs are set to zero if the source is not showing.
 170      * <p>Note that passing in an invalid <code>id</code> results in
 171      * unspecified behavior. This method throws an
 172      * <code>IllegalArgumentException</code> if <code>source</code>
 173      * is <code>null</code>.
 174      *
 175      * @param source         the <code>Component</code> that originated
 176      *                       the event
 177      * @param id             the integer that identifies the event
 178      * @param when           a long that gives the time the event occurred
 179      * @param modifiers      the modifier keys down during event
 180      *                       (shift, ctrl, alt, meta)
 181      * @param x              the horizontal x coordinate for the mouse location
 182      * @param y              the vertical y coordinate for the mouse location
 183      * @param clickCount     the number of mouse clicks associated with event
 184      * @param popupTrigger   a boolean, true if this event is a trigger for a
 185      *                       popup-menu
 186      * @param scrollType     the type of scrolling which should take place in
 187      *                       response to this event;  valid values are
 188      *                       <code>WHEEL_UNIT_SCROLL</code> and
 189      *                       <code>WHEEL_BLOCK_SCROLL</code>
 190      * @param  scrollAmount  for scrollType <code>WHEEL_UNIT_SCROLL</code>,
 191      *                       the number of units to be scrolled
 192      * @param wheelRotation  the integer number of "clicks" by which the mouse
 193      *                       wheel was rotated
 194      *
 195      * @throws IllegalArgumentException if <code>source</code> is null
 196      * @see MouseEvent#MouseEvent(java.awt.Component, int, long, int, int, int, int, boolean)
 197      * @see MouseEvent#MouseEvent(java.awt.Component, int, long, int, int, int, int, int, int, boolean, int)
 198      */
 199     public MouseWheelEvent (Component source, int id, long when, int modifiers,
 200                       int x, int y, int clickCount, boolean popupTrigger,
 201                       int scrollType, int scrollAmount, int wheelRotation) {
 202 
 203         this(source, id, when, modifiers, x, y, 0, 0, clickCount,
 204              popupTrigger, scrollType, scrollAmount, wheelRotation);
 205     }
 206 
 207     /**
 208      * Constructs a <code>MouseWheelEvent</code> object with the
 209      * specified source component, type, modifiers, coordinates,
 210      * absolute coordinates, scroll type, scroll amount, and wheel rotation.
 211      * <p>Note that passing in an invalid <code>id</code> results in
 212      * unspecified behavior. This method throws an
 213      * <code>IllegalArgumentException</code> if <code>source</code>
 214      * is <code>null</code>.<p>
 215      * Even if inconsistent values for relative and absolute coordinates are
 216      * passed to the constructor, the MouseWheelEvent instance is still
 217      * created and no exception is thrown.
 218      *
 219      * @param source         the <code>Component</code> that originated
 220      *                       the event
 221      * @param id             the integer that identifies the event
 222      * @param when           a long that gives the time the event occurred
 223      * @param modifiers      the modifier keys down during event
 224      *                       (shift, ctrl, alt, meta)
 225      * @param x              the horizontal x coordinate for the mouse location
 226      * @param y              the vertical y coordinate for the mouse location
 227      * @param xAbs           the absolute horizontal x coordinate for the mouse location
 228      * @param yAbs           the absolute vertical y coordinate for the mouse location
 229      * @param clickCount     the number of mouse clicks associated with event
 230      * @param popupTrigger   a boolean, true if this event is a trigger for a
 231      *                       popup-menu
 232      * @param scrollType     the type of scrolling which should take place in
 233      *                       response to this event;  valid values are
 234      *                       <code>WHEEL_UNIT_SCROLL</code> and
 235      *                       <code>WHEEL_BLOCK_SCROLL</code>
 236      * @param  scrollAmount  for scrollType <code>WHEEL_UNIT_SCROLL</code>,
 237      *                       the number of units to be scrolled
 238      * @param wheelRotation  the integer number of "clicks" by which the mouse
 239      *                       wheel was rotated
 240      *
 241      * @throws IllegalArgumentException if <code>source</code> is null
 242      * @see MouseEvent#MouseEvent(java.awt.Component, int, long, int, int, int, int, boolean)
 243      * @see MouseEvent#MouseEvent(java.awt.Component, int, long, int, int, int, int, int, int, boolean, int)
 244      * @since 1.6
 245      */
 246     public MouseWheelEvent (Component source, int id, long when, int modifiers,
 247                             int x, int y, int xAbs, int yAbs, int clickCount, boolean popupTrigger,
 248                             int scrollType, int scrollAmount, int wheelRotation) {
 249 
 250         this(source, id, when, modifiers, x, y, xAbs, yAbs, clickCount, popupTrigger,
 251              scrollType, scrollAmount, wheelRotation, wheelRotation);
 252 
 253     }
 254 
 255 
 256     /**
 257      * Constructs a <code>MouseWheelEvent</code> object with the specified
 258      * source component, type, modifiers, coordinates, absolute coordinates,
 259      * scroll type, scroll amount, and wheel rotation.
 260      * <p>Note that passing in an invalid <code>id</code> parameter results
 261      * in unspecified behavior. This method throws an
 262      * <code>IllegalArgumentException</code> if <code>source</code> equals
 263      * <code>null</code>.
 264      * <p>Even if inconsistent values for relative and absolute coordinates
 265      * are passed to the constructor, a <code>MouseWheelEvent</code> instance
 266      * is still created and no exception is thrown.
 267      *
 268      * @param source         the <code>Component</code> that originated the event
 269      * @param id             the integer value that identifies the event
 270      * @param when           a long value that gives the time when the event occurred
 271      * @param modifiers      the modifier keys down during event
 272      *                       (shift, ctrl, alt, meta)
 273      * @param x              the horizontal <code>x</code> coordinate for the
 274      *                       mouse location
 275      * @param y              the vertical <code>y</code> coordinate for the
 276      *                       mouse location
 277      * @param xAbs           the absolute horizontal <code>x</code> coordinate for
 278      *                       the mouse location
 279      * @param yAbs           the absolute vertical <code>y</code> coordinate for
 280      *                       the mouse location
 281      * @param clickCount     the number of mouse clicks associated with the event
 282      * @param popupTrigger   a boolean value, <code>true</code> if this event is a trigger
 283      *                       for a popup-menu
 284      * @param scrollType     the type of scrolling which should take place in
 285      *                       response to this event;  valid values are
 286      *                       <code>WHEEL_UNIT_SCROLL</code> and
 287      *                       <code>WHEEL_BLOCK_SCROLL</code>
 288      * @param  scrollAmount  for scrollType <code>WHEEL_UNIT_SCROLL</code>,
 289      *                       the number of units to be scrolled
 290      * @param wheelRotation  the integer number of "clicks" by which the mouse wheel
 291      *                       was rotated
 292      * @param preciseWheelRotation the double number of "clicks" by which the mouse wheel
 293      *                       was rotated
 294      *
 295      * @throws IllegalArgumentException if <code>source</code> is null
 296      * @see MouseEvent#MouseEvent(java.awt.Component, int, long, int, int, int, int, boolean)
 297      * @see MouseEvent#MouseEvent(java.awt.Component, int, long, int, int, int, int, int, int, boolean, int)
 298      * @since 1.7
 299      */
 300     public MouseWheelEvent (Component source, int id, long when, int modifiers,
 301                             int x, int y, int xAbs, int yAbs, int clickCount, boolean popupTrigger,
 302                             int scrollType, int scrollAmount, int wheelRotation, double preciseWheelRotation) {
 303 
 304         super(source, id, when, modifiers, x, y, xAbs, yAbs, clickCount,
 305               popupTrigger, MouseEvent.NOBUTTON);
 306 
 307         this.scrollType = scrollType;
 308         this.scrollAmount = scrollAmount;
 309         this.wheelRotation = wheelRotation;
 310         this.preciseWheelRotation = preciseWheelRotation;
 311 
 312     }
 313 
 314     /**
 315      * Returns the type of scrolling that should take place in response to this
 316      * event.  This is determined by the native platform.  Legal values are:
 317      * <ul>
 318      * <li> MouseWheelEvent.WHEEL_UNIT_SCROLL
 319      * <li> MouseWheelEvent.WHEEL_BLOCK_SCROLL
 320      * </ul>
 321      *
 322      * @return either MouseWheelEvent.WHEEL_UNIT_SCROLL or
 323      *  MouseWheelEvent.WHEEL_BLOCK_SCROLL, depending on the configuration of
 324      *  the native platform.
 325      * @see java.awt.Adjustable#getUnitIncrement
 326      * @see java.awt.Adjustable#getBlockIncrement
 327      * @see javax.swing.Scrollable#getScrollableUnitIncrement
 328      * @see javax.swing.Scrollable#getScrollableBlockIncrement
 329      */
 330     public int getScrollType() {
 331         return scrollType;
 332     }
 333 
 334     /**
 335      * Returns the number of units that should be scrolled per
 336      * click of mouse wheel rotation.
 337      * Only valid if <code>getScrollType</code> returns
 338      * <code>MouseWheelEvent.WHEEL_UNIT_SCROLL</code>
 339      *
 340      * @return number of units to scroll, or an undefined value if
 341      *  <code>getScrollType</code> returns
 342      *  <code>MouseWheelEvent.WHEEL_BLOCK_SCROLL</code>
 343      * @see #getScrollType
 344      */
 345     public int getScrollAmount() {
 346         return scrollAmount;
 347     }
 348 
 349     /**
 350      * Returns the number of "clicks" the mouse wheel was rotated, as an integer.
 351      * A partial rotation may occur if the mouse supports a high-resolution wheel.
 352      * In this case, the method returns zero until a full "click" has been accumulated.
 353      *
 354      * @return negative values if the mouse wheel was rotated up/away from
 355      * the user, and positive values if the mouse wheel was rotated down/
 356      * towards the user
 357      * @see #getPreciseWheelRotation
 358      */
 359     public int getWheelRotation() {
 360         return wheelRotation;
 361     }
 362 
 363     /**
 364      * Returns the number of "clicks" the mouse wheel was rotated, as a double.
 365      * A partial rotation may occur if the mouse supports a high-resolution wheel.
 366      * In this case, the return value will include a fractional "click".
 367      *
 368      * @return negative values if the mouse wheel was rotated up or away from
 369      * the user, and positive values if the mouse wheel was rotated down or
 370      * towards the user
 371      * @see #getWheelRotation
 372      * @since 1.7
 373      */
 374     public double getPreciseWheelRotation() {
 375         return preciseWheelRotation;
 376     }
 377 
 378     /**
 379      * This is a convenience method to aid in the implementation of
 380      * the common-case MouseWheelListener - to scroll a ScrollPane or
 381      * JScrollPane by an amount which conforms to the platform settings.
 382      * (Note, however, that <code>ScrollPane</code> and
 383      * <code>JScrollPane</code> already have this functionality built in.)
 384      * <P>
 385      * This method returns the number of units to scroll when scroll type is
 386      * MouseWheelEvent.WHEEL_UNIT_SCROLL, and should only be called if
 387      * <code>getScrollType</code> returns MouseWheelEvent.WHEEL_UNIT_SCROLL.
 388      * <P>
 389      * Direction of scroll, amount of wheel movement,
 390      * and platform settings for wheel scrolling are all accounted for.
 391      * This method does not and cannot take into account value of the
 392      * Adjustable/Scrollable unit increment, as this will vary among
 393      * scrolling components.
 394      * <P>
 395      * A simplified example of how this method might be used in a
 396      * listener:
 397      * <pre>
 398      *  mouseWheelMoved(MouseWheelEvent event) {
 399      *      ScrollPane sp = getScrollPaneFromSomewhere();
 400      *      Adjustable adj = sp.getVAdjustable()
 401      *      if (MouseWheelEvent.getScrollType() == WHEEL_UNIT_SCROLL) {
 402      *          int totalScrollAmount =
 403      *              event.getUnitsToScroll() *
 404      *              adj.getUnitIncrement();
 405      *          adj.setValue(adj.getValue() + totalScrollAmount);
 406      *      }
 407      *  }
 408      * </pre>
 409      *
 410      * @return the number of units to scroll based on the direction and amount
 411      *  of mouse wheel rotation, and on the wheel scrolling settings of the
 412      *  native platform
 413      * @see #getScrollType
 414      * @see #getScrollAmount
 415      * @see MouseWheelListener
 416      * @see java.awt.Adjustable
 417      * @see java.awt.Adjustable#getUnitIncrement
 418      * @see javax.swing.Scrollable
 419      * @see javax.swing.Scrollable#getScrollableUnitIncrement
 420      * @see java.awt.ScrollPane
 421      * @see java.awt.ScrollPane#setWheelScrollingEnabled
 422      * @see javax.swing.JScrollPane
 423      * @see javax.swing.JScrollPane#setWheelScrollingEnabled
 424      */
 425     public int getUnitsToScroll() {
 426         return scrollAmount * wheelRotation;
 427     }
 428 
 429     /**
 430      * Returns a parameter string identifying this event.
 431      * This method is useful for event-logging and for debugging.
 432      *
 433      * @return a string identifying the event and its attributes
 434      */
 435     public String paramString() {
 436         String scrollTypeStr = null;
 437 
 438         if (getScrollType() == WHEEL_UNIT_SCROLL) {
 439             scrollTypeStr = "WHEEL_UNIT_SCROLL";
 440         }
 441         else if (getScrollType() == WHEEL_BLOCK_SCROLL) {
 442             scrollTypeStr = "WHEEL_BLOCK_SCROLL";
 443         }
 444         else {
 445             scrollTypeStr = "unknown scroll type";
 446         }
 447         return super.paramString()+",scrollType="+scrollTypeStr+
 448          ",scrollAmount="+getScrollAmount()+",wheelRotation="+
 449          getWheelRotation()+",preciseWheelRotation="+getPreciseWheelRotation();
 450     }
 451 }