2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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
9 // http://www.apache.org/licenses/LICENSE-2.0/
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.
18 * @file FUi_TouchRotationGestureDetector.cpp
19 * @brief This is the implementation file for %_TouchRotationGestureDetector class
22 * This file contains the implementation of %_TouchRotationGestureDetector class.
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"
35 using namespace Tizen::Base::Collection;
36 using namespace Tizen::Base::Runtime;
37 using namespace Tizen::Base::Utility;
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;
56 namespace Tizen { namespace Ui
58 _TouchRotationGestureDetector::_TouchRotationGestureDetector(void)
64 , __firstPrevPoint(0, 0)
65 , __secondPrevPoint(0, 0)
66 , __firstMovedDirection(0)
67 , __secondMovedDirection(0)
69 , __firstPointId(INVALID_POINT_ID)
70 , __secondPointId(INVALID_POINT_ID)
72 result r = GetLastResult();
73 SysTryReturnVoidResult(NID_UI, r == E_SUCCESS, r, GetErrorMessage(r));
75 __pTimer = new (std::nothrow) Timer;
76 SysTryReturnVoidResult(NID_UI, __pTimer, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
78 r = __pTimer->Construct(*this);
79 SysTryCatch(NID_UI, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
81 SetDetectorType(_TOUCH_GESTURE_DETECTOR_TYPE_ROTATION);
89 _TouchRotationGestureDetector::~_TouchRotationGestureDetector(void)
96 _TouchRotationGestureDetector::GetAngle(float x1, float y1, float x2, float y2) const
105 angle = acos( (tempX * x2 + tempY * y2) /
106 (sqrt( tempX * tempX + tempY * tempY ) *
107 sqrt(x2 * x2 + y2 * y2) ) )* DEGREE_180 / PI;
109 if (angle > DEGREE_90)
111 angle = DEGREE_360 - acos( (x1 * x2 + y1 * y2) /
112 (sqrt( x1 * x1 + y1 * y1 ) *
113 sqrt(x2 * x2 + y2 * y2) ) )* DEGREE_180 / PI;
117 angle = acos( (x1 * x2 + y1 * y2) /
118 (sqrt( x1 * x1 + y1 * y1 ) *
119 sqrt(x2 * x2 + y2 * y2) ) )* DEGREE_180 / PI;
126 _TouchRotationGestureDetector::GetAngle(void) const
132 _TouchRotationGestureDetector::GetDistance(void) const
138 _TouchRotationGestureDetector::GetDistanceF(void) const
144 _TouchRotationGestureDetector::OnTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
148 switch(__fingerCount)
152 __firstPrevPoint.x = touchinfo.GetCurrentPosition().x;
153 __firstPrevPoint.y = touchinfo.GetCurrentPosition().y;
154 __firstPoint.x = touchinfo.GetCurrentPosition().x;
155 __firstPoint.y = touchinfo.GetCurrentPosition().y;
158 __firstPointId = touchinfo.GetPointId();
159 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_READY);
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);
171 __secondPointId = touchinfo.GetPointId();
172 __firstMovedDirection = 0;
173 __secondMovedDirection = 0;
174 SetGestureStart(true);
175 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_STARTED);
177 _Control* pControl = GetControl();
178 if (pControl && !pControl->IsMultiTouchEnabled())
180 pControl->SetMultiTouchEnabled(true);
193 _TouchRotationGestureDetector::OnTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
195 if (touchinfo.GetPointId() == __firstPointId || touchinfo.GetPointId() == __secondPointId)
198 _TouchGestureDetectorState state = GetDetectorState();
200 if (state == _TOUCH_GESTURE_DETECTOR_STATE_STARTED || state == _TOUCH_GESTURE_DETECTOR_STATE_SUCCESS_AND_WAIT || state == _TOUCH_GESTURE_DETECTOR_STATE_CHANGED)
202 if (touchinfo.GetPointId() == __firstPointId)
204 if (state == _TOUCH_GESTURE_DETECTOR_STATE_CHANGED)
206 __firstPrevPoint.x = __firstPoint.x;
207 __firstPrevPoint.y = __firstPoint.y;
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);
216 if (state == _TOUCH_GESTURE_DETECTOR_STATE_CHANGED)
218 __secondPrevPoint.x = __secondPoint.x;
219 __secondPrevPoint.y = __secondPoint.y;
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);
227 __distance = Distance(__firstPoint.x, __firstPoint.y, __secondPoint.x, __secondPoint.y);
229 if (state == _TOUCH_GESTURE_DETECTOR_STATE_STARTED)
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)
238 NONE = 0x0, RIGHT = 0x1, UP = 0x2, LEFT = 0x4, DOWN = 0x8
241 if (__firstPrevPoint.y - __firstPoint.y > 0)
243 if (__firstMovedDirection & DOWN)
245 __firstMovedDirection ^= DOWN;
248 __firstMovedDirection |= UP;
250 else if (__firstPrevPoint.y - __firstPoint.y < 0)
252 if (__firstMovedDirection & UP)
254 __firstMovedDirection ^= UP;
257 __firstMovedDirection |= DOWN;
260 if (__secondPrevPoint.y - __secondPoint.y > 0)
262 if (__secondMovedDirection & DOWN)
264 __secondMovedDirection ^= DOWN;
267 __secondMovedDirection |= UP;
270 else if (__secondPrevPoint.y - __secondPoint.y < 0)
272 if (__secondMovedDirection & UP)
274 __secondMovedDirection ^= UP;
277 __secondMovedDirection |= DOWN;
280 // Do not check same direction during rotation gesture.
281 // If not check the direction, it dooesn't display any result until.
283 if (__firstMovedDirection & __secondMovedDirection)
285 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_FINISHED);
291 if (angle >= DEGREE_360 - (MIN_ANGLE*2))
293 if (angle <= DEGREE_360 - MIN_ANGLE)
295 __angle = -(DEGREE_360 - angle);
297 /* if (state == _TOUCH_GESTURE_DETECTOR_STATE_STARTED)
299 __pTimer->Start(POLLING_ROTATION);
302 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_CHANGED);
307 if (angle >= MIN_ANGLE)
311 /* if (state == _TOUCH_GESTURE_DETECTOR_STATE_STARTED)
313 __pTimer->Start(POLLING_ROTATION);
316 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_CHANGED);
322 if (angle >= DEGREE_360 - MIN_ANGLE)
324 __angle = -(DEGREE_360 - angle);
331 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_CHANGED);
340 _TouchRotationGestureDetector::OnTimerExpired(Timer& timer)
342 SetDetectorStateChanged();
344 __pTimer->Start(POLLING_ROTATION);
348 _TouchRotationGestureDetector::SetDetectorStateChanged(void)
350 if (GetDetectorState() == _TOUCH_GESTURE_DETECTOR_STATE_CHANGED)
352 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_CHANGED);
357 _TouchRotationGestureDetector::OnTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
361 if (touchinfo.GetPointId() == __firstPointId || touchinfo.GetPointId() == __secondPointId)
365 if (touchinfo.GetPointId() == __firstPointId)
367 __firstPointId = INVALID_POINT_ID;
371 __secondPointId = INVALID_POINT_ID;
374 _TouchGestureDetectorState state = GetDetectorState();
376 if (IsGestureStarted())
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)
381 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_FINISHED);
390 _TouchRotationGestureDetector::OnTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
392 __firstMovedDirection = 0;
393 __secondMovedDirection = 0;
395 __firstPointId = INVALID_POINT_ID;
396 __secondPointId = INVALID_POINT_ID;
403 _TouchRotationGestureDetector::OnTouchGestureDetectorAdded(void)
405 __firstMovedDirection = 0;
406 __secondMovedDirection = 0;
408 __firstPointId = INVALID_POINT_ID;
409 __secondPointId = INVALID_POINT_ID;
413 _TouchRotationGestureDetector::OnTouchGestureDetectorRemoved(void)