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