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

Last change on this file since 1413 was 1413, checked in by bln4, 5 years ago

Changed surrogates to work the way discussed with David. EncryptedExpReader/Writer updated to work with this.

File size: 74.3 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 if (kbmTranslator.isKeyDown(Key.SHIFT)) {
701 UndoGestureData data = new UndoGestureData(kbmTranslator.isKeyDown(Key.CTRL));
702 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.TOGGLE_SURROGATE_MODE), data);
703 } else {
704 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.TOGGLE_XRAY_MODE), null);
705 }
706 }
707 });
708
709 // Add the F11 -> SAVE gesture recogniser
710 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
711 {
712 @Override
713 public String details() { return "F11 -> SAVE"; }
714
715 @Override
716 public List<Gesture> onInputEvent(InputEvent event) {
717 // Cast to keyboard/mouse event
718 KBMInputEvent kbmEvent = (KBMInputEvent) event;
719
720 // Must be pressing F11 to save
721 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F11) {
722 return null;
723 }
724
725 // Return the gesture
726 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.SAVE), null);
727 }
728 });
729
730 // Add the F12 -> REFRESH gesture recogniser
731 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
732 {
733 @Override
734 public String details() { return "F12 -> REFRESH"; }
735
736 @Override
737 public List<Gesture> onInputEvent(InputEvent event) {
738 // Cast to keyboard/mouse event
739 KBMInputEvent kbmEvent = (KBMInputEvent) event;
740
741 // Must be pressing F12 to refresh
742 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F12) {
743 return null;
744 }
745
746 // Decide how to refresh
747 boolean shouldReloadFrameFirst = kbmTranslator.isKeyDown(Key.CTRL);
748 boolean shouldRefreshFrameSize = kbmTranslator.isKeyDown(Key.SHIFT);
749
750 // Return the gesture
751 return standardSingle(StandardGestureType.REFRESH, new RefreshGestureData(shouldReloadFrameFirst, shouldRefreshFrameSize));
752 }
753 });
754
755 // Add the ESC -> DROP_DOWN gesture recogniser
756 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
757 {
758 @Override
759 public String details() { return "ESC -> DROP_DOWN"; }
760
761 @Override
762 public List<Gesture> onInputEvent(InputEvent event) {
763 // Cast to keyboard/mouse event
764 KBMInputEvent kbmEvent = (KBMInputEvent) event;
765
766 // Shift/Ctrl + Esc is calculate
767 if (kbmTranslator.isKeyDown(Key.SHIFT) || kbmTranslator.isKeyDown(Key.CTRL)) {
768 return null;
769 }
770
771 // Must be pressing ESC to drop down
772 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.ESC) {
773 return null;
774 }
775
776 // Return the gesture
777 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.DROP_DOWN), null);
778 }
779 });
780
781 // Add the SHIFT/CTRL + ESC -> CALCULATE gesture recogniser
782 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
783 {
784 @Override
785 public String details() { return "SHIFT/CTRL + ESC -> CALCULATE"; }
786
787 @Override
788 public List<Gesture> onInputEvent(InputEvent event) {
789 // Cast to keyboard/mouse event
790 KBMInputEvent kbmEvent = (KBMInputEvent) event;
791
792 // Check that shift or ctrl is down
793 if (!kbmTranslator.isKeyDown(Key.SHIFT) && !kbmTranslator.isKeyDown(Key.CTRL)) {
794 return null;
795 }
796
797 // Must be pressing Esc to calculate
798 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.ESC) {
799 return null;
800 }
801
802 // Return the gesture
803 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CALCULATE), new ItemSpecificGestureData());
804 }
805 });
806
807 // Add the CTRL + TAB -> CALCULATE gesture recogniser
808 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
809 {
810 @Override
811 public String details() { return "CTRL + TAB -> CALCULATE"; }
812
813 @Override
814 public List<Gesture> onInputEvent(InputEvent event) {
815 // Cast to keyboard/mouse event
816 KBMInputEvent kbmEvent = (KBMInputEvent) event;
817
818 // Check that ctrl is down
819 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
820 return null;
821 }
822
823 // Must be pressing tab to calculate
824 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.TAB) {
825 return null;
826 }
827
828 // Return the gesture
829 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CALCULATE), new ItemSpecificGestureData());
830 }
831 });
832
833 // Add the CTRL + L -> LINK gesture recogniser
834 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
835 {
836 @Override
837 public String details() { return "CTRL + L -> LINK"; }
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)) {
846 return null;
847 }
848
849 // Must be pressing L to link
850 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.L) {
851 return null;
852 }
853
854 // Return the gesture
855 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.LINK), new LinkGestureData(false));
856 }
857 });
858
859 // Add the CTRL + G -> LINK gesture recogniser
860 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
861 {
862 @Override
863 public String details() { return "CTRL + G -> LINK"; }
864
865 @Override
866 public List<Gesture> onInputEvent(InputEvent event) {
867 // Cast to keyboard/mouse event
868 KBMInputEvent kbmEvent = (KBMInputEvent) event;
869
870 // Check that ctrl is down
871 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
872 return null;
873 }
874
875 // Must be pressing G to link
876 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.G) {
877 return null;
878 }
879
880 // Return the gesture
881 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.LINK), new LinkGestureData(true));
882 }
883 });
884
885 // Add the CTRL + A -> ACTION gesture recogniser
886 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
887 {
888 @Override
889 public String details() { return "CTRL + A -> ACTION"; }
890
891 @Override
892 public List<Gesture> onInputEvent(InputEvent event) {
893 // Cast to keyboard/mouse event
894 KBMInputEvent kbmEvent = (KBMInputEvent) event;
895
896 // Check that ctrl is down
897 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
898 return null;
899 }
900
901 // Must be pressing A to action
902 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.A) {
903 return null;
904 }
905
906 // Return the gesture
907 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.ACTION), new ItemSpecificGestureData());
908 }
909 });
910
911 // Add the CTRL + B -> TOGGLE_BOLD gesture recogniser
912 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
913 {
914 @Override
915 public String details() { return "CTRL + B -> TOGGLE_BOLD"; }
916
917 @Override
918 public List<Gesture> onInputEvent(InputEvent event) {
919 // Cast to keyboard/mouse event
920 KBMInputEvent kbmEvent = (KBMInputEvent) event;
921
922 // Check that ctrl is down
923 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
924 return null;
925 }
926
927 // Must be pressing B to toggle bold
928 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.B) {
929 return null;
930 }
931
932 // Return the gesture
933 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.TOGGLE_BOLD), new ItemSpecificGestureData());
934 }
935 });
936
937 // Add the CTRL + I -> TOGGLE_ITALICS gesture recogniser
938 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
939 {
940 @Override
941 public String details() { return "CTRL + I -> TOGGLE_ITALICS"; }
942
943 @Override
944 public List<Gesture> onInputEvent(InputEvent event) {
945 // Cast to keyboard/mouse event
946 KBMInputEvent kbmEvent = (KBMInputEvent) event;
947
948 // Check that ctrl is down
949 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
950 return null;
951 }
952
953 // Must be pressing I to toggle italics
954 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.I) {
955 return null;
956 }
957
958 // Return the gesture
959 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.TOGGLE_ITALICS), new ItemSpecificGestureData());
960 }
961 });
962
963 // Add the CTRL + V -> PASTE gesture recogniser
964 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
965 {
966 @Override
967 public String details() { return "CTRL + V -> PASTE"; }
968
969 @Override
970 public List<Gesture> onInputEvent(InputEvent event) {
971 // Cast to keyboard/mouse event
972 KBMInputEvent kbmEvent = (KBMInputEvent) event;
973
974 // Check that ctrl is down
975 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
976 return null;
977 }
978
979 // Must be pressing V to paste
980 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.V) {
981 return null;
982 }
983
984 // Return the gesture
985 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PASTE), null);
986 }
987 });
988
989 // Add the CTRL + C -> COPY gesture recogniser
990 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
991 {
992 @Override
993 public String details() { return "CTRL + C -> COPY"; }
994
995 @Override
996 public List<Gesture> onInputEvent(InputEvent event) {
997 // Cast to keyboard/mouse event
998 KBMInputEvent kbmEvent = (KBMInputEvent) event;
999
1000 // Check that ctrl is down
1001 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
1002 return null;
1003 }
1004
1005 // Must be pressing C to copy
1006 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.C) {
1007 return null;
1008 }
1009
1010 // Return the gesture
1011 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.COPY), new ItemSpecificGestureData());
1012 }
1013 });
1014
1015 // Add the CTRL + C -> MAKE_CIRCLE gesture recogniser
1016 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1017 {
1018 @Override
1019 public String details() { return "CTRL + C -> MAKE_CIRCLE"; }
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)) {
1028 return null;
1029 }
1030
1031 // Must be pressing C to make circle
1032 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.C) {
1033 return null;
1034 }
1035
1036 // Make sure we aren't trying to do a copy-clone
1037 if (FreeItems.hasItemsAttachedToCursor()) {
1038 return null;
1039 }
1040
1041 // Return the gesture
1042 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.MAKE_CIRCLE), new ItemSpecificGestureData());
1043 }
1044 });
1045
1046 // Add the CTRL + X -> CUT gesture recogniser
1047 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1048 {
1049 @Override
1050 public String details() { return "CTRL + X -> CUT"; }
1051
1052 @Override
1053 public List<Gesture> onInputEvent(InputEvent event) {
1054 // Cast to keyboard/mouse event
1055 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1056
1057 // Check that ctrl is down
1058 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
1059 return null;
1060 }
1061
1062 // Must be pressing X to cut
1063 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.X) {
1064 return null;
1065 }
1066
1067 // Return the gesture
1068 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CUT), null);
1069 }
1070 });
1071
1072 // Add the CTRL + M -> TOGGLE_ITEMS_MARK gesture recogniser
1073 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1074 {
1075 @Override
1076 public String details() { return "CTRL + M -> TOGGLE_ITEMS_MARK"; }
1077
1078 @Override
1079 public List<Gesture> onInputEvent(InputEvent event) {
1080 // Cast to keyboard/mouse event
1081 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1082
1083 // Check that ctrl is down
1084 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
1085 return null;
1086 }
1087
1088 // Must be pressing M to toggle items mark
1089 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.M) {
1090 return null;
1091 }
1092
1093 // Return the gesture
1094 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.TOGGLE_ITEMS_MARK), new ItemSpecificGestureData());
1095 }
1096 });
1097
1098 // Add the CTRL + Z -> UNDO gesture recogniser
1099 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1100 {
1101 @Override
1102 public String details() { return "CTRL + Z -> UNDO"; }
1103
1104 @Override
1105 public List<Gesture> onInputEvent(InputEvent event) {
1106 // Cast to keyboard/mouse event
1107 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1108
1109 // Check that ctrl is down
1110 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
1111 return null;
1112 }
1113
1114 // Must be pressing Z to undo
1115 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.X) {
1116 return null;
1117 }
1118
1119 // Holding shift as well makes this a redo gesture
1120 boolean redo = kbmTranslator.isKeyDown(Key.SHIFT);
1121
1122 // Return the gesture
1123 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.UNDO), new UndoGestureData(redo));
1124 }
1125 });
1126
1127 // Add the CTRL + D -> INSERT_STRING gesture recogniser
1128 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1129 {
1130 @Override
1131 public String details() { return "CTRL + D -> INSERT_STRING"; }
1132
1133 @Override
1134 public List<Gesture> onInputEvent(InputEvent event) {
1135 // Cast to keyboard/mouse event
1136 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1137
1138 // Check that ctrl is down
1139 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
1140 return null;
1141 }
1142
1143 // Must be pressing D to delete character
1144 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.D) {
1145 return null;
1146 }
1147
1148 // Return the gesture
1149 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.INSERT_STRING), new InsertStringGestureData(Text.DELETE_CHARACTER, false));
1150 }
1151 });
1152
1153 // Add the CTRL + DELETE -> DELETE gesture recogniser
1154 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1155 {
1156 @Override
1157 public String details() { return "CTRL + DELETE -> DELETE"; }
1158
1159 @Override
1160 public List<Gesture> onInputEvent(InputEvent event) {
1161 // Cast to keyboard/mouse event
1162 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1163
1164 // Check that ctrl is down
1165 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
1166 return null;
1167 }
1168
1169 // Must be pressing DELETE to delete
1170 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.DELETE) {
1171 return null;
1172 }
1173
1174 // Decide if this is an alternate mode delete
1175 // TODO: What specifically is alternate mode delete? cts16
1176 boolean alternateMode = kbmTranslator.isKeyDown(Key.SHIFT);
1177
1178 // Return the gesture
1179 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.DELETE), new DeleteGestureData(alternateMode));
1180 }
1181 });
1182
1183 // Add the CTRL + F -> FORMAT gesture recogniser
1184 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1185 {
1186 @Override
1187 public String details() { return "CTRL + F -> FORMAT"; }
1188
1189 @Override
1190 public List<Gesture> onInputEvent(InputEvent event) {
1191 // Cast to keyboard/mouse event
1192 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1193
1194 // Check that ctrl is down
1195 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
1196 return null;
1197 }
1198
1199 // Must be pressing F to format
1200 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.F) {
1201 return null;
1202 }
1203
1204 // Decide if this is an horizontal or vertical format
1205 boolean horizontal = kbmTranslator.isKeyDown(Key.SHIFT);
1206
1207 // Return the gesture
1208 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.FORMAT), new FormatGestureData(horizontal));
1209 }
1210 });
1211
1212 // Add the CTRL + J -> JUSTIFY gesture recogniser
1213 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1214 {
1215 @Override
1216 public String details() { return "CTRL + J -> JUSTIFY"; }
1217
1218 @Override
1219 public List<Gesture> onInputEvent(InputEvent event) {
1220 // Cast to keyboard/mouse event
1221 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1222
1223 // Check that ctrl is down
1224 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
1225 return null;
1226 }
1227
1228 // Must be pressing J to justify
1229 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.J) {
1230 return null;
1231 }
1232
1233 // Return the gesture
1234 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.JUSTIFY), new JustifyGestureData(false));
1235 }
1236 });
1237
1238 // Add the CTRL + R -> JUSTIFY gesture recogniser
1239 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1240 {
1241 @Override
1242 public String details() { return "CTRL + R -> JUSTIFY"; }
1243
1244 @Override
1245 public List<Gesture> onInputEvent(InputEvent event) {
1246 // Cast to keyboard/mouse event
1247 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1248
1249 // Check that ctrl is down
1250 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
1251 return null;
1252 }
1253
1254 // Must be pressing R to justify
1255 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.R) {
1256 return null;
1257 }
1258
1259 // Return the gesture
1260 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.JUSTIFY), new JustifyGestureData(true));
1261 }
1262 });
1263
1264 // Add the CTRL + S -> SAVE gesture recogniser
1265 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1266 {
1267 @Override
1268 public String details() { return "CTRL + S -> SAVE"; }
1269
1270 @Override
1271 public List<Gesture> onInputEvent(InputEvent event) {
1272 // Cast to keyboard/mouse event
1273 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1274
1275 // Check that ctrl is down
1276 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
1277 return null;
1278 }
1279
1280 // Ctrl + Shift + S is split text
1281 if (kbmTranslator.isKeyDown(Key.SHIFT)) {
1282 return null;
1283 }
1284
1285 // Must be pressing S to save
1286 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.S) {
1287 return null;
1288 }
1289
1290 // Return the gesture
1291 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.SAVE), null);
1292 }
1293 });
1294
1295 // Add the CTRL + SHIFT + S -> SPLIT_TEXT gesture recogniser
1296 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1297 {
1298 @Override
1299 public String details() { return "CTRL + SHIFT + S -> SPLIT_TEXT"; }
1300
1301 @Override
1302 public List<Gesture> onInputEvent(InputEvent event) {
1303 // Cast to keyboard/mouse event
1304 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1305
1306 // Check that ctrl is down
1307 if (!kbmTranslator.isKeyDown(Key.CTRL)) {
1308 return null;
1309 }
1310
1311 // Ctrl + Shift + S is split text
1312 if (!kbmTranslator.isKeyDown(Key.SHIFT)) {
1313 return null;
1314 }
1315
1316 // Must be pressing S to save
1317 if (kbmEvent.getKeyDown() != KBMInputEvent.Key.S) {
1318 return null;
1319 }
1320
1321 // Return the gesture
1322 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.SPLIT_TEXT), new ItemSpecificGestureData());
1323 }
1324 });
1325
1326 // Add the MIDDLE MOUSE + MOUSE_MOVE -> PICK_UP gesture recogniser
1327 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1328 {
1329 private SelectAreaGestureData _draggedFromData = null;
1330
1331 @Override
1332 public String details() { return "MIDDLE MOUSE + MOUSE_MOVE -> PICK_UP"; }
1333
1334 @Override
1335 public List<Gesture> onInputEvent(InputEvent event) {
1336 // Cast to keyboard/mouse event
1337 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1338
1339 // Check we are holding the middle button only
1340 if (!kbmTranslator.isOnlyMouseButtonDown(MouseButton.MIDDLE)) {
1341 // If we were dragging, reset the dragging tracker and send the drag-finished gesture
1342 if (_draggedFromData != null) {
1343 SelectAreaGestureData finalData = _draggedFromData.finalise();
1344 _draggedFromData = null;
1345 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PICK_UP), finalData);
1346
1347 // Otherwise just return
1348 } else {
1349 return null;
1350 }
1351 }
1352
1353 // Check if it's a mouse movement event
1354 if (kbmEvent.getEventType() != KBMInputEvent.EventType.MOUSE_MOVE) {
1355 return null;
1356 }
1357
1358 // See if we should inherit the attributes of the thing we're picking up
1359 boolean inheritAttributes = kbmTranslator.isKeyDown(Key.SHIFT);
1360
1361 // If we are just starting to drag, save the start position of the gesture
1362 if (_draggedFromData == null) {
1363 _draggedFromData = new PickUpGestureData(kbmEvent.getMouseMove().getSecondEnd().clone(), kbmEvent.getMouseMove().getFirstEnd().clone(), false, inheritAttributes);
1364 }
1365
1366 // Wait till we have moved out of no-op range before performing drag-pickup
1367 if (!isMouseDragNoOp()) {
1368 return null;
1369 }
1370
1371 // Generate a PICK_UP gesture
1372 _draggedFromData = _draggedFromData.carryOn(kbmEvent.getMouseMove().getSecondEnd().clone());
1373 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PICK_UP), _draggedFromData);
1374 }
1375 });
1376
1377 // Add the MIDDLE MOUSE -> PICK_UP gesture recogniser
1378 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1379 {
1380 private Boolean _pickup = null;
1381 private Item _clickDownOn = null;
1382
1383 @Override
1384 public String details() { return "MIDDLE MOUSE -> PICK_UP"; }
1385
1386 @Override
1387 public List<Gesture> onInputEvent(InputEvent event) {
1388 // Cast to keyboard/mouse event
1389 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1390
1391 // Check for single middle click
1392 if (_pickup == null && kbmEvent.getMouseButtonDown() == MouseButton.MIDDLE) {
1393 _pickup = true;
1394 _clickDownOn = FrameUtils.getCurrentItem();
1395 return null;
1396 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1397 _pickup = false;
1398 return null;
1399 } else if (Boolean.FALSE.equals(_pickup) && kbmTranslator.isAnyMouseButtonDown() == false) {
1400 _pickup = null;
1401 return null;
1402 }
1403
1404 // Wait for the button up to perform the pickup
1405 if (!Boolean.TRUE.equals(_pickup) || kbmEvent.getMouseButtonUp() != MouseButton.MIDDLE) {
1406 return null;
1407 }
1408
1409 // Reset pickup for next gesture
1410 _pickup = null;
1411
1412 // Check we haven't moved too far
1413 if (isMouseDragNoOp()) {
1414 if (!(_clickDownOn instanceof Text)) {
1415 printNoopMessage();
1416 }
1417 return null;
1418 }
1419
1420 // Check we should be picking up (shift forces line creation)
1421 if (FreeItems.hasItemsAttachedToCursor() || kbmTranslator.isKeyDown(Key.SHIFT)) {
1422 return null;
1423 }
1424
1425 // Check there is something to pick up
1426 if (!FrameUtils.hasCurrentItem() && FrameUtils.getCurrentItems() == null) {
1427 return null;
1428 }
1429
1430 // Return the gesture
1431 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PICK_UP), new PickUpGestureData(false));
1432 }
1433 });
1434
1435 // Add the RIGHT MOUSE + MOUSE_MOVE -> PICK_UP gesture recogniser
1436 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1437 {
1438 private SelectAreaGestureData _draggedFromData = null;
1439
1440 @Override
1441 public String details() { return "RIGHT MOUSE + MOUSE_MOVE -> PICK_UP"; }
1442
1443 @Override
1444 public List<Gesture> onInputEvent(InputEvent event) {
1445 // Cast to keyboard/mouse event
1446 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1447
1448 // Check we are holding the middle button only
1449 if (!kbmTranslator.isOnlyMouseButtonDown(MouseButton.RIGHT)) {
1450 // If we were dragging, reset the dragging tracker and send the drag-finished gesture
1451 if (_draggedFromData != null) {
1452 SelectAreaGestureData finalData = _draggedFromData.finalise();
1453 _draggedFromData = null;
1454 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PICK_UP), finalData);
1455
1456 // Otherwise just return
1457 } else {
1458 return null;
1459 }
1460 }
1461
1462 // Check if it's a mouse movement event
1463 if (kbmEvent.getEventType() != KBMInputEvent.EventType.MOUSE_MOVE) {
1464 return null;
1465 }
1466
1467 // See if we should inherit the attributes of the thing we're picking up
1468 boolean inheritAttributes = kbmTranslator.isKeyDown(Key.SHIFT);
1469
1470 // If we are just starting to drag, save the start position of the gesture
1471 if (_draggedFromData == null) {
1472 _draggedFromData = new PickUpGestureData(kbmEvent.getMouseMove().getSecondEnd().clone(), kbmEvent.getMouseMove().getFirstEnd().clone(), true, inheritAttributes);
1473 }
1474
1475 // Wait till we have moved out of no-op range before performing drag-pickup
1476 if (!isMouseDragNoOp()) {
1477 return null;
1478 }
1479
1480 // Generate a PICK_UP gesture
1481 _draggedFromData = _draggedFromData.carryOn(kbmEvent.getMouseMove().getSecondEnd().clone());
1482 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PICK_UP), _draggedFromData);
1483 }
1484 });
1485
1486 // Add the RIGHT MOUSE -> PICK_UP gesture recogniser
1487 addTranslator(new InputEventToGestureTranslator(new InputType[] { InputType.KBM, InputType.TIMEOUT })
1488 {
1489 private final static int EXTRUSION_DELAY_MS = 750;
1490 private final static int PULSE_AMOUNT = 2;
1491 private Boolean _pickup = null;
1492 private Item _clickedItem = null;
1493 private TimeoutHandle _timeoutHandle;
1494 private boolean _extrusionDelayExpired = false;
1495
1496 @Override
1497 public String details() { return "RIGHT MOUSE -> PICK_UP"; }
1498
1499 @Override
1500 public List<Gesture> onInputEvent(InputEvent event)
1501 {
1502 if (event == null) {
1503 return null;
1504 } else if (event.getInputType() == InputType.KBM) {
1505 return onKBMInputEvent((KBMInputEvent) event);
1506 } else if (event.getInputType() == InputType.TIMEOUT) {
1507 return onTimeoutInputEvent((TimeoutInputEvent) event);
1508 }
1509
1510 return null;
1511 }
1512
1513 private List<Gesture> onKBMInputEvent(KBMInputEvent kbmEvent)
1514 {
1515 // Check for single right click
1516 if (_pickup == null && kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1517 _pickup = true;
1518 _timeoutHandle = EcosystemManager.getInputManager().addTimeout(EXTRUSION_DELAY_MS);
1519 _extrusionDelayExpired = false;
1520 _clickedItem = FrameUtils.getCurrentItem();
1521 return null;
1522 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1523 _pickup = false;
1524 EcosystemManager.getInputManager().cancelTimeout(_timeoutHandle);
1525 return null;
1526 } else if (Boolean.FALSE.equals(_pickup) && kbmTranslator.isAnyMouseButtonDown() == false) {
1527 _pickup = null;
1528 return null;
1529 }
1530
1531 // Wait for the button up to perform the pickup
1532 if (!Boolean.TRUE.equals(_pickup) || kbmEvent.getMouseButtonUp() != MouseButton.RIGHT) {
1533 return null;
1534 }
1535
1536 // Reset pickup for next gesture
1537 _pickup = null;
1538
1539 // Cancel the extrusion timeout if it's pending
1540 EcosystemManager.getInputManager().cancelTimeout(_timeoutHandle);
1541
1542 // Reset the line pulse if it occured
1543 if (_extrusionDelayExpired) {
1544 pulseExtrusionLines(false);
1545 }
1546
1547 // Check we haven't moved too far
1548 if (isMouseDragNoOp()) {
1549 printNoopMessage();
1550 return null;
1551 }
1552
1553 // Check we should be picking up (shift forces line creation)
1554 if (FreeItems.hasItemsAttachedToCursor() || kbmTranslator.isKeyDown(Key.SHIFT)) {
1555 return null;
1556 }
1557
1558 // Check there is something to pick up
1559 if (!FrameUtils.hasCurrentItem() && FrameUtils.getCurrentItems() == null) {
1560 return null;
1561 }
1562
1563 // Return the gesture
1564 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PICK_UP), new PickUpGestureData(true, _extrusionDelayExpired));
1565 }
1566
1567 private List<Gesture> onTimeoutInputEvent(TimeoutInputEvent event)
1568 {
1569 if (event.getHandle() == _timeoutHandle) {
1570 _extrusionDelayExpired = true;
1571 pulseExtrusionLines(true);
1572 }
1573
1574 return null;
1575 }
1576
1577 private void pulseExtrusionLines(boolean pulseOn)
1578 {
1579 int amount = PULSE_AMOUNT;
1580 if (!pulseOn) {
1581 amount *= -1;
1582 }
1583
1584 if (_clickedItem != null) {
1585 for (Item i : _clickedItem.getAllConnected()) {
1586 if (i instanceof Line) {
1587 Line line = (Line) i;
1588 line.setThickness(line.getThickness() + amount);
1589 }
1590 }
1591 }
1592
1593 DisplayController.requestRefresh(true);
1594 }
1595 });
1596
1597 // Add the MIDDLE MOUSE -> PLACE gesture recogniser
1598 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1599 {
1600 Boolean _place = null;
1601
1602 @Override
1603 public String details() { return "MIDDLE MOUSE -> PLACE"; }
1604
1605 @Override
1606 public List<Gesture> onInputEvent(InputEvent event) {
1607 // Cast to keyboard/mouse event
1608 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1609
1610 // Check for single middle click
1611 if (_place == null && kbmEvent.getMouseButtonDown() == MouseButton.MIDDLE) {
1612 _place = true;
1613 return null;
1614 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1615 _place = false;
1616 return null;
1617 } else if (Boolean.FALSE.equals(_place) && isAnyMouseButtonDown() == false) {
1618 _place = null;
1619 return null;
1620 }
1621
1622 // Wait for the button up to perform the place
1623 if (!Boolean.TRUE.equals(_place) || kbmEvent.getMouseButtonUp() != MouseButton.MIDDLE) {
1624 return null;
1625 }
1626
1627 // Reset place for next gesture
1628 _place = null;
1629
1630 // Check we haven't moved too far
1631 if (isMouseDragNoOp()) {
1632 printNoopMessage();
1633 return null;
1634 }
1635
1636 // Check we should be placing
1637 if (!FreeItems.hasItemsAttachedToCursor()) {
1638 return null;
1639 }
1640
1641 // Return the gesture
1642 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PLACE), new PickUpGestureData(false));
1643 }
1644 });
1645
1646 // Add the RIGHT MOUSE -> PLACE gesture recogniser
1647 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1648 {
1649 Boolean _place = null;
1650 @Override
1651 public String details() { return "RIGHT MOUSE -> PLACE"; }
1652
1653 @Override
1654 public List<Gesture> onInputEvent(InputEvent event) {
1655 // Cast to keyboard/mouse event
1656 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1657
1658 // Check for single right click
1659 if (_place == null && kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1660 _place = true;
1661 return null;
1662 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1663 _place = false;
1664 return null;
1665 } else if (Boolean.FALSE.equals(_place) && kbmTranslator.isAnyMouseButtonDown() == false) {
1666 _place = null;
1667 return null;
1668 }
1669
1670 // Wait for the button up to perform the place
1671 if (!Boolean.TRUE.equals(_place) || kbmEvent.getMouseButtonUp() != MouseButton.RIGHT) {
1672 return null;
1673 }
1674
1675 // Reset place for next gesture
1676 _place = null;
1677
1678 // Check we haven't moved too far
1679 if (isMouseDragNoOp()) {
1680 printNoopMessage();
1681 return null;
1682 }
1683
1684 // Check we should be placing
1685 if (!FreeItems.hasItemsAttachedToCursor()) {
1686 return null;
1687 }
1688
1689 // Return the gesture
1690 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.PLACE), new PickUpGestureData(true));
1691 }
1692 });
1693
1694 // Add the MIDDLE + RIGHT MOUSE -> DELETE gesture recogniser
1695 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1696 {
1697 private static final int STATE_NO_MOUSE_BUTTON_DOWN = 0;
1698 private static final int STATE_MIDDLE_MOUSE_BUTTON_DOWN = 1;
1699 private static final int STATE_RIGHT_MOUSE_BUTTON_DOWN = 2;
1700 private static final int STATE_BOTH_MOUSE_BUTTON_DOWN = 3;
1701 private static final int STATE_ERROR = 4;
1702 private int _state = STATE_NO_MOUSE_BUTTON_DOWN;
1703
1704 @Override
1705 public String details() { return "MIDDLE + RIGHT MOUSE -> DELETE"; }
1706
1707 @Override
1708 public List<Gesture> onInputEvent(InputEvent event) {
1709 // Cast to keyboard/mouse event
1710 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1711
1712 // Keep track of mouse button state
1713 if (_state == STATE_NO_MOUSE_BUTTON_DOWN) {
1714 if (kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1715 _state = STATE_RIGHT_MOUSE_BUTTON_DOWN;
1716 } else if (kbmEvent.getMouseButtonDown() == MouseButton.MIDDLE) {
1717 _state = STATE_MIDDLE_MOUSE_BUTTON_DOWN;
1718 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1719 _state = STATE_ERROR;
1720 }
1721 return null;
1722 } else if (_state == STATE_MIDDLE_MOUSE_BUTTON_DOWN) {
1723 if (kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1724 _state = STATE_BOTH_MOUSE_BUTTON_DOWN;
1725 } else if (kbmEvent.getMouseButtonUp() == MouseButton.MIDDLE) {
1726 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1727 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1728 _state = STATE_ERROR;
1729 }
1730 return null;
1731 } else if (_state == STATE_RIGHT_MOUSE_BUTTON_DOWN) {
1732 if (kbmEvent.getMouseButtonDown() == MouseButton.MIDDLE) {
1733 _state = STATE_BOTH_MOUSE_BUTTON_DOWN;
1734 } else if (kbmEvent.getMouseButtonUp() == MouseButton.RIGHT) {
1735 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1736 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1737 _state = STATE_ERROR;
1738 }
1739 return null;
1740 } else if (_state == STATE_BOTH_MOUSE_BUTTON_DOWN) {
1741 if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1742 _state = STATE_ERROR;
1743 return null;
1744 }
1745 } else if (kbmTranslator.isAnyMouseButtonDown() == false) {
1746 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1747 return null;
1748 }
1749
1750 // Wait for the button up to perform the delete
1751 if (_state != STATE_BOTH_MOUSE_BUTTON_DOWN || kbmTranslator.isAnyMouseButtonDown()) {
1752 return null;
1753 }
1754
1755 // Reset state for next gesture
1756 _state = STATE_NO_MOUSE_BUTTON_DOWN;
1757
1758 // Check we haven't moved too far
1759 if (isMouseDragNoOp()) {
1760 printNoopMessage();
1761 return null;
1762 }
1763
1764 // Decide if this is an alternate mode delete
1765 // TODO: What specifically is alternate mode delete? cts16
1766 boolean alternateMode = kbmTranslator.isKeyDown(Key.SHIFT);
1767
1768 // Return the gesture
1769 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.DELETE), new DeleteGestureData(alternateMode));
1770 }
1771 });
1772
1773 // Add the MIDDLE MOUSE -> CREATE_ITEM gesture recogniser
1774 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1775 {
1776 Boolean _create = null;
1777 @Override
1778 public String details() { return "MIDDLE MOUSE -> CREATE_ITEM"; }
1779
1780 @Override
1781 public List<Gesture> onInputEvent(InputEvent event) {
1782 // Cast to keyboard/mouse event
1783 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1784
1785 // Check for single middle click
1786 if (_create == null && kbmEvent.getMouseButtonDown() == MouseButton.MIDDLE) {
1787 _create = true;
1788 return null;
1789 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1790 _create = false;
1791 return null;
1792 } else if (Boolean.FALSE.equals(_create) && kbmTranslator.isAnyMouseButtonDown() == false) {
1793 _create = null;
1794 return null;
1795 }
1796
1797 // Wait for the button up to perform the create
1798 if (!Boolean.TRUE.equals(_create) || kbmEvent.getMouseButtonUp() != MouseButton.MIDDLE) {
1799 return null;
1800 }
1801
1802 // Reset create for next gesture
1803 _create = null;
1804
1805 // Check we haven't moved too far
1806 if (isMouseDragNoOp()) {
1807 printNoopMessage();
1808 return null;
1809 }
1810
1811 // Check we can create
1812 if (FreeItems.hasItemsAttachedToCursor()) {
1813 return null;
1814 }
1815
1816 // Check we're not trying to pick up (shift forces item creation)
1817 if (!kbmTranslator.isKeyDown(Key.SHIFT) && (FrameUtils.hasCurrentItem() || FrameUtils.getCurrentItems() != null)) {
1818 return null;
1819 }
1820
1821 // Return the gesture
1822 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CREATE_ITEM), new CreateItemGestureData(ItemType.LINE));
1823 }
1824 });
1825
1826 // Add the RIGHT MOUSE -> CREATE_ITEM gesture recogniser
1827 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1828 {
1829 Boolean _create = null;
1830 @Override
1831 public String details() { return "RIGHT MOUSE -> CREATE_ITEM"; }
1832
1833 @Override
1834 public List<Gesture> onInputEvent(InputEvent event) {
1835 // Cast to keyboard/mouse event
1836 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1837
1838 // Check for single middle click
1839 if (_create == null && kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
1840 _create = true;
1841 return null;
1842 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1843 _create = false;
1844 return null;
1845 } else if (Boolean.FALSE.equals(_create) && kbmTranslator.isAnyMouseButtonDown() == false) {
1846 _create = null;
1847 return null;
1848 }
1849
1850 // Wait for the button up to perform the create
1851 if (!Boolean.TRUE.equals(_create) || kbmEvent.getMouseButtonUp() != MouseButton.RIGHT) {
1852 return null;
1853 }
1854
1855 // Reset create for next gesture
1856 _create = null;
1857
1858 // Check we haven't moved too far
1859 if (isMouseDragNoOp()) {
1860 printNoopMessage();
1861 return null;
1862 }
1863
1864 // Check we can create
1865 if (FreeItems.hasItemsAttachedToCursor()) {
1866 return null;
1867 }
1868
1869 // Check we're not trying to pick up (shift forces item creation)
1870 if (!kbmTranslator.isKeyDown(Key.SHIFT) && (FrameUtils.hasCurrentItem() || FrameUtils.getCurrentItems() != null)) {
1871 return null;
1872 }
1873
1874 // Return the gesture
1875 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CREATE_ITEM), new CreateItemGestureData(ItemType.BOX));
1876 }
1877 });
1878
1879 // Add the LEFT MOUSE -> CLICK gesture recogniser
1880 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
1881 {
1882 private static final int LONG_CLICK_DELAY_MS = 500;
1883 private Boolean _click = null;
1884 private long _clickStartTime;
1885 @Override
1886 public String details() { return "LEFT MOUSE -> CLICK"; }
1887
1888 @Override
1889 public List<Gesture> onInputEvent(InputEvent event) {
1890 // Cast to keyboard/mouse event
1891 KBMInputEvent kbmEvent = (KBMInputEvent) event;
1892
1893 // Check for single left click
1894 if (_click == null && kbmEvent.getMouseButtonDown() == MouseButton.LEFT) {
1895 _click = true;
1896 _clickStartTime = System.currentTimeMillis();
1897 return null;
1898 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1899 _click = false;
1900 return null;
1901 } else if (Boolean.FALSE.equals(_click) && kbmTranslator.isAnyMouseButtonDown() == false) {
1902 _click = null;
1903 return null;
1904 }
1905
1906 // Wait for the button up to perform the click
1907 if (!Boolean.TRUE.equals(_click) || kbmEvent.getMouseButtonUp() != MouseButton.LEFT) {
1908 return null;
1909 }
1910
1911 // Reset click for next gesture
1912 _click = null;
1913
1914 // Check if this is a long click
1915 boolean longClick = System.currentTimeMillis() >= _clickStartTime + LONG_CLICK_DELAY_MS;
1916
1917 // Check if we are toggling arrowhead
1918 if (longClick && FrameUtils.getCurrentItem() == null) {
1919 if (FreeItems.getInstance().size() <= 2) {
1920 for (Item i : FreeItems.getInstance()) {
1921 if (i instanceof Line) {
1922 return null;
1923 }
1924 }
1925 }
1926 }
1927
1928 // Check we haven't moved too far
1929 if (isMouseDragNoOp()) {
1930 printNoopMessage();
1931 return null;
1932 }
1933
1934 // Return the gesture
1935 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.CLICK), new ClickGestureData(longClick));
1936 }
1937 });
1938
1939 // Add the LEFT MOUSE -> TOGGLE_ARROWHEAD gesture recogniser
1940 addTranslator(new InputEventToGestureTranslator(new InputType[] { InputType.KBM, InputType.TIMEOUT })
1941 {
1942 private static final int LONG_CLICK_DELAY_MS = 500;
1943 private Boolean _click = null;
1944 private TimeoutHandle _timeoutHandle = null;
1945
1946 @Override
1947 public String details() { return "LEFT MOUSE -> TOGGLE_ARROWHEAD"; }
1948
1949 @Override
1950 public List<Gesture> onInputEvent(InputEvent event)
1951 {
1952 if (event == null) {
1953 return null;
1954 } else if (event.getInputType() == InputType.KBM) {
1955 return onKBMInputEvent((KBMInputEvent) event);
1956 } else if (event.getInputType() == InputType.TIMEOUT) {
1957 return onTimeoutInputEvent((TimeoutInputEvent) event);
1958 }
1959
1960 return null;
1961 }
1962
1963 private List<Gesture> onKBMInputEvent(KBMInputEvent kbmEvent)
1964 {
1965 // Check for single left click
1966 if (_click == null && kbmEvent.getMouseButtonDown() == MouseButton.LEFT) {
1967 _click = true;
1968 _timeoutHandle = EcosystemManager.getInputManager().addTimeout(LONG_CLICK_DELAY_MS);
1969 return null;
1970 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
1971 _click = false;
1972 EcosystemManager.getInputManager().cancelTimeout(_timeoutHandle);
1973 return null;
1974 } else if (Boolean.FALSE.equals(_click) && kbmTranslator.isAnyMouseButtonDown() == false) {
1975 _click = null;
1976 return null;
1977 }
1978
1979 // Wait for the button up to perform the click
1980 if (!Boolean.TRUE.equals(_click) || kbmEvent.getMouseButtonUp() != MouseButton.LEFT) {
1981 return null;
1982 }
1983
1984 // Reset click for next gesture
1985 _click = null;
1986
1987 // Cancel the timer if it's still pending
1988 EcosystemManager.getInputManager().cancelTimeout(_timeoutHandle);
1989
1990 return null;
1991 }
1992
1993 private List<Gesture> onTimeoutInputEvent(TimeoutInputEvent event)
1994 {
1995 if (event.getHandle() == _timeoutHandle) {
1996 // Check if we are toggling arrowhead
1997 Item line = null;
1998 if (FrameUtils.getCurrentItem() == null) {
1999 if (FreeItems.getInstance().size() <= 2) {
2000 for (Item i : FreeItems.getInstance()) {
2001 if (i instanceof Line) {
2002 line = i;
2003 }
2004 }
2005 }
2006 }
2007 if (line == null) {
2008 return null;
2009 }
2010
2011 // Check we haven't moved too far
2012 if (isMouseDragNoOp()) {
2013 printNoopMessage();
2014 return null;
2015 }
2016
2017 return Gesture.single(StandardGestureActions.getInstance().gestureType(StandardGestureType.TOGGLE_ARROWHEAD), new ItemSpecificGestureData(line));
2018 }
2019
2020 // Someone else's timeout event
2021 return null;
2022 }
2023 });
2024
2025 // Add the LEFT + RIGHT MOUSE -> EXTRACT_ATTRIBUTES gesture recogniser
2026 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
2027 {
2028 private static final int STATE_NO_MOUSE_BUTTON_DOWN = 0;
2029 private static final int STATE_LEFT_MOUSE_BUTTON_DOWN = 1;
2030 private static final int STATE_RIGHT_MOUSE_BUTTON_DOWN = 2;
2031 private static final int STATE_BOTH_MOUSE_BUTTON_DOWN = 3;
2032 private static final int STATE_ERROR = 4;
2033 private int _state = STATE_NO_MOUSE_BUTTON_DOWN;
2034
2035 @Override
2036 public String details() { return "LEFT + RIGHT MOUSE -> EXTRACT_ATTRIBUTES"; }
2037
2038 @Override
2039 public List<Gesture> onInputEvent(InputEvent event) {
2040 // Cast to keyboard/mouse event
2041 KBMInputEvent kbmEvent = (KBMInputEvent) event;
2042
2043 // Keep track of mouse button state
2044 if (_state == STATE_NO_MOUSE_BUTTON_DOWN) {
2045 if (kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
2046 _state = STATE_RIGHT_MOUSE_BUTTON_DOWN;
2047 } else if (kbmEvent.getMouseButtonDown() == MouseButton.LEFT) {
2048 _state = STATE_LEFT_MOUSE_BUTTON_DOWN;
2049 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
2050 _state = STATE_ERROR;
2051 }
2052 return null;
2053 } else if (_state == STATE_LEFT_MOUSE_BUTTON_DOWN) {
2054 if (kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
2055 _state = STATE_BOTH_MOUSE_BUTTON_DOWN;
2056 } else if (kbmEvent.getMouseButtonUp() == MouseButton.LEFT) {
2057 _state = STATE_NO_MOUSE_BUTTON_DOWN;
2058 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
2059 _state = STATE_ERROR;
2060 }
2061 return null;
2062 } else if (_state == STATE_RIGHT_MOUSE_BUTTON_DOWN) {
2063 if (kbmEvent.getMouseButtonDown() == MouseButton.LEFT) {
2064 _state = STATE_BOTH_MOUSE_BUTTON_DOWN;
2065 } else if (kbmEvent.getMouseButtonUp() == MouseButton.RIGHT) {
2066 _state = STATE_NO_MOUSE_BUTTON_DOWN;
2067 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
2068 _state = STATE_ERROR;
2069 }
2070 return null;
2071 } else if (_state == STATE_BOTH_MOUSE_BUTTON_DOWN) {
2072 if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
2073 _state = STATE_ERROR;
2074 return null;
2075 }
2076 } else if (kbmTranslator.isAnyMouseButtonDown() == false) {
2077 _state = STATE_NO_MOUSE_BUTTON_DOWN;
2078 return null;
2079 }
2080
2081 // Wait for the button up to perform the extraction
2082 if (_state != STATE_BOTH_MOUSE_BUTTON_DOWN || kbmTranslator.isAnyMouseButtonDown()) {
2083 return null;
2084 }
2085
2086 // Reset state for next gesture
2087 _state = STATE_NO_MOUSE_BUTTON_DOWN;
2088
2089 // Check we haven't moved too far
2090 if (isMouseDragNoOp()) {
2091 printNoopMessage();
2092 return null;
2093 }
2094
2095 // Make sure we are over something to extract from
2096 if (!FrameUtils.hasCurrentItem()) {
2097 return null;
2098 }
2099
2100 // Return the gesture
2101 return standardSingle(StandardGestureType.EXTRACT_ATTRIBUTES, new ItemSpecificGestureData());
2102 }
2103 });
2104
2105 // Add the LEFT + RIGHT MOUSE -> FORMAT gesture recogniser
2106 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
2107 {
2108 private static final int STATE_NO_MOUSE_BUTTON_DOWN = 0;
2109 private static final int STATE_LEFT_MOUSE_BUTTON_DOWN = 1;
2110 private static final int STATE_RIGHT_MOUSE_BUTTON_DOWN = 2;
2111 private static final int STATE_BOTH_MOUSE_BUTTON_DOWN = 3;
2112 private static final int STATE_ERROR = 4;
2113 private int _state = STATE_NO_MOUSE_BUTTON_DOWN;
2114
2115 @Override
2116 public String details() { return "LEFT + RIGHT MOUSE -> FORMAT"; }
2117
2118 @Override
2119 public List<Gesture> onInputEvent(InputEvent event) {
2120 // Cast to keyboard/mouse event
2121 KBMInputEvent kbmEvent = (KBMInputEvent) event;
2122
2123 // Keep track of mouse button state
2124 if (_state == STATE_NO_MOUSE_BUTTON_DOWN) {
2125 if (kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
2126 _state = STATE_RIGHT_MOUSE_BUTTON_DOWN;
2127 } else if (kbmEvent.getMouseButtonDown() == MouseButton.LEFT) {
2128 _state = STATE_LEFT_MOUSE_BUTTON_DOWN;
2129 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
2130 _state = STATE_ERROR;
2131 }
2132 return null;
2133 } else if (_state == STATE_LEFT_MOUSE_BUTTON_DOWN) {
2134 if (kbmEvent.getMouseButtonDown() == MouseButton.RIGHT) {
2135 _state = STATE_BOTH_MOUSE_BUTTON_DOWN;
2136 } else if (kbmEvent.getMouseButtonUp() == MouseButton.LEFT) {
2137 _state = STATE_NO_MOUSE_BUTTON_DOWN;
2138 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
2139 _state = STATE_ERROR;
2140 }
2141 return null;
2142 } else if (_state == STATE_RIGHT_MOUSE_BUTTON_DOWN) {
2143 if (kbmEvent.getMouseButtonDown() == MouseButton.LEFT) {
2144 _state = STATE_BOTH_MOUSE_BUTTON_DOWN;
2145 } else if (kbmEvent.getMouseButtonUp() == MouseButton.RIGHT) {
2146 _state = STATE_NO_MOUSE_BUTTON_DOWN;
2147 } else if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
2148 _state = STATE_ERROR;
2149 }
2150 return null;
2151 } else if (_state == STATE_BOTH_MOUSE_BUTTON_DOWN) {
2152 if (kbmEvent.getEventType() == EventType.MOUSE_BUTTON_DOWN) {
2153 _state = STATE_ERROR;
2154 return null;
2155 }
2156 } else if (kbmTranslator.isAnyMouseButtonDown() == false) {
2157 _state = STATE_NO_MOUSE_BUTTON_DOWN;
2158 return null;
2159 }
2160
2161 // Wait for the button up to perform the extraction
2162 if (_state != STATE_BOTH_MOUSE_BUTTON_DOWN || kbmTranslator.isAnyMouseButtonDown()) {
2163 return null;
2164 }
2165
2166 // Reset state for next gesture
2167 _state = STATE_NO_MOUSE_BUTTON_DOWN;
2168
2169 // Check we haven't moved too far
2170 if (isMouseDragNoOp()) {
2171 printNoopMessage();
2172 return null;
2173 }
2174
2175 // Make sure we are not extracting
2176 if (FrameUtils.hasCurrentItem()) {
2177 return null;
2178 }
2179
2180 // Return the gestures
2181 Gesture hFormat = new Gesture(StandardGestureActions.getInstance().gestureType(StandardGestureType.FORMAT), new FormatGestureData(true));
2182 Gesture vFormat = new Gesture(StandardGestureActions.getInstance().gestureType(StandardGestureType.FORMAT), new FormatGestureData(false));
2183 if (kbmTranslator.isKeyDown(Key.CTRL) && kbmTranslator.isKeyDown(Key.SHIFT)) {
2184 List<Gesture> gestures = Gesture.single(hFormat);
2185 gestures.add(vFormat);
2186 return gestures;
2187 } else if (kbmTranslator.isKeyDown(Key.CTRL)) {
2188 return Gesture.single(hFormat);
2189 } else {
2190 return Gesture.single(vFormat);
2191 }
2192 }
2193 });
2194
2195 // TEMPLATE
2196 // Add the DETAILS gesture recogniser
2197 addTranslator(new InputEventToGestureTranslator(InputType.KBM)
2198 {
2199 @Override
2200 public String details() { return "DETAILS"; }
2201
2202 @Override
2203 public List<Gesture> onInputEvent(InputEvent event) {
2204 // Cast to keyboard/mouse event
2205 KBMInputEvent kbmEvent = (KBMInputEvent) event;
2206
2207 // TODO Auto-generated method stub
2208 return null;
2209 }
2210 });
2211 }
2212
2213 public boolean isKeyDown(Key key)
2214 {
2215 return StandardInputEventListeners.kbmStateListener.isKeyDown(key);
2216 }
2217
2218 public boolean isMouseButtonDown(MouseButton button)
2219 {
2220 return StandardInputEventListeners.kbmStateListener.isMouseButtonDown(button);
2221 }
2222
2223 public boolean isOnlyMouseButtonDown(MouseButton button)
2224 {
2225 return StandardInputEventListeners.kbmStateListener.isOnlyMouseButtonDown(button);
2226 }
2227
2228 public boolean isAnyMouseButtonDown()
2229 {
2230 return StandardInputEventListeners.kbmStateListener.isAnyMouseButtonDown();
2231 }
2232
2233 public static boolean isMouseDragNoOp()
2234 {
2235 return _noop;
2236 }
2237
2238 public static void printNoopMessage()
2239 {
2240 System.err.println("Exceeded NoOp Threshold of " + UserSettings.NoOpThreshold.get() + " pixels. Reinterpreting origonal Gesture.");
2241 //MessageBay.displayMessage("Gesture cancelled, mouse moved more than " + UserSettings.NoOpThreshold.get() + " pixels.");
2242 }
2243
2244 public static void trackMouseDragNoop(KBMInputEvent event)
2245 {
2246 if (!StandardInputEventListeners.kbmStateListener.isAnyMouseButtonDown() && (event.getEventType() != EventType.MOUSE_BUTTON_UP)) {
2247 _noop = false;
2248 _mouseDragStart = null;
2249 } else if (_mouseDragStart == null) {
2250 org.expeditee.core.Line mouseMove = event.getMouseMove();
2251 if (mouseMove != null) {
2252 _mouseDragStart = mouseMove.getFirstEnd().clone();
2253 }
2254 } else if (_noop == false) {
2255 org.expeditee.core.Line mouseMove = event.getMouseMove();
2256 if (mouseMove != null) {
2257 mouseMove.setFirstEnd(_mouseDragStart.clone());
2258 if (mouseMove.length() > UserSettings.NoOpThreshold.get()) {
2259 _noop = true;
2260 }
2261 }
2262 }
2263 }
2264
2265 /** Convenience function to create a single standard gesture. */
2266 public static List<Gesture> standardSingle(StandardGestureType type, GestureData data)
2267 {
2268 return Gesture.single(StandardGestureActions.getInstance().gestureType(type), data);
2269 }
2270}
Note: See TracBrowser for help on using the repository browser.