Changed indicator bg color.
[platform/framework/native/uifw.git] / src / ui / FUi_TouchLongPressGestureDetector.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_TouchLongPressGestureDetector.cpp
19  * @brief               This is the implementation file for %_TouchLongPressGestureDetector class
20  * @version             2.0
21  *
22  * This file contains the implementation of %_TouchLongPressGestureDetector class.
23  *
24  */
25 #include <Elementary.h>
26 #include <FBaseUtilMath.h>
27 #include <FBaseColIEnumeratorT.h>
28 #include <FUiITouchLongPressGestureEventListener.h>
29 #include "FUi_TouchLongPressGestureDetector.h"
30 #include "FUi_ITouchLongPressGestureEventListener.h"
31 #include "FUi_TouchManager.h"
32 #include "FUi_TouchLongPressGestureDetectorImpl.h"
33 #include "FUi_TouchGestureTimerManager.h"
34
35 using namespace Tizen::Base::Utility;
36 using namespace Tizen::Base::Collection;
37 using namespace Tizen::Graphics;
38
39 namespace Tizen { namespace Ui
40 {
41 const int DEFAULT_DURATION = 500;
42 const int DEFAULT_MOVE_ALLOWANCE = 10;
43 const int DEFAULT_TOUCH_COUNT = 1;
44 const int MAX_TOUCH_COUNT = 10;
45
46 class _TouchLongPressGestureDetector::_LongPressInfo
47 {
48 public:
49         bool __isPressed;
50         bool __isInBounds;
51         int __touchCount;
52 };
53
54 _TouchLongPressGestureDetector::_TouchLongPressGestureDetector(void)
55         : __duration(DEFAULT_DURATION)
56         , __moveAllowance(DEFAULT_MOVE_ALLOWANCE)
57         , __touchCount(DEFAULT_TOUCH_COUNT)
58         , __maxPointId(DEFAULT_TOUCH_COUNT-1)
59         , __pGestureTimerManager(null)
60         , __touchCanceled(false)
61         , __deleteTimer(true)
62         , __pLongPressInfoList(null)
63 {
64         result r = GetLastResult();
65         SysTryReturnVoidResult(NID_UI, r == E_SUCCESS, r, GetErrorMessage(r));
66
67         __pLongPressInfoList = new (std::nothrow) ArrayListT<_LongPressInfo*>;
68         SysTryReturnVoidResult(NID_UI, __pLongPressInfoList, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
69
70         int __duration = static_cast<int>(elm_config_longpress_timeout_get() * 1000);
71         if (__duration == 0)
72         {
73                 __duration = 500;
74         }
75
76         for(int i=0; i < MAX_TOUCH_COUNT; i++)
77         {
78                 _LongPressInfo* pLongPressInfo = new (std::nothrow) _LongPressInfo;
79                 SysTryCatch(NID_UI, pLongPressInfo, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
80
81                 pLongPressInfo->__isPressed = false;
82                 pLongPressInfo->__isInBounds = false;
83                 pLongPressInfo->__touchCount = 0;
84
85                 __pLongPressInfoList->Add(pLongPressInfo);
86         }
87
88         SetDetectorType(_TOUCH_GESTURE_DETECTOR_TYPE_LONG_PRESS);
89         return;
90
91 CATCH:
92         if (__pLongPressInfoList)
93         {
94                 RemoveLongPressInfoList();
95                 delete __pLongPressInfoList;
96                 __pLongPressInfoList = null;
97         }
98 }
99
100 _TouchLongPressGestureDetector::~_TouchLongPressGestureDetector(void)
101 {
102         RemoveLongPressInfoList();
103         __pLongPressInfoList->RemoveAll();
104
105         delete __pLongPressInfoList;
106         __pLongPressInfoList = null;
107
108         if (__pGestureTimerManager != null)
109         {
110                 __pGestureTimerManager->CancelTimer();
111
112                 delete __pGestureTimerManager;
113                 __pGestureTimerManager = null;
114
115                 __touchCanceled = false;
116         }
117 }
118
119 void
120 _TouchLongPressGestureDetector::RemoveLongPressInfoList(void)
121 {
122         IEnumeratorT<_LongPressInfo*>* pEnumerator = __pLongPressInfoList->GetEnumeratorN();
123         if (pEnumerator)
124         {
125                 while(pEnumerator->MoveNext() == E_SUCCESS)
126                 {
127                         _LongPressInfo* pLongPressInfo = null;
128                         pEnumerator->GetCurrent(pLongPressInfo);
129                         if (!pLongPressInfo)
130                         {
131                                 continue;
132                         }
133                         delete pLongPressInfo;
134                 }
135                 delete pEnumerator;
136         }
137 }
138
139 result
140 _TouchLongPressGestureDetector::SetDuration(int duration)
141 {
142         SysTryReturnResult(NID_UI, duration > 0, E_INVALID_ARG, "[E_INVALID_ARG] Argument is less than 0");
143
144         __duration = duration;
145         return E_SUCCESS;
146 }
147
148 int
149 _TouchLongPressGestureDetector::GetDuration(void) const
150 {
151         return __duration;
152 }
153
154 result
155 _TouchLongPressGestureDetector::SetMoveAllowance(int allowance)
156 {
157         SysTryReturnResult(NID_UI, allowance > 0, E_INVALID_ARG, "[E_INVALID_ARG] Argument is less than 0");
158
159         __moveAllowance = allowance;
160         return E_SUCCESS;
161 }
162
163 result
164 _TouchLongPressGestureDetector::SetMoveAllowance(float allowance)
165 {
166         SysTryReturnResult(NID_UI, allowance > 0, E_INVALID_ARG, "[E_INVALID_ARG] Argument is less than 0");
167
168         __moveAllowance = allowance;
169         return E_SUCCESS;
170 }
171
172 int
173 _TouchLongPressGestureDetector::GetMoveAllowance(void) const
174 {
175         return __moveAllowance;
176 }
177
178 float
179 _TouchLongPressGestureDetector::GetMoveAllowanceF(void) const
180 {
181         return __moveAllowance;
182 }
183
184 result
185 _TouchLongPressGestureDetector::SetTouchCount(int count)
186 {
187         SysTryReturnResult(NID_UI, count > 0, E_INVALID_ARG, "[E_INVALID_ARG] Argument is less than 0");
188
189         __touchCount = count;
190         __maxPointId = __touchCount-1;
191
192         if (__touchCount > DEFAULT_TOUCH_COUNT)
193         {
194                 _Control* pControl = GetControl();
195                 if (pControl && !pControl->IsMultiTouchEnabled())
196                 {
197                         pControl->SetMultiTouchEnabled(true);
198                 }
199         }
200
201         return E_SUCCESS;
202 }
203
204 int
205 _TouchLongPressGestureDetector::GetTouchCount(void) const
206 {
207         return __touchCount;
208 }
209
210 void
211 _TouchLongPressGestureDetector::EnableToDeleteTimer(bool deleteTimer)
212 {
213         __deleteTimer = deleteTimer;
214 }
215
216 bool
217 _TouchLongPressGestureDetector::IsPressed(void)
218 {
219         bool allPressed = false;
220         for(int i=0; i<__touchCount; i++)
221         {
222                 _LongPressInfo* pLongPressInfo = null;
223                 __pLongPressInfoList->GetAt(i, pLongPressInfo);
224                 if (pLongPressInfo)
225                 {
226                         if (pLongPressInfo->__isPressed && pLongPressInfo->__isInBounds
227                                         && (pLongPressInfo->__touchCount == DEFAULT_TOUCH_COUNT))
228                         {
229                                 allPressed = true;
230                         }
231                         else
232                         {
233                                 allPressed = false;
234                         }
235                 }
236         }
237
238         return allPressed;
239 }
240
241 void
242 _TouchLongPressGestureDetector::ResetGestureTimerManager(void)
243 {
244         if (__pGestureTimerManager)
245         {
246                 delete __pGestureTimerManager;
247                 __pGestureTimerManager = null;
248         }
249         __touchCanceled = false;
250         __deleteTimer = true;
251 }
252
253 bool
254 _TouchLongPressGestureDetector::IsTouchCanceled(void) const
255 {
256         return __touchCanceled;
257 }
258
259 bool
260 _TouchLongPressGestureDetector::OnTouchPressed(const _Control& source, const _TouchInfo& touchinfo)
261 {
262         if (touchinfo.GetPointId() > __maxPointId || GetDetectorState() != _TOUCH_GESTURE_DETECTOR_STATE_READY )
263         {
264                 return false;
265         }
266
267         _LongPressInfo* pLongPressInfo = null;
268         __pLongPressInfoList->GetAt(touchinfo.GetPointId(), pLongPressInfo);
269         SysTryReturn(NID_UI, pLongPressInfo, false, E_SYSTEM, "[E_SYSTEM] System error occurred. ");
270
271         pLongPressInfo->__isPressed = true;
272         pLongPressInfo->__isInBounds = true;
273         pLongPressInfo->__touchCount++;
274         SysTryReturn(NID_UI, __pLongPressInfoList->SetAt(pLongPressInfo, touchinfo.GetPointId()) == E_SUCCESS,
275                                 false, E_SYSTEM, "[E_SYSTEM] System error occurred.");
276
277         bool allTouched = false;
278         for(int i=0; i<__touchCount; i++)
279         {
280                 _LongPressInfo* pLongPressInfo = null;
281                 __pLongPressInfoList->GetAt(i, pLongPressInfo);
282                 if (pLongPressInfo)
283                 {
284                         if (pLongPressInfo->__isPressed)
285                         {
286                                 allTouched = true;
287                         }
288                         else
289                         {
290                                 allTouched = false;
291                         }
292                 }
293         }
294
295         if (allTouched)
296         {
297                 SetGestureStart(true);
298
299                 __pGestureTimerManager = new (std::nothrow) _TouchGestureTimerManager(*this);
300                 SysTryReturn(NID_UI, __pGestureTimerManager, null, E_SYSTEM, "[E_SYSTEM] System error occurred.");
301
302                 if (__pGestureTimerManager->IsTimerStarted() == false)
303                 {
304                         _Control* pControl = GetControl();
305                         if (!pControl)
306                         {
307                                 SetControl(source);
308                         }
309
310                         if (__pGestureTimerManager->StartTimer(__duration) != E_SUCCESS)
311                         {
312                                 SysLogException(NID_UI, E_SYSTEM, "[E_SYSTEM] LongPress timer is not started.");
313                         }
314                 }
315         }
316
317         return false;
318 }
319
320 bool
321 _TouchLongPressGestureDetector::OnTouchMoved(const _Control& source, const _TouchInfo& touchinfo)
322 {
323         if (touchinfo.GetPointId() > __maxPointId || GetDetectorState() != _TOUCH_GESTURE_DETECTOR_STATE_READY )
324         {
325                 return false;
326         }
327
328         _LongPressInfo* pLongPressInfo = null;
329         __pLongPressInfoList->GetAt(touchinfo.GetPointId(), pLongPressInfo);
330         SysTryReturn(NID_UI, pLongPressInfo, false, E_SYSTEM, "[E_SYSTEM] System error occurred. ");
331
332         if (!pLongPressInfo->__isInBounds)
333         {
334                 return false;
335         }
336
337         _TouchManager* pTouchManager = _TouchManager::GetInstance();
338         SysTryReturn(NID_UI, pTouchManager, false, E_SYSTEM, "[E_SYSTEM] _TouchManager does not exist.");
339
340         Point startPoint(pTouchManager->GetStartPoint(touchinfo.GetPointId()).x, pTouchManager->GetStartPoint(touchinfo.GetPointId()).y);
341         _Control* pControl = GetControl();
342         if (pControl)
343         {
344                 startPoint.x -= pControl->GetAbsoluteBounds().x;
345                 startPoint.y -= pControl->GetAbsoluteBounds().y;
346         }
347
348         if (Math::Abs(startPoint.x- touchinfo.GetCurrentPosition().x) > __moveAllowance
349                 || Math::Abs(startPoint.y - touchinfo.GetCurrentPosition().y) > __moveAllowance)
350         {
351                 pLongPressInfo->__isInBounds = false;
352         }
353         else
354         {
355                 pLongPressInfo->__isInBounds = true;
356         }
357
358         SysTryReturn(NID_UI, __pLongPressInfoList->SetAt(pLongPressInfo, touchinfo.GetPointId()) == E_SUCCESS,
359                                 false, E_SYSTEM, "[E_SYSTEM] System error occurred.");
360
361         return false;
362 }
363
364 bool
365 _TouchLongPressGestureDetector::OnTouchReleased(const _Control& source, const _TouchInfo& touchinfo)
366 {
367         if (touchinfo.GetPointId() > __maxPointId || GetDetectorState() != _TOUCH_GESTURE_DETECTOR_STATE_READY )
368         {
369                 return false;
370         }
371
372         _LongPressInfo* pLongPressInfo = null;
373         __pLongPressInfoList->GetAt(touchinfo.GetPointId(), pLongPressInfo);
374         SysTryReturn(NID_UI, pLongPressInfo, false, E_SYSTEM, "[E_SYSTEM] System error occurred. ");
375
376         pLongPressInfo->__isPressed = false;
377         pLongPressInfo->__isInBounds = false;
378
379         SysTryReturn(NID_UI, __pLongPressInfoList->SetAt(pLongPressInfo, touchinfo.GetPointId()) == E_SUCCESS,
380                         false, E_SYSTEM, "[E_SYSTEM] System error occurred.");
381
382         //when touch is released not expired timer -> failed
383         if (IsGestureStarted() && __pGestureTimerManager != null && !__pGestureTimerManager->IsTimerExpired())
384         {
385                 __pGestureTimerManager->CancelTimer();
386
387                 delete __pGestureTimerManager;
388                 __pGestureTimerManager = null;
389
390                 SetDetectorState(_TOUCH_GESTURE_DETECTOR_STATE_FAILED);
391                 ClearLongPressInfoList();
392         }
393
394         return false;
395 }
396
397 bool
398 _TouchLongPressGestureDetector::OnTouchCanceled(const _Control& source, const _TouchInfo& touchinfo)
399 {
400         ClearLongPressInfoList();
401
402         if (__pGestureTimerManager != null && __pGestureTimerManager->IsTimerExpired() == false)
403         {
404                 __pGestureTimerManager->CancelTimer();
405                 __touchCanceled = true;
406
407                 if (__deleteTimer)
408                 {
409                         delete __pGestureTimerManager;
410                         __pGestureTimerManager = null;
411                 }
412                 else
413                 {
414                         __touchCanceled = true;
415                 }
416         }
417
418         return false;
419 }
420
421 void
422 _TouchLongPressGestureDetector::ClearLongPressInfoList(void)
423 {
424         for(int i=0; i < MAX_TOUCH_COUNT; i++)
425         {
426                 _LongPressInfo* pLongPressInfo = null;
427                 __pLongPressInfoList->GetAt(i, pLongPressInfo);
428                 if (!pLongPressInfo)
429                 {
430                         continue;
431                 }
432
433                 pLongPressInfo->__isPressed = false;
434                 pLongPressInfo->__touchCount = 0;
435                 pLongPressInfo->__isInBounds = false;
436
437                 __pLongPressInfoList->SetAt(pLongPressInfo, i);
438         }
439 }
440
441 } } // Tizen::Ui
442