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

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