2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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
8 // http://floralicense.org/license/
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.
18 #include <dali/internal/event/events/tap-gesture-processor.h>
24 #include <dali/public-api/actors/actor.h>
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/events/tap-gesture.h>
27 #include <dali/public-api/math/vector2.h>
28 #include <dali/integration-api/events/tap-gesture-event.h>
29 #include <dali/integration-api/gesture-manager.h>
30 #include <dali/integration-api/debug.h>
31 #include <dali/internal/event/actors/actor-impl.h>
32 #include <dali/internal/event/render-tasks/render-task-impl.h>
33 #include <dali/internal/event/common/stage-impl.h>
45 * Creates a TapGesture and asks the specified detector to emit its detected signal.
46 * @param[in] actor The actor on which a tap has occurred.
47 * @param[in] gestureDetectors A reference to gesture detectors that should emit the signal.
48 * @param[in] tapEvent The tapEvent received from the adaptor.
49 * @param[in] localPoint Relative to the actor attached to the detector.
53 TapGestureDetectorContainer& gestureDetectors,
54 const Integration::TapGestureEvent& tapEvent,
58 tap.time = tapEvent.time;
59 tap.numberOfTaps = tapEvent.numberOfTaps;
60 tap.numberOfTouches = tapEvent.numberOfTouches;
61 tap.screenPoint = tapEvent.point;
62 tap.localPoint = localPoint;
64 for ( TapGestureDetectorContainer::iterator iter = gestureDetectors.begin(), endIter = gestureDetectors.end(); iter != endIter; ++iter )
66 (*iter)->EmitTapGestureSignal( actor, tap );
70 } // unnamed namespace
72 struct TapGestureProcessor::TapEventFunctor : public GestureProcessor::Functor
76 * @param[in] tapEvent The current gesture event.
78 TapEventFunctor( const Integration::TapGestureEvent& tapEvent )
84 * Check if the detector meets the current gesture event parameters.
86 virtual bool operator() ( GestureDetector* detector, Actor* )
88 TapGestureDetector* tapDetector ( static_cast< TapGestureDetector* >( detector ) );
90 return tapDetector->GetTapsRequired() == tapEvent.numberOfTaps &&
91 tapDetector->GetTouchesRequired() == tapEvent.numberOfTouches;
95 * Gestured actor and gesture detectors that meet the gesture's parameters found, emit and save required information.
97 virtual void operator() ( Dali::Actor actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates )
99 TapGestureDetectorContainer derivedContainer;
100 DownCastContainer<TapGestureDetector>( gestureDetectors, derivedContainer );
101 EmitTapSignal( actor, derivedContainer, tapEvent, actorCoordinates );
104 const Integration::TapGestureEvent& tapEvent;
107 TapGestureProcessor::TapGestureProcessor( Stage& stage, Integration::GestureManager& gestureManager)
109 mGestureManager( gestureManager ),
111 mMinTapsRequired( 1 ),
112 mMaxTapsRequired( 1 ),
113 mMinTouchesRequired( 1 ),
114 mMaxTouchesRequired( 1 )
118 TapGestureProcessor::~TapGestureProcessor()
122 void TapGestureProcessor::Process( const Integration::TapGestureEvent& tapEvent )
124 switch ( tapEvent.state )
126 case Gesture::Possible:
130 HitTestAlgorithm::Results hitTestResults;
131 if( HitTest( mStage, tapEvent.point, hitTestResults ) )
133 // Only sets the actor if we have a hit.
134 SetActor( hitTestResults.actor );
139 case Gesture::Started:
141 if ( GetCurrentGesturedActor() )
143 HitTestAlgorithm::Results hitTestResults;
144 HitTestAlgorithm::HitTest( mStage, tapEvent.point, hitTestResults );
146 if ( hitTestResults.actor && ( GetCurrentGesturedActor() == &GetImplementation( hitTestResults.actor ) ) )
148 TapEventFunctor functor( tapEvent );
149 GestureDetectorContainer gestureDetectors;
150 UpCastContainer<TapGestureDetector>( mGestureDetectors, gestureDetectors );
151 ProcessAndEmit( hitTestResults, gestureDetectors, functor );
159 case Gesture::Cancelled:
163 case Gesture::Continuing:
164 DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Continuing\n" );
167 case Gesture::Finished:
168 DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Finished\n" );
172 DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Clear\n" );
177 void TapGestureProcessor::AddGestureDetector( TapGestureDetector* gestureDetector )
179 bool firstRegistration(mGestureDetectors.empty());
181 mGestureDetectors.push_back(gestureDetector);
183 unsigned int tapsRequired = gestureDetector->GetTapsRequired();
184 unsigned int touchesRequired = gestureDetector->GetTouchesRequired();
186 if (firstRegistration)
188 // If this is the first tap gesture detector that has been added, then our minimum and maximum
189 // requirements are the same as each other.
191 mMinTapsRequired = mMaxTapsRequired = tapsRequired;
192 mMinTouchesRequired = mMaxTouchesRequired = touchesRequired;
194 Integration::TapGestureRequest request;
195 request.minTaps = mMinTapsRequired;
196 request.maxTaps = mMaxTapsRequired;
197 request.minTouches = mMinTouchesRequired;
198 request.maxTouches = mMaxTouchesRequired;
199 mGestureManager.Register(request);
203 // If we have already registered for tap gesture detection before then we need to check our
204 // minimum and maximums and see if our gesture detection requirements have changed, if they
205 // have, then we should ask the adaptor to update its detection policy.
207 unsigned int minTaps = mMinTapsRequired < tapsRequired ? mMinTapsRequired : tapsRequired;
208 unsigned int maxTaps = mMaxTapsRequired > tapsRequired ? mMaxTapsRequired : tapsRequired;
209 unsigned int minTouches = mMinTouchesRequired < touchesRequired ? mMinTouchesRequired : touchesRequired;
210 unsigned int maxTouches = mMaxTouchesRequired > touchesRequired ? mMaxTouchesRequired : touchesRequired;
212 if ( (minTaps != mMinTapsRequired)||(maxTaps != mMaxTapsRequired) ||
213 (minTouches != mMinTouchesRequired)||(maxTouches != mMaxTouchesRequired) )
215 Integration::TapGestureRequest request;
216 request.minTaps = mMinTapsRequired = minTaps;
217 request.maxTaps = mMaxTapsRequired = maxTaps;
218 request.minTouches = mMinTouchesRequired = minTouches;
219 request.maxTouches = mMaxTouchesRequired = maxTouches;
220 mGestureManager.Update(request);
225 void TapGestureProcessor::RemoveGestureDetector( TapGestureDetector* gestureDetector )
228 TapGestureDetectorContainer::iterator endIter = std::remove( mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector );
229 DALI_ASSERT_DEBUG( endIter != mGestureDetectors.end() );
232 mGestureDetectors.erase( endIter, mGestureDetectors.end() );
234 if ( mGestureDetectors.empty() )
236 Integration::GestureRequest request(Gesture::Tap);
237 mGestureManager.Unregister(request);
247 void TapGestureProcessor::GestureDetectorUpdated( TapGestureDetector* gestureDetector )
249 DALI_ASSERT_DEBUG(find(mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector) != mGestureDetectors.end());
254 void TapGestureProcessor::UpdateDetection()
256 DALI_ASSERT_DEBUG(!mGestureDetectors.empty());
258 unsigned int minTaps = UINT_MAX;
259 unsigned int maxTaps = 0;
260 unsigned int minTouches = UINT_MAX;
261 unsigned int maxTouches = 0;
263 for ( TapGestureDetectorContainer::iterator iter = mGestureDetectors.begin(), endIter = mGestureDetectors.end(); iter != endIter; ++iter )
265 TapGestureDetector* detector(*iter);
267 unsigned int tapsRequired = detector->GetTapsRequired();
268 unsigned int touchesRequired = detector->GetTouchesRequired();
270 minTaps = tapsRequired < minTaps ? tapsRequired : minTaps;
271 maxTaps = tapsRequired > maxTaps ? tapsRequired : maxTaps;
272 minTouches = touchesRequired < minTouches ? touchesRequired : minTouches;
273 maxTouches = touchesRequired > maxTouches ? touchesRequired : maxTouches;
276 if ( (minTaps != mMinTapsRequired)||(maxTaps != mMaxTapsRequired) ||
277 (minTouches != mMinTouchesRequired)||(maxTouches != mMaxTouchesRequired) )
279 Integration::TapGestureRequest request;
280 request.minTaps = mMinTapsRequired = minTaps;
281 request.maxTaps = mMaxTapsRequired = maxTaps;
282 request.minTouches = mMinTouchesRequired = minTouches;
283 request.maxTouches = mMaxTouchesRequired = maxTouches;
284 mGestureManager.Update(request);
288 } // namespace Internal