source: trunk/src/org/expeditee/gio/gesture/ExpediteeKBMGestureTranslator.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: 72.4 KB
Line 
1package org.expeditee.gio.gesture;
2
3import java.util.Collection;
4import java.util.List;
5
6import org.expeditee.core.Point;
7import org.expeditee.gio.EcosystemManager;
8import org.expeditee.gio.TimeoutQueue.TimeoutHandle;
9import org.expeditee.gio.gesture.StandardGestureActions.StandardGestureType;
10import org.expeditee.gio.gesture.data.ChangeColourGestureData;
11import org.expeditee.gio.gesture.data.ClickGestureData;
12import org.expeditee.gio.gesture.data.CreateItemGestureData;
13import org.expeditee.gio.gesture.data.CreateItemGestureData.ItemType;
14import org.expeditee.gio.gesture.data.DeleteGestureData;
15import org.expeditee.gio.gesture.data.FormatGestureData;
16import org.expeditee.gio.gesture.data.GestureData;
17import org.expeditee.gio.gesture.data.InsertStringGestureData;
18import org.expeditee.gio.gesture.data.ItemSpecificGestureData;
19import org.expeditee.gio.gesture.data.JustifyGestureData;
20import org.expeditee.gio.gesture.data.LinkGestureData;
21import org.expeditee.gio.gesture.data.SelectAreaGestureData;
22import org.expeditee.gio.gesture.data.NavigateFrameGestureData;
23import org.expeditee.gio.gesture.data.NavigateTextGestureData;
24import org.expeditee.gio.gesture.data.PanGestureData;
25import org.expeditee.gio.gesture.data.PickUpGestureData;
26import org.expeditee.gio.gesture.data.RefreshGestureData;
27import org.expeditee.gio.gesture.data.ScaleGestureData;
28import org.expeditee.gio.gesture.data.UndoGestureData;
29import org.expeditee.gio.gesture.data.ZoomGestureData;
30import org.expeditee.gio.input.InputEvent;
31import org.expeditee.gio.input.InputEventToGestureTranslator;
32import org.expeditee.gio.input.InputEventToGestureTranslatorSet;
33import org.expeditee.gio.input.KBMInputEvent;
34import org.expeditee.gio.input.StandardInputEventListeners;
35import org.expeditee.gio.input.InputEvent.InputType;
36import org.expeditee.gio.input.KBMInputEvent.EventType;
37import org.expeditee.gio.input.KBMInputEvent.Key;
38import org.expeditee.gio.input.KBMInputEvent.MouseButton;
39import org.expeditee.gio.input.TimeoutInputEvent;
40import org.expeditee.gui.DisplayController;
41import org.expeditee.gui.FrameUtils;
42import org.expeditee.gui.FreeItems;
43import org.expeditee.gui.MessageBay;
44import org.expeditee.items.Item;
45import org.expeditee.items.Line;
46import org.expeditee.items.Text;
47import org.expeditee.settings.UserSettings;
48import org.expeditee.settings.experimental.ExperimentalFeatures;
49
50/**
51 * Class for translating raw keyboard and mouse input into Expeditee gestures.
52 *
53 * @author cts16
54 */
55public class ExpediteeKBMGestureTranslator extends InputEventToGestureTranslatorSet
56{
57 /** Convenience definition of this translator's input type. */
58 private static final InputType KBM = InputType.KBM;
59
60 /** Tracks when the mouse has moved too far away from it's click position and should no-op. */
61 private static boolean _noop = false;
62 /** Tracks the starting position of a mouse drag. */
63 private static Point _mouseDragStart;
64
65 public ExpediteeKBMGestureTranslator()
66 {
67 // Create the list of sub-translators
68 initialiseExpediteeTranslators();
69 }
70
71 @Override
72 public List<Gesture> onInputEvent(InputEvent event)
73 {
74 // Track when the mouse has moved too far and should no-op
75 if (event.getInputType() == KBM) trackMouseDragNoop((KBMInputEvent) event);
76
77 return super.onInputEvent(event);
78 }
79
80 /** Adds all gesture translators that base Expeditee utilises. */
81 private void initialiseExpediteeTranslators()
82 {
83 // TODO: Remove. Reference automatically falls through. cts16
84 ExpediteeKBMGestureTranslator kbmTranslator = this;
85
86 // Add the CHAR_TYPED -> INSERT_STRING gesture recogniser
87 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
88 {
89 @Override
90 public String details() { return "CHAR_TYPED -> INSERT_STRING"; }
91
92 @Override
93 public List<Gesture> onInputEvent(InputEvent event) {
94 // Cast to keyboard/mouse event
95 KBMInputEvent kbmEvent = (KBMInputEvent) event;
96
97 // Check if it's a typing event
98 if (kbmEvent.getEventType() != KBMInputEvent.EventType.CHAR_TYPED) return null;
99
100 // Generate a INSERT_STRING gesture
101 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.INSERT_STRING), new InsertStringGestureData(kbmEvent.getCharTyped(), kbmTranslator.isKeyDown(Key.SHIFT)));
102 }
103 });
104
105 // Add the MOUSE_MOVED -> MOVE_CURSOR gesture recogniser
106 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
107 {
108 @Override
109 public String details() { return "MOUSE_MOVED -> MOVE_CURSOR"; }
110
111 @Override
112 public List<Gesture> onInputEvent(InputEvent event) {
113 // Cast to keyboard/mouse event
114 KBMInputEvent kbmEvent = (KBMInputEvent) event;
115
116 // Check if it's a mouse movement event
117 if (kbmEvent.getEventType() != KBMInputEvent.EventType.MOUSE_MOVE) return null;
118
119 // Generate a CURSOR_MOVED gesture
120 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.MOVE_CURSOR), new GestureData(kbmEvent.getMouseMove().getSecondEnd().clone()));
121 }
122 });
123
124 // Add the LEFT CLICK + MOUSE_MOVE -> SELECT_AREA gesture recogniser
125 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
126 {
127 private static final int NO_CONSTRAINT = 0;
128 private SelectAreaGestureData _draggedFromData = null;
129 private int _constrainedDirection = NO_CONSTRAINT;
130
131 @Override
132 public String details() { return "LEFT CLICK + MOUSE_MOVE -> SELECT_AREA"; }
133
134 @Override
135 public List<Gesture> onInputEvent(InputEvent event) {
136 // Cast to keyboard/mouse event
137 KBMInputEvent kbmEvent = (KBMInputEvent) event;
138
139 // Check we are holding the left button only
140 if (!kbmTranslator.isOnlyMouseButtonDown(MouseButton.LEFT)) {
141 // If we were dragging, reset the dragging tracker and send the drag-finished gesture
142 if (_draggedFromData != null) {
143 SelectAreaGestureData finalData = _draggedFromData.finalise();
144 _draggedFromData = null;
145 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.SELECT_AREA), finalData);
146
147 // Otherwise just return
148 } else {
149 return null;
150 }
151 }
152
153 // Check if it's a mouse movement event
154 if (kbmEvent.getEventType() != KBMInputEvent.EventType.MOUSE_MOVE) return null;
155
156 // If we are just starting to drag, save the start position of the gesture
157 if (_draggedFromData == null) {
158 _draggedFromData = new SelectAreaGestureData(kbmEvent.getMouseMove().getSecondEnd().clone(), kbmEvent.getMouseMove().getFirstEnd().clone());
159 }
160
161 // If holding control, move the mouse cursor to a constrained position
162 Point newMousePos = kbmEvent.getMouseMove().getFirstEnd().clone();
163/* if (kbmTranslator.isKeyDown(Key.CTRL) && FreeItems.hasItemsAttachedToCursor()) {
164 if (_constrainedDirection == NO_CONSTRAINT) {
165 // Decide the direction of constraint
166 _constrainedDirection = Constraint.DIAGONAL_POS;
167 int absX = kbmEvent.getMouseMove().deltaX();
168 if (absX < 0) {
169 absX = -absX;
170 _constrainedDirection = Constraint.DIAGONAL_NEG;
171 }
172 int absY = kbmEvent.getMouseMove().deltaY();
173 if (absY < 0) {
174 absY = -absY;
175 if (_constrainedDirection == Constraint.DIAGONAL_NEG) {
176 _constrainedDirection = Constraint.DIAGONAL_POS;
177 } else {
178 _constrainedDirection = Constraint.DIAGONAL_NEG;
179 }
180 }
181 if (absY <= absX / 2) {
182 _constrainedDirection = Constraint.HORIZONTAL;
183 } else if (absX <= absY / 2) {
184 _constrainedDirection = Constraint.VERTICAL;
185 }
186 }
187
188 int dX, dY;
189 if (_constrainedDirection == Constraint.HORIZONTAL) {
190 dX = kbmEvent.getMouseMove().deltaX();
191 dY = 0;
192 } else if (_constrainedDirection == Constraint.VERTICAL) {
193 dX = 0;
194 dY = kbmEvent.getMouseMove().deltaY();
195 } else if (_constrainedDirection == Constraint.DIAGONAL_POS) {
196 dX = dY = (kbmEvent.getMouseMove().deltaX() + kbmEvent.getMouseMove().deltaY()) / 2;
197 } else {
198 dY = (kbmEvent.getMouseMove().deltaY() - kbmEvent.getMouseMove().deltaX()) / 2;
199 dX = -dY;
200 }
201
202 // Cause feedback loop by moving the mouse to the calculated position
203 newMousePos.add(1, 1);
204 } else*/ {
205 _constrainedDirection = NO_CONSTRAINT;
206 newMousePos = kbmEvent.getMouseMove().getSecondEnd().clone();
207 }
208
209 // Generate a SELECT_AREA gesture
210 _draggedFromData = _draggedFromData.carryOn(newMousePos);
211 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.SELECT_AREA), _draggedFromData);
212 }
213 });
214
215 // Add the HOME/END/LEFT/RIGHT/PAGE_UP/PAGE_DOWN -> NAVIGATE_FRAME gesture recogniser
216 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
217 {
218 @Override
219 public String details() { return "HOME/END/LEFT/RIGHT/PAGE_UP/PAGE_DOWN/BACKSPACE -> NAVIGATE_FRAME"; }
220
221 @Override
222 public List<Gesture> onInputEvent(InputEvent event) {
223 // Cast to keyboard/mouse event
224 KBMInputEvent kbmEvent = (KBMInputEvent) event;
225
226 // Alt is for mouse emulation
227 if (kbmTranslator.isKeyDown(Key.ALT)) return null;
228
229 // Decide which frame to navigate to
230 NavigateFrameGestureData.NavigateTo navigateTo;
231 if (kbmEvent.getKeyDown() == Key.HOME) {
232 if (kbmTranslator.isKeyDown(Key.CTRL)) {
233 navigateTo = NavigateFrameGestureData.NavigateTo.EARLIEST_FRAME;
234 } else {
235 navigateTo = NavigateFrameGestureData.NavigateTo.ZERO_FRAME;
236 }
237 } else if(kbmEvent.getKeyDown() == Key.END) {
238 if (kbmTranslator.isKeyDown(Key.CTRL)) {
239 navigateTo = NavigateFrameGestureData.NavigateTo.LATEST_FRAME;
240 } else {
241 navigateTo = NavigateFrameGestureData.NavigateTo.LAST_FRAME;
242 }
243 } else if(kbmEvent.getKeyDown() == Key.LEFT_ARROW && !kbmTranslator.isKeyDown(Key.CTRL)) {
244 navigateTo = NavigateFrameGestureData.NavigateTo.PREVIOUS_FRAME;
245 } else if(kbmEvent.getKeyDown() == Key.RIGHT_ARROW && !kbmTranslator.isKeyDown(Key.CTRL)) {
246 navigateTo = NavigateFrameGestureData.NavigateTo.NEXT_FRAME;
247 } else if(kbmEvent.getKeyDown() == Key.PAGE_UP) {
248 if (kbmTranslator.isKeyDown(Key.CTRL)) {
249 navigateTo = NavigateFrameGestureData.NavigateTo.BACK_FRAME;
250 } else {
251 navigateTo = NavigateFrameGestureData.NavigateTo.NEXT_FRAME;
252 }
253 } else if(kbmEvent.getKeyDown() == Key.PAGE_DOWN) {
254 if (kbmTranslator.isKeyDown(Key.CTRL)) {
255 navigateTo = NavigateFrameGestureData.NavigateTo.FORWARD_FRAME;
256 } else {
257 navigateTo = NavigateFrameGestureData.NavigateTo.PREVIOUS_FRAME;
258 }
259 } else if(kbmEvent.getKeyDown() == Key.BACKSPACE && kbmTranslator.isKeyDown(Key.CTRL)) {
260 navigateTo = NavigateFrameGestureData.NavigateTo.BACK_FRAME;
261 } else {
262 return null;
263 }
264
265 // Check we aren't over text
266 Item on = FrameUtils.getCurrentItem();
267 if (on != null && on instanceof Text && !on.isFrameName()) return null;
268
269 // Generate a CURSOR_MOVED gesture
270 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.NAVIGATE_FRAME), new NavigateFrameGestureData(navigateTo));
271 }
272 });
273
274 // Add the HOME/END/LEFT/RIGHT/PAGE_UP/PAGE_DOWN -> NAVIGATE_TEXT gesture recogniser
275 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
276 {
277 @Override
278 public String details() { return "HOME/END/LEFT/RIGHT/PAGE_UP/PAGE_DOWN -> NAVIGATE_TEXT"; }
279
280 @Override
281 public List<Gesture> onInputEvent(InputEvent event) {
282 // Cast to keyboard/mouse event
283 KBMInputEvent kbmEvent = (KBMInputEvent) event;
284
285 // Alt is for mouse emulation
286 if (kbmTranslator.isKeyDown(Key.ALT)) return null;
287
288 // Decide which frame to navigate to
289 NavigateTextGestureData.NavigateTo navigateTo;
290 if (kbmEvent.getKeyDown() == Key.HOME) {
291 if (kbmTranslator.isKeyDown(Key.CTRL)) {
292 navigateTo = NavigateTextGestureData.NavigateTo.PARAGRAPH_HOME;
293 } else {
294 navigateTo = NavigateTextGestureData.NavigateTo.LINE_HOME;
295 }
296 } else if(kbmEvent.getKeyDown() == Key.END) {
297 if (kbmTranslator.isKeyDown(Key.CTRL)) {
298 navigateTo = NavigateTextGestureData.NavigateTo.PARAGRAPH_END;
299 } else {
300 navigateTo = NavigateTextGestureData.NavigateTo.LINE_END;
301 }
302 } else if(kbmEvent.getKeyDown() == Key.LEFT_ARROW) {
303 if (kbmTranslator.isKeyDown(Key.CTRL)) {
304 navigateTo = NavigateTextGestureData.NavigateTo.PREVIOUS_WORD;
305 } else {
306 navigateTo = NavigateTextGestureData.NavigateTo.PREVIOUS_CHARACTER;
307 }
308 } else if(kbmEvent.getKeyDown() == Key.RIGHT_ARROW) {
309 if (kbmTranslator.isKeyDown(Key.CTRL)) {
310 navigateTo = NavigateTextGestureData.NavigateTo.NEXT_WORD;
311 } else {
312 navigateTo = NavigateTextGestureData.NavigateTo.NEXT_CHARACTER;
313 }
314 } else if(kbmEvent.getKeyDown() == Key.UP_ARROW) {
315 if (kbmTranslator.isKeyDown(Key.CTRL)) {
316 navigateTo = NavigateTextGestureData.NavigateTo.PREVIOUS_TEXT_ITEM;
317 } else {
318 navigateTo = NavigateTextGestureData.NavigateTo.ABOVE_LINE;
319 }
320 } else if(kbmEvent.getKeyDown() == Key.DOWN_ARROW) {
321 if (kbmTranslator.isKeyDown(Key.CTRL)) {
322 navigateTo = NavigateTextGestureData.NavigateTo.NEXT_TEXT_ITEM;
323 } else {
324 navigateTo = NavigateTextGestureData.NavigateTo.BELOW_LINE;
325 }
326 } else {
327 return null;
328 }
329
330 // Check we are over text
331 Item on = FrameUtils.getCurrentItem();
332 if (on == null || !(on instanceof Text) || on.isFrameName()) return null;
333
334 // See if we are holding shift to select text
335 boolean selecting = kbmTranslator.isKeyDown(Key.SHIFT);
336
337 // Generate a CURSOR_MOVED gesture
338 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.NAVIGATE_TEXT), new NavigateTextGestureData(navigateTo, selecting));
339 }
340 });
341
342 // Add the SHIFT + LEFT_CLICK + MOUSE_MOVE -> PAN gesture recogniser
343 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
344 {
345 private Point _panStart;
346
347 @Override
348 public String details() { return "SHIFT + LEFT_CLICK + MOUSE_MOVE -> PAN"; }
349
350 @Override
351 public List<Gesture> onInputEvent(InputEvent event) {
352 // Cast to keyboard/mouse event
353 KBMInputEvent kbmEvent = (KBMInputEvent) event;
354
355 // See if we are panning
356 if (ExperimentalFeatures.MousePan.get() &&
357 !FrameUtils.hasCurrentItem() &&
358 kbmTranslator.isMouseButtonDown(MouseButton.LEFT) &&
359 kbmTranslator.isKeyDown(Key.SHIFT) &&
360 kbmEvent.getEventType() == KBMInputEvent.EventType.MOUSE_MOVE)
361 {
362 if (_panStart == null) {
363 _panStart = kbmEvent.getMouseMove().getFirstEnd().clone();
364 }
365 } else {
366 _panStart = null;
367 return null;
368 }
369
370 // Generate a PAN gesture
371 Point panPosition = kbmEvent.getMouseMove().getSecondEnd();
372 Point panDelta = Point.difference(kbmEvent.getMouseMove().getSecondEnd(), kbmEvent.getMouseMove().getFirstEnd());
373
374 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PAN), new PanGestureData(panPosition, _panStart, panDelta));
375 }
376 });
377
378 // Add the ALT + ARROW_KEYS -> MOVE_CURSOR gesture recogniser
379 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
380 {
381 private final int MACRO_CURSOR_MOVE_DISTANCE = 20;
382 private final int MICRO_CURSOR_MOVE_DISTANCE = 1;
383
384 @Override
385 public String details() { return "ALT + ARROW_KEYS -> MOVE_CURSOR"; }
386
387 @Override
388 public List<Gesture> onInputEvent(InputEvent event) {
389 // Cast to keyboard/mouse event
390 KBMInputEvent kbmEvent = (KBMInputEvent) event;
391
392 // Can return if not pressing any of the arrow keys
393 if ( (kbmEvent.getKeyDown() != Key.UP_ARROW) &&
394 (kbmEvent.getKeyDown() != Key.DOWN_ARROW) &&
395 (kbmEvent.getKeyDown() != Key.LEFT_ARROW) &&
396 (kbmEvent.getKeyDown() != Key.RIGHT_ARROW))
397 {
398 return null;
399 }
400
401 // Must be holding ALT for mouse emulation
402 if (!kbmTranslator.isKeyDown(Key.ALT)) return null;
403
404 // Decide how far to move
405 int distance = kbmTranslator.isKeyDown(Key.SHIFT) ? MICRO_CURSOR_MOVE_DISTANCE : MACRO_CURSOR_MOVE_DISTANCE;
406
407 // Calculate the new cursor position
408 Point cursorPosition = EcosystemManager.getInputManager().getCursorPosition();
409 if (kbmEvent.getKeyDown() == Key.UP_ARROW) cursorPosition.y -= distance;
410 if (kbmEvent.getKeyDown() == Key.DOWN_ARROW) cursorPosition.y += distance;
411 if (kbmEvent.getKeyDown() == Key.LEFT_ARROW) cursorPosition.x -= distance;
412 if (kbmEvent.getKeyDown() == Key.RIGHT_ARROW) cursorPosition.x += distance;
413
414 // Create the MOVE_CURSOR gesture and return it
415 Gesture moveCursorGesture = new Gesture(StandardGestureActions.getInstance().gestureType(StandardGestureType.MOVE_CURSOR), new SelectAreaGestureData(cursorPosition));
416 moveCursorGesture.setRobotic(true);
417 return Gesture.single(moveCursorGesture);
418 }
419 });
420
421 // Add the F1/F2 -> ZOOM_IN/OUT gesture recogniser
422 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
423 {
424 private final float ZOOM_IN_SCALE_FACTOR = 1.1f;
425 private final float ZOOM_OUT_SCALE_FACTOR = 1f / ZOOM_IN_SCALE_FACTOR;
426
427 @Override
428 public String details() { return "F1/F2 -> ZOOM_IN/OUT"; }
429
430 @Override
431 public List<Gesture> onInputEvent(InputEvent event) {
432 // Cast to keyboard/mouse event
433 KBMInputEvent kbmEvent = (KBMInputEvent) event;
434
435 // Decide on a scale factor
436 float scaleFactor;
437 if (kbmEvent.getKeyDown() == KBMInputEvent.Key.F1) {
438 scaleFactor = ZOOM_IN_SCALE_FACTOR;
439 } else if (kbmEvent.getKeyDown() == KBMInputEvent.Key.F2) {
440 scaleFactor = ZOOM_OUT_SCALE_FACTOR;
441 } else {
442 return null;
443 }
444
445 // Return if zoom is disabled
446 if (!ExperimentalFeatures.FrameZoom.get()) return null;
447
448 // Make sure we are pointing at free space (or the frame name)
449 Item currentItem = FrameUtils.getCurrentItem();
450 Collection<Item> currentItems = FrameUtils.getCurrentItems(currentItem);
451 if ((currentItem != null && !currentItem.isFrameName()) || (currentItems != null && currentItems.size() > 0)) return null;
452
453 // Decide on where to zoom around
454 Point centreOfZoom;
455 if (ExperimentalFeatures.FrameZoomAroundCursor.get()) {
456 centreOfZoom = EcosystemManager.getInputManager().getCursorPosition();
457 } else {
458 centreOfZoom = new Point(0, 0);
459 }
460
461 // Return zoom gesture
462 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.ZOOM), new ZoomGestureData(centreOfZoom, scaleFactor));
463 }
464 });
465
466 // Add the F1/F2 -> SCALE gesture recogniser
467 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
468 {
469 private final int SCALE_UP_FACTOR = 1;
470 private final int SCALE_DOWN_FACTOR = -1;
471
472 @Override
473 public String details() { return "F1/F2 -> SCALE"; }
474
475 @Override
476 public List<Gesture> onInputEvent(InputEvent event) {
477 // Cast to keyboard/mouse event
478 KBMInputEvent kbmEvent = (KBMInputEvent) event;
479
480 // Decide whether to scale up or down or not at all
481 int scaleFactor;
482 if (kbmEvent.getKeyDown() == KBMInputEvent.Key.F1) {
483 scaleFactor = SCALE_UP_FACTOR;
484 } else if (kbmEvent.getKeyDown() == KBMInputEvent.Key.F2) {
485 scaleFactor = SCALE_DOWN_FACTOR;
486 } else {
487 return null;
488 }
489
490 // Decide where to scale around
491 ScaleGestureData data;
492 if (kbmTranslator.isKeyDown(Key.CTRL)) {
493 data = new ScaleGestureData(scaleFactor);
494 } else {
495 data = new ScaleGestureData(null, scaleFactor);
496 }
497
498 // Return scale gestures
499 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.SCALE), data);
500 }
501 });
502
503 // Add the F3 -> CHANGE_COLOUR gesture recogniser
504 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
505 {
506 @Override
507 public String details() { return "F3 -> CHANGE_COLOUR"; }
508
509 @Override
510 public List<Gesture> onInputEvent(InputEvent event) {
511 // Cast to keyboard/mouse event
512 KBMInputEvent kbmEvent = (KBMInputEvent) event;
513
514 // Must be pressing F3 to change colours
515 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F3) return null;
516
517 // Decide how to change the colour
518 boolean shouldSetTransparent = kbmTranslator.isKeyDown(Key.SHIFT);
519 boolean shouldSetSecondaryColour = kbmTranslator.isKeyDown(Key.CTRL);
520
521 // Return the gesture
522 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CHANGE_COLOUR), new ChangeColourGestureData(shouldSetTransparent, shouldSetSecondaryColour));
523 }
524 });
525
526 // Add the F4 -> TOGGLE_ANNOTATION gesture recogniser
527 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
528 {
529 @Override
530 public String details() { return "F4 -> TOGGLE_ANNOTATION"; }
531
532 @Override
533 public List<Gesture> onInputEvent(InputEvent event) {
534 // Cast to keyboard/mouse event
535 KBMInputEvent kbmEvent = (KBMInputEvent) event;
536
537 // Must be pressing F4 to toggle annotations
538 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F4) return null;
539
540 // Return the gesture
541 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.TOGGLE_ANNOTATION), new ItemSpecificGestureData());
542 }
543 });
544
545 // Add the F5 -> INSERT_DATE gesture recogniser
546 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
547 {
548 @Override
549 public String details() { return "F5 -> INSERT_DATE"; }
550
551 @Override
552 public List<Gesture> onInputEvent(InputEvent event) {
553 // Cast to keyboard/mouse event
554 KBMInputEvent kbmEvent = (KBMInputEvent) event;
555
556 // Must be pressing F5 to insert the date
557 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F5) return null;
558
559 // Return the gesture
560 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.INSERT_DATE), new ItemSpecificGestureData());
561 }
562 });
563
564 // Add the F6 -> NEW_FRAMESET gesture recogniser
565 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
566 {
567 @Override
568 public String details() { return "F6 -> NEW_FRAMESET"; }
569
570 @Override
571 public List<Gesture> onInputEvent(InputEvent event) {
572 // Cast to keyboard/mouse event
573 KBMInputEvent kbmEvent = (KBMInputEvent) event;
574
575 // Must be pressing F6 to create a new frameset
576 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F6) return null;
577
578 // Return the gesture
579 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.NEW_FRAMESET), new ItemSpecificGestureData());
580 }
581 });
582
583 // Add the F7 -> ROTATE_FONT_STYLE gesture recogniser
584 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
585 {
586 @Override
587 public String details() { return "F7 -> ROTATE_FONT_STYLE"; }
588
589 @Override
590 public List<Gesture> onInputEvent(InputEvent event) {
591 // Cast to keyboard/mouse event
592 KBMInputEvent kbmEvent = (KBMInputEvent) event;
593
594 // Must be pressing F7 to rotate font style
595 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F7) return null;
596
597 // Return the gesture
598 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.ROTATE_FONT_STYLE), new ItemSpecificGestureData());
599 }
600 });
601
602 // Add the F8 -> ROTATE_FONT_FAMILY gesture recogniser
603 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
604 {
605 @Override
606 public String details() { return "F8 -> ROTATE_FONT_FAMILY"; }
607
608 @Override
609 public List<Gesture> onInputEvent(InputEvent event) {
610 // Cast to keyboard/mouse event
611 KBMInputEvent kbmEvent = (KBMInputEvent) event;
612
613 // Must be pressing F8 to rotate font family
614 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F8) return null;
615
616 // Return the gesture
617 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.ROTATE_FONT_FAMILY), new ItemSpecificGestureData());
618 }
619 });
620
621 // Add the F9 -> TOGGLE_AUDIENCE_MODE gesture recogniser
622 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
623 {
624 @Override
625 public String details() { return "F9 -> TOGGLE_AUDIENCE_MODE"; }
626
627 @Override
628 public List<Gesture> onInputEvent(InputEvent event) {
629 // Cast to keyboard/mouse event
630 KBMInputEvent kbmEvent = (KBMInputEvent) event;
631
632 // Must be pressing F9 to toggle audience mode
633 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F9) return null;
634
635 // Return the gesture
636 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.ROTATE_DISPLAY_MODE), null);
637 }
638 });
639
640 // Add the F10 -> TOGGLE_XRAY_MODE gesture recogniser
641 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
642 {
643 @Override
644 public String details() { return "F10 -> TOGGLE_XRAY_MODE"; }
645
646 @Override
647 public List<Gesture> onInputEvent(InputEvent event) {
648 // Cast to keyboard/mouse event
649 KBMInputEvent kbmEvent = (KBMInputEvent) event;
650
651 // Must be pressing F10 to xray mode
652 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F10) return null;
653
654 // Return the gesture
655 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.TOGGLE_XRAY_MODE), null);
656 }
657 });
658
659 // Add the F11 -> SAVE gesture recogniser
660 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
661 {
662 @Override
663 public String details() { return "F11 -> SAVE"; }
664
665 @Override
666 public List<Gesture> onInputEvent(InputEvent event) {
667 // Cast to keyboard/mouse event
668 KBMInputEvent kbmEvent = (KBMInputEvent) event;
669
670 // Must be pressing F11 to save
671 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F11) return null;
672
673 // Return the gesture
674 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.SAVE), null);
675 }
676 });
677
678 // Add the F12 -> REFRESH gesture recogniser
679 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
680 {
681 @Override
682 public String details() { return "F12 -> REFRESH"; }
683
684 @Override
685 public List<Gesture> onInputEvent(InputEvent event) {
686 // Cast to keyboard/mouse event
687 KBMInputEvent kbmEvent = (KBMInputEvent) event;
688
689 // Must be pressing F12 to refresh
690 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F12) return null;
691
692 // Decide how to refresh
693 boolean shouldReloadFrameFirst = kbmTranslator.isKeyDown(Key.CTRL);
694 boolean shouldRefreshFrameSize = kbmTranslator.isKeyDown(Key.SHIFT);
695
696 // Return the gesture
697 return standardSingle(StandardGestureType.REFRESH, new RefreshGestureData(shouldReloadFrameFirst, shouldRefreshFrameSize));
698 }
699 });
700
701 // Add the ESC -> DROP_DOWN gesture recogniser
702 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
703 {
704 @Override
705 public String details() { return "ESC -> DROP_DOWN"; }
706
707 @Override
708 public List<Gesture> onInputEvent(InputEvent event) {
709 // Cast to keyboard/mouse event
710 KBMInputEvent kbmEvent = (KBMInputEvent) event;
711
712 // Shift/Ctrl + Esc is calculate
713 if (kbmTranslator.isKeyDown(Key.SHIFT) || kbmTranslator.isKeyDown(Key.CTRL)) return null;
714
715 // Must be pressing ESC to drop down
716 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.ESC) return null;
717
718 // Return the gesture
719 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.DROP_DOWN), null);
720 }
721 });
722
723 // Add the SHIFT/CTRL + ESC -> CALCULATE gesture recogniser
724 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
725 {
726 @Override
727 public String details() { return "SHIFT/CTRL + ESC -> CALCULATE"; }
728
729 @Override
730 public List<Gesture> onInputEvent(InputEvent event) {
731 // Cast to keyboard/mouse event
732 KBMInputEvent kbmEvent = (KBMInputEvent) event;
733
734 // Check that shift or ctrl is down
735 if (!kbmTranslator.isKeyDown(Key.SHIFT) && !kbmTranslator.isKeyDown(Key.CTRL)) return null;
736
737 // Must be pressing Esc to calculate
738 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.ESC) return null;
739
740 // Return the gesture
741 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CALCULATE), new ItemSpecificGestureData());
742 }
743 });
744
745 // Add the CTRL + TAB -> CALCULATE gesture recogniser
746 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
747 {
748 @Override
749 public String details() { return "CTRL + TAB -> CALCULATE"; }
750
751 @Override
752 public List<Gesture> onInputEvent(InputEvent event) {
753 // Cast to keyboard/mouse event
754 KBMInputEvent kbmEvent = (KBMInputEvent) event;
755
756 // Check that ctrl is down
757 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
758
759 // Must be pressing tab to calculate
760 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.TAB) return null;
761
762 // Return the gesture
763 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CALCULATE), new ItemSpecificGestureData());
764 }
765 });
766
767 // Add the CTRL + L -> LINK gesture recogniser
768 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
769 {
770 @Override
771 public String details() { return "CTRL + L -> LINK"; }
772
773 @Override
774 public List<Gesture> onInputEvent(InputEvent event) {
775 // Cast to keyboard/mouse event
776 KBMInputEvent kbmEvent = (KBMInputEvent) event;
777
778 // Check that ctrl is down
779 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
780
781 // Must be pressing L to link
782 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.L) return null;
783
784 // Return the gesture
785 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.LINK), new LinkGestureData(false));
786 }
787 });
788
789 // Add the CTRL + G -> LINK gesture recogniser
790 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
791 {
792 @Override
793 public String details() { return "CTRL + G -> LINK"; }
794
795 @Override
796 public List<Gesture> onInputEvent(InputEvent event) {
797 // Cast to keyboard/mouse event
798 KBMInputEvent kbmEvent = (KBMInputEvent) event;
799
800 // Check that ctrl is down
801 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
802
803 // Must be pressing G to link
804 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.G) return null;
805
806 // Return the gesture
807 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.LINK), new LinkGestureData(true));
808 }
809 });
810
811 // Add the CTRL + A -> ACTION gesture recogniser
812 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
813 {
814 @Override
815 public String details() { return "CTRL + A -> ACTION"; }
816
817 @Override
818 public List<Gesture> onInputEvent(InputEvent event) {
819 // Cast to keyboard/mouse event
820 KBMInputEvent kbmEvent = (KBMInputEvent) event;
821
822 // Check that ctrl is down
823 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
824
825 // Must be pressing A to action
826 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.A) return null;
827
828 // Return the gesture
829 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.ACTION), new ItemSpecificGestureData());
830 }
831 });
832
833 // Add the CTRL + B -> TOGGLE_BOLD gesture recogniser
834 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
835 {
836 @Override
837 public String details() { return "CTRL + B -> TOGGLE_BOLD"; }
838
839 @Override
840 public List<Gesture> onInputEvent(InputEvent event) {
841 // Cast to keyboard/mouse event
842 KBMInputEvent kbmEvent = (KBMInputEvent) event;
843
844 // Check that ctrl is down
845 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
846
847 // Must be pressing B to toggle bold
848 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.B) return null;
849
850 // Return the gesture
851 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.TOGGLE_BOLD), new ItemSpecificGestureData());
852 }
853 });
854
855 // Add the CTRL + I -> TOGGLE_ITALICS gesture recogniser
856 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
857 {
858 @Override
859 public String details() { return "CTRL + I -> TOGGLE_ITALICS"; }
860
861 @Override
862 public List<Gesture> onInputEvent(InputEvent event) {
863 // Cast to keyboard/mouse event
864 KBMInputEvent kbmEvent = (KBMInputEvent) event;
865
866 // Check that ctrl is down
867 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
868
869 // Must be pressing I to toggle italics
870 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.I) return null;
871
872 // Return the gesture
873 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.TOGGLE_ITALICS), new ItemSpecificGestureData());
874 }
875 });
876
877 // Add the CTRL + V -> PASTE gesture recogniser
878 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
879 {
880 @Override
881 public String details() { return "CTRL + V -> PASTE"; }
882
883 @Override
884 public List<Gesture> onInputEvent(InputEvent event) {
885 // Cast to keyboard/mouse event
886 KBMInputEvent kbmEvent = (KBMInputEvent) event;
887
888 // Check that ctrl is down
889 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
890
891 // Must be pressing V to paste
892 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.V) return null;
893
894 // Return the gesture
895 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PASTE), null);
896 }
897 });
898
899 // Add the CTRL + C -> COPY gesture recogniser
900 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
901 {
902 @Override
903 public String details() { return "CTRL + C -> COPY"; }
904
905 @Override
906 public List<Gesture> onInputEvent(InputEvent event) {
907 // Cast to keyboard/mouse event
908 KBMInputEvent kbmEvent = (KBMInputEvent) event;
909
910 // Check that ctrl is down
911 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
912
913 // Must be pressing C to copy
914 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.C) return null;
915
916 // Return the gesture
917 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.COPY), new ItemSpecificGestureData());
918 }
919 });
920
921 // Add the CTRL + C -> MAKE_CIRCLE gesture recogniser
922 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
923 {
924 @Override
925 public String details() { return "CTRL + C -> MAKE_CIRCLE"; }
926
927 @Override
928 public List<Gesture> onInputEvent(InputEvent event) {
929 // Cast to keyboard/mouse event
930 KBMInputEvent kbmEvent = (KBMInputEvent) event;
931
932 // Check that ctrl is down
933 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
934
935 // Must be pressing C to make circle
936 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.C) return null;
937
938 // Make sure we aren't trying to do a copy-clone
939 if (FreeItems.hasItemsAttachedToCursor()) return null;
940
941 // Return the gesture
942 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.MAKE_CIRCLE), new ItemSpecificGestureData());
943 }
944 });
945
946 // Add the CTRL + X -> CUT gesture recogniser
947 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
948 {
949 @Override
950 public String details() { return "CTRL + X -> CUT"; }
951
952 @Override
953 public List<Gesture> onInputEvent(InputEvent event) {
954 // Cast to keyboard/mouse event
955 KBMInputEvent kbmEvent = (KBMInputEvent) event;
956
957 // Check that ctrl is down
958 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
959
960 // Must be pressing X to cut
961 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.X) return null;
962
963 // Return the gesture
964 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CUT), null);
965 }
966 });
967
968 // Add the CTRL + M -> TOGGLE_ITEMS_MARK gesture recogniser
969 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
970 {
971 @Override
972 public String details() { return "CTRL + M -> TOGGLE_ITEMS_MARK"; }
973
974 @Override
975 public List<Gesture> onInputEvent(InputEvent event) {
976 // Cast to keyboard/mouse event
977 KBMInputEvent kbmEvent = (KBMInputEvent) event;
978
979 // Check that ctrl is down
980 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
981
982 // Must be pressing M to toggle items mark
983 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.M) return null;
984
985 // Return the gesture
986 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.TOGGLE_ITEMS_MARK), new ItemSpecificGestureData());
987 }
988 });
989
990 // Add the CTRL + Z -> UNDO gesture recogniser
991 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
992 {
993 @Override
994 public String details() { return "CTRL + Z -> UNDO"; }
995
996 @Override
997 public List<Gesture> onInputEvent(InputEvent event) {
998 // Cast to keyboard/mouse event
999 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1000
1001 // Check that ctrl is down
1002 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
1003
1004 // Must be pressing Z to undo
1005 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.X) return null;
1006
1007 // Holding shift as well makes this a redo gesture
1008 boolean redo = kbmTranslator.isKeyDown(Key.SHIFT);
1009
1010 // Return the gesture
1011 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.UNDO), new UndoGestureData(redo));
1012 }
1013 });
1014
1015 // Add the CTRL + D -> INSERT_STRING gesture recogniser
1016 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1017 {
1018 @Override
1019 public String details() { return "CTRL + D -> INSERT_STRING"; }
1020
1021 @Override
1022 public List<Gesture> onInputEvent(InputEvent event) {
1023 // Cast to keyboard/mouse event
1024 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1025
1026 // Check that ctrl is down
1027 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
1028
1029 // Must be pressing D to delete character
1030 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.D) return null;
1031
1032 // Return the gesture
1033 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.INSERT_STRING), new InsertStringGestureData(Text.DELETE_CHARACTER, false));
1034 }
1035 });
1036
1037 // Add the CTRL + DELETE -> DELETE gesture recogniser
1038 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1039 {
1040 @Override
1041 public String details() { return "CTRL + DELETE -> DELETE"; }
1042
1043 @Override
1044 public List<Gesture> onInputEvent(InputEvent event) {
1045 // Cast to keyboard/mouse event
1046 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1047
1048 // Check that ctrl is down
1049 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
1050
1051 // Must be pressing DELETE to delete
1052 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.DELETE) return null;
1053
1054 // Decide if this is an alternate mode delete
1055 // TODO: What specifically is alternate mode delete? cts16
1056 boolean alternateMode = kbmTranslator.isKeyDown(Key.SHIFT);
1057
1058 // Return the gesture
1059 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.DELETE), new DeleteGestureData(alternateMode));
1060 }
1061 });
1062
1063 // Add the CTRL + F -> FORMAT gesture recogniser
1064 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1065 {
1066 @Override
1067 public String details() { return "CTRL + F -> FORMAT"; }
1068
1069 @Override
1070 public List<Gesture> onInputEvent(InputEvent event) {
1071 // Cast to keyboard/mouse event
1072 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1073
1074 // Check that ctrl is down
1075 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
1076
1077 // Must be pressing F to format
1078 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F) return null;
1079
1080 // Decide if this is an horizontal or vertical format
1081 boolean horizontal = kbmTranslator.isKeyDown(Key.SHIFT);
1082
1083 // Return the gesture
1084 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.FORMAT), new FormatGestureData(horizontal));
1085 }
1086 });
1087
1088 // Add the CTRL + J -> JUSTIFY gesture recogniser
1089 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1090 {
1091 @Override
1092 public String details() { return "CTRL + J -> JUSTIFY"; }
1093
1094 @Override
1095 public List<Gesture> onInputEvent(InputEvent event) {
1096 // Cast to keyboard/mouse event
1097 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1098
1099 // Check that ctrl is down
1100 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
1101
1102 // Must be pressing J to justify
1103 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.J) return null;
1104
1105 // Return the gesture
1106 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.JUSTIFY), new JustifyGestureData(false));
1107 }
1108 });
1109
1110 // Add the CTRL + R -> JUSTIFY gesture recogniser
1111 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1112 {
1113 @Override
1114 public String details() { return "CTRL + R -> JUSTIFY"; }
1115
1116 @Override
1117 public List<Gesture> onInputEvent(InputEvent event) {
1118 // Cast to keyboard/mouse event
1119 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1120
1121 // Check that ctrl is down
1122 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
1123
1124 // Must be pressing R to justify
1125 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.R) return null;
1126
1127 // Return the gesture
1128 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.JUSTIFY), new JustifyGestureData(true));
1129 }
1130 });
1131
1132 // Add the CTRL + S -> SAVE gesture recogniser
1133 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1134 {
1135 @Override
1136 public String details() { return "CTRL + S -> SAVE"; }
1137
1138 @Override
1139 public List<Gesture> onInputEvent(InputEvent event) {
1140 // Cast to keyboard/mouse event
1141 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1142
1143 // Check that ctrl is down
1144 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
1145
1146 // Ctrl + Shift + S is split text
1147 if (kbmTranslator.isKeyDown(Key.SHIFT)) return null;
1148
1149 // Must be pressing S to save
1150 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.S) return null;
1151
1152 // Return the gesture
1153 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.SAVE), null);
1154 }
1155 });
1156
1157 // Add the CTRL + SHIFT + S -> SPLIT_TEXT gesture recogniser
1158 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1159 {
1160 @Override
1161 public String details() { return "CTRL + SHIFT + S -> SPLIT_TEXT"; }
1162
1163 @Override
1164 public List<Gesture> onInputEvent(InputEvent event) {
1165 // Cast to keyboard/mouse event
1166 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1167
1168 // Check that ctrl is down
1169 if (!kbmTranslator.isKeyDown(Key.CTRL)) return null;
1170
1171 // Ctrl + Shift + S is split text
1172 if (!kbmTranslator.isKeyDown(Key.SHIFT)) return null;
1173
1174 // Must be pressing S to save
1175 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.S) return null;
1176
1177 // Return the gesture
1178 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.SPLIT_TEXT), new ItemSpecificGestureData());
1179 }
1180 });
1181
1182 // Add the MIDDLE MOUSE + MOUSE_MOVE -> PICK_UP gesture recogniser
1183 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1184 {
1185 private SelectAreaGestureData _draggedFromData = null;
1186
1187 @Override
1188 public String details() { return "MIDDLE MOUSE + MOUSE_MOVE -> PICK_UP"; }
1189
1190 @Override
1191 public List<Gesture> onInputEvent(InputEvent event) {
1192 // Cast to keyboard/mouse event
1193 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1194
1195 // Check we are holding the middle button only
1196 if (!kbmTranslator.isOnlyMouseButtonDown(MouseButton.MIDDLE)) {
1197 // If we were dragging, reset the dragging tracker and send the drag-finished gesture
1198 if (_draggedFromData != null) {
1199 SelectAreaGestureData finalData = _draggedFromData.finalise();
1200 _draggedFromData = null;
1201 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PICK_UP), finalData);
1202
1203 // Otherwise just return
1204 } else {
1205 return null;
1206 }
1207 }
1208
1209 // Check if it's a mouse movement event
1210 if (kbmEvent.getEventType() != KBMInputEvent.EventType.MOUSE_MOVE) return null;
1211
1212 // See if we should inherit the attributes of the thing we're picking up
1213 boolean inheritAttributes = kbmTranslator.isKeyDown(Key.SHIFT);
1214
1215 // If we are just starting to drag, save the start position of the gesture
1216 if (_draggedFromData == null) {
1217 _draggedFromData = new PickUpGestureData(kbmEvent.getMouseMove().getSecondEnd().clone(), kbmEvent.getMouseMove().getFirstEnd().clone(), false, inheritAttributes);
1218 }
1219
1220 // Wait till we have moved out of no-op range before performing drag-pickup
1221 if (!isMouseDragNoOp()) return null;
1222
1223 // Generate a PICK_UP gesture
1224 _draggedFromData = _draggedFromData.carryOn(kbmEvent.getMouseMove().getSecondEnd().clone());
1225 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PICK_UP), _draggedFromData);
1226 }
1227 });
1228
1229 // Add the MIDDLE MOUSE -> PICK_UP gesture recogniser
1230 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1231 {
1232 private Boolean _pickup = null;
1233 private Item _clickDownOn = null;
1234
1235 @Override
1236 public String details() { return "MIDDLE MOUSE -> PICK_UP"; }
1237
1238 @Override
1239 public List<Gesture> onInputEvent(InputEvent event) {
1240 // Cast to keyboard/mouse event
1241 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1242
1243 // Check for single middle click
1244 if (_pickup == null && kbmEvent.getMouseButtonDown() == MouseButton.MIDDLE) {
1245 _pickup = true;
1246 _clickDownOn = FrameUtils.getCurrentItem();
1247 return null;
1248 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1249 _pickup = false;
1250 return null;
1251 } else if (Boolean.FALSE.equals(_pickup) && kbmTranslator.isAnyMouseButtonDown() == false) {
1252 _pickup = null;
1253 return null;
1254 }
1255
1256 // Wait for the button up to perform the pickup
1257 if (!Boolean.TRUE.equals(_pickup) || kbmEvent.getMouseButtonUp() != MouseButton.MIDDLE) return null;
1258
1259 // Reset pickup for next gesture
1260 _pickup = null;
1261
1262 // Check we haven't moved too far
1263 if (isMouseDragNoOp()) {
1264 if (!(_clickDownOn instanceof Text)) printNoopMessage();
1265 return null;
1266 }
1267
1268 // Check we should be picking up (shift forces line creation)
1269 if (FreeItems.hasItemsAttachedToCursor() || kbmTranslator.isKeyDown(Key.SHIFT)) return null;
1270
1271 // Check there is something to pick up
1272 if (!FrameUtils.hasCurrentItem() && FrameUtils.getCurrentItems() == null) return null;
1273
1274 // Return the gesture
1275 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PICK_UP), new PickUpGestureData(false));
1276 }
1277 });
1278
1279 // Add the RIGHT MOUSE + MOUSE_MOVE -> PICK_UP gesture recogniser
1280 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1281 {
1282 private SelectAreaGestureData _draggedFromData = null;
1283
1284 @Override
1285 public String details() { return "RIGHT MOUSE + MOUSE_MOVE -> PICK_UP"; }
1286
1287 @Override
1288 public List<Gesture> onInputEvent(InputEvent event) {
1289 // Cast to keyboard/mouse event
1290 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1291
1292 // Check we are holding the middle button only
1293 if (!kbmTranslator.isOnlyMouseButtonDown(MouseButton.RIGHT)) {
1294 // If we were dragging, reset the dragging tracker and send the drag-finished gesture
1295 if (_draggedFromData != null) {
1296 SelectAreaGestureData finalData = _draggedFromData.finalise();
1297 _draggedFromData = null;
1298 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PICK_UP), finalData);
1299
1300 // Otherwise just return
1301 } else {
1302 return null;
1303 }
1304 }
1305
1306 // Check if it's a mouse movement event
1307 if (kbmEvent.getEventType() != KBMInputEvent.EventType.MOUSE_MOVE) return null;
1308
1309 // See if we should inherit the attributes of the thing we're picking up
1310 boolean inheritAttributes = kbmTranslator.isKeyDown(Key.SHIFT);
1311
1312 // If we are just starting to drag, save the start position of the gesture
1313 if (_draggedFromData == null) {
1314 _draggedFromData = new PickUpGestureData(kbmEvent.getMouseMove().getSecondEnd().clone(), kbmEvent.getMouseMove().getFirstEnd().clone(), true, inheritAttributes);
1315 }
1316
1317 // Wait till we have moved out of no-op range before performing drag-pickup
1318 if (!isMouseDragNoOp()) return null;
1319
1320 // Generate a PICK_UP gesture
1321 _draggedFromData = _draggedFromData.carryOn(kbmEvent.getMouseMove().getSecondEnd().clone());
1322 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PICK_UP), _draggedFromData);
1323 }
1324 });
1325
1326 // Add the RIGHT MOUSE -> PICK_UP gesture recogniser
1327 addTranslator(new InputEventToGestureTranslator(new InputType[] { InputType.KBM, InputType.TIMEOUT })
1328 {
1329 private final static int EXTRUSION_DELAY_MS = 750;
1330 private final static int PULSE_AMOUNT = 2;
1331 private Boolean _pickup = null;
1332 private Item _clickedItem = null;
1333 private TimeoutHandle _timeoutHandle;
1334 private boolean _extrusionDelayExpired = false;
1335
1336 @Override
1337 public String details() { return "RIGHT MOUSE -> PICK_UP"; }
1338
1339 public List<Gesture> onInputEvent(InputEvent event)
1340 {
1341 if (event == null) {
1342 return null;
1343 } else if (event.getInputType() == InputType.KBM) {
1344 return onKBMInputEvent((KBMInputEvent) event);
1345 } else if (event.getInputType() == InputType.TIMEOUT) {
1346 return onTimeoutInputEvent((TimeoutInputEvent) event);
1347 }
1348
1349 return null;
1350 }
1351
1352 private List<Gesture> onKBMInputEvent(KBMInputEvent kbmEvent)
1353 {
1354 // Check for single right click
1355 if (_pickup == null && kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1356 _pickup = true;
1357 _timeoutHandle = EcosystemManager.getInputManager().addTimeout(EXTRUSION_DELAY_MS);
1358 _extrusionDelayExpired = false;
1359 _clickedItem = FrameUtils.getCurrentItem();
1360 return null;
1361 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1362 _pickup = false;
1363 EcosystemManager.getInputManager().cancelTimeout(_timeoutHandle);
1364 return null;
1365 } else if (Boolean.FALSE.equals(_pickup) && kbmTranslator.isAnyMouseButtonDown() == false) {
1366 _pickup = null;
1367 return null;
1368 }
1369
1370 // Wait for the button up to perform the pickup
1371 if (!Boolean.TRUE.equals(_pickup) || kbmEvent.getMouseButtonUp() != MouseButton.RIGHT) return null;
1372
1373 // Reset pickup for next gesture
1374 _pickup = null;
1375
1376 // Cancel the extrusion timeout if it's pending
1377 EcosystemManager.getInputManager().cancelTimeout(_timeoutHandle);
1378
1379 // Reset the line pulse if it occured
1380 if (_extrusionDelayExpired) pulseExtrusionLines(false);
1381
1382 // Check we haven't moved too far
1383 if (isMouseDragNoOp()) {
1384 printNoopMessage();
1385 return null;
1386 }
1387
1388 // Check we should be picking up (shift forces line creation)
1389 if (FreeItems.hasItemsAttachedToCursor() || kbmTranslator.isKeyDown(Key.SHIFT)) return null;
1390
1391 // Check there is something to pick up
1392 if (!FrameUtils.hasCurrentItem() && FrameUtils.getCurrentItems() == null) return null;
1393
1394 // Return the gesture
1395 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PICK_UP), new PickUpGestureData(true, _extrusionDelayExpired));
1396 }
1397
1398 private List<Gesture> onTimeoutInputEvent(TimeoutInputEvent event)
1399 {
1400 if (event.getHandle() == _timeoutHandle) {
1401 _extrusionDelayExpired = true;
1402 pulseExtrusionLines(true);
1403 }
1404
1405 return null;
1406 }
1407
1408 private void pulseExtrusionLines(boolean pulseOn)
1409 {
1410 int amount = PULSE_AMOUNT;
1411 if (!pulseOn) amount *= -1;
1412
1413 if (_clickedItem != null) {
1414 for (Item i : _clickedItem.getAllConnected()) {
1415 if (i instanceof Line) {
1416 Line line = (Line) i;
1417 line.setThickness(line.getThickness() + amount);
1418 }
1419 }
1420 }
1421
1422 DisplayController.requestRefresh(true);
1423 }
1424 });
1425
1426 // Add the MIDDLE MOUSE -> PLACE gesture recogniser
1427 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1428 {
1429 Boolean _place = null;
1430
1431 @Override
1432 public String details() { return "MIDDLE MOUSE -> PLACE"; }
1433
1434 @Override
1435 public List<Gesture> onInputEvent(InputEvent event) {
1436 // Cast to keyboard/mouse event
1437 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1438
1439 // Check for single middle click
1440 if (_place == null && kbmEvent.getMouseButtonDown() == MouseButton.MIDDLE) {
1441 _place = true;
1442 return null;
1443 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1444 _place = false;
1445 return null;
1446 } else if (Boolean.FALSE.equals(_place) && isAnyMouseButtonDown() == false) {
1447 _place = null;
1448 return null;
1449 }
1450
1451 // Wait for the button up to perform the place
1452 if (!Boolean.TRUE.equals(_place) || kbmEvent.getMouseButtonUp() != MouseButton.MIDDLE) return null;
1453
1454 // Reset place for next gesture
1455 _place = null;
1456
1457 // Check we haven't moved too far
1458 if (isMouseDragNoOp()) {
1459 printNoopMessage();
1460 return null;
1461 }
1462
1463 // Check we should be placing
1464 if (!FreeItems.hasItemsAttachedToCursor()) return null;
1465
1466 // Return the gesture
1467 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PLACE), new PickUpGestureData(false));
1468 }
1469 });
1470
1471 // Add the RIGHT MOUSE -> PLACE gesture recogniser
1472 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1473 {
1474 Boolean _place = null;
1475 @Override
1476 public String details() { return "RIGHT MOUSE -> PLACE"; }
1477
1478 @Override
1479 public List<Gesture> onInputEvent(InputEvent event) {
1480 // Cast to keyboard/mouse event
1481 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1482
1483 // Check for single right click
1484 if (_place == null && kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1485 _place = true;
1486 return null;
1487 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1488 _place = false;
1489 return null;
1490 } else if (Boolean.FALSE.equals(_place) && kbmTranslator.isAnyMouseButtonDown() == false) {
1491 _place = null;
1492 return null;
1493 }
1494
1495 // Wait for the button up to perform the place
1496 if (!Boolean.TRUE.equals(_place) || kbmEvent.getMouseButtonUp() != MouseButton.RIGHT) return null;
1497
1498 // Reset place for next gesture
1499 _place = null;
1500
1501 // Check we haven't moved too far
1502 if (isMouseDragNoOp()) {
1503 printNoopMessage();
1504 return null;
1505 }
1506
1507 // Check we should be placing
1508 if (!FreeItems.hasItemsAttachedToCursor()) return null;
1509
1510 // Return the gesture
1511 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PLACE), new PickUpGestureData(true));
1512 }
1513 });
1514
1515 // Add the MIDDLE + RIGHT MOUSE -> DELETE gesture recogniser
1516 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1517 {
1518 private static final int STATE_NO_MOUSE_BUTTON_DOWN = 0;
1519 private static final int STATE_MIDDLE_MOUSE_BUTTON_DOWN = 1;
1520 private static final int STATE_RIGHT_MOUSE_BUTTON_DOWN = 2;
1521 private static final int STATE_BOTH_MOUSE_BUTTON_DOWN = 3;
1522 private static final int STATE_ERROR = 4;
1523 private int _state = STATE_NO_MOUSE_BUTTON_DOWN;
1524
1525 @Override
1526 public String details() { return "MIDDLE + RIGHT MOUSE -> DELETE"; }
1527
1528 @Override
1529 public List<Gesture> onInputEvent(InputEvent event) {
1530 // Cast to keyboard/mouse event
1531 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1532
1533 // Keep track of mouse button state
1534 if (_state == STATE_NO_MOUSE_BUTTON_DOWN) {
1535 if (kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1536 _state = STATE_RIGHT_MOUSE_BUTTON_DOWN;
1537 } else if (kbmEvent.getMouseButtonDown() == MouseButton.MIDDLE) {
1538 _state = STATE_MIDDLE_MOUSE_BUTTON_DOWN;
1539 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1540 _state = STATE_ERROR;
1541 }
1542 return null;
1543 } else if (_state == STATE_MIDDLE_MOUSE_BUTTON_DOWN) {
1544 if (kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1545 _state = STATE_BOTH_MOUSE_BUTTON_DOWN;
1546 } else if (kbmEvent.getMouseButtonUp() == MouseButton.MIDDLE) {
1547 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1548 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1549 _state = STATE_ERROR;
1550 }
1551 return null;
1552 } else if (_state == STATE_RIGHT_MOUSE_BUTTON_DOWN) {
1553 if (kbmEvent.getMouseButtonDown() == MouseButton.MIDDLE) {
1554 _state = STATE_BOTH_MOUSE_BUTTON_DOWN;
1555 } else if (kbmEvent.getMouseButtonUp() == MouseButton.RIGHT) {
1556 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1557 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1558 _state = STATE_ERROR;
1559 }
1560 return null;
1561 } else if (_state == STATE_BOTH_MOUSE_BUTTON_DOWN) {
1562 if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1563 _state = STATE_ERROR;
1564 return null;
1565 }
1566 } else if (kbmTranslator.isAnyMouseButtonDown() == false) {
1567 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1568 return null;
1569 }
1570
1571 // Wait for the button up to perform the delete
1572 if (_state != STATE_BOTH_MOUSE_BUTTON_DOWN || kbmTranslator.isAnyMouseButtonDown()) return null;
1573
1574 // Reset state for next gesture
1575 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1576
1577 // Check we haven't moved too far
1578 if (isMouseDragNoOp()) {
1579 printNoopMessage();
1580 return null;
1581 }
1582
1583 // Decide if this is an alternate mode delete
1584 // TODO: What specifically is alternate mode delete? cts16
1585 boolean alternateMode = kbmTranslator.isKeyDown(Key.SHIFT);
1586
1587 // Return the gesture
1588 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.DELETE), new DeleteGestureData(alternateMode));
1589 }
1590 });
1591
1592 // Add the MIDDLE MOUSE -> CREATE_ITEM gesture recogniser
1593 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1594 {
1595 Boolean _create = null;
1596 @Override
1597 public String details() { return "MIDDLE MOUSE -> CREATE_ITEM"; }
1598
1599 @Override
1600 public List<Gesture> onInputEvent(InputEvent event) {
1601 // Cast to keyboard/mouse event
1602 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1603
1604 // Check for single middle click
1605 if (_create == null && kbmEvent.getMouseButtonDown() == MouseButton.MIDDLE) {
1606 _create = true;
1607 return null;
1608 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1609 _create = false;
1610 return null;
1611 } else if (Boolean.FALSE.equals(_create) && kbmTranslator.isAnyMouseButtonDown() == false) {
1612 _create = null;
1613 return null;
1614 }
1615
1616 // Wait for the button up to perform the create
1617 if (!Boolean.TRUE.equals(_create) || kbmEvent.getMouseButtonUp() != MouseButton.MIDDLE) return null;
1618
1619 // Reset create for next gesture
1620 _create = null;
1621
1622 // Check we haven't moved too far
1623 if (isMouseDragNoOp()) {
1624 printNoopMessage();
1625 return null;
1626 }
1627
1628 // Check we can create
1629 if (FreeItems.hasItemsAttachedToCursor()) return null;
1630
1631 // Check we're not trying to pick up (shift forces item creation)
1632 if (!kbmTranslator.isKeyDown(Key.SHIFT) && (FrameUtils.hasCurrentItem() || FrameUtils.getCurrentItems() != null)) return null;
1633
1634 // Return the gesture
1635 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CREATE_ITEM), new CreateItemGestureData(ItemType.LINE));
1636 }
1637 });
1638
1639 // Add the RIGHT MOUSE -> CREATE_ITEM gesture recogniser
1640 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1641 {
1642 Boolean _create = null;
1643 @Override
1644 public String details() { return "RIGHT MOUSE -> CREATE_ITEM"; }
1645
1646 @Override
1647 public List<Gesture> onInputEvent(InputEvent event) {
1648 // Cast to keyboard/mouse event
1649 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1650
1651 // Check for single middle click
1652 if (_create == null && kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1653 _create = true;
1654 return null;
1655 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1656 _create = false;
1657 return null;
1658 } else if (Boolean.FALSE.equals(_create) && kbmTranslator.isAnyMouseButtonDown() == false) {
1659 _create = null;
1660 return null;
1661 }
1662
1663 // Wait for the button up to perform the create
1664 if (!Boolean.TRUE.equals(_create) || kbmEvent.getMouseButtonUp() != MouseButton.RIGHT) return null;
1665
1666 // Reset create for next gesture
1667 _create = null;
1668
1669 // Check we haven't moved too far
1670 if (isMouseDragNoOp()) {
1671 printNoopMessage();
1672 return null;
1673 }
1674
1675 // Check we can create
1676 if (FreeItems.hasItemsAttachedToCursor()) return null;
1677
1678 // Check we're not trying to pick up (shift forces item creation)
1679 if (!kbmTranslator.isKeyDown(Key.SHIFT) && (FrameUtils.hasCurrentItem() || FrameUtils.getCurrentItems() != null)) return null;
1680
1681 // Return the gesture
1682 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CREATE_ITEM), new CreateItemGestureData(ItemType.BOX));
1683 }
1684 });
1685
1686 // Add the LEFT MOUSE -> CLICK gesture recogniser
1687 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1688 {
1689 private static final int LONG_CLICK_DELAY_MS = 500;
1690 private Boolean _click = null;
1691 private long _clickStartTime;
1692 @Override
1693 public String details() { return "LEFT MOUSE -> CLICK"; }
1694
1695 @Override
1696 public List<Gesture> onInputEvent(InputEvent event) {
1697 // Cast to keyboard/mouse event
1698 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1699
1700 // Check for single left click
1701 if (_click == null && kbmEvent.getMouseButtonDown() == MouseButton.LEFT) {
1702 _click = true;
1703 _clickStartTime = System.currentTimeMillis();
1704 return null;
1705 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1706 _click = false;
1707 return null;
1708 } else if (Boolean.FALSE.equals(_click) && kbmTranslator.isAnyMouseButtonDown() == false) {
1709 _click = null;
1710 return null;
1711 }
1712
1713 // Wait for the button up to perform the click
1714 if (!Boolean.TRUE.equals(_click) || kbmEvent.getMouseButtonUp() != MouseButton.LEFT) return null;
1715
1716 // Reset click for next gesture
1717 _click = null;
1718
1719 // Check if this is a long click
1720 boolean longClick = System.currentTimeMillis() >= _clickStartTime + LONG_CLICK_DELAY_MS;
1721
1722 // Check if we are toggling arrowhead
1723 if (longClick && FrameUtils.getCurrentItem() == null) {
1724 if (FreeItems.getInstance().size() <= 2) {
1725 for (Item i : FreeItems.getInstance()) {
1726 if (i instanceof Line) {
1727 return null;
1728 }
1729 }
1730 }
1731 }
1732
1733 // Check we haven't moved too far
1734 if (isMouseDragNoOp()) {
1735 printNoopMessage();
1736 return null;
1737 }
1738
1739 // Return the gesture
1740 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CLICK), new ClickGestureData(longClick));
1741 }
1742 });
1743
1744 // Add the LEFT MOUSE -> TOGGLE_ARROWHEAD gesture recogniser
1745 addTranslator(new InputEventToGestureTranslator(new InputType[] { InputType.KBM, InputType.TIMEOUT })
1746 {
1747 private static final int LONG_CLICK_DELAY_MS = 500;
1748 private Boolean _click = null;
1749 private TimeoutHandle _timeoutHandle = null;
1750
1751 @Override
1752 public String details() { return "LEFT MOUSE -> TOGGLE_ARROWHEAD"; }
1753
1754 @Override
1755 public List<Gesture> onInputEvent(InputEvent event)
1756 {
1757 if (event == null) {
1758 return null;
1759 } else if (event.getInputType() == InputType.KBM) {
1760 return onKBMInputEvent((KBMInputEvent) event);
1761 } else if (event.getInputType() == InputType.TIMEOUT) {
1762 return onTimeoutInputEvent((TimeoutInputEvent) event);
1763 }
1764
1765 return null;
1766 }
1767
1768 private List<Gesture> onKBMInputEvent(KBMInputEvent kbmEvent)
1769 {
1770 // Check for single left click
1771 if (_click == null && kbmEvent.getMouseButtonDown() == MouseButton.LEFT) {
1772 _click = true;
1773 _timeoutHandle = EcosystemManager.getInputManager().addTimeout(LONG_CLICK_DELAY_MS);
1774 return null;
1775 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1776 _click = false;
1777 EcosystemManager.getInputManager().cancelTimeout(_timeoutHandle);
1778 return null;
1779 } else if (Boolean.FALSE.equals(_click) && kbmTranslator.isAnyMouseButtonDown() == false) {
1780 _click = null;
1781 return null;
1782 }
1783
1784 // Wait for the button up to perform the click
1785 if (!Boolean.TRUE.equals(_click) || kbmEvent.getMouseButtonUp() != MouseButton.LEFT) return null;
1786
1787 // Reset click for next gesture
1788 _click = null;
1789
1790 // Cancel the timer if it's still pending
1791 EcosystemManager.getInputManager().cancelTimeout(_timeoutHandle);
1792
1793 return null;
1794 }
1795
1796 private List<Gesture> onTimeoutInputEvent(TimeoutInputEvent event)
1797 {
1798 if (event.getHandle() == _timeoutHandle) {
1799 // Check if we are toggling arrowhead
1800 Item line = null;
1801 if (FrameUtils.getCurrentItem() == null) {
1802 if (FreeItems.getInstance().size() <= 2) {
1803 for (Item i : FreeItems.getInstance()) {
1804 if (i instanceof Line) {
1805 line = i;
1806 }
1807 }
1808 }
1809 }
1810 if (line == null) return null;
1811
1812 // Check we haven't moved too far
1813 if (isMouseDragNoOp()) {
1814 printNoopMessage();
1815 return null;
1816 }
1817
1818 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.TOGGLE_ARROWHEAD), new ItemSpecificGestureData(line));
1819 }
1820
1821 // Someone else's timeout event
1822 return null;
1823 }
1824 });
1825
1826 // Add the LEFT + RIGHT MOUSE -> EXTRACT_ATTRIBUTES gesture recogniser
1827 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1828 {
1829 private static final int STATE_NO_MOUSE_BUTTON_DOWN = 0;
1830 private static final int STATE_LEFT_MOUSE_BUTTON_DOWN = 1;
1831 private static final int STATE_RIGHT_MOUSE_BUTTON_DOWN = 2;
1832 private static final int STATE_BOTH_MOUSE_BUTTON_DOWN = 3;
1833 private static final int STATE_ERROR = 4;
1834 private int _state = STATE_NO_MOUSE_BUTTON_DOWN;
1835
1836 @Override
1837 public String details() { return "LEFT + RIGHT MOUSE -> EXTRACT_ATTRIBUTES"; }
1838
1839 @Override
1840 public List<Gesture> onInputEvent(InputEvent event) {
1841 // Cast to keyboard/mouse event
1842 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1843
1844 // Keep track of mouse button state
1845 if (_state == STATE_NO_MOUSE_BUTTON_DOWN) {
1846 if (kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1847 _state = STATE_RIGHT_MOUSE_BUTTON_DOWN;
1848 } else if (kbmEvent.getMouseButtonDown() == MouseButton.LEFT) {
1849 _state = STATE_LEFT_MOUSE_BUTTON_DOWN;
1850 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1851 _state = STATE_ERROR;
1852 }
1853 return null;
1854 } else if (_state == STATE_LEFT_MOUSE_BUTTON_DOWN) {
1855 if (kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1856 _state = STATE_BOTH_MOUSE_BUTTON_DOWN;
1857 } else if (kbmEvent.getMouseButtonUp() == MouseButton.LEFT) {
1858 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1859 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1860 _state = STATE_ERROR;
1861 }
1862 return null;
1863 } else if (_state == STATE_RIGHT_MOUSE_BUTTON_DOWN) {
1864 if (kbmEvent.getMouseButtonDown() == MouseButton.LEFT) {
1865 _state = STATE_BOTH_MOUSE_BUTTON_DOWN;
1866 } else if (kbmEvent.getMouseButtonUp() == MouseButton.RIGHT) {
1867 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1868 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1869 _state = STATE_ERROR;
1870 }
1871 return null;
1872 } else if (_state == STATE_BOTH_MOUSE_BUTTON_DOWN) {
1873 if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1874 _state = STATE_ERROR;
1875 return null;
1876 }
1877 } else if (kbmTranslator.isAnyMouseButtonDown() == false) {
1878 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1879 return null;
1880 }
1881
1882 // Wait for the button up to perform the extraction
1883 if (_state != STATE_BOTH_MOUSE_BUTTON_DOWN || kbmTranslator.isAnyMouseButtonDown()) return null;
1884
1885 // Reset state for next gesture
1886 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1887
1888 // Check we haven't moved too far
1889 if (isMouseDragNoOp()) {
1890 printNoopMessage();
1891 return null;
1892 }
1893
1894 // Make sure we are over something to extract from
1895 if (!FrameUtils.hasCurrentItem()) return null;
1896
1897 // Return the gesture
1898 return standardSingle(StandardGestureType.EXTRACT_ATTRIBUTES, new ItemSpecificGestureData());
1899 }
1900 });
1901
1902 // Add the LEFT + RIGHT MOUSE -> FORMAT gesture recogniser
1903 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1904 {
1905 private static final int STATE_NO_MOUSE_BUTTON_DOWN = 0;
1906 private static final int STATE_LEFT_MOUSE_BUTTON_DOWN = 1;
1907 private static final int STATE_RIGHT_MOUSE_BUTTON_DOWN = 2;
1908 private static final int STATE_BOTH_MOUSE_BUTTON_DOWN = 3;
1909 private static final int STATE_ERROR = 4;
1910 private int _state = STATE_NO_MOUSE_BUTTON_DOWN;
1911
1912 @Override
1913 public String details() { return "LEFT + RIGHT MOUSE -> FORMAT"; }
1914
1915 @Override
1916 public List<Gesture> onInputEvent(InputEvent event) {
1917 // Cast to keyboard/mouse event
1918 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1919
1920 // Keep track of mouse button state
1921 if (_state == STATE_NO_MOUSE_BUTTON_DOWN) {
1922 if (kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1923 _state = STATE_RIGHT_MOUSE_BUTTON_DOWN;
1924 } else if (kbmEvent.getMouseButtonDown() == MouseButton.LEFT) {
1925 _state = STATE_LEFT_MOUSE_BUTTON_DOWN;
1926 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1927 _state = STATE_ERROR;
1928 }
1929 return null;
1930 } else if (_state == STATE_LEFT_MOUSE_BUTTON_DOWN) {
1931 if (kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1932 _state = STATE_BOTH_MOUSE_BUTTON_DOWN;
1933 } else if (kbmEvent.getMouseButtonUp() == MouseButton.LEFT) {
1934 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1935 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1936 _state = STATE_ERROR;
1937 }
1938 return null;
1939 } else if (_state == STATE_RIGHT_MOUSE_BUTTON_DOWN) {
1940 if (kbmEvent.getMouseButtonDown() == MouseButton.LEFT) {
1941 _state = STATE_BOTH_MOUSE_BUTTON_DOWN;
1942 } else if (kbmEvent.getMouseButtonUp() == MouseButton.RIGHT) {
1943 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1944 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1945 _state = STATE_ERROR;
1946 }
1947 return null;
1948 } else if (_state == STATE_BOTH_MOUSE_BUTTON_DOWN) {
1949 if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1950 _state = STATE_ERROR;
1951 return null;
1952 }
1953 } else if (kbmTranslator.isAnyMouseButtonDown() == false) {
1954 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1955 return null;
1956 }
1957
1958 // Wait for the button up to perform the extraction
1959 if (_state != STATE_BOTH_MOUSE_BUTTON_DOWN || kbmTranslator.isAnyMouseButtonDown()) return null;
1960
1961 // Reset state for next gesture
1962 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1963
1964 // Check we haven't moved too far
1965 if (isMouseDragNoOp()) {
1966 printNoopMessage();
1967 return null;
1968 }
1969
1970 // Make sure we are not extracting
1971 if (FrameUtils.hasCurrentItem()) return null;
1972
1973 // Return the gestures
1974 Gesture hFormat = new Gesture(StandardGestureActions.getInstance().gestureType(StandardGestureType.FORMAT), new FormatGestureData(true));
1975 Gesture vFormat = new Gesture(StandardGestureActions.getInstance().gestureType(StandardGestureType.FORMAT), new FormatGestureData(false));
1976 if (kbmTranslator.isKeyDown(Key.CTRL) && kbmTranslator.isKeyDown(Key.SHIFT)) {
1977 List<Gesture> gestures = Gesture.single(hFormat);
1978 gestures.add(vFormat);
1979 return gestures;
1980 } else if (kbmTranslator.isKeyDown(Key.CTRL)) {
1981 return Gesture.single(hFormat);
1982 } else {
1983 return Gesture.single(vFormat);
1984 }
1985 }
1986 });
1987
1988 // TEMPLATE
1989 // Add the DETAILS gesture recogniser
1990 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1991 {
1992 @Override
1993 public String details() { return "DETAILS"; }
1994
1995 @Override
1996 public List<Gesture> onInputEvent(InputEvent event) {
1997 // Cast to keyboard/mouse event
1998 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1999
2000 // TODO Auto-generated method stub
2001 return null;
2002 }
2003 });
2004 }
2005
2006 public boolean isKeyDown(Key key)
2007 {
2008 return StandardInputEventListeners.kbmStateListener.isKeyDown(key);
2009 }
2010
2011 public boolean isMouseButtonDown(MouseButton button)
2012 {
2013 return StandardInputEventListeners.kbmStateListener.isMouseButtonDown(button);
2014 }
2015
2016 public boolean isOnlyMouseButtonDown(MouseButton button)
2017 {
2018 return StandardInputEventListeners.kbmStateListener.isOnlyMouseButtonDown(button);
2019 }
2020
2021 public boolean isAnyMouseButtonDown()
2022 {
2023 return StandardInputEventListeners.kbmStateListener.isAnyMouseButtonDown();
2024 }
2025
2026 public static boolean isMouseDragNoOp()
2027 {
2028 return _noop;
2029 }
2030
2031 public static void printNoopMessage()
2032 {
2033 MessageBay.displayMessage("Action cancelled, mouse moved more than " + UserSettings.NoOpThreshold.get() + " pixels.");
2034 }
2035
2036 public static void trackMouseDragNoop(KBMInputEvent event)
2037 {
2038 if (!StandardInputEventListeners.kbmStateListener.isAnyMouseButtonDown() && event.getEventType() != EventType.MOUSE_BUTTON_UP) {
2039 _noop = false;
2040 _mouseDragStart = null;
2041 } else if (_mouseDragStart == null) {
2042 org.expeditee.core.Line mouseMove = event.getMouseMove();
2043 if (mouseMove != null) _mouseDragStart = mouseMove.getFirstEnd().clone();
2044 } else if (_noop == false) {
2045 org.expeditee.core.Line mouseMove = event.getMouseMove();
2046 if (mouseMove != null) {
2047 mouseMove.setFirstEnd(_mouseDragStart.clone());
2048 if (mouseMove.length() > UserSettings.NoOpThreshold.get()) {
2049 _noop = true;
2050 }
2051 }
2052 }
2053 }
2054
2055 /** Convenience function to create a single standard gesture. */
2056 public static List<Gesture> standardSingle(StandardGestureType type, GestureData data)
2057 {
2058 return Gesture.single(StandardGestureActions.getInstance().gestureType(type), data);
2059 }
2060}
Note: See TracBrowser for help on using the repository browser.