2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/events/gesture-detector-impl.h>
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>
37 GestureDetector::GestureDetector( DevelGesture::Type type, const SceneGraph::PropertyOwner* sceneObject )
38 : Object( sceneObject ),
40 mGestureEventProcessor( ThreadLocalStorage::Get().GetGestureEventProcessor() )
44 GestureDetector::GestureDetector( Gesture::Type type, const SceneGraph::PropertyOwner* sceneObject )
45 : GestureDetector( static_cast< DevelGesture::Type >( type ), sceneObject )
49 GestureDetector::~GestureDetector()
51 if ( !mPendingAttachActors.empty() )
53 for ( GestureDetectorActorContainer::iterator iter = mPendingAttachActors.begin(), endIter = mPendingAttachActors.end(); iter != endIter; ++iter )
55 Actor* actor( *iter );
56 actor->RemoveObserver( *this );
57 actor->GetGestureData().RemoveGestureDetector( *this );
60 mPendingAttachActors.clear();
63 if ( !mAttachedActors.empty() )
65 for ( GestureDetectorActorContainer::iterator iter = mAttachedActors.begin(), endIter = mAttachedActors.end(); iter != endIter; ++iter )
67 Actor* actor( *iter );
68 actor->RemoveObserver( *this );
69 actor->GetGestureData().RemoveGestureDetector( *this );
72 mAttachedActors.clear();
74 // Guard to allow handle destruction after Core has been destroyed
75 if ( Stage::IsInstalled() )
77 mGestureEventProcessor.RemoveGestureDetector( this );
82 void GestureDetector::Attach( Actor& actor )
84 if ( !IsAttached( actor ) )
88 // Register with EventProcessor if first actor being added
89 if( mAttachedActors.empty() )
91 mGestureEventProcessor.AddGestureDetector( this, actor.GetScene() );
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 );
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 );
107 mPendingAttachActors.push_back( &actor );
112 void GestureDetector::SceneObjectAdded( Object& object )
114 Actor& actor = dynamic_cast< Actor& >( object );
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() )
119 GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
121 if ( match != mPendingAttachActors.end() )
123 mPendingAttachActors.erase(match);
125 // Register with EventProcessor if first actor being added
126 if( mAttachedActors.empty() )
128 mGestureEventProcessor.AddGestureDetector( this, actor.GetScene() );
130 mAttachedActors.push_back( &actor );
132 // Notification for derived classes
133 OnActorAttach( actor );
137 // Actor was not in the pending list
138 DALI_ASSERT_DEBUG( false );
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() );
148 void GestureDetector::Detach(Actor& actor)
150 if ( !mPendingAttachActors.empty() )
152 GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
154 if ( match != mPendingAttachActors.end() )
156 // We no longer need to observe the actor's destruction
157 actor.RemoveObserver(*this);
159 // Remove detector from actor-gesture-data
160 actor.GetGestureData().RemoveGestureDetector( *this );
162 mPendingAttachActors.erase(match);
166 if ( !mAttachedActors.empty() )
168 GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &actor);
170 if ( match != mAttachedActors.end() )
172 // We no longer need to observe the actor's destruction
173 actor.RemoveObserver(*this);
175 // Remove detector from actor-gesture-data
176 actor.GetGestureData().RemoveGestureDetector( *this );
178 mAttachedActors.erase(match);
180 // Notification for derived classes
181 OnActorDetach(actor);
183 // Unregister from gesture event processor if we do not have any actors
184 if ( mAttachedActors.empty() )
186 // Guard to allow handle destruction after Core has been destroyed
187 if( Stage::IsInstalled() )
189 mGestureEventProcessor.RemoveGestureDetector(this);
196 void GestureDetector::DetachAll()
198 if ( !mPendingAttachActors.empty() )
200 GestureDetectorActorContainer pendingActors(mPendingAttachActors);
202 mPendingAttachActors.clear();
204 for ( GestureDetectorActorContainer::iterator iter = pendingActors.begin(), endIter = pendingActors.end(); iter != endIter; ++iter )
208 // We no longer need to observe the actor's destruction
209 actor->RemoveObserver(*this);
211 // Remove detector from actor-gesture-data
212 actor->GetGestureData().RemoveGestureDetector( *this );
216 if ( !mAttachedActors.empty() )
218 GestureDetectorActorContainer attachedActors(mAttachedActors);
220 // Clear mAttachedActors before we call OnActorDetach in case derived classes call a method which manipulates mAttachedActors.
221 mAttachedActors.clear();
223 for ( GestureDetectorActorContainer::iterator iter = attachedActors.begin(), endIter = attachedActors.end(); iter != endIter; ++iter )
227 // We no longer need to observe the actor's destruction
228 actor->RemoveObserver(*this);
230 // Remove detector from actor-gesture-data
231 actor->GetGestureData().RemoveGestureDetector( *this );
233 // Notification for derived classes
234 OnActorDetach(*actor);
237 // Guard to allow handle destruction after Core has been destroyed
238 if ( Stage::IsInstalled() )
240 // Unregister from gesture event processor
241 mGestureEventProcessor.RemoveGestureDetector(this);
246 size_t GestureDetector::GetAttachedActorCount() const
248 return mPendingAttachActors.size() + mAttachedActors.size();
251 Dali::Actor GestureDetector::GetAttachedActor(size_t index) const
255 if( index < mPendingAttachActors.size() )
257 actor = Dali::Actor( mPendingAttachActors[index] );
259 else if( index < mPendingAttachActors.size() + mAttachedActors.size() )
261 actor = Dali::Actor( mAttachedActors[index - mPendingAttachActors.size()] );
267 bool GestureDetector::IsAttached(Actor& actor) const
269 return ( find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) != mPendingAttachActors.end() ) ||
270 ( find(mAttachedActors.begin(), mAttachedActors.end(), &actor) != mAttachedActors.end() );
273 void GestureDetector::ObjectDestroyed(Object& object)
275 if ( !mPendingAttachActors.empty() )
277 GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &object);
279 if ( match != mPendingAttachActors.end() )
281 mPendingAttachActors.erase(match);
285 if ( !mAttachedActors.empty() )
287 GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &object);
289 if ( match != mAttachedActors.end() )
291 mAttachedActors.erase(match);
293 // Notification for derived classes
294 OnActorDestroyed(object);
296 // Unregister from gesture event processor if we do not have any actors
297 if ( mAttachedActors.empty() )
299 // Guard to allow handle destruction after Core has been destroyed
300 if ( Stage::IsInstalled() )
302 mGestureEventProcessor.RemoveGestureDetector(this);
309 } // namespace Internal