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