2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/events/tap-gesture-processor.h>
25 #include <dali/public-api/actors/actor.h>
26 #include <dali/public-api/common/dali-common.h>
27 #include <dali/public-api/events/tap-gesture.h>
28 #include <dali/public-api/math/vector2.h>
29 #include <dali/integration-api/events/tap-gesture-event.h>
30 #include <dali/integration-api/gesture-manager.h>
31 #include <dali/integration-api/debug.h>
32 #include <dali/internal/event/actors/actor-impl.h>
33 #include <dali/internal/event/render-tasks/render-task-impl.h>
34 #include <dali/internal/event/common/stage-impl.h>
46 * Creates a TapGesture and asks the specified detector to emit its detected signal.
47 * @param[in] actor The actor on which a tap has occurred.
48 * @param[in] gestureDetectors A reference to gesture detectors that should emit the signal.
49 * @param[in] tapEvent The tapEvent received from the adaptor.
50 * @param[in] localPoint Relative to the actor attached to the detector.
54 TapGestureDetectorContainer& gestureDetectors,
55 const Integration::TapGestureEvent& tapEvent,
59 tap.time = tapEvent.time;
60 tap.numberOfTaps = tapEvent.numberOfTaps;
61 tap.numberOfTouches = tapEvent.numberOfTouches;
62 tap.screenPoint = tapEvent.point;
63 tap.localPoint = localPoint;
65 for ( TapGestureDetectorContainer::iterator iter = gestureDetectors.begin(), endIter = gestureDetectors.end(); iter != endIter; ++iter )
67 (*iter)->EmitTapGestureSignal( actor, tap );
71 } // unnamed namespace
73 struct TapGestureProcessor::TapEventFunctor : public GestureProcessor::Functor
77 * @param[in] tapEvent The current gesture event.
79 TapEventFunctor( const Integration::TapGestureEvent& tapEvent )
85 * Check if the detector meets the current gesture event parameters.
87 virtual bool operator() ( GestureDetector* detector, Actor* )
89 TapGestureDetector* tapDetector ( static_cast< TapGestureDetector* >( detector ) );
91 return tapDetector->GetTapsRequired() == tapEvent.numberOfTaps &&
92 tapDetector->GetTouchesRequired() == tapEvent.numberOfTouches;
96 * Gestured actor and gesture detectors that meet the gesture's parameters found, emit and save required information.
98 virtual void operator() ( Dali::Actor actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates )
100 TapGestureDetectorContainer derivedContainer;
101 DownCastContainer<TapGestureDetector>( gestureDetectors, derivedContainer );
102 EmitTapSignal( actor, derivedContainer, tapEvent, actorCoordinates );
105 const Integration::TapGestureEvent& tapEvent;
108 TapGestureProcessor::TapGestureProcessor( Stage& stage, Integration::GestureManager& gestureManager)
110 mGestureManager( gestureManager ),
112 mMinTapsRequired( 1 ),
113 mMaxTapsRequired( 1 ),
114 mMinTouchesRequired( 1 ),
115 mMaxTouchesRequired( 1 )
119 TapGestureProcessor::~TapGestureProcessor()
123 void TapGestureProcessor::Process( const Integration::TapGestureEvent& tapEvent )
125 switch ( tapEvent.state )
127 case Gesture::Possible:
131 HitTestAlgorithm::Results hitTestResults;
132 if( HitTest( mStage, tapEvent.point, hitTestResults ) )
134 // Only sets the actor if we have a hit.
135 SetActor( hitTestResults.actor );
140 case Gesture::Started:
142 if ( GetCurrentGesturedActor() )
144 HitTestAlgorithm::Results hitTestResults;
145 HitTestAlgorithm::HitTest( mStage, tapEvent.point, hitTestResults );
147 if ( hitTestResults.actor && ( GetCurrentGesturedActor() == &GetImplementation( hitTestResults.actor ) ) )
149 TapEventFunctor functor( tapEvent );
150 GestureDetectorContainer gestureDetectors;
151 UpCastContainer<TapGestureDetector>( mGestureDetectors, gestureDetectors );
152 ProcessAndEmit( hitTestResults, gestureDetectors, functor );
160 case Gesture::Cancelled:
164 case Gesture::Continuing:
165 DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Continuing\n" );
168 case Gesture::Finished:
169 DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Finished\n" );
173 DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Clear\n" );
178 void TapGestureProcessor::AddGestureDetector( TapGestureDetector* gestureDetector )
180 bool firstRegistration(mGestureDetectors.empty());
182 mGestureDetectors.push_back(gestureDetector);
184 unsigned int tapsRequired = gestureDetector->GetTapsRequired();
185 unsigned int touchesRequired = gestureDetector->GetTouchesRequired();
187 if (firstRegistration)
189 // If this is the first tap gesture detector that has been added, then our minimum and maximum
190 // requirements are the same as each other.
192 mMinTapsRequired = mMaxTapsRequired = tapsRequired;
193 mMinTouchesRequired = mMaxTouchesRequired = touchesRequired;
195 Integration::TapGestureRequest request;
196 request.minTaps = mMinTapsRequired;
197 request.maxTaps = mMaxTapsRequired;
198 request.minTouches = mMinTouchesRequired;
199 request.maxTouches = mMaxTouchesRequired;
200 mGestureManager.Register(request);
204 // If we have already registered for tap gesture detection before then we need to check our
205 // minimum and maximums and see if our gesture detection requirements have changed, if they
206 // have, then we should ask the adaptor to update its detection policy.
208 unsigned int minTaps = mMinTapsRequired < tapsRequired ? mMinTapsRequired : tapsRequired;
209 unsigned int maxTaps = mMaxTapsRequired > tapsRequired ? mMaxTapsRequired : tapsRequired;
210 unsigned int minTouches = mMinTouchesRequired < touchesRequired ? mMinTouchesRequired : touchesRequired;
211 unsigned int maxTouches = mMaxTouchesRequired > touchesRequired ? mMaxTouchesRequired : touchesRequired;
213 if ( (minTaps != mMinTapsRequired)||(maxTaps != mMaxTapsRequired) ||
214 (minTouches != mMinTouchesRequired)||(maxTouches != mMaxTouchesRequired) )
216 Integration::TapGestureRequest request;
217 request.minTaps = mMinTapsRequired = minTaps;
218 request.maxTaps = mMaxTapsRequired = maxTaps;
219 request.minTouches = mMinTouchesRequired = minTouches;
220 request.maxTouches = mMaxTouchesRequired = maxTouches;
221 mGestureManager.Update(request);
226 void TapGestureProcessor::RemoveGestureDetector( TapGestureDetector* gestureDetector )
229 TapGestureDetectorContainer::iterator endIter = std::remove( mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector );
230 DALI_ASSERT_DEBUG( endIter != mGestureDetectors.end() );
233 mGestureDetectors.erase( endIter, mGestureDetectors.end() );
235 if ( mGestureDetectors.empty() )
237 Integration::GestureRequest request(Gesture::Tap);
238 mGestureManager.Unregister(request);
248 void TapGestureProcessor::GestureDetectorUpdated( TapGestureDetector* gestureDetector )
250 DALI_ASSERT_DEBUG(find(mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector) != mGestureDetectors.end());
255 void TapGestureProcessor::UpdateDetection()
257 DALI_ASSERT_DEBUG(!mGestureDetectors.empty());
259 unsigned int minTaps = UINT_MAX;
260 unsigned int maxTaps = 0;
261 unsigned int minTouches = UINT_MAX;
262 unsigned int maxTouches = 0;
264 for ( TapGestureDetectorContainer::iterator iter = mGestureDetectors.begin(), endIter = mGestureDetectors.end(); iter != endIter; ++iter )
266 TapGestureDetector* detector(*iter);
268 unsigned int tapsRequired = detector->GetTapsRequired();
269 unsigned int touchesRequired = detector->GetTouchesRequired();
271 minTaps = tapsRequired < minTaps ? tapsRequired : minTaps;
272 maxTaps = tapsRequired > maxTaps ? tapsRequired : maxTaps;
273 minTouches = touchesRequired < minTouches ? touchesRequired : minTouches;
274 maxTouches = touchesRequired > maxTouches ? touchesRequired : maxTouches;
277 if ( (minTaps != mMinTapsRequired)||(maxTaps != mMaxTapsRequired) ||
278 (minTouches != mMinTouchesRequired)||(maxTouches != mMaxTouchesRequired) )
280 Integration::TapGestureRequest request;
281 request.minTaps = mMinTapsRequired = minTaps;
282 request.maxTaps = mMaxTapsRequired = maxTaps;
283 request.minTouches = mMinTouchesRequired = minTouches;
284 request.maxTouches = mMaxTouchesRequired = maxTouches;
285 mGestureManager.Update(request);
289 } // namespace Internal