Dali 3D User Interface Engine
long-press-gesture-detector.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 // CLASS HEADER
20 
21 // EXTERNAL INCLUDES
22 #include <cmath>
23 
26 
30 
31 #include <system-settings.h>
32 
33 // INTERNAL INCLUDES
35 
36 namespace Dali
37 {
38 
39 namespace Internal
40 {
41 
42 namespace Adaptor
43 {
44 
45 namespace
46 {
47 // TODO: Set these according to DPI
48 const float MAXIMUM_MOTION_ALLOWED = 60.0f;
49 // TODO: Set this time according to system setting (vconf)
50 const unsigned long LONG_PRESS_TIME = 500u;
51 } // unnamed namespace
52 
53 LongPressGestureDetector::LongPressGestureDetector(CoreEventInterface& coreEventInterface, Vector2 screenSize, const Integration::LongPressGestureRequest& request)
54 : GestureDetector(screenSize, Gesture::LongPress),
55  mCoreEventInterface(coreEventInterface),
56  mState(Clear),
57  mMinimumTouchesRequired(request.minTouches),
58  mMaximumTouchesRequired(request.maxTouches),
59  mTouchTime(0),
60  mTimerSlot( this )
61 {
64 }
65 
67 {
68 }
69 
70 void LongPressGestureDetector::SendEvent(const Integration::TouchEvent& event)
71 {
72  unsigned int pointCount( event.GetPointCount() );
73 
74  switch (mState)
75  {
76  // Clear: Wait till one point touches the screen before starting timer.
77  case Clear:
78  {
79  const TouchPoint& point = event.points[0];
80 
81  if ( point.state == TouchPoint::Down )
82  {
83  mTouchPositions.clear();
84  mTouchPositions[point.deviceId] = point.screen;
85 
86  mTouchTime = event.time;
87 
89  mTimer.Start();
90 
91  // A long press gesture may be possible, tell Core about this and change state to Touched.
92  mState = Touched;
94  }
95 
96  break;
97  }
98 
99  // Touched: Monitor movement and addition/removal of points.
100  case Touched:
101  {
102  if (pointCount > mMaximumTouchesRequired)
103  {
104  // A long press did not occur, tell Core that it was cancelled and change state to Failed.
106  mTouchPositions.clear();
107  mTimer.Stop();
108  mState = Failed;
109  break;
110  }
111 
112  bool endLoop(false);
113 
114  for (std::vector<TouchPoint>::const_iterator iter = event.points.begin(), endIter = event.points.end();
115  iter != endIter && !endLoop; ++iter)
116  {
117  switch( iter->state )
118  {
119  // add point.
120  case TouchPoint::Down:
121  {
122  mTouchPositions[iter->deviceId] = iter->screen;
123  break;
124  }
125 
126  // remove point.
127  case TouchPoint::Up:
129  {
130  // System has interrupted us, long press is not possible, inform Core
132  mTouchPositions.clear();
133  mTimer.Stop();
134  mState = ( pointCount == 1 ) ? Clear : Failed; // Change state to Clear if only one point, Failed otherwise.
135  endLoop = true;
136  break;
137  }
138 
139  case TouchPoint::Motion:
140  {
141  const Vector2 touchPosition( mTouchPositions[iter->deviceId] - iter->screen );
142  float distanceSquared = touchPosition.LengthSquared();
143 
144  if (distanceSquared > ( MAXIMUM_MOTION_ALLOWED * MAXIMUM_MOTION_ALLOWED ) )
145  {
146  // We have moved more than the allowable motion for a long press gesture. Inform Core and change state to Failed.
148  mTimer.Stop();
149  mState = Failed;
150  endLoop = true;
151  }
152  break;
153  }
154 
156  case TouchPoint::Leave:
157  case TouchPoint::Last:
158  {
159  break;
160  }
161  }
162  }
163  break;
164  }
165 
166  // Failed/Finished: Monitor the touches, waiting for all touches to be released.
167  case Failed:
168  case Finished:
169  {
170  // eventually the final touch point will be removed, marking the end of this gesture.
171  if ( pointCount == 1 )
172  {
173  TouchPoint::State primaryPointState = event.points[0].state;
174 
175  if ( (primaryPointState == TouchPoint::Up) || (primaryPointState == TouchPoint::Interrupted) )
176  {
177  if(mState == Finished)
178  {
179  // When the last touch point is lifted, we should inform the Core that the Long press has finished.
181  }
182  mTouchPositions.clear();
183  mState = Clear; // Reset state to clear when last touch point is lifted.
184  }
185  }
186  break;
187  }
188  }
189 }
190 
191 void LongPressGestureDetector::Update(const Integration::GestureRequest& request)
192 {
193  const Integration::LongPressGestureRequest& longPress = static_cast<const Integration::LongPressGestureRequest&>(request);
194 
195  mMinimumTouchesRequired = longPress.minTouches;
196  mMaximumTouchesRequired = longPress.maxTouches;
197 }
198 
200 {
202 
203  mState = Finished;
204 
205  // There is no touch event at this time, so ProcessEvents must be called directly
207 
208  return false;
209 }
210 
212 {
213  unsigned int touchPoints ( mTouchPositions.size() );
214 
215  // We should tell Core about the Possible and Cancelled states regardless of whether we have satisfied long press requirements.
216  if ( (state == Gesture::Possible) ||
217  (state == Gesture::Cancelled) ||
218  (touchPoints >= mMinimumTouchesRequired) )
219  {
220  Integration::LongPressGestureEvent longPress( state );
221  longPress.numberOfTouches = touchPoints;
222 
223  for (std::map<int, Vector2>::iterator iter = mTouchPositions.begin(), endIter = mTouchPositions.end();
224  iter != endIter; ++iter)
225  {
226  longPress.point += iter->second;
227  }
228  longPress.point /= touchPoints;
229 
230  longPress.time = mTouchTime;
231  if ( state != Gesture::Possible )
232  {
233  longPress.time += GetSystemValue();
234  }
235 
237  }
238 }
239 
241 {
243 }
244 
245 } // namespace Adaptor
246 
247 } // namespace Internal
248 
249 } // namespace Dali
Dali Docs Home
Read more about Dali