Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-core.git] / dali / internal / event / events / gesture-detector-impl.cpp
1 /*
2  * Copyright (c) 2020 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/gesture-detector-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23
24 // INTERNAL INCLUDES
25 #include <dali/integration-api/debug.h>
26 #include <dali/internal/event/events/actor-gesture-data.h>
27 #include <dali/internal/event/events/gesture-event-processor.h>
28 #include <dali/internal/event/common/thread-local-storage.h>
29 #include <dali/internal/event/common/stage-impl.h>
30
31 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 GestureDetector::GestureDetector( DevelGesture::Type type, const SceneGraph::PropertyOwner* sceneObject )
38 : Object( sceneObject ),
39   mType( type ),
40   mGestureEventProcessor( ThreadLocalStorage::Get().GetGestureEventProcessor() )
41 {
42 }
43
44 GestureDetector::GestureDetector( Gesture::Type type, const SceneGraph::PropertyOwner* sceneObject )
45 : GestureDetector( static_cast< DevelGesture::Type >( type ), sceneObject )
46 {
47 }
48
49 GestureDetector::~GestureDetector()
50 {
51   if ( !mPendingAttachActors.empty() )
52   {
53     for ( GestureDetectorActorContainer::iterator iter = mPendingAttachActors.begin(), endIter = mPendingAttachActors.end(); iter != endIter; ++iter )
54     {
55       Actor* actor( *iter );
56       actor->RemoveObserver( *this );
57       actor->GetGestureData().RemoveGestureDetector( *this );
58     }
59
60     mPendingAttachActors.clear();
61   }
62
63   if ( !mAttachedActors.empty() )
64   {
65     for ( GestureDetectorActorContainer::iterator iter = mAttachedActors.begin(), endIter = mAttachedActors.end(); iter != endIter; ++iter )
66     {
67       Actor* actor( *iter );
68       actor->RemoveObserver( *this );
69       actor->GetGestureData().RemoveGestureDetector( *this );
70     }
71
72     mAttachedActors.clear();
73
74     // Guard to allow handle destruction after Core has been destroyed
75     if ( Stage::IsInstalled() )
76     {
77       mGestureEventProcessor.RemoveGestureDetector( this );
78     }
79   }
80 }
81
82 void GestureDetector::Attach( Actor& actor )
83 {
84   if ( !IsAttached( actor ) )
85   {
86     if( actor.OnScene() )
87     {
88       // Register with EventProcessor if first actor being added
89       if( mAttachedActors.empty() )
90       {
91         mGestureEventProcessor.AddGestureDetector( this, actor.GetScene() );
92       }
93       mAttachedActors.push_back( &actor );
94       // We need to observe the actor's destruction
95       actor.AddObserver( *this );
96       // Add the detector to the actor (so the actor knows it requires this gesture when going through hit-test algorithm)
97       actor.GetGestureData().AddGestureDetector( *this );
98       // Notification for derived classes
99       OnActorAttach( actor );
100     }
101     else
102     {
103       actor.AddObserver( *this );
104       // Add the detector to the actor (so the actor knows it requires this gesture when going through hit-test algorithm)
105       actor.GetGestureData().AddGestureDetector( *this );
106
107       mPendingAttachActors.push_back( &actor );
108     }
109   }
110 }
111
112 void GestureDetector::SceneObjectAdded( Object& object )
113 {
114   Actor& actor = dynamic_cast< Actor& >( object );
115
116   // Make sure the actor has not already been attached. Can't use IsAttached() as that checks the pending list as well
117   if( find(mAttachedActors.begin(), mAttachedActors.end(), &actor) == mAttachedActors.end() )
118   {
119     GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
120
121     if ( match != mPendingAttachActors.end() )
122     {
123       mPendingAttachActors.erase(match);
124
125       // Register with EventProcessor if first actor being added
126       if( mAttachedActors.empty() )
127       {
128         mGestureEventProcessor.AddGestureDetector( this, actor.GetScene() );
129       }
130       mAttachedActors.push_back( &actor );
131
132       // Notification for derived classes
133       OnActorAttach( actor );
134     }
135     else
136     {
137       // Actor was not in the pending list
138       DALI_ASSERT_DEBUG( false );
139     }
140   }
141   else
142   {
143     // Check if actor has been attached and is still in the pending list - this would not be correct
144     DALI_ASSERT_DEBUG( find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) == mPendingAttachActors.end() );
145   }
146 }
147
148 void GestureDetector::Detach(Actor& actor)
149 {
150   if ( !mPendingAttachActors.empty() )
151   {
152     GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
153
154     if ( match != mPendingAttachActors.end() )
155     {
156       // We no longer need to observe the actor's destruction
157       actor.RemoveObserver(*this);
158
159       // Remove detector from actor-gesture-data
160       actor.GetGestureData().RemoveGestureDetector( *this );
161
162       mPendingAttachActors.erase(match);
163     }
164   }
165
166   if ( !mAttachedActors.empty() )
167   {
168     GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &actor);
169
170     if ( match != mAttachedActors.end() )
171     {
172       // We no longer need to observe the actor's destruction
173       actor.RemoveObserver(*this);
174
175       // Remove detector from actor-gesture-data
176       actor.GetGestureData().RemoveGestureDetector( *this );
177
178       mAttachedActors.erase(match);
179
180       // Notification for derived classes
181       OnActorDetach(actor);
182
183       // Unregister from gesture event processor if we do not have any actors
184       if ( mAttachedActors.empty() )
185       {
186         // Guard to allow handle destruction after Core has been destroyed
187         if( Stage::IsInstalled() )
188         {
189           mGestureEventProcessor.RemoveGestureDetector(this);
190         }
191       }
192     }
193   }
194 }
195
196 void GestureDetector::DetachAll()
197 {
198   if ( !mPendingAttachActors.empty() )
199   {
200     GestureDetectorActorContainer pendingActors(mPendingAttachActors);
201
202     mPendingAttachActors.clear();
203
204     for ( GestureDetectorActorContainer::iterator iter = pendingActors.begin(), endIter = pendingActors.end(); iter != endIter; ++iter )
205     {
206       Actor* actor(*iter);
207
208       // We no longer need to observe the actor's destruction
209       actor->RemoveObserver(*this);
210
211       // Remove detector from actor-gesture-data
212       actor->GetGestureData().RemoveGestureDetector( *this );
213     }
214   }
215
216   if ( !mAttachedActors.empty() )
217   {
218     GestureDetectorActorContainer attachedActors(mAttachedActors);
219
220     // Clear mAttachedActors before we call OnActorDetach in case derived classes call a method which manipulates mAttachedActors.
221     mAttachedActors.clear();
222
223     for ( GestureDetectorActorContainer::iterator iter = attachedActors.begin(), endIter = attachedActors.end(); iter != endIter; ++iter )
224     {
225       Actor* actor(*iter);
226
227       // We no longer need to observe the actor's destruction
228       actor->RemoveObserver(*this);
229
230       // Remove detector from actor-gesture-data
231       actor->GetGestureData().RemoveGestureDetector( *this );
232
233       // Notification for derived classes
234       OnActorDetach(*actor);
235     }
236
237     // Guard to allow handle destruction after Core has been destroyed
238     if ( Stage::IsInstalled() )
239     {
240       // Unregister from gesture event processor
241       mGestureEventProcessor.RemoveGestureDetector(this);
242     }
243   }
244 }
245
246 size_t GestureDetector::GetAttachedActorCount() const
247 {
248   return mPendingAttachActors.size() + mAttachedActors.size();
249 }
250
251 Dali::Actor GestureDetector::GetAttachedActor(size_t index) const
252 {
253   Dali::Actor actor;
254
255   if( index < mPendingAttachActors.size() )
256   {
257     actor = Dali::Actor( mPendingAttachActors[index] );
258   }
259   else if( index < mPendingAttachActors.size() + mAttachedActors.size() )
260   {
261     actor = Dali::Actor( mAttachedActors[index - mPendingAttachActors.size()] );
262   }
263
264   return actor;
265 }
266
267 bool GestureDetector::IsAttached(Actor& actor) const
268 {
269   return ( find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) != mPendingAttachActors.end() ) ||
270          ( find(mAttachedActors.begin(), mAttachedActors.end(), &actor) != mAttachedActors.end() );
271 }
272
273 void GestureDetector::ObjectDestroyed(Object& object)
274 {
275   if ( !mPendingAttachActors.empty() )
276   {
277     GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &object);
278
279     if ( match != mPendingAttachActors.end() )
280     {
281       mPendingAttachActors.erase(match);
282     }
283   }
284
285   if ( !mAttachedActors.empty() )
286   {
287     GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &object);
288
289     if ( match != mAttachedActors.end() )
290     {
291       mAttachedActors.erase(match);
292
293       // Notification for derived classes
294       OnActorDestroyed(object);
295
296       // Unregister from gesture event processor if we do not have any actors
297       if ( mAttachedActors.empty() )
298       {
299         // Guard to allow handle destruction after Core has been destroyed
300         if ( Stage::IsInstalled() )
301         {
302           mGestureEventProcessor.RemoveGestureDetector(this);
303         }
304       }
305     }
306   }
307 }
308
309 } // namespace Internal
310
311 } // namespace Dali