source: trunk/src/org/expeditee/gio/gesture/ExpediteeKBMGestureTranslator.java@ 1186

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