77b83be6a593dc2104070a6446a9de62ccaab6a5
[platform/core/uifw/dali-core.git] / dali / internal / event / events / tap-gesture-processor.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 //     http://floralicense.org/license/
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 // CLASS HEADER
18 #include <dali/internal/event/events/tap-gesture-processor.h>
19
20 // EXTERNAL INCLUDES
21 #include <algorithm>
22
23 // INTERNAL INCLUDES
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>
34
35 namespace Dali
36 {
37
38 namespace Internal
39 {
40
41 namespace
42 {
43
44 /**
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.
50  */
51 void EmitTapSignal(
52     Dali::Actor actor,
53     TapGestureDetectorContainer& gestureDetectors,
54     const Integration::TapGestureEvent& tapEvent,
55     Vector2 localPoint)
56 {
57   TapGesture tap;
58   tap.time = tapEvent.time;
59   tap.numberOfTaps = tapEvent.numberOfTaps;
60   tap.numberOfTouches = tapEvent.numberOfTouches;
61   tap.screenPoint = tapEvent.point;
62   tap.localPoint = localPoint;
63
64   for ( TapGestureDetectorContainer::iterator iter = gestureDetectors.begin(), endIter = gestureDetectors.end(); iter != endIter; ++iter )
65   {
66     (*iter)->EmitTapGestureSignal( actor, tap );
67   }
68 }
69
70 } // unnamed namespace
71
72 struct TapGestureProcessor::TapEventFunctor : public GestureProcessor::Functor
73 {
74   /**
75    * Constructor
76    * @param[in]  tapEvent   The current gesture event.
77    */
78   TapEventFunctor( const Integration::TapGestureEvent& tapEvent )
79   : tapEvent(tapEvent)
80   {
81   }
82
83   /**
84    * Check if the detector meets the current gesture event parameters.
85    */
86    virtual bool operator() ( GestureDetector* detector, Actor* )
87   {
88     TapGestureDetector* tapDetector ( static_cast< TapGestureDetector* >( detector ) );
89
90     return tapDetector->GetTapsRequired() == tapEvent.numberOfTaps &&
91            tapDetector->GetTouchesRequired() == tapEvent.numberOfTouches;
92   }
93
94   /**
95    * Gestured actor and gesture detectors that meet the gesture's parameters found, emit and save required information.
96    */
97   virtual void operator() ( Dali::Actor actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates )
98   {
99     TapGestureDetectorContainer derivedContainer;
100     DownCastContainer<TapGestureDetector>( gestureDetectors, derivedContainer );
101     EmitTapSignal( actor, derivedContainer, tapEvent, actorCoordinates );
102   }
103
104   const Integration::TapGestureEvent& tapEvent;
105 };
106
107 TapGestureProcessor::TapGestureProcessor( Stage& stage, Integration::GestureManager& gestureManager)
108 : mStage( stage ),
109   mGestureManager( gestureManager ),
110   mGestureDetectors(),
111   mMinTapsRequired( 1 ),
112   mMaxTapsRequired( 1 ),
113   mMinTouchesRequired( 1 ),
114   mMaxTouchesRequired( 1 )
115 {
116 }
117
118 TapGestureProcessor::~TapGestureProcessor()
119 {
120 }
121
122 void TapGestureProcessor::Process( const Integration::TapGestureEvent& tapEvent )
123 {
124   switch ( tapEvent.state )
125   {
126     case Gesture::Possible:
127     {
128       ResetActor();
129
130       HitTestAlgorithm::Results hitTestResults;
131       if( HitTest( mStage, tapEvent.point, hitTestResults ) )
132       {
133         // Only sets the actor if we have a hit.
134         SetActor( hitTestResults.actor );
135       }
136       break;
137     }
138
139     case Gesture::Started:
140     {
141       if ( GetCurrentGesturedActor() )
142       {
143         HitTestAlgorithm::Results hitTestResults;
144         HitTestAlgorithm::HitTest( mStage, tapEvent.point, hitTestResults );
145
146         if ( hitTestResults.actor && ( GetCurrentGesturedActor() == &GetImplementation( hitTestResults.actor ) ) )
147         {
148           TapEventFunctor functor( tapEvent );
149           GestureDetectorContainer gestureDetectors;
150           UpCastContainer<TapGestureDetector>( mGestureDetectors, gestureDetectors );
151           ProcessAndEmit( hitTestResults, gestureDetectors, functor );
152         }
153
154         ResetActor();
155       }
156       break;
157     }
158
159     case Gesture::Cancelled:
160       ResetActor();
161       break;
162
163     case Gesture::Continuing:
164       DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Continuing\n" );
165       break;
166
167     case Gesture::Finished:
168       DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Finished\n" );
169       break;
170
171     case Gesture::Clear:
172       DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Clear\n" );
173       break;
174   }
175 }
176
177 void TapGestureProcessor::AddGestureDetector( TapGestureDetector* gestureDetector )
178 {
179   bool firstRegistration(mGestureDetectors.empty());
180
181   mGestureDetectors.push_back(gestureDetector);
182
183   unsigned int tapsRequired = gestureDetector->GetTapsRequired();
184   unsigned int touchesRequired = gestureDetector->GetTouchesRequired();
185
186   if (firstRegistration)
187   {
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.
190
191     mMinTapsRequired = mMaxTapsRequired = tapsRequired;
192     mMinTouchesRequired = mMaxTouchesRequired = touchesRequired;
193
194     Integration::TapGestureRequest request;
195     request.minTaps = mMinTapsRequired;
196     request.maxTaps = mMaxTapsRequired;
197     request.minTouches = mMinTouchesRequired;
198     request.maxTouches = mMaxTouchesRequired;
199     mGestureManager.Register(request);
200   }
201   else
202   {
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.
206
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;
211
212     if ( (minTaps != mMinTapsRequired)||(maxTaps != mMaxTapsRequired) ||
213          (minTouches != mMinTouchesRequired)||(maxTouches != mMaxTouchesRequired) )
214     {
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);
221     }
222   }
223 }
224
225 void TapGestureProcessor::RemoveGestureDetector( TapGestureDetector* gestureDetector )
226 {
227   // Find detector ...
228   TapGestureDetectorContainer::iterator endIter = std::remove( mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector );
229   DALI_ASSERT_DEBUG( endIter != mGestureDetectors.end() );
230
231   // ... and remove it
232   mGestureDetectors.erase( endIter, mGestureDetectors.end() );
233
234   if ( mGestureDetectors.empty() )
235   {
236     Integration::GestureRequest request(Gesture::Tap);
237     mGestureManager.Unregister(request);
238
239     ResetActor();
240   }
241   else
242   {
243     UpdateDetection();
244   }
245 }
246
247 void TapGestureProcessor::GestureDetectorUpdated( TapGestureDetector* gestureDetector )
248 {
249   DALI_ASSERT_DEBUG(find(mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector) != mGestureDetectors.end());
250
251   UpdateDetection();
252 }
253
254 void TapGestureProcessor::UpdateDetection()
255 {
256   DALI_ASSERT_DEBUG(!mGestureDetectors.empty());
257
258   unsigned int minTaps = UINT_MAX;
259   unsigned int maxTaps = 0;
260   unsigned int minTouches = UINT_MAX;
261   unsigned int maxTouches = 0;
262
263   for ( TapGestureDetectorContainer::iterator iter = mGestureDetectors.begin(), endIter = mGestureDetectors.end(); iter != endIter; ++iter )
264   {
265     TapGestureDetector* detector(*iter);
266
267     unsigned int tapsRequired = detector->GetTapsRequired();
268     unsigned int touchesRequired = detector->GetTouchesRequired();
269
270     minTaps = tapsRequired < minTaps ? tapsRequired : minTaps;
271     maxTaps = tapsRequired > maxTaps ? tapsRequired : maxTaps;
272     minTouches = touchesRequired < minTouches ? touchesRequired : minTouches;
273     maxTouches = touchesRequired > maxTouches ? touchesRequired : maxTouches;
274   }
275
276   if ( (minTaps != mMinTapsRequired)||(maxTaps != mMaxTapsRequired) ||
277        (minTouches != mMinTouchesRequired)||(maxTouches != mMaxTouchesRequired) )
278   {
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);
285   }
286 }
287
288 } // namespace Internal
289
290 } // namespace Dali