source: trunk/src/org/expeditee/gio/javafx/JavaFXInputManager.java@ 1097

Last change on this file since 1097 was 1097, checked in by davidb, 6 years ago

Newly structured files from Corey's work on logic/graphics separation

File size: 9.5 KB
Line 
1package org.expeditee.gio.javafx;
2
3import java.awt.AWTException;
4import java.awt.Robot;
5
6import org.expeditee.core.Dimension;
7import org.expeditee.core.Line;
8import org.expeditee.core.Point;
9import org.expeditee.gio.EcosystemManager;
10import org.expeditee.gio.InputManager;
11import org.expeditee.gio.input.InputEvent;
12import org.expeditee.gio.input.KBMInputEvent;
13import org.expeditee.gio.input.InputEvent.InputType;
14import org.expeditee.gio.javafx.JavaFXGraphicsManager.ExpediteeApplication;
15import org.expeditee.items.Text;
16
17import javafx.animation.KeyFrame;
18import javafx.animation.Timeline;
19import javafx.beans.value.ChangeListener;
20import javafx.beans.value.ObservableValue;
21import javafx.event.ActionEvent;
22import javafx.event.EventHandler;
23import javafx.scene.input.KeyEvent;
24import javafx.scene.input.MouseEvent;
25import javafx.scene.input.ScrollEvent;
26import javafx.stage.WindowEvent;
27import javafx.util.Duration;
28
29public class JavaFXInputManager extends InputManager {
30
31 /** Singleton instance. */
32 private static JavaFXInputManager _instance;
33
34 /** Singleton instantiator. */
35 public static JavaFXInputManager getInstance()
36 {
37 if (_instance == null) _instance = new JavaFXInputManager();
38
39 return _instance;
40 }
41
42 // TODO: Is there a JavaFX way of controlling the mouse? cts16
43 /** For robotically controlling the mouse position. */
44 private Robot _robot;
45
46 /** JavaFX sends spurious enter/exit events when pressing the middle mouse button. Ignore these. */
47 boolean _lastExitSpurious = false;
48
49 private JavaFXInputManager()
50 {
51 JavaFXInputManager manager = this;
52
53 // Exit the program on window closed
54 JavaFXGraphicsManager.ExpediteeApplication.theStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
55 @Override
56 public void handle(WindowEvent event)
57 {
58 distributeWindowEvent(WindowEventType.WINDOW_CLOSED);
59 }
60 });
61
62 // Register to receive window resize events
63 ChangeListener<Number> windowSizeListener = new ChangeListener<Number>() {
64 @Override
65 public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue)
66 {
67 Dimension windowSize = EcosystemManager.getGraphicsManager().getWindowSize();
68 ExpediteeApplication.theCanvas.setWidth(windowSize.width);
69 ExpediteeApplication.theCanvas.setHeight(windowSize.height);
70 distributeWindowEvent(WindowEventType.WINDOW_RESIZED);
71 }
72 };
73 JavaFXGraphicsManager.ExpediteeApplication.theStage.widthProperty().addListener(windowSizeListener);
74 JavaFXGraphicsManager.ExpediteeApplication.theStage.heightProperty().addListener(windowSizeListener);
75
76 // Handle mouse wheel events
77 JavaFXGraphicsManager.ExpediteeApplication.theScene.addEventHandler(ScrollEvent.SCROLL, new EventHandler<ScrollEvent>() {
78 @Override
79 public void handle(ScrollEvent event) {
80 try {
81 // Create an input event
82 Integer rotation = new Integer((int) (event.getDeltaY() / event.getMultiplierY()));
83 InputEvent expEvent = new KBMInputEvent(KBMInputEvent.EventType.MOUSE_WHEEL_SCROLL, rotation);
84
85 // Translate and perform the input
86 distributeInputEvent(expEvent);
87 } catch (Exception exception) {
88 System.err.println(exception.getMessage());
89 }
90 }
91 });
92
93 // Handle mouse movement events
94 EventHandler<MouseEvent> mouseMovementEventHandler = new EventHandler<MouseEvent>() {
95 @Override
96 public void handle(MouseEvent event) {
97 try {
98 // Create an input event
99 Point movedFrom = getCursorPosition();
100 Point movedTo = new Point((int) event.getSceneX(), (int) event.getSceneY());
101 InputEvent expEvent = new KBMInputEvent(KBMInputEvent.EventType.MOUSE_MOVE, new Line(movedFrom, movedTo));
102
103 // Translate and perform the input
104 distributeInputEvent(expEvent);
105 } catch (Exception exception) {
106 System.err.println(exception.getMessage());
107 }
108
109 // Update the cursor position
110 updateCursorPosition((int) event.getSceneX(), (int) event.getSceneY());
111 }
112 };
113 JavaFXGraphicsManager.ExpediteeApplication.theScene.addEventHandler(MouseEvent.MOUSE_DRAGGED, mouseMovementEventHandler);
114 JavaFXGraphicsManager.ExpediteeApplication.theScene.addEventHandler(MouseEvent.MOUSE_MOVED, mouseMovementEventHandler);
115
116 // Handle mouse press/release events
117 EventHandler<MouseEvent> mousePressReleaseEventHandler = new EventHandler<MouseEvent>() {
118 @Override
119 public void handle(MouseEvent event) {
120 // Work out which button was pressed
121 KBMInputEvent.MouseButton button;
122 switch (event.getButton()) {
123 case PRIMARY:
124 button = KBMInputEvent.MouseButton.LEFT;
125 break;
126 case MIDDLE:
127 button = KBMInputEvent.MouseButton.MIDDLE;
128 break;
129 case SECONDARY:
130 button = KBMInputEvent.MouseButton.RIGHT;
131 break;
132 default:
133 return;
134 }
135
136 try {
137 // Create an input event
138 KBMInputEvent.EventType type = (event.getEventType() == MouseEvent.MOUSE_PRESSED) ? KBMInputEvent.EventType.MOUSE_BUTTON_DOWN : KBMInputEvent.EventType.MOUSE_BUTTON_UP;
139 InputEvent expEvent = new KBMInputEvent(type, button);
140
141 // Translate and perform the input
142 distributeInputEvent(expEvent);
143 } catch (Exception exception) {
144 System.err.println(exception.getMessage());
145 }
146 }
147 };
148 JavaFXGraphicsManager.ExpediteeApplication.theScene.addEventHandler(MouseEvent.MOUSE_PRESSED, mousePressReleaseEventHandler);
149 JavaFXGraphicsManager.ExpediteeApplication.theScene.addEventHandler(MouseEvent.MOUSE_RELEASED, mousePressReleaseEventHandler);
150
151
152 // Handle mouse-enters-window events
153 JavaFXGraphicsManager.ExpediteeApplication.theCanvas.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
154 @Override
155 public void handle(MouseEvent event) {
156 if (!_lastExitSpurious) distributeWindowEvent(WindowEventType.MOUSE_ENTERED_WINDOW);
157 }
158 });
159
160 // Handle mouse-exits-window events
161 JavaFXGraphicsManager.ExpediteeApplication.theCanvas.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() {
162 @Override
163 public void handle(MouseEvent event) {
164 _lastExitSpurious = event.isMiddleButtonDown();
165 if (!_lastExitSpurious) distributeWindowEvent(WindowEventType.MOUSE_EXITED_WINDOW);
166 }
167 });
168
169 // Handle key-typed events
170 JavaFXGraphicsManager.ExpediteeApplication.theScene.addEventHandler(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {
171 @Override
172 public void handle(KeyEvent event) {
173 // Ignore control characters
174 if (event.isControlDown() || event.isAltDown()) return;
175
176 String typedText = event.getCharacter();
177
178 for (int i = 0; i < typedText.length(); i++) {
179 try {
180 // Ignore Esc typing
181 if (typedText.charAt(i) == Text.ESC_CHARACTER) continue;
182
183 // Create an input event
184 Character character = new Character(typedText.charAt(i));
185 InputEvent expEvent = new KBMInputEvent(KBMInputEvent.EventType.CHAR_TYPED, character);
186
187 // Translate and perform the input
188 distributeInputEvent(expEvent);
189 } catch (Exception exception) {
190 System.err.println(exception.getMessage());
191 }
192 }
193 }
194 });
195
196 // Handle key pressed/released events
197 EventHandler<KeyEvent> keyPressReleaseEventHandler = new EventHandler<KeyEvent>() {
198 @Override
199 public void handle(KeyEvent event) {
200
201 KBMInputEvent.Key key = JavaFXConversions.fromJavaFXKeyCode(event.getCode());
202 if (key == null) return;
203
204 try {
205 // Create an input event
206 KBMInputEvent.EventType type = (event.getEventType() == KeyEvent.KEY_PRESSED) ? KBMInputEvent.EventType.KEY_DOWN : KBMInputEvent.EventType.KEY_UP;
207 InputEvent expEvent = new KBMInputEvent(type, key);
208
209 // Translate and perform the input
210 distributeInputEvent(expEvent);
211 } catch (Exception exception) {
212 System.err.println(exception.getMessage());
213 }
214 }
215 };
216 JavaFXGraphicsManager.ExpediteeApplication.theScene.addEventHandler(KeyEvent.KEY_PRESSED, keyPressReleaseEventHandler);
217 JavaFXGraphicsManager.ExpediteeApplication.theScene.addEventHandler(KeyEvent.KEY_RELEASED, keyPressReleaseEventHandler);
218
219 // Set up the robot (for controlling the mouse)
220 // TODO: What to do if robot throws exception??? cts16
221 try {
222 _robot = new Robot();
223 } catch (AWTException e) {
224 e.printStackTrace();
225 }
226
227 _timer = new Timeline();
228 _timer.cycleCountProperty().set(1);
229 }
230
231 @Override
232 protected Point getRealCursorPosition()
233 {
234 // Can't get the real mouse position. Not a big deal as only used for initialisation
235 // and is forgotten as soon as the mouse moves.
236 return new Point(0, 0);
237 }
238
239 @Override
240 public void setCursorPosition(Point position)
241 {
242 Point screenPosition = windowToScreenPosition(position);
243 _robot.mouseMove(screenPosition.x, screenPosition.y);
244 }
245
246 @Override
247 protected boolean isInputTypeSupported(InputType type)
248 {
249 // Only keyboard/mouse input is currently supported
250 if (type == InputEvent.InputType.KBM) return true;
251
252 return false;
253 }
254
255 /** Converts a location given in window-space to screen-space. */
256 private Point windowToScreenPosition(Point windowPosition)
257 {
258 Point windowTopLeft = EcosystemManager.getGraphicsManager().getWindowLocation();
259
260 return windowPosition.clone().add(windowTopLeft);
261 }
262
263 private Timeline _timer;
264
265 @Override
266 protected void updateTimer(long nextTimeout)
267 {
268 JavaFXInputManager jfxInputManager = this;
269
270 if (nextTimeout < 0) nextTimeout = 0;
271 _timer.stop();
272 _timer.getKeyFrames().clear();
273 _timer.getKeyFrames().add(new KeyFrame(new Duration(nextTimeout), new EventHandler<ActionEvent>() {
274 @Override
275 public void handle(ActionEvent event) {
276 jfxInputManager.triggerTimeoutEvents();
277 }
278 }));
279 _timer.playFromStart();
280 }
281
282}
Note: See TracBrowser for help on using the repository browser.