Clover Coverage Report - FEST Swing 1.2
Coverage timestamp: Tue Jun 1 2010 15:19:25 PDT
../../../../img/srcFileCovDistChart6.png 97% of files have more coverage
53   252   32   2.21
12   120   0.6   24
24     1.33  
1    
 
  InputState       Line # 39 53 0% 32 39 56.2% 0.56179774
 
No Tests
 
1    /*
2    * Created on Mar 28, 2008
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5    * the License. You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10    * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11    * specific language governing permissions and limitations under the License.
12    *
13    * Copyright @2008-2010 the original author or authors.
14    */
15    package org.fest.swing.input;
16   
17    import static java.awt.AWTEvent.*;
18    import static javax.swing.SwingUtilities.getDeepestComponentAt;
19    import static org.fest.swing.awt.AWT.locationOnScreenOf;
20    import static org.fest.swing.input.MouseInfo.BUTTON_MASK;
21   
22    import java.awt.*;
23    import java.awt.event.*;
24   
25    import net.jcip.annotations.GuardedBy;
26    import net.jcip.annotations.ThreadSafe;
27   
28    import org.fest.swing.exception.UnexpectedException;
29    import org.fest.swing.listener.EventDispatchThreadedEventListener;
30   
31    /**
32    * Class to keep track of a given input state. Includes mouse/pointer position and keyboard modifier key state.
33    * <p>
34    * Synchronization assumes that any given instance might be called from more than one event dispatch thread.
35    * </p>
36    */
37    // TODO: add a BitSet with the full keyboard key press state
38    @ThreadSafe
 
