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_TouchFlickGestureDetector.cpp
19 * @brief This is the implementation file for %_TouchFlickGestureDetector class
22 * This file contains the implementation of %_TouchFlickGestureDetector class.
26 #include <FBaseUtilMath.h>
27 #include <FBaseColIEnumeratorT.h>
28 #include <FUiITouchFlickGestureEventListener.h>
29 #include "FUi_TouchManager.h"
30 #include "FUi_TouchFlickGestureDetector.h"
31 #include "FUi_ITouchFlickGestureEventListener.h"
32 #include "FUi_TouchFlickGestureDetectorImpl.h"
34 using namespace Tizen::Base::Utility;
35 using namespace Tizen::System;
36 using namespace Tizen::Base::Collection;
38 namespace Tizen { namespace Ui
42 const int MAX_VALUE = -10000;
43 const int MIN_VALUE = 10000;
44 const int IGNORE_OVERSHOOT_TIME = 80;
45 const int IGNORE_OVERSHOOT_MM = 5;
46 const int DIRECT_MOVE_TIME = 80;;
47 const int DIRECT_MOVE_MM = 3;
48 const int MAX_TIME_WND = 200;
49 const int MIN_TIME_WND = 30;
50 const int FIRST_MOVE_BOUND_MM = 2;
52 const int RES_H = 800;
53 const int IGNORE_OVERSHOOT_PXL = IGNORE_OVERSHOOT_MM * RES_H / MM_H;
54 const int DIRECT_MOVE_PXL = DIRECT_MOVE_MM * RES_H / MM_H;
55 const int MIN_MOVE_PXL = FIRST_MOVE_BOUND_MM * RES_H / MM_H;
56 const unsigned int FIRST_POINT_ID = 0;
59 /* lcd size 480x800 DEVICE_SIZE_VERTICAL 72
60 * lcd size 240x400 DEVICE_SIZE_VERTICAL 66
61 * lcd size 320x480 DEVICE_SIZE_VERTICAL 66
63 * RES_H = lcd size(height)
65 _TouchFlickGestureDetector::_TouchFlickGestureDetector(void)
69 , __direction(_FLICK_DIRECTION_NONE)
70 , __maxMoveX(MAX_VALUE)
71 , __minMoveX(MIN_VALUE)
72 , __maxMoveY(MAX_VALUE)
73 , __minMoveY(MIN_VALUE)
74 , __pFlickInfoList(null)
76 result r = GetLastResult();
77 SysTryReturnVoidResult(NID_UI, r == E_SUCCESS, r, GetErrorMessage(r));
79 SetDetectorType(_TOUCH_GESTURE_DETECTOR_TYPE_FLICK);
81 __pFlickInfoList = new (std::nothrow) ArrayListT<_FlickInfo*>;
82 SysTryReturnVoidResult(NID_UI, __pFlickInfoList, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
87 _TouchFlickGestureDetector::~_TouchFlickGestureDetector(void)
91 delete __pFlickInfoList;
92 __pFlickInfoList = null;
96 _TouchFlickGestureDetector::CheckMoveMinMax(const int x, const int y)
120 _TouchFlickGestureDetector::ClearVariables(void)
127 for (int i = 0; i < __pFlickInfoList->GetCount(); i++)
129 _FlickInfo* pFlickInfo = null;
130 __pFlickInfoList->GetAt(i, pFlickInfo);
138 __pFlickInfoList->RemoveAll();
142 _TouchFlickGestureDetector::FindFlickWindow(const ArrayListT<_FlickInfo*>* pList, const _FlickInfo* pFlickInfo, int* pStartIndex, int* pEndIndex)
144 int pointCount = pList->GetCount();
145 int endIdx = pointCount - 1;
149 FD_NONE = 0, FD_RIGHT = 0x1, FD_UP = 0x2, FD_LEFT = 0x4, FD_DOWN = 0x8
152 int dirOpp = FD_NONE;
154 int deltaX = 0, deltaY = 0;
157 for (i = endIdx - 1; i > 0; i--)
159 bool isDirChanged = false;
162 _FlickInfo* pVecPoints = null;
163 _FlickInfo* pPrevVecPoints = null;
165 pList->GetAt(i, pVecPoints);
166 pList->GetAt(i - 1, pPrevVecPoints);
168 if (pVecPoints && pPrevVecPoints)
170 distanceX = pVecPoints->x - pPrevVecPoints->x;
171 distanceY = pVecPoints->y - pPrevVecPoints->y;
174 if (distanceX == 0 && distanceY == 0)
178 else if (distanceX > 0 && distanceX > Math::Abs(distanceY)) // Right
182 if (dirOpp & FD_RIGHT)
191 else if (distanceX < 0 && distanceX < -Math::Abs(distanceY)) // Left
195 if (dirOpp & FD_LEFT)
204 else if (distanceY > 0 && distanceY >= Math::Abs(distanceX)) // Down
208 if (dirOpp & FD_DOWN)
217 else if (distanceY < 0 && distanceY <= -Math::Abs(distanceX)) // Up
233 if (pFlickInfo->time - pVecPoints->time < IGNORE_OVERSHOOT_TIME
234 && Math::Abs(deltaX) < IGNORE_OVERSHOOT_PXL && Math::Abs(deltaY) < IGNORE_OVERSHOOT_PXL)
251 if (pFlickInfo->time - pPrevVecPoints->time > DIRECT_MOVE_TIME
252 && Math::Abs(deltaX) < DIRECT_MOVE_PXL && Math::Abs(deltaY) < DIRECT_MOVE_PXL)
260 if (pFlickInfo->time - pVecPoints->time > MAX_TIME_WND)
272 __direction = _FLICK_DIRECTION_NONE;
276 __direction = _FLICK_DIRECTION_RIGHT;
280 __direction = _FLICK_DIRECTION_LEFT;
284 __direction = _FLICK_DIRECTION_UP;
288 __direction = _FLICK_DIRECTION_DOWN;
298 _TouchFlickGestureDetector::CalculateFlick(const ArrayListT<_FlickInfo*>* pList, const _FlickInfo* pFlickInfo, _FlickInfo* pReturnFlick)
302 ITEM_EXECUTION, DIRECT_MOVE, FLICK_START
305 flickStatus = FLICK_START;
307 if ((__maxMoveX - __minMoveX) < MIN_MOVE_PXL
308 && (__maxMoveY - __minMoveY) < MIN_MOVE_PXL)
310 flickStatus = ITEM_EXECUTION;
312 pReturnFlick->x = pReturnFlick->y = 0;
313 pReturnFlick->time = MIN_TIME_WND;
315 return (flickStatus != ITEM_EXECUTION);
330 if (!FindFlickWindow(pList, pFlickInfo, &startIdx, &endIdx))
332 flickStatus = DIRECT_MOVE;
335 _FlickInfo* pEndVecPoint = null;
336 _FlickInfo* pStartVecPoint = null;
338 pList->GetAt(endIdx, pEndVecPoint);
339 pList->GetAt(startIdx, pStartVecPoint);
343 endPosX = pEndVecPoint->x;
344 endPosY = pEndVecPoint->y;
346 endTime = pFlickInfo->time;
350 startPosX = pStartVecPoint->x;
351 startPosY = pStartVecPoint->y;
352 startTime = pStartVecPoint->time;
355 distanceX = endPosX - startPosX;
356 distanceY = endPosY - startPosY;
357 time = endTime - startTime;
359 if (time < MIN_TIME_WND)
364 pReturnFlick->x = distanceX;
365 pReturnFlick->y = distanceY;
366 pReturnFlick->time = time;
368 if (flickStatus == DIRECT_MOVE)
370 pReturnFlick->x = pReturnFlick->y = 0;
378 _TouchFlickGestureDetector::OnTouchDown(ArrayListT<_FlickInfo*>* pList, const _FlickInfo* pFlickInfo)
380 result r = pList->Add(const_cast<_FlickInfo*>(pFlickInfo));
381 SysTryReturnResult(NID_UI, r == E_SUCCESS, r, "%s", GetErrorMessage(r));
383 CheckMoveMinMax(pFlickInfo->x, pFlickInfo->y);
389 _TouchFlickGestureDetector::OnTouchMove(ArrayListT<_FlickInfo*>* pList, const _FlickInfo* pFlickInfo)
391 result r = pList->Add(const_cast<_FlickInfo*>(pFlickInfo));
392 SysTryReturnResult(NID_UI, r == E_SUCCESS, r, "%s", GetErrorMessage(r));
394 CheckMoveMinMax(pFlickInfo->x, pFlickInfo->y);
400 _TouchFlickGestureDetector::OnTouchUp(ArrayListT<_FlickInfo*>* pList, const _FlickInfo* pFlickInfo, _FlickInfo* pReturnFlick, bool& isFlicked)
402 result r = pList->Add(const_cast<_FlickInfo*>(pFlickInfo));
403 SysTryReturnResult(NID_UI, r == E_SUCCESS, r, "%s", GetErrorMessage(r));
405 CheckMoveMinMax(pFlickInfo->x, pFlickInfo->y);
407 _FlickInfo* pTempVecPoint = null;
408 bool flickEnable = false;
410 int count = pList->GetCount();
411 for(int i=0; i < count; i++)
413 pList->GetAt(i, pTempVecPoint);
414 if(pTempVecPoint->touchStatus == _TOUCH_MOVED)
421 isFlicked = flickEnable?(CalculateFlick(pList, pFlickInfo, pReturnFlick)):false;
427 _TouchFlickGestureDetector::OnTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
429 if (touchinfo.GetPointId() != FIRST_POINT_ID)
434 _FlickInfo* pFlickInfo = new (std::nothrow) _FlickInfo;
435 SysTryReturn(NID_UI, pFlickInfo, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
437 pFlickInfo->time = touchinfo.GetTimeStamp();
438 pFlickInfo->x = touchinfo.GetCurrentPosition().x;
439 pFlickInfo->y = touchinfo.GetCurrentPosition().y;
440 pFlickInfo->touchStatus = touchinfo.GetTouchStatus();
445 __direction = _FLICK_DIRECTION_NONE;
447 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_READY);
448 SetGestureStart(true);
450 result r = OnTouchDown(__pFlickInfoList, pFlickInfo);
460 _TouchFlickGestureDetector::OnTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
462 if (touchinfo.GetPointId() != FIRST_POINT_ID)
467 _FlickInfo* pFlickInfo = new (std::nothrow) _FlickInfo;
468 SysTryReturn(NID_UI, pFlickInfo, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
470 pFlickInfo->time = touchinfo.GetTimeStamp();
471 pFlickInfo->x = touchinfo.GetCurrentPosition().x;
472 pFlickInfo->y = touchinfo.GetCurrentPosition().y;
473 pFlickInfo->touchStatus = touchinfo.GetTouchStatus();
475 result r = OnTouchMove(__pFlickInfoList, pFlickInfo);
485 _TouchFlickGestureDetector::OnTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
487 if (touchinfo.GetPointId() != FIRST_POINT_ID)
492 _TouchManager* pTouchManager = _TouchManager::GetInstance();
493 SysTryReturn(NID_UI, pTouchManager, false, E_SYSTEM, "[E_SYSTEM] _TouchManager does not exist.");
495 _FlickInfo returnedFlickInfo = {0, };
497 _FlickInfo* pFlickInfo = new (std::nothrow) _FlickInfo;
498 SysTryReturn(NID_UI, pFlickInfo, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
500 pFlickInfo->time = touchinfo.GetTimeStamp();
501 pFlickInfo->x = touchinfo.GetCurrentPosition().x;
502 pFlickInfo->y = touchinfo.GetCurrentPosition().y;
503 pFlickInfo->touchStatus = touchinfo.GetTouchStatus();
505 bool isFlicked = false;
507 if (pTouchManager->GetPointCount() > 1) //supports only one finger count
514 result r = OnTouchUp(__pFlickInfoList, pFlickInfo, &returnedFlickInfo, isFlicked);
521 SetGestureStart(false);
522 if (isFlicked && (returnedFlickInfo.x != 0 || returnedFlickInfo.y != 0))
524 __xDistance = returnedFlickInfo.x;
525 __yDistance = returnedFlickInfo.y;
526 __duration = returnedFlickInfo.time;
528 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_SUCCESS);
536 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_FAILED);
543 _TouchFlickGestureDetector::OnTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
551 _TouchFlickGestureDetector::GetDistance(int& x, int &y) const
558 _TouchFlickGestureDetector::GetDistance(float& x, float &y) const
565 _TouchFlickGestureDetector::GetDuration(void) const
571 _TouchFlickGestureDetector::GetDirection(void) const