1 /* Copyright (c) 2010-2014 Samsung Electronics Co., Ltd. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "gesture_detector_statemachine.h"
22 view::gesture_detector_statemachine::gesture_detector_statemachine(maps_view_h v)
24 , _current_state(STATE_NONE)
27 , is_2fingers_panning(false)
29 for(int i = 0; i < MAX_FINGERS; i ++)
30 is_panning[i] = false;
33 view::gesture_detector_statemachine::~gesture_detector_statemachine()
37 void view::gesture_detector_statemachine::tap(int finger_no,
38 const touch_point &tp)
41 case 0: /* Single finger pressed */
42 _info._finger_down[0] = tp;
43 _info._finger_move[0] = tp;
44 _info._prev_finger_down[0] = tp;
45 _info._is_finger_pressed[0] = true;
47 _info._fingers_pressed = _info.calc_finger_pressed();
49 if(_info._fingers_pressed > 2)
50 log("ERROR! Too many fingers pressed!!!", FG_RED);
52 /* Run state machine */
53 state_machine_on_event(FINGER_DOWN);
56 case 1: /* Second finger pressed */
57 _info._finger_down[1] = tp;
58 _info._finger_move[1] = tp;
59 _info._prev_finger_down[1] = tp;
60 _info._is_finger_pressed[1] = true;
62 _info._fingers_pressed = _info.calc_finger_pressed();
64 if(_info._fingers_pressed > 2)
65 log("ERROR! Too many fingers pressed!!!", FG_RED);
67 /* Run state machine */
68 state_machine_on_event(FINGER2_DOWN);
77 MAPS_LOGI("%c[%d;%d;%dm"
78 "Fingers pressed [after press]: %d"
80 0x1B, 1, 0, FG_LITE_WHITE,
81 _info._fingers_pressed,
85 void view::gesture_detector_statemachine::up(int finger_no,
86 const touch_point &tp)
89 case 0: /* Up the single finger */
90 _info._finger_up[0] = tp;
92 /* Run state machine */
93 state_machine_on_event(FINGER_UP);
95 /* Remove the info about lifted finger */
96 _info._is_finger_pressed[0] = false;
98 _info._fingers_pressed = _info.calc_finger_pressed();
100 if(_info._fingers_pressed < 0)
101 log("ERROR! Too few fingers pressed!!!", FG_RED);
103 /* This is the end of the gesture */
104 if(_info._fingers_pressed <= 0)
108 case 1: /* Up the second finger */
110 _info._finger_move[1] = tp;
111 _info._finger_up[1] = tp;
113 /* Run state machine */
114 state_machine_on_event(FINGER2_UP);
116 /* Remove the info about lifted finger */
117 _info._is_finger_pressed[1] = false;
119 _info._fingers_pressed = _info.calc_finger_pressed();
121 if(_info._fingers_pressed < 0)
122 log("ERROR! Too few fingers pressed!!!", FG_RED);
124 /* This is the end of the gesture */
125 if(_info._fingers_pressed <= 0)
133 stop_long_press_timer();
135 MAPS_LOGI("%c[%d;%d;%dm"
136 "Fingers pressed [after unpress]: %d"
138 0x1B, 1, 0, FG_LITE_WHITE,
139 _info._fingers_pressed,
143 void view::gesture_detector_statemachine::move(int finger_no,
144 const touch_point &tp)
146 /* There can not be a long press any more */
147 stop_long_press_timer();
150 case 0: /* Moving the first (single) finger */
151 _info._prev_finger_down[0] = _info._finger_move[0];
152 _info._finger_move[0] = tp;
154 /* Run state machine */
155 state_machine_on_event(FINGER_MOVE);
158 case 1: /* Moving the second finger */
159 _info._prev_finger_down[1] = _info._finger_move[1];
160 _info._finger_move[1] = tp;
162 /* Run state machine */
163 state_machine_on_event(FINGER2_MOVE);
170 void view::gesture_detector_statemachine::start_panning(int finger_no)
172 if(!is_panning[finger_no]) {
173 /*_info._prev_finger_down[finger_no] =
174 _info._finger_move[finger_no];*/
175 is_panning[finger_no] = true;
179 void view::gesture_detector_statemachine::finish_panning(int finger_no)
181 if(is_panning[finger_no]) {
182 _gp.on_panning_finished(finger_no);
184 _info._start_view_state.capture(_view);
185 _info._finger_down[finger_no] = _info._finger_move[finger_no];
187 is_panning[finger_no] = false;
190 void view::gesture_detector_statemachine::on_tap_timer()
192 /* TODO: think about concurent access to following member variables */
194 /* Run state machine */
195 state_machine_on_event(TAP_TIMER);
198 void view::gesture_detector_statemachine::on_long_press_timer()
200 /* TODO: think about concurent access to following member variables */
202 /* Run state machine */
203 state_machine_on_event(LONG_PRESS_TIMER);
206 void view::gesture_detector_statemachine::halt_gesture()
208 _current_state = STATE_NONE;
213 void view::gesture_detector_statemachine::state_machine_on_event(view_event_e event)
216 detector_states_e old_state = _current_state;
218 switch(_current_state) {
220 _info._start_view_state.capture(_view);
221 log_map_center(FG_WHITE);
225 _current_state = STATE_PRESSED;
226 start_long_press_timer();
230 log_state(event, _current_state);
237 case STATE_PRESSED: {
240 _current_state = STATE_MOVING;
243 if(finger_pressed_enough(0, 0, __CLICK_DURATION)) {
244 _current_state = STATE_CLICKED;
247 _current_state = STATE_NONE;
251 case LONG_PRESS_TIMER:
252 _current_state = STATE_LONG_PRESSED;
253 detected_long_press(); /* Long Press */
256 _current_state = STATE_2FINGERS_PRESSED;
259 log_state(event, _current_state);
265 case STATE_CLICKED: {
268 /* Calculate the time between clicks */
269 unsigned int last_click_time =
270 _info_history._finger_up[0]._timestamp;
271 unsigned int cur_time =
272 _info._finger_down[0]._timestamp;
273 unsigned int duration = cur_time - last_click_time;
275 /* Decide if we can have a souble click, or just a
277 if(duration < __DOUBLE_CLICK_DURATION)
278 _current_state = STATE_SECOND_PRESSED;
280 _current_state = STATE_PRESSED;
282 /* Start timer expecting the long press */
283 start_long_press_timer();
287 stop_long_press_timer();
288 _current_state = STATE_NONE;
289 detected_tap(); /* Tap */
292 log_state(event, _current_state);
298 case STATE_LONG_PRESSED: {
301 _current_state = STATE_NONE;
304 _current_state = STATE_MOVING;
307 _current_state = STATE_2FINGERS_PRESSED;
310 log_state(event, _current_state);
316 case STATE_SECOND_PRESSED: {
319 /* First click position */
320 const touch_point p1 = _info_history._finger_down[0];
322 /* Second click position */
323 const touch_point p2 = _info._finger_down[0];
325 MAPS_LOGI("Checking double tap: [%d, %d] -> [%d, %d]",
326 p1._x, p1._y, p2._x, p2._y);
329 * Check if tapped in the same point
330 * Note: accuracy is decreased for the sake of user's
334 if(get_trajectory_effective_length(p1, p2) <= (4 * __CLICK_AREA)) {
335 /* Switching to Double Tap state */
336 _current_state = STATE_SECOND_CLICKED;
338 detected_double_tap(); /* Double Tap */
341 * No need to expect other events here.
342 * Immediatelly switching to the initial State
345 _current_state = STATE_NONE;
347 /* Seems like it is a simple click */
348 _current_state = STATE_CLICKED;
349 stop_long_press_timer();
355 _current_state = STATE_NONE;
356 detected_tap(); /* Tap */
358 case LONG_PRESS_TIMER:
359 _current_state = STATE_SECOND_LONG_PRESSED;
360 detected_second_long_press(); /* Second Long Press */
363 _current_state = STATE_MOVING;
364 detected_pan(); /* Tap */
368 _current_state = STATE_2FINGERS_PRESSED;
371 log_state(event, _current_state);
378 case STATE_SECOND_CLICKED: {
380 _current_state = STATE_NONE;
384 case STATE_SECOND_LONG_PRESSED: {
387 _current_state = STATE_NONE;
390 _current_state = STATE_MOVING;
395 _current_state = STATE_2FINGERS_PRESSED;
398 log_state(event, _current_state);
405 if(event != FINGER_MOVE)
410 _current_state = STATE_MOVING;
411 detected_pan(); /* Pan */
415 /* When two fingers untouched simultaneously,
416 * Ecore sends finger1_up and then finger2_up
418 * The finger1_up switches the detector from
419 * STATE_2FINGERS_MOVING to STATE_MOVING.
420 * Now we are receiving finger2_up and should switch to
424 _current_state = STATE_NONE;
427 _current_state = STATE_2FINGERS_PRESSED;
430 log_state(event, _current_state);
436 case STATE_FINGER2_MOVING: {
437 if(event != FINGER2_MOVE)
442 _current_state = STATE_FINGER2_MOVING;
443 detected_finger2_pan(); /* Pan (finger2) */
446 _current_state = STATE_NONE;
449 _current_state = STATE_2FINGERS_PRESSED;
453 log_state(event, _current_state);
459 case STATE_2FINGERS_PRESSED: {
460 if(event != FINGER_MOVE && event != FINGER2_MOVE) {
463 finish_2fingers_panning();
468 _current_state = STATE_FINGER2_PRESSED;
471 _current_state = STATE_FINGER1_PRESSED;
475 _current_state = STATE_2FINGERS_MOVING;
476 detected_zoom_rotate(); /* Zoom, Rotate etc */
478 case LONG_PRESS_TIMER:
479 /* Just ignoring this event */
480 _current_state = STATE_2FINGERS_PRESSED;
483 log_state(event, _current_state);
489 case STATE_FINGER2_PRESSED: {
493 if(finger_pressed_enough(0, 0, __CLICK_DURATION)
494 && finger_pressed_enough(1, 0, __CLICK_DURATION)){
495 _current_state = STATE_2FINGERS_CLICKED;
496 detected_2finger_tap(); /* 2Finger Tap */
499 /* Nothing to do here: switching to initial state */
500 _current_state = STATE_NONE;
503 _current_state = STATE_FINGER2_MOVING;
504 detected_finger2_pan(); /* Pan (by second finger) */
507 _current_state = STATE_2FINGERS_PRESSED;
509 case LONG_PRESS_TIMER:
510 /* Just ignoring this event */
511 _current_state = STATE_FINGER2_PRESSED;
514 log_state(event, _current_state);
520 case STATE_FINGER1_PRESSED: {
523 if(finger_pressed_enough(0, 0, __CLICK_DURATION)
524 && finger_pressed_enough(1, 0, __CLICK_DURATION)){
525 _current_state = STATE_2FINGERS_CLICKED;
526 detected_2finger_tap(); /* 2Finger Tap */
529 /* No need to expect other events here.
530 * Immediatelly switching to the initial State */
531 _current_state = STATE_NONE;
534 _current_state = STATE_2FINGERS_PRESSED;
537 _current_state = STATE_MOVING;
538 detected_pan(); /* Pan */
542 log_state(event, _current_state);
548 case STATE_2FINGERS_CLICKED: {
553 case STATE_2FINGERS_MOVING: {
554 if(event != FINGER_MOVE && event != FINGER2_MOVE) {
557 finish_2fingers_panning();
558 _info._start_view_state.capture(_view);
563 _current_state = STATE_2FINGERS_MOVING;
564 detected_zoom_rotate(); /* Zoom, Rotate etc */
567 _current_state = STATE_2FINGERS_MOVING;
568 detected_zoom_rotate(); /* Zoom, Rotate etc */
571 _current_state = STATE_FINGER2_MOVING;
574 _current_state = STATE_MOVING;
577 log_state(event, _current_state);
583 case STATE_MOVING_AFTER_SECOND_PRESS: {
586 _current_state = STATE_NONE;
589 _current_state = STATE_2FINGERS_PRESSED;
592 _current_state = STATE_MOVING_AFTER_SECOND_PRESS;
595 log_state(event, _current_state);
602 log_state(event, _current_state);
603 _current_state = STATE_NONE;
607 string s_old = get_state_str(old_state);
608 string s = get_state_str(_current_state);
609 MAPS_LOGI("%c[%d;%d;%dm"
610 "switched from %s[%d] to %s[%d]"
612 0x1B, 1, 0, FG_LITE_CYAN,
613 s_old.c_str(), old_state,
614 s.c_str(), _current_state,
617 /* DEBUG: trace current central coordinates */
621 void view::gesture_detector_statemachine::detected_tap() /* Tap */
623 if (!is_gesture_available(MAPS_VIEW_GESTURE_TAP))
626 log("GESTURE TAP DETECTED", FG_GREEN);
630 void view::gesture_detector_statemachine::detected_long_press() /* Long Press */
632 if (!is_gesture_available(MAPS_VIEW_GESTURE_LONG_PRESS))
635 log("GESTURE LONG PRESS DETECTED", FG_GREEN);
639 void view::gesture_detector_statemachine::detected_double_tap() /* Double Tap */
641 if (!is_gesture_available(MAPS_VIEW_GESTURE_DOUBLE_TAP))
644 log("GESTURE DOUBLE TAP DETECTED", FG_GREEN);
648 void view::gesture_detector_statemachine::detected_second_long_press() /* Second Long Press */
650 if (!is_gesture_available(MAPS_VIEW_GESTURE_LONG_PRESS))
653 log("GESTURE SECOND LONG PRESS DETECTED", FG_GREEN);
657 void view::gesture_detector_statemachine::detected_pan() /* Pan */
659 if (!is_gesture_available(MAPS_VIEW_GESTURE_SCROLL))
662 log("GESTURE PAN DETECTED", FG_GREEN);
667 void view::gesture_detector_statemachine::detected_finger2_pan() /* Pan (second finger)*/
669 if (!is_gesture_available(MAPS_VIEW_GESTURE_SCROLL))
672 log("GESTURE FINGER2 PAN DETECTED", FG_GREEN);
677 /* Zoom, Rotate etc */
678 void view::gesture_detector_statemachine::detected_zoom_rotate()
680 if (!is_gesture_available(MAPS_VIEW_GESTURE_ZOOM)
681 && !is_gesture_available(MAPS_VIEW_GESTURE_ROTATE)
682 && !is_gesture_available(MAPS_VIEW_GESTURE_SCROLL))
685 log("GESTURE ZOOM ROTATE DETECTED", FG_GREEN);
687 bool zoom_changed = false;
688 bool rotation_changed = false;
689 bool panning_changed = false;
690 double zoom_factor = .0;
691 double rotation_angle = .0;
695 zoom_changed = _gp.on_zoom(is_zoomming, is_rotating, zoom_factor);
699 rotation_changed = _gp.on_rotate(is_zoomming, is_rotating, rotation_angle);
700 if (rotation_changed)
703 panning_changed = _gp.on_two_fingers_pan(is_2fingers_panning, &panning_x, &panning_y);
705 start_2fingers_panning();
707 _gp.on_zoom_rotate(zoom_changed, zoom_factor, rotation_changed, rotation_angle, panning_changed, panning_x, panning_y);
710 void view::gesture_detector_statemachine::detected_2finger_tap() /* 2Finger Tap */
712 if (!is_gesture_available(MAPS_VIEW_GESTURE_2_FINGER_TAP))
715 log("GESTURE 2 FINGER TAP DETECTED", FG_GREEN);
716 _gp.on_two_finger_tap();
719 string view::gesture_detector_statemachine::get_state_str(detector_states_e
733 case STATE_LONG_PRESSED:
734 s = "STATE_LONG_PRESSED";
736 case STATE_SECOND_PRESSED:
737 s = "STATE_SECOND_PRESSED";
739 case STATE_SECOND_CLICKED:
740 s = "STATE_SECOND_CLICKED";
742 case STATE_SECOND_LONG_PRESSED:
743 s = "STATE_SECOND_LONG_PRESSED";
748 case STATE_FINGER2_MOVING:
749 s = "STATE_FINGER2_MOVING";
751 case STATE_FINGER2_PRESSED:
752 s = "STATE_FINGER2_PRESSED";
754 case STATE_FINGER1_PRESSED:
755 s = "STATE_FINGER1_PRESSED";
757 case STATE_2FINGERS_PRESSED:
758 s = "STATE_2FINGERS_PRESSED";
760 case STATE_2FINGERS_CLICKED:
761 s = "STATE_2FINGERS_CLICKED";
763 case STATE_2FINGERS_MOVING:
764 s = "STATE_2FINGERS_MOVING";
766 case STATE_MOVING_AFTER_SECOND_PRESS:
767 s = "STATE_MOVING_AFTER_SECOND_PRESS";
776 string view::gesture_detector_statemachine::get_event_str(view_event_e event)
798 case LONG_PRESS_TIMER:
799 e = "LONG_PRESS_TIMER";
811 void view::gesture_detector_statemachine::log_event(view_event_e event)
813 string e = get_event_str(event);
814 log(e.c_str(), FG_BLUE);
817 void view::gesture_detector_statemachine::log_state(view_event_e event,
818 detector_states_e state)
820 string e = get_event_str(event);
821 string s = get_state_str(state);
823 MAPS_LOGE("%c[%d;%d;%dm"
824 "DEFAULT: state: %s[%d],\tevent: %s[%d]"
827 s.c_str(), state, e.c_str(), event,