39    public class InputState {
40   
41    @GuardedBy("this") private final MouseInfo mouseInfo = new MouseInfo();
42    @GuardedBy("this") private final DragDropInfo dragDropInfo = new DragDropInfo();
43   
44    @GuardedBy("this") private int modifiers;
45    @GuardedBy("this") private long lastEventTime;
46   
47    private EventNormalizer normalizer;
48   
 
49  582 toggle public InputState(Toolkit toolkit) {
50  582 long mask = MOUSE_MOTION_EVENT_MASK | MOUSE_EVENT_MASK | KEY_EVENT_MASK;
51  582 AWTEventListener listener = new EventDispatchThreadedEventListener() {
 
52  5205 toggle protected void processEvent(AWTEvent event) {
53  5205 update(event);
54    }
55    };
56  582 normalizer = new EventNormalizer();
57  582 normalizer.startListening(toolkit, listener, mask);
58    }
59   
 
60  0 toggle public synchronized void clear() {
61  0 mouseInfo.clear();
62  0 dragDropInfo.clear();
63  0 modifiers = 0;
64  0 lastEventTime = 0;
65    }
66   
 
67  0 toggle public void dispose() {
68  0 normalizer.stopListening();
69  0 normalizer = null;
70    }
71   
72    /**
73    * Explicitly update the internal state.
74    * @param event the event to use to update the internal state.
75    */
 
76  5205 toggle public void update(AWTEvent event) {
77  837 if (event instanceof KeyEvent) updateState((KeyEvent) event);
78  4368 if (event instanceof MouseEvent) updateState((MouseEvent) event);
79    }
80   
 
81  837 toggle private void updateState(KeyEvent event) {
82  2 if (isOld(event)) return;
83  835 synchronized (this) {
84  835 lastEventTime(event);
85  835 modifiers(event.getModifiers());
86    // FIXME add state of individual keys
87    }
88    }
89   
 
90  4368 toggle private void updateState(MouseEvent event) {
91  15 if (isOld(event)) return;
92    // childAt and locationOnScreenOf want the tree lock, so be careful not to use any additional locks at the same time
93    // to avoid deadlock.
94  4353 Point eventScreenLocation = null;
95    // Determine the current mouse position in screen coordinates
96  4353 try {
97  4353 eventScreenLocation = locationOnScreenOf(event.getComponent());
98    } catch (IllegalComponentStateException e) {
99    // component might be hidden by the time we process this event
100    } catch (UnexpectedException e) {
101  0 if (!(e.getCause() instanceof IllegalComponentStateException)) throw e;
102    }
103  4353 synchronized (this) {
104  4353 lastEventTime(event);
105  4353 dragDropInfo.update(event);
106  4353 mouseInfo.modifiers(modifiers);
107  4353 mouseInfo.update(event, eventScreenLocation);
108  4353 modifiers(mouseInfo.modifiers());
109    }
110    }
111   
 
112  5205 toggle private boolean isOld(InputEvent event) {
113  5205 return event.getWhen() < lastEventTime();
114    }
115   
 
116  5188 toggle private void lastEventTime(InputEvent event) {
117  5188 lastEventTime = event.getWhen();
118    }
119   
 
120  5188 toggle private void modifiers(int newModifiers) {
121  5188 modifiers = newModifiers;
122    }
123   
124    /**
125    * Returns the most deeply nested component which currently contains the pointer.
126    * @return the most deeply nested component which currently contains the pointer.
127    */
 
128  0 toggle public synchronized Component deepestComponentUnderMousePointer() {
129  0 Component c = mouseComponent();
130  0 if (c != null) c = childAt(c, mouseLocation());
131  0 return c;
132    }
133   
134    /**
135    * Returns the last known Component to contain the pointer, or <code>null</code> if none. Note that this may not
136    * correspond to the component that actually shows up in AWTEvents.
137    * @return the last known Component to contain the pointer, or <code>null</code> if none.
138    */
 
139  0 toggle public synchronized Component mouseComponent() {
140  0 return mouseInfo.component();
141    }
142   
143    /**
144    * Returns the component under the given coordinates in the given parent component. Events are often generated only
145    * for the outermost container, so we have to determine if the pointer is actually within a child. Basically the same
146    * as Component.getComponentAt, but recurses to the lowest-level component instead of only one level. Point is in
147    * component coordinates.
148    * <p>
149    * The default Component.getComponentAt can return invisible components (JRootPane has an invisible JPanel (glass
150    * pane?) which will otherwise swallow everything).
151    * <p>
152    * NOTE: childAt grabs the TreeLock, so this should *only* be invoked on the event dispatch thread, preferably with no
153    * other locks held. Use it elsewhere at your own risk.
154    * <p>
155    * @param parent the given parent.
156    * @param where the given coordinates.
157    * @return the component under the given coordinates in the given parent component.
158    */
 
159  0 toggle public static Component childAt(Component parent, Point where) {
160  0 return getDeepestComponentAt(parent, where.x, where.y);
161    }
162   
163    /**
164    * Indicates there is a drag operation in progress.
165    * @return <code>true</code> if there is a drag operation in progress, <code>false</code> otherwise.
166    */
 
167  21 toggle public synchronized boolean dragInProgress() {
168  21 return dragDropInfo.isDragging();
169    }
170   
171    /**
172    * Returns the <code>{@link Component}</code> where a drag operation started.
173    * @return the <code>Component</code> where a drag operation started.
174    */
 
175  0 toggle public synchronized Component dragSource() {
176  0 return dragDropInfo.source();
177    }
178   
179    /**
180    * Returns the coordinates where a drag operation started.
181    * @return the coordinates where a drag operation started.
182    */
 
183  0 toggle public synchronized Point dragOrigin() {
184  0 return dragDropInfo.origin();
185    }
186   
187    /**
188    * Indicates the number of times a mouse button was clicked.
189    * @return the number of times a mouse button was clicked.
190    */
 
191  0 toggle public synchronized int clickCount() {
192  0 return mouseInfo.clickCount();
193    }
194   
195    /**
196    * Returns the time when the last input event occurred.
197    * @return the time when the last input event occurred.
198    */
 
199  5205 toggle public synchronized long lastEventTime() {
200  5205 return lastEventTime;
201    }
202   
203    /**
204    * Returns all currently active modifiers.
205    * @return all currently active modifiers.
206    */
 
207  0 toggle public synchronized int modifiers() {
208  0 return modifiers;
209    }
210   
211    /**
212    * Returns the currently pressed key modifiers.
213    * @return the currently pressed key modifiers.
214    */
 
215  0 toggle public synchronized int keyModifiers() {
216  0 return modifiers & ~BUTTON_MASK;
217    }
218   
219    /**
220    * Returns the mouse buttons used in the last input event.
221    * @return the mouse buttons used in the last input event.
222    */
 
223  1611 toggle public synchronized int buttons() {
224  1611 return mouseInfo.buttons();
225    }
226   
227    /**
228    * Returns the mouse location relative to the component that currently contains the pointer, or <code>null</code> if
229    * outside all components.
230    * @return the mouse location relative to the component that currently contains the pointer, or <code>null</code> if
231    * outside all components.
232    */
 
233  0 toggle public synchronized Point mouseLocation() {
234  0 return mouseInfo.location();
235    }
236   
237    /**
238    * Returns the last known mouse location.
239    * @return the last known mouse location.
240    */
 
241  0 toggle public synchronized Point mouseLocationOnScreen() {
242  0 return mouseInfo.locationOnScreen();
243    }
244   
245    /**
246    * Indicates whether there is a native drag/drop operation in progress.
247    * @return <code>true</code> if there is a native drag/drop operation in progress, <code>false</code> otherwise.
248    */
 
249  0 toggle public boolean isNativeDragActive() {
250  0 return dragDropInfo.isNativeDragActive();
251    }
252    }