Fork for IVI: mesa fixing
[profile/ivi/uifw.git] / src / ui / FUi_TouchPanningGestureDetector.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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_TouchPanningGestureDetector.cpp
19  * @brief               This is the implementation file for %_TouchPanningGestureDetector class
20  * @version             2.0
21  *
22  * This file contains the implementation of %_TouchPanningGestureDetector class.
23  *
24  */
25 #include <FBaseUtilMath.h>
26 #include <FBaseColIEnumeratorT.h>
27 #include <FUiITouchPanningGestureEventListener.h>
28 #include "FUi_TouchPanningGestureDetector.h"
29 #include "FUi_ITouchPanningGestureEventListener.h"
30 #include "FUi_TouchManager.h"
31 #include "FUi_TouchPanningGestureDetectorImpl.h"
32
33 using namespace Tizen::Base::Utility;
34 using namespace Tizen::Base::Collection;
35 using namespace Tizen::Base::Runtime;
36 using namespace Tizen::Graphics;
37
38 namespace
39 {
40 const int DEFAULT_TOUCH_COUNT = 1;
41 const int MIN_MOVEALLOWANCE = 20;
42 const int POLLING_PANNING = 16;
43 }
44
45 namespace Tizen { namespace Ui
46 {
47 _TouchPanningGestureDetector::_TouchPanningGestureDetector(void)
48         : __touchCount(DEFAULT_TOUCH_COUNT)
49         , __fingerCount(0)
50         , __maxPointId(DEFAULT_TOUCH_COUNT-1)
51         , __pTimer(null)
52 {
53         result r = GetLastResult();
54         SysTryReturnVoidResult(NID_UI, r == E_SUCCESS, r, GetErrorMessage(r));
55
56         __pTimer = new (std::nothrow)Timer;
57         SysTryReturnVoidResult(NID_UI, __pTimer, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
58
59         r = __pTimer->Construct(*this);
60         SysTryCatch(NID_UI, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
61
62         SetDetectorType(_TOUCH_GESTURE_DETECTOR_TYPE_PANNING);
63         return;
64
65 CATCH:
66         delete __pTimer;
67         __pTimer = null;
68 }
69
70 _TouchPanningGestureDetector::~_TouchPanningGestureDetector(void)
71 {
72         delete __pTimer;
73         __pTimer = null;
74 }
75
76 result
77 _TouchPanningGestureDetector::SetTouchCount(int count)
78 {
79         SysTryReturnResult(NID_UI, count > 0, E_INVALID_ARG, "[E_INVALID_ARG] Argument is less than 0");
80
81         __touchCount = count;
82         __maxPointId = __touchCount-1;
83
84         if (__touchCount > DEFAULT_TOUCH_COUNT)
85         {
86                 _Control* pControl = GetControl();
87                 if (pControl && !pControl->IsMultiTouchEnabled())
88                 {
89                         pControl->SetMultiTouchEnabled(true);
90                 }
91         }
92
93         return E_SUCCESS;
94 }
95
96 int
97 _TouchPanningGestureDetector::GetTouchCount(void) const
98 {
99         return __touchCount;
100 }
101
102 IListT<_TouchInfo*>*
103 _TouchPanningGestureDetector::GetTouchInfoListN(const _Control* pControl) const
104 {
105         if (GetDetectorState() != _TOUCH_GESTURE_DETECTOR_STATE_STARTED
106                         && GetDetectorState() != _TOUCH_GESTURE_DETECTOR_STATE_CHANGED
107                         && GetDetectorState() != _TOUCH_GESTURE_DETECTOR_STATE_FINISHED)
108         {
109                 return null;
110         }
111
112         Point controlPos(0, 0);
113         if (pControl != null)
114         {
115                 controlPos.x = pControl->GetAbsoluteBounds().x;
116                 controlPos.y = pControl->GetAbsoluteBounds().y;
117         }
118
119         _TouchManager* pTouchManager = _TouchManager::GetInstance();
120         SysTryReturn(NID_UI, pTouchManager != null, null, E_SYSTEM, "[E_SYSTEM] _TouchManager does not exist.");
121
122         IListT<_FingerInfo*>* pFingerInfoList = pTouchManager->GetMultiFingerInfoListN();
123         SysTryReturn(NID_UI, pFingerInfoList, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
124
125         LinkedListT<_TouchInfo*>* pReturnList = new (std::nothrow) LinkedListT<_TouchInfo*>;
126         SysTryCatch(NID_UI, pReturnList, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
127
128         for (int i = 0; i < pFingerInfoList->GetCount(); i++)
129         {
130                 _FingerInfo* pFingerInfo = null;
131                 pFingerInfoList->GetAt(i, pFingerInfo);
132
133                 if (pFingerInfo == null)
134                 {
135                         continue;
136                 }
137
138                 if (pFingerInfo->GetStatus() != _TOUCH_FOCUS_OUT)
139                 {
140                         _TouchInfo* pTouchInfo = new (std::nothrow) _TouchInfo;
141                         SysTryCatch(NID_UI, pTouchInfo, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.\n");
142                         Point point(pFingerInfo->GetScreenPoint().x - controlPos.x, pFingerInfo->GetScreenPoint().y - controlPos.y);
143
144                         pTouchInfo->SetTouchInfo(pFingerInfo->GetPointId(), pFingerInfo->GetStatus(), point, false, 0);
145                         pReturnList->Add(pTouchInfo);
146
147                         if (pReturnList->GetCount() == __touchCount)
148                         {
149                                 break;
150                         }
151                 }
152         }
153
154         delete pFingerInfoList;
155
156         return pReturnList;
157
158 CATCH:
159         if (pReturnList)
160         {
161                 IEnumeratorT<_TouchInfo*>* pEnumerator = pReturnList->GetEnumeratorN();
162                 if (pEnumerator)
163                 {
164                         while(pEnumerator->MoveNext() == E_SUCCESS)
165                         {
166                                 _TouchInfo* pTouchInfo = null;
167                                 pEnumerator->GetCurrent(pTouchInfo);
168                                 if (pTouchInfo == null)
169                                 {
170                                         continue;
171                                 }
172
173                                 delete pTouchInfo;
174                         }
175                         delete pEnumerator;
176                 }
177                 pReturnList->RemoveAll();
178                 delete pReturnList;
179                 pReturnList = null;
180         }
181         if (pFingerInfoList)
182         {
183                 delete pFingerInfoList;
184                 pFingerInfoList = null;
185         }
186
187         return null;
188 }
189
190 bool
191 _TouchPanningGestureDetector::OnTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
192 {
193         if (touchinfo.GetPointId() > __maxPointId)
194         {
195                 return false;
196         }
197
198         if (__fingerCount < 0)
199         {
200                 __fingerCount = 0;
201         }
202
203         __fingerCount++;
204         if ( __fingerCount < __touchCount)
205         {
206                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_READY);
207         }
208         else if (__touchCount == __fingerCount)
209         {
210                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_READY);
211                 SetGestureStart(true);
212                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_STARTED);
213                 __pTimer->Start(POLLING_PANNING);
214         }
215
216         return false;
217 }
218
219 bool
220 _TouchPanningGestureDetector::OnTouchMoved(const  _Control& source, const _TouchInfo& touchinfo)
221 {
222         if (touchinfo.GetPointId() > __maxPointId)
223         {
224                 return false;
225         }
226
227         _TouchGestureDetectorState state = GetDetectorState();
228         if (state == _TOUCH_GESTURE_DETECTOR_STATE_STARTED || state == _TOUCH_GESTURE_DETECTOR_STATE_SUCCESS_AND_WAIT || state == _TOUCH_GESTURE_DETECTOR_STATE_CHANGED)
229         {
230                 if (__touchCount > DEFAULT_TOUCH_COUNT)
231                 {
232                         _TouchManager* pTouchManager = _TouchManager::GetInstance();
233                         SysTryReturn(NID_UI, pTouchManager != null, null, E_SYSTEM, "[E_SYSTEM] _TouchManager does not found.");
234
235                         IListT<_FingerInfo*>* pFingerInfoList = pTouchManager->GetMultiFingerInfoListN();
236                         bool movedAll = false;
237                         enum moveDirection
238                         {
239                                 NONE = 0x0, RIGHT = 0x1, UP = 0x2, LEFT = 0x4, DOWN = 0x8
240                         };
241
242                         int directionList[__touchCount];
243
244                         if (pFingerInfoList)
245                         {
246                                 for(int i=0; i < __touchCount; i++)
247                                 {
248                                         _FingerInfo* pFingerInfo = null;
249                                         pFingerInfoList->GetAt(i, pFingerInfo);
250                                         directionList[i] = NONE;
251
252                                         if (pFingerInfo)
253                                         {
254                                                 Point currentPoint = pFingerInfo->GetPoint();
255                                                 Point controlPosition(0,0);
256                                                 _Control* pControl = GetControl();
257                                                 if (pControl)
258                                                 {
259                                                         controlPosition.x = pControl->GetAbsoluteBounds().x;
260                                                         controlPosition.y = pControl->GetAbsoluteBounds().y;
261                                                 }
262                                                 Point startPoint = pFingerInfo->GetStartPoint();
263                                                 startPoint.x = startPoint.x - controlPosition.x;
264                                                 startPoint.y = startPoint.y - controlPosition.y;
265
266                                                 if (Math::Abs(startPoint.x - currentPoint.x) >= MIN_MOVEALLOWANCE || Math::Abs(startPoint.y - currentPoint.y) >= MIN_MOVEALLOWANCE)
267                                                 {
268                                                         movedAll = true;
269
270                                                         if (currentPoint.x - startPoint.x > 0)
271                                                         {
272                                                                 directionList[i] |= RIGHT;
273                                                         }
274                                                         else if (currentPoint.x - startPoint.x < 0)
275                                                         {
276                                                                 directionList[i] |= LEFT;
277                                                         }
278
279                                                         if (currentPoint.y - startPoint.y > 0)
280                                                         {
281                                                                 directionList[i] |= DOWN;
282                                                         }
283                                                         else if (currentPoint.y - startPoint.y < 0)
284                                                         {
285                                                                 directionList[i] |= UP;
286                                                         }
287                                                 }
288                                                 else
289                                                 {
290                                                         movedAll = false;
291                                                 }
292                                         }
293                                 }
294                                 delete pFingerInfoList;
295                         }
296
297                         if (movedAll)
298                         {
299                                 bool sameDirection = true;
300                                 for(int i=0; i<__touchCount-1; i++)
301                                 {
302                                         if (directionList[i] != directionList[i+1])
303                                         {
304                                                 sameDirection = false;
305                                                 break;
306                                         }
307                                 }
308
309                                 if (sameDirection)
310                                 {
311                                         SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_CHANGED);
312                                         __pTimer->Start(POLLING_PANNING);
313                                 }
314                         }
315                 }
316                 else
317                 {
318                         SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_CHANGED);
319                         __pTimer->Start(POLLING_PANNING);
320                 }
321         }
322         return false;
323 }
324
325 void
326 _TouchPanningGestureDetector::OnTimerExpired(Timer& timer)
327 {
328         SetDetectorStateChanged();
329
330         __pTimer->Start(POLLING_PANNING);
331 }
332
333 void
334 _TouchPanningGestureDetector::SetDetectorStateChanged(void)
335 {
336         if ( GetDetectorState() == _TOUCH_GESTURE_DETECTOR_STATE_CHANGED )
337         {
338                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_CHANGED);
339         }
340 }
341
342 bool
343 _TouchPanningGestureDetector::OnTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
344 {
345         if (touchinfo.GetPointId() > __maxPointId)
346         {
347                 return false;
348         }
349
350         __fingerCount--;
351         _TouchGestureDetectorState state = GetDetectorState();
352         __pTimer->Cancel();
353
354         if (IsGestureStarted())
355         {
356                 SetGestureStart(false);
357                 if ( state == _TOUCH_GESTURE_DETECTOR_STATE_STARTED || state == _TOUCH_GESTURE_DETECTOR_STATE_CHANGED || state == _TOUCH_GESTURE_DETECTOR_STATE_SUCCESS_AND_WAIT)
358                 {
359                         SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_FINISHED);
360                 }
361         }
362
363         return false;
364 }
365
366 bool
367 _TouchPanningGestureDetector::OnTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
368 {
369         __fingerCount = 0;
370
371         return false;
372 }
373
374 }} // Tizen::Ui