Dali 3D User Interface Engine
tap-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
19 #include "tap-gesture-detector.h"
20 
21 // EXTERNAL INCLUDES
22 #include <cmath>
23 
25 
29 
30 // INTERNAL INCLUDES
31 
32 namespace Dali
33 {
34 
35 namespace Internal
36 {
37 
38 namespace Adaptor
39 {
40 
41 namespace
42 {
43 // TODO: Set these according to DPI
44 const float MAXIMUM_MOTION_ALLOWED = 20.0f;
45 const unsigned long MAXIMUM_TIME_ALLOWED = 500u;
46 } // unnamed namespace
47 
48 TapGestureDetector::TapGestureDetector(CoreEventInterface& coreEventInterface, Vector2 screenSize, const Integration::TapGestureRequest& request)
49 : GestureDetector(screenSize, Gesture::Tap),
50  mCoreEventInterface(coreEventInterface),
51  mState(Clear),
52  mMinimumTapsRequired(request.minTaps),
53  mMaximumTapsRequired(request.maxTaps),
54  mTapsRegistered(0),
55  mTouchPosition(),
56  mTouchTime(0u),
57  mLastTapTime(0u)
58 {
59 }
60 
62 {
63 }
64 
65 void TapGestureDetector::SendEvent(const Integration::TouchEvent& event)
66 {
67  if (event.GetPointCount() == 1)
68  {
69  const TouchPoint& point = event.points[0];
70  TouchPoint::State pointState = point.state;
71 
72  switch (mState)
73  {
74  case Clear:
75  {
76  if (pointState == TouchPoint::Down)
77  {
78  SetupForTouchDown( event, point );
79  }
80  break;
81  }
82 
83  case Touched:
84  {
85  unsigned long deltaBetweenTouchDownTouchUp = abs( event.time - mTouchTime ) ;
86 
87  if ( pointState == TouchPoint::Up )
88  {
89  if ( deltaBetweenTouchDownTouchUp < MAXIMUM_TIME_ALLOWED )
90  {
92  EmitSingleTap( event.time, point );
94  }
95  else
96  {
97  mState = Clear;
98  }
99  }
100  else if (pointState == TouchPoint::Interrupted)
101  {
102  mState = Clear;
103  }
104  break;
105  }
106 
107  case Registered:
108  {
109  if ( pointState == TouchPoint::Up )
110  {
111  unsigned long deltaBetweenTouchDownTouchUp = abs( event.time - mTouchTime ) ;
112 
113  if ( deltaBetweenTouchDownTouchUp < MAXIMUM_TIME_ALLOWED )
114  {
115  // This is a possible multiple tap, so has it been quick enough ?
116  unsigned long timeDelta = abs( event.time - mLastTapTime );
117  if ( timeDelta > MAXIMUM_TIME_ALLOWED ) // If exceeded time between taps then just a single tap.
118  {
119  mLastTapTime = event.time;
120  EmitSingleTap( event.time, point );
121  mState = Registered;
122  }
123  else
124  {
125  ++mTapsRegistered;
126  EmitGesture( Gesture::Started, event.time );
127  mState = Clear;
128  }
129  }
130  else // Delta between touch down and touch up too long to be considered a Tap event
131  {
132  mState = Clear;
133  }
134  }
135  else if (pointState == TouchPoint::Down)
136  {
137  Vector2 distanceDelta(abs(mTouchPosition.x - point.screen.x),
138  abs(mTouchPosition.y - point.screen.y));
139 
140  unsigned long timeDelta = abs( event.time - mLastTapTime );
141 
142  if (distanceDelta.x > MAXIMUM_MOTION_ALLOWED ||
143  distanceDelta.y > MAXIMUM_MOTION_ALLOWED ||
144  timeDelta > MAXIMUM_TIME_ALLOWED )
145  {
146  SetupForTouchDown( event, point );
147  }
148  else
149  {
150  EmitPossibleState( event );
151  }
152  }
153  break;
154  }
155 
156  case Failed:
157  default:
158  {
159  mState = Clear;
160  break;
161  }
162  }
163  }
164  else
165  {
166  mState = Failed;
167 
168  // We have entered a multi-touch event so emit registered gestures if required.
169  EmitGesture(Gesture::Started, event.time);
170  }
171 }
172 
173 void TapGestureDetector::SetupForTouchDown( const Integration::TouchEvent& event, const TouchPoint& point )
174 {
175  mTouchPosition.x = point.screen.x;
176  mTouchPosition.y = point.screen.y;
177  mTouchTime = event.time;
178  mLastTapTime = 0u;
179  mTapsRegistered = 0;
180  mState = Touched;
181  EmitPossibleState( event );
182 }
183 
184 void TapGestureDetector::EmitPossibleState( const Integration::TouchEvent& event )
185 {
186  Integration::TapGestureEvent tapEvent( Gesture::Possible );
187  tapEvent.point = mTouchPosition;
188  tapEvent.time = event.time;
190 }
191 
192 
193 void TapGestureDetector::Update(const Integration::GestureRequest& request)
194 {
195  const Integration::TapGestureRequest& tap = static_cast<const Integration::TapGestureRequest&>(request);
196 
197  mMinimumTapsRequired = tap.minTaps;
198  mMaximumTapsRequired = tap.maxTaps;
199 }
200 
201 void TapGestureDetector::EmitGesture( Gesture::State state, unsigned int time )
202 {
203  if ( (state == Gesture::Cancelled) ||
205 
206  {
207  Integration::TapGestureEvent event( state );
208  EmitTap( time, event );
209  }
210 }
211 
212 void TapGestureDetector::EmitSingleTap( unsigned int time, const TouchPoint& point )
213 {
214  Integration::TapGestureEvent event( Gesture::Started );
215  Vector2 distanceDelta(abs(mTouchPosition.x - point.screen.x),
216  abs(mTouchPosition.y - point.screen.y));
217 
218  if (distanceDelta.x > MAXIMUM_MOTION_ALLOWED ||
219  distanceDelta.y > MAXIMUM_MOTION_ALLOWED )
220  {
221  event.state = Gesture::Cancelled;
222  }
223  mTapsRegistered = 1u;
224  EmitTap( time, event );
225 }
226 
227 void TapGestureDetector::EmitTap( unsigned int time, Integration::TapGestureEvent& event )
228 {
229  event.numberOfTaps = mTapsRegistered;
230  event.point = mTouchPosition;
231  event.time = time;
233 }
234 
235 } // namespace Adaptor
236 
237 } // namespace Internal
238 
239 } // namespace Dali
Dali Docs Home
Read more about Dali