Revert "License conversion from Flora to Apache 2.0"
[platform/core/uifw/dali-core.git] / dali / internal / event / events / long-press-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 "long-press-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/long-press-gesture.h>
27 #include <dali/integration-api/events/long-press-gesture-event.h>
28 #include <dali/integration-api/gesture-manager.h>
29 #include <dali/integration-api/debug.h>
30 #include <dali/internal/event/actors/actor-impl.h>
31 #include <dali/internal/event/common/stage-impl.h>
32 #include <dali/internal/event/render-tasks/render-task-impl.h>
33
34 namespace Dali
35 {
36
37 namespace Internal
38 {
39
40 namespace
41 {
42
43 /**
44  * Creates a LongPressGesture and asks the specified detector to emit its detected signal.
45  * @param[in]  actor             The actor on which the long press gesture has occurred.
46  * @param[in]  gestureDetectors  A reference to gesture detectors that should emit the signal.
47  * @param[in]  longPressEvent    The longPressEvent received from the adaptor.
48  * @param[in]  localPoint        Relative to the actor attached to the detector.
49  */
50 void EmitLongPressSignal(
51     Dali::Actor actor,
52     LongPressGestureDetectorContainer& gestureDetectors,
53     const Integration::LongPressGestureEvent& longPressEvent,
54     Vector2 localPoint)
55 {
56   LongPressGesture longPress(longPressEvent.state);
57   longPress.time = longPressEvent.time;
58   longPress.numberOfTouches = longPressEvent.numberOfTouches;
59   longPress.screenPoint = longPressEvent.point;
60   longPress.localPoint = localPoint;
61
62   for ( LongPressGestureDetectorContainer::iterator iter = gestureDetectors.begin(), endIter = gestureDetectors.end(); iter != endIter; ++iter )
63   {
64     (*iter)->EmitLongPressGestureSignal(actor, longPress);
65   }
66 }
67
68 /**
69  * Functor which checks whether the specified actor is attached to the gesture detector.
70  * It returns true if it is no longer attached.  This can be used in remove_if functions.
71  */
72 struct IsNotAttachedFunctor
73 {
74   /**
75    * Constructor
76    * @param[in]  actor  The actor to check whether it is attached.
77    */
78   IsNotAttachedFunctor( Actor* actor )
79   : actorToCheck( actor )
80   {
81   }
82
83   /**
84    * Returns true if not attached, false if it is still attached.
85    * @param[in]  detector  The detector to check.
86    * @return true, if not attached, false otherwise.
87    */
88   bool operator()( const LongPressGestureDetector* detector ) const
89   {
90     return !detector->IsAttached( *actorToCheck );
91   }
92
93   Actor* actorToCheck; ///< The actor to check whether it is attached or not.
94 };
95
96 } // unnamed namespace
97
98 struct LongPressGestureProcessor::LongPressEventFunctor : public GestureProcessor::Functor
99 {
100   /**
101    * Constructor
102    * @param[in]  event      The current gesture event.
103    * @param[in]  processor  Reference to the processor.
104    */
105   LongPressEventFunctor( const Integration::LongPressGestureEvent& event, LongPressGestureProcessor& processor )
106   : longPressEvent( event ),
107     processor( processor )
108   {
109   }
110
111   /**
112    * Check if the detector meets the current gesture event parameters.
113    */
114   virtual bool operator() ( GestureDetector* detector, Actor* )
115   {
116     LongPressGestureDetector* longPressDetector ( static_cast< LongPressGestureDetector* >( detector ) );
117
118     return ( longPressDetector->GetMinimumTouchesRequired() <= longPressEvent.numberOfTouches ) &&
119            ( longPressDetector->GetMaximumTouchesRequired() >= longPressEvent.numberOfTouches );
120   }
121
122   /**
123    * Gestured actor and gesture detectors that meet the gesture's parameters found, emit and save required information.
124    */
125   virtual void operator() ( Dali::Actor actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates )
126   {
127     LongPressGestureDetectorContainer derivedContainer;
128     DownCastContainer<LongPressGestureDetector>( gestureDetectors, derivedContainer );
129
130     // Clear actor as
131     processor.mCurrentEmitters.clear();
132     processor.ResetActor();
133
134     EmitLongPressSignal( actor, derivedContainer, longPressEvent, actorCoordinates );
135
136     if ( actor.OnStage() )
137     {
138       processor.mCurrentEmitters = derivedContainer;
139       processor.SetActor( actor );
140     }
141   }
142
143   const Integration::LongPressGestureEvent& longPressEvent;
144   LongPressGestureProcessor& processor;
145 };
146
147 LongPressGestureProcessor::LongPressGestureProcessor(
148     Stage& stage,
149     Integration::GestureManager& gestureManager)
150 : mStage( stage ),
151   mGestureManager( gestureManager ),
152   mGestureDetectors(),
153   mCurrentEmitters(),
154   mCurrentRenderTask(),
155   mMinTouchesRequired( 1 ),
156   mMaxTouchesRequired( 1 )
157 {
158 }
159
160 LongPressGestureProcessor::~LongPressGestureProcessor()
161 {
162 }
163
164 void LongPressGestureProcessor::Process( const Integration::LongPressGestureEvent& longPressEvent )
165 {
166   switch ( longPressEvent.state )
167   {
168     case Gesture::Possible:
169     {
170       mCurrentEmitters.clear();
171       ResetActor();
172
173       HitTestAlgorithm::Results hitTestResults;
174       if( HitTest( mStage, longPressEvent.point, hitTestResults ) )
175       {
176         SetActor( hitTestResults.actor );
177       }
178       break;
179     }
180
181     case Gesture::Started:
182     {
183       Actor* currentGesturedActor = GetCurrentGesturedActor();
184       if ( currentGesturedActor )
185       {
186         HitTestAlgorithm::Results hitTestResults;
187         HitTestAlgorithm::HitTest( mStage, longPressEvent.point, hitTestResults );
188
189         if ( hitTestResults.actor && ( currentGesturedActor == &GetImplementation( hitTestResults.actor ) ) )
190         {
191           // Record the current render-task for Screen->Actor coordinate conversions
192           mCurrentRenderTask = hitTestResults.renderTask;
193
194           LongPressEventFunctor functor( longPressEvent, *this );
195           GestureDetectorContainer gestureDetectors;
196           UpCastContainer<LongPressGestureDetector>( mGestureDetectors, gestureDetectors );
197           ProcessAndEmit( hitTestResults, gestureDetectors, functor );
198         }
199         else
200         {
201           mCurrentEmitters.clear();
202           ResetActor();
203         }
204       }
205       break;
206     }
207
208     case Gesture::Finished:
209     {
210       // The gesture should only be sent to the gesture detector which first received it so that it
211       // can be told when the gesture ends as well.
212
213       // Only send subsequent long press gesture signals if we processed the gesture when it started.
214       // Check if actor is still touchable.
215
216       Actor* currentGesturedActor = GetCurrentGesturedActor();
217       if ( currentGesturedActor )
218       {
219         if ( currentGesturedActor->IsHittable() && !mCurrentEmitters.empty() && mCurrentRenderTask )
220         {
221           // Ensure actor is still attached to the emitters, if it is not then remove the emitter.
222           LongPressGestureDetectorContainer::iterator endIter = std::remove_if( mCurrentEmitters.begin(), mCurrentEmitters.end(), IsNotAttachedFunctor(currentGesturedActor) );
223           mCurrentEmitters.erase( endIter, mCurrentEmitters.end() );
224
225           if ( !mCurrentEmitters.empty() )
226           {
227             Vector2 actorCoords;
228             RenderTask& renderTaskImpl( GetImplementation( mCurrentRenderTask ) );
229             currentGesturedActor->ScreenToLocal( renderTaskImpl, actorCoords.x, actorCoords.y, longPressEvent.point.x, longPressEvent.point.y );
230
231             EmitLongPressSignal( Dali::Actor( currentGesturedActor ), mCurrentEmitters, longPressEvent, actorCoords );
232           }
233         }
234
235         // Clear current emitters and emitted actor
236         mCurrentEmitters.clear();
237         ResetActor();
238       }
239       break;
240     }
241
242     case Gesture::Cancelled:
243     {
244       mCurrentEmitters.clear();
245       ResetActor();
246       break;
247     }
248
249     case Gesture::Continuing:
250       DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Continuing\n" );
251       break;
252
253     case Gesture::Clear:
254       DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Clear\n" );
255       break;
256   }
257 }
258
259 void LongPressGestureProcessor::AddGestureDetector( LongPressGestureDetector* gestureDetector )
260 {
261   bool firstRegistration(mGestureDetectors.empty());
262
263   mGestureDetectors.push_back(gestureDetector);
264
265   if (firstRegistration)
266   {
267     mMinTouchesRequired = gestureDetector->GetMinimumTouchesRequired();
268     mMaxTouchesRequired = gestureDetector->GetMaximumTouchesRequired();
269
270     Integration::LongPressGestureRequest request;
271     request.minTouches = mMinTouchesRequired;
272     request.maxTouches = mMaxTouchesRequired;
273     mGestureManager.Register( request );
274   }
275   else
276   {
277     UpdateDetection();
278   }
279 }
280
281 void LongPressGestureProcessor::RemoveGestureDetector( LongPressGestureDetector* gestureDetector )
282 {
283   // Find detector ...
284   LongPressGestureDetectorContainer::iterator endIter = std::remove( mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector );
285   DALI_ASSERT_DEBUG( endIter != mGestureDetectors.end() );
286
287   // ... and remove it
288   mGestureDetectors.erase( endIter, mGestureDetectors.end() );
289
290   if ( mGestureDetectors.empty() )
291   {
292     Integration::GestureRequest request( Gesture::LongPress );
293     mGestureManager.Unregister(request);
294   }
295   else
296   {
297     UpdateDetection();
298   }
299 }
300
301 void LongPressGestureProcessor::GestureDetectorUpdated( LongPressGestureDetector* gestureDetector )
302 {
303   DALI_ASSERT_DEBUG( find( mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector ) != mGestureDetectors.end() );
304
305   UpdateDetection();
306 }
307
308 void LongPressGestureProcessor::UpdateDetection()
309 {
310   DALI_ASSERT_DEBUG(!mGestureDetectors.empty());
311
312   unsigned int minimumRequired = UINT_MAX;
313   unsigned int maximumRequired = 0;
314
315   for ( LongPressGestureDetectorContainer::iterator iter = mGestureDetectors.begin(), endIter = mGestureDetectors.end(); iter != endIter; ++iter )
316   {
317     LongPressGestureDetector* current(*iter);
318
319     unsigned int minimum = current->GetMinimumTouchesRequired();
320     if (minimum < minimumRequired)
321     {
322       minimumRequired = minimum;
323     }
324
325     unsigned int maximum = current->GetMaximumTouchesRequired();
326     if ( maximum > maximumRequired )
327     {
328       maximumRequired = maximum;
329     }
330   }
331
332   if ( (minimumRequired != mMinTouchesRequired) || (maximumRequired != mMaxTouchesRequired) )
333   {
334     mMinTouchesRequired = minimumRequired;
335     mMaxTouchesRequired = maximumRequired;
336
337     Integration::LongPressGestureRequest request;
338     request.minTouches = mMinTouchesRequired;
339     request.maxTouches = mMaxTouchesRequired;
340     mGestureManager.Update(request);
341   }
342 }
343
344 void LongPressGestureProcessor::OnGesturedActorStageDisconnection()
345 {
346   mCurrentEmitters.clear();
347 }
348
349 } // namespace Internal
350
351 } // namespace Dali