Changed indicator bg color.
[platform/framework/native/uifw.git] / src / ui / FUi_TouchRotationGestureDetector.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 /**
18  * @file                        FUi_TouchRotationGestureDetector.cpp
19  * @brief               This is the implementation file for %_TouchRotationGestureDetector class
20  * @version     2.0
21  *
22  * This file contains the implementation of %_TouchRotationGestureDetector class.
23  *
24  */
25 #include <FBaseUtilMath.h>
26 #include <FBaseColIEnumeratorT.h>
27 #include <FBaseColIListT.h>
28 #include <FUiITouchRotationGestureEventListener.h>
29 #include "FUi_TouchRotationGestureDetector.h"
30 #include "FUi_ITouchRotationGestureEventListener.h"
31 #include "FUi_TouchRotationGestureDetectorImpl.h"
32 #include "FUi_Control.h"
33 #include "FUi_FingerInfo.h"
34
35 using namespace Tizen::Base::Collection;
36 using namespace Tizen::Base::Runtime;
37 using namespace Tizen::Base::Utility;
38
39 namespace
40 {
41 const float PI = 3.14159265;
42 const float RAD_90DEGREE = PI / 2;
43 const float RAD_180DEGREE = PI;
44 const float RAD_270DEGREE = RAD_90DEGREE * 3;
45 const float RAD_360DEGREE = RAD_180DEGREE * 2;
46 const int DEFAULT_TOUCH_COUNT = 2;
47 const int MIN_ANGLE = 15;
48 const float DEGREE_360 = 360.0;
49 const int DEGREE_180 = 180;
50 const int DEGREE_90 = 90;
51 const float MIN_MOVEALLOWANCE = 20;
52 const int POLLING_ROTATION = 16;
53 const unsigned int SECOND_POINT_ID = 1;
54 }
55
56 namespace Tizen { namespace Ui
57 {
58 _TouchRotationGestureDetector::_TouchRotationGestureDetector(void)
59         : __distance(0)
60         , __angle(0)
61         , __fingerCount(0)
62         , __firstPoint(0, 0)
63         , __secondPoint(0, 0)
64         , __firstPrevPoint(0, 0)
65         , __secondPrevPoint(0, 0)
66         , __firstMovedDirection(0)
67         , __secondMovedDirection(0)
68         , __pTimer(null)
69         , __firstPointId(INVALID_POINT_ID)
70         , __secondPointId(INVALID_POINT_ID)
71 {
72         result r = GetLastResult();
73         SysTryReturnVoidResult(NID_UI, r == E_SUCCESS, r, GetErrorMessage(r));
74
75         __pTimer = new (std::nothrow) Timer;
76         SysTryReturnVoidResult(NID_UI, __pTimer, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
77
78         r = __pTimer->Construct(*this);
79         SysTryCatch(NID_UI, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
80
81         SetDetectorType(_TOUCH_GESTURE_DETECTOR_TYPE_ROTATION);
82         return;
83
84 CATCH:
85         delete __pTimer;
86         __pTimer = null;
87 }
88
89 _TouchRotationGestureDetector::~_TouchRotationGestureDetector(void)
90 {
91         delete __pTimer;
92         __pTimer = null;
93 }
94
95 double
96 _TouchRotationGestureDetector::GetAngle(float x1, float y1, float x2, float y2) const
97 {
98         float tempX = 0;
99         float tempY = 0;
100         float angle = 0;
101
102         tempX= -y1;
103         tempY = x1;
104
105         angle = acos( (tempX * x2 + tempY * y2) /
106           (sqrt( tempX * tempX + tempY * tempY ) *
107           sqrt(x2 * x2 + y2 * y2) ) )* DEGREE_180 / PI;
108
109         if (angle > DEGREE_90)
110         {
111                 angle = DEGREE_360 - acos( (x1 * x2 + y1 * y2) /
112                                   (sqrt( x1 * x1 + y1 * y1 ) *
113                                   sqrt(x2 * x2 + y2 * y2) ) )* DEGREE_180 / PI;
114         }
115         else
116         {
117                 angle = acos( (x1 * x2 + y1 * y2) /
118                                   (sqrt( x1 * x1 + y1 * y1 ) *
119                                   sqrt(x2 * x2 + y2 * y2) ) )* DEGREE_180 / PI;
120         }
121
122         return angle;
123 }
124
125 float
126 _TouchRotationGestureDetector::GetAngle(void) const
127 {
128         return __angle;
129 }
130
131 float
132 _TouchRotationGestureDetector::GetDistance(void) const
133 {
134         return __distance;
135 }
136
137 float
138 _TouchRotationGestureDetector::GetDistanceF(void) const
139 {
140         return __distance;
141 }
142
143 bool
144 _TouchRotationGestureDetector::OnTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
145 {
146         __fingerCount++;
147
148         switch(__fingerCount)
149         {
150         case 1:
151         {
152                 __firstPrevPoint.x = touchinfo.GetCurrentPosition().x;
153                 __firstPrevPoint.y = touchinfo.GetCurrentPosition().y;
154                 __firstPoint.x = touchinfo.GetCurrentPosition().x;
155                 __firstPoint.y = touchinfo.GetCurrentPosition().y;
156                 __distance = 0;
157                 __angle = 0;
158                 __firstPointId = touchinfo.GetPointId();
159                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_READY);
160         }
161         break;
162
163         case 2:
164         {
165                 __secondPrevPoint.x = touchinfo.GetCurrentPosition().x;
166                 __secondPrevPoint.y = touchinfo.GetCurrentPosition().y;
167                 __secondPoint.x = touchinfo.GetCurrentPosition().x;
168                 __secondPoint.y = touchinfo.GetCurrentPosition().y;
169                 __distance = Distance(__firstPrevPoint.x, __firstPrevPoint.y, __secondPrevPoint.x, __secondPrevPoint.y);
170                 __angle = 0;
171                 __secondPointId = touchinfo.GetPointId();
172                 __firstMovedDirection = 0;
173                 __secondMovedDirection = 0;
174                 SetGestureStart(true);
175                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_STARTED);
176
177                 _Control* pControl = GetControl();
178                 if (pControl && !pControl->IsMultiTouchEnabled())
179                 {
180                         pControl->SetMultiTouchEnabled(true);
181                 }
182         }
183         break;
184
185         default:
186                 break;
187         }
188
189         return false;
190 }
191
192 bool
193 _TouchRotationGestureDetector::OnTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
194 {
195         if (touchinfo.GetPointId() == __firstPointId || touchinfo.GetPointId() == __secondPointId)
196         {
197                 float angle = 0;
198                 _TouchGestureDetectorState state = GetDetectorState();
199
200                 if (state == _TOUCH_GESTURE_DETECTOR_STATE_STARTED || state == _TOUCH_GESTURE_DETECTOR_STATE_SUCCESS_AND_WAIT || state == _TOUCH_GESTURE_DETECTOR_STATE_CHANGED)
201                 {
202                         if (touchinfo.GetPointId() == __firstPointId)
203                         {
204                                 if (state == _TOUCH_GESTURE_DETECTOR_STATE_CHANGED)
205                                 {
206                                         __firstPrevPoint.x = __firstPoint.x;
207                                         __firstPrevPoint.y = __firstPoint.y;
208                                 }
209
210                                 __firstPoint.x = touchinfo.GetCurrentPosition().x;
211                                 __firstPoint.y = touchinfo.GetCurrentPosition().y;
212                                 angle = GetAngle(__secondPoint.x - __firstPrevPoint.x, __secondPoint.y - __firstPrevPoint.y, __secondPoint.x - __firstPoint.x, __secondPoint.y - __firstPoint.y);
213                         }
214                         else
215                         {
216                                 if (state == _TOUCH_GESTURE_DETECTOR_STATE_CHANGED)
217                                 {
218                                         __secondPrevPoint.x = __secondPoint.x;
219                                         __secondPrevPoint.y = __secondPoint.y;
220                                 }
221
222                                 __secondPoint.x = touchinfo.GetCurrentPosition().x;
223                                 __secondPoint.y = touchinfo.GetCurrentPosition().y;
224                                 angle = GetAngle(__firstPoint.x-__secondPrevPoint.x, __firstPoint.y - __secondPrevPoint.y, __firstPoint.x - __secondPoint.x, __firstPoint.y - __secondPoint.y);
225                         }
226
227                         __distance = Distance(__firstPoint.x, __firstPoint.y, __secondPoint.x, __secondPoint.y);
228
229                         if (state == _TOUCH_GESTURE_DETECTOR_STATE_STARTED)
230                         {
231                                 if (Math::Abs(__firstPrevPoint.x - __firstPoint.x) >= MIN_MOVEALLOWANCE
232                                                 || Math::Abs(__firstPrevPoint.y - __firstPoint.y) >= MIN_MOVEALLOWANCE
233                                                 || Math::Abs(__secondPrevPoint.x - __secondPoint.x) >= MIN_MOVEALLOWANCE
234                                                 ||  Math::Abs(__secondPrevPoint.y - __secondPoint.y) >= MIN_MOVEALLOWANCE)
235                                 {
236                                         enum moveDirection
237                                         {
238                                                 NONE = 0x0, RIGHT = 0x1, UP = 0x2, LEFT = 0x4, DOWN = 0x8
239                                         };
240
241                                         if (__firstPrevPoint.y - __firstPoint.y > 0)
242                                         {
243                                                 if (__firstMovedDirection & DOWN)
244                                                 {
245                                                         __firstMovedDirection ^= DOWN;
246                                                 }
247
248                                                 __firstMovedDirection |= UP;
249                                         }
250                                         else if (__firstPrevPoint.y - __firstPoint.y < 0)
251                                         {
252                                                 if (__firstMovedDirection & UP)
253                                                 {
254                                                         __firstMovedDirection ^= UP;
255                                                 }
256
257                                                 __firstMovedDirection |= DOWN;
258                                         }
259
260                                         if (__secondPrevPoint.y - __secondPoint.y > 0)
261                                         {
262                                                 if (__secondMovedDirection & DOWN)
263                                                 {
264                                                         __secondMovedDirection ^= DOWN;
265                                                 }
266
267                                                 __secondMovedDirection |= UP;
268
269                                         }
270                                         else if (__secondPrevPoint.y - __secondPoint.y < 0)
271                                         {
272                                                 if (__secondMovedDirection & UP)
273                                                 {
274                                                         __secondMovedDirection ^= UP;
275                                                 }
276
277                                                 __secondMovedDirection |= DOWN;
278                                         }
279
280 // Do not check same direction during rotation gesture.
281 // If not check the direction, it dooesn't display any result until.
282 /*
283                                         if (__firstMovedDirection & __secondMovedDirection)
284                                         {
285                                                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_FINISHED);
286                                                 return false;
287                                         }
288 */
289                                 }
290
291                                 if (angle >= DEGREE_360 - (MIN_ANGLE*2))
292                                 {
293                                         if (angle <= DEGREE_360 - MIN_ANGLE)
294                                         {
295                                                 __angle = -(DEGREE_360 - angle);
296
297 /*                                              if (state == _TOUCH_GESTURE_DETECTOR_STATE_STARTED)
298                                                 {
299                                                         __pTimer->Start(POLLING_ROTATION);
300                                                 }*/
301
302                                                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_CHANGED);
303                                         }
304                                 }
305                                 else
306                                 {
307                                         if (angle >= MIN_ANGLE)
308                                         {
309                                                 __angle = angle;
310
311                                         /*      if (state == _TOUCH_GESTURE_DETECTOR_STATE_STARTED)
312                                                 {
313                                                         __pTimer->Start(POLLING_ROTATION);
314                                                 }*/
315
316                                                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_CHANGED);
317                                         }
318                                 }
319                         }
320                         else
321                         {
322                                 if (angle >= DEGREE_360 - MIN_ANGLE)
323                                 {
324                                         __angle = -(DEGREE_360 - angle);
325                                 }
326                                 else
327                                 {
328                                         __angle = angle;
329                                 }
330
331                                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_CHANGED);
332                         }
333                 }
334         }
335
336         return false;
337 }
338
339 void
340 _TouchRotationGestureDetector::OnTimerExpired(Timer& timer)
341 {
342         SetDetectorStateChanged();
343
344         __pTimer->Start(POLLING_ROTATION);
345 }
346
347 void
348 _TouchRotationGestureDetector::SetDetectorStateChanged(void)
349 {
350         if (GetDetectorState() == _TOUCH_GESTURE_DETECTOR_STATE_CHANGED)
351         {
352                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_CHANGED);
353         }
354 }
355
356 bool
357 _TouchRotationGestureDetector::OnTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
358 {
359         __fingerCount--;
360
361         if (touchinfo.GetPointId() == __firstPointId || touchinfo.GetPointId() == __secondPointId)
362         {
363                 __pTimer->Cancel();
364
365                 if (touchinfo.GetPointId() == __firstPointId)
366                 {
367                         __firstPointId = INVALID_POINT_ID;
368                 }
369                 else
370                 {
371                         __secondPointId = INVALID_POINT_ID;
372                 }
373
374                 _TouchGestureDetectorState state = GetDetectorState();
375
376                 if (IsGestureStarted())
377                 {
378                         SetGestureStart(false);
379                         if (state == _TOUCH_GESTURE_DETECTOR_STATE_STARTED || state == _TOUCH_GESTURE_DETECTOR_STATE_CHANGED || state == _TOUCH_GESTURE_DETECTOR_STATE_SUCCESS_AND_WAIT)
380                         {
381                                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_FINISHED);
382                         }
383                 }
384         }
385
386         return false;
387 }
388
389 bool
390 _TouchRotationGestureDetector::OnTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
391 {
392         __firstMovedDirection = 0;
393         __secondMovedDirection = 0;
394         __fingerCount = 0;
395         __firstPointId = INVALID_POINT_ID;
396         __secondPointId = INVALID_POINT_ID;
397         __pTimer->Cancel();
398
399         return false;
400 }
401
402 void
403 _TouchRotationGestureDetector::OnTouchGestureDetectorAdded(void)
404 {
405         __firstMovedDirection = 0;
406         __secondMovedDirection = 0;
407         __fingerCount = 0;
408         __firstPointId = INVALID_POINT_ID;
409         __secondPointId = INVALID_POINT_ID;
410 }
411
412 void
413 _TouchRotationGestureDetector::OnTouchGestureDetectorRemoved(void)
414 {
415         if (__pTimer)
416         {
417                 __pTimer->Cancel();
418         }
419 }
420
421 }} // Tizen::Ui