1. /*
  2. * @(#)Autoscroller.java 1.14 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. /**
  11. * Autoscroller is responsible for generating synthetic mouse dragged
  12. * events. It is the responsibility of the Component (or its MouseListeners)
  13. * that receive the events to do the actual scrolling in response to the
  14. * mouse dragged events.
  15. *
  16. * @version 1.14 12/19/03
  17. * @author Dave Moore
  18. * @author Scott Violet
  19. */
  20. class Autoscroller implements ActionListener {
  21. /**
  22. * Global Autoscroller.
  23. */
  24. private static Autoscroller sharedInstance = new Autoscroller();
  25. // As there can only ever be one autoscroller active these fields are
  26. // static. The Timer is recreated as necessary to target the appropriate
  27. // Autoscroller instance.
  28. private static MouseEvent event;
  29. private static Timer timer;
  30. private static JComponent component;
  31. //
  32. // The public API, all methods are cover methods for an instance method
  33. //
  34. /**
  35. * Stops autoscroll events from happening on the specified component.
  36. */
  37. public static void stop(JComponent c) {
  38. sharedInstance._stop(c);
  39. }
  40. /**
  41. * Stops autoscroll events from happening on the specified component.
  42. */
  43. public static boolean isRunning(JComponent c) {
  44. return sharedInstance._isRunning(c);
  45. }
  46. /**
  47. * Invoked when a mouse dragged event occurs, will start the autoscroller
  48. * if necessary.
  49. */
  50. public static void processMouseDragged(MouseEvent e) {
  51. sharedInstance._processMouseDragged(e);
  52. }
  53. Autoscroller() {
  54. }
  55. /**
  56. * Starts the timer targeting the passed in component.
  57. */
  58. private void start(JComponent c, MouseEvent e) {
  59. Point screenLocation = c.getLocationOnScreen();
  60. if (component != c) {
  61. _stop(component);
  62. }
  63. component = c;
  64. event = new MouseEvent(component, e.getID(), e.getWhen(),
  65. e.getModifiers(), e.getX() + screenLocation.x,
  66. e.getY() + screenLocation.y,
  67. e.getClickCount(), e.isPopupTrigger());
  68. if (timer == null) {
  69. timer = new Timer(100, this);
  70. }
  71. if (!timer.isRunning()) {
  72. timer.start();
  73. }
  74. }
  75. //
  76. // Methods mirror the public static API
  77. //
  78. /**
  79. * Stops scrolling for the passed in widget.
  80. */
  81. private void _stop(JComponent c) {
  82. if (component == c) {
  83. if (timer != null) {
  84. timer.stop();
  85. }
  86. timer = null;
  87. event = null;
  88. component = null;
  89. }
  90. }
  91. /**
  92. * Returns true if autoscrolling is currently running for the specified
  93. * widget.
  94. */
  95. private boolean _isRunning(JComponent c) {
  96. return (c == component && timer != null && timer.isRunning());
  97. }
  98. /**
  99. * MouseListener method, invokes start/stop as necessary.
  100. */
  101. private void _processMouseDragged(MouseEvent e) {
  102. JComponent component = (JComponent)e.getComponent();
  103. Rectangle visibleRect = component.getVisibleRect();
  104. boolean contains = visibleRect.contains(e.getX(), e.getY());
  105. if (contains) {
  106. _stop(component);
  107. } else {
  108. start(component, e);
  109. }
  110. }
  111. //
  112. // ActionListener
  113. //
  114. /**
  115. * ActionListener method. Invoked when the Timer fires. This will scroll
  116. * if necessary.
  117. */
  118. public void actionPerformed(ActionEvent x) {
  119. JComponent component = Autoscroller.component;
  120. if (component == null || !component.isShowing() || (event == null)) {
  121. _stop(component);
  122. return;
  123. }
  124. Point screenLocation = component.getLocationOnScreen();
  125. MouseEvent e = new MouseEvent(component, event.getID(),
  126. event.getWhen(), event.getModifiers(),
  127. event.getX() - screenLocation.x,
  128. event.getY() - screenLocation.y,
  129. event.getClickCount(),
  130. event.isPopupTrigger());
  131. component.superProcessMouseMotionEvent(e);
  132. }
  133. }