blob: 892e297473bfefcb76e60833cf6c1da5706e9191 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2006 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
26package javax.swing;
27
28import java.awt.*;
29import java.awt.event.*;
30
31/**
32 * Autoscroller is responsible for generating synthetic mouse dragged
33 * events. It is the responsibility of the Component (or its MouseListeners)
34 * that receive the events to do the actual scrolling in response to the
35 * mouse dragged events.
36 *
37 * @author Dave Moore
38 * @author Scott Violet
39 */
40class Autoscroller implements ActionListener {
41 /**
42 * Global Autoscroller.
43 */
44 private static Autoscroller sharedInstance = new Autoscroller();
45
46 // As there can only ever be one autoscroller active these fields are
47 // static. The Timer is recreated as necessary to target the appropriate
48 // Autoscroller instance.
49 private static MouseEvent event;
50 private static Timer timer;
51 private static JComponent component;
52
53 //
54 // The public API, all methods are cover methods for an instance method
55 //
56 /**
57 * Stops autoscroll events from happening on the specified component.
58 */
59 public static void stop(JComponent c) {
60 sharedInstance._stop(c);
61 }
62
63 /**
64 * Stops autoscroll events from happening on the specified component.
65 */
66 public static boolean isRunning(JComponent c) {
67 return sharedInstance._isRunning(c);
68 }
69
70 /**
71 * Invoked when a mouse dragged event occurs, will start the autoscroller
72 * if necessary.
73 */
74 public static void processMouseDragged(MouseEvent e) {
75 sharedInstance._processMouseDragged(e);
76 }
77
78
79 Autoscroller() {
80 }
81
82 /**
83 * Starts the timer targeting the passed in component.
84 */
85 private void start(JComponent c, MouseEvent e) {
86 Point screenLocation = c.getLocationOnScreen();
87
88 if (component != c) {
89 _stop(component);
90 }
91 component = c;
92 event = new MouseEvent(component, e.getID(), e.getWhen(),
93 e.getModifiers(), e.getX() + screenLocation.x,
94 e.getY() + screenLocation.y,
95 e.getXOnScreen(),
96 e.getYOnScreen(),
97 e.getClickCount(), e.isPopupTrigger(),
98 MouseEvent.NOBUTTON);
99
100 if (timer == null) {
101 timer = new Timer(100, this);
102 }
103
104 if (!timer.isRunning()) {
105 timer.start();
106 }
107 }
108
109 //
110 // Methods mirror the public static API
111 //
112
113 /**
114 * Stops scrolling for the passed in widget.
115 */
116 private void _stop(JComponent c) {
117 if (component == c) {
118 if (timer != null) {
119 timer.stop();
120 }
121 timer = null;
122 event = null;
123 component = null;
124 }
125 }
126
127 /**
128 * Returns true if autoscrolling is currently running for the specified
129 * widget.
130 */
131 private boolean _isRunning(JComponent c) {
132 return (c == component && timer != null && timer.isRunning());
133 }
134
135 /**
136 * MouseListener method, invokes start/stop as necessary.
137 */
138 private void _processMouseDragged(MouseEvent e) {
139 JComponent component = (JComponent)e.getComponent();
140 boolean stop = true;
141 if (component.isShowing()) {
142 Rectangle visibleRect = component.getVisibleRect();
143 stop = visibleRect.contains(e.getX(), e.getY());
144 }
145 if (stop) {
146 _stop(component);
147 } else {
148 start(component, e);
149 }
150 }
151
152 //
153 // ActionListener
154 //
155 /**
156 * ActionListener method. Invoked when the Timer fires. This will scroll
157 * if necessary.
158 */
159 public void actionPerformed(ActionEvent x) {
160 JComponent component = Autoscroller.component;
161
162 if (component == null || !component.isShowing() || (event == null)) {
163 _stop(component);
164 return;
165 }
166 Point screenLocation = component.getLocationOnScreen();
167 MouseEvent e = new MouseEvent(component, event.getID(),
168 event.getWhen(), event.getModifiers(),
169 event.getX() - screenLocation.x,
170 event.getY() - screenLocation.y,
171 event.getXOnScreen(),
172 event.getYOnScreen(),
173 event.getClickCount(),
174 event.isPopupTrigger(),
175 MouseEvent.NOBUTTON);
176 component.superProcessMouseMotionEvent(e);
177 }
178
179}