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( GestureType::Value type, const SceneGraph::PropertyOwner* sceneObject )
38 : Object( sceneObject ),
40 mGestureEventProcessor( ThreadLocalStorage::Get().GetGestureEventProcessor() )
44 GestureDetector::~GestureDetector()
46 if ( !mPendingAttachActors.empty() )
48 for ( GestureDetectorActorContainer::iterator iter = mPendingAttachActors.begin(), endIter = mPendingAttachActors.end(); iter != endIter; ++iter )
50 Actor* actor( *iter );
51 actor->RemoveObserver( *this );
52 actor->GetGestureData().RemoveGestureDetector( *this );
55 mPendingAttachActors.clear();
58 if ( !mAttachedActors.empty() )
60 for ( GestureDetectorActorContainer::iterator iter = mAttachedActors.begin(), endIter = mAttachedActors.end(); iter != endIter; ++iter )
62 Actor* actor( *iter );
63 actor->RemoveObserver( *this );
64 actor->GetGestureData().RemoveGestureDetector( *this );
67 mAttachedActors.clear();
69 // Guard to allow handle destruction after Core has been destroyed
70 if ( Stage::IsInstalled() )
72 mGestureEventProcessor.RemoveGestureDetector( this );
77 void GestureDetector::Attach( Actor& actor )
79 if ( !IsAttached( actor ) )
83 // Register with EventProcessor if first actor being added
84 if( mAttachedActors.empty() )
86 mGestureEventProcessor.AddGestureDetector( this, actor.GetScene() );
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 );
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 );
102 mPendingAttachActors.push_back( &actor );
107 void GestureDetector::SceneObjectAdded( Object& object )
109 Actor& actor = dynamic_cast< Actor& >( object );
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() )
114 GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
116 if ( match != mPendingAttachActors.end() )
118 mPendingAttachActors.erase(match);
120 // Register with EventProcessor if first actor being added
121 if( mAttachedActors.empty() )
123 mGestureEventProcessor.AddGestureDetector( this, actor.GetScene() );
125 mAttachedActors.push_back( &actor );
127 // Notification for derived classes
128 OnActorAttach( actor );
132 // Actor was not in the pending list
133 DALI_ASSERT_DEBUG( false );
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() );
143 void GestureDetector::Detach(Actor& actor)
145 if ( !mPendingAttachActors.empty() )
147 GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
149 if ( match != mPendingAttachActors.end() )
151 // We no longer need to observe the actor's destruction
152 actor.RemoveObserver(*this);
154 // Remove detector from actor-gesture-data
155 actor.GetGestureData().RemoveGestureDetector( *this );
157 mPendingAttachActors.erase(match);
161 if ( !mAttachedActors.empty() )
163 GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &actor);
165 if ( match != mAttachedActors.end() )
167 // We no longer need to observe the actor's destruction
168 actor.RemoveObserver(*this);
170 // Remove detector from actor-gesture-data
171 actor.GetGestureData().RemoveGestureDetector( *this );
173 mAttachedActors.erase(match);
175 // Notification for derived classes
176 OnActorDetach(actor);
178 // Unregister from gesture event processor if we do not have any actors
179 if ( mAttachedActors.empty() )
181 // Guard to allow handle destruction after Core has been destroyed
182 if( Stage::IsInstalled() )
184 mGestureEventProcessor.RemoveGestureDetector(this);
191 void GestureDetector::DetachAll()
193 if ( !mPendingAttachActors.empty() )
195 GestureDetectorActorContainer pendingActors(mPendingAttachActors);
197 mPendingAttachActors.clear();
199 for ( GestureDetectorActorContainer::iterator iter = pendingActors.begin(), endIter = pendingActors.end(); iter != endIter; ++iter )
203 // We no longer need to observe the actor's destruction
204 actor->RemoveObserver(*this);
206 // Remove detector from actor-gesture-data
207 actor->GetGestureData().RemoveGestureDetector( *this );
211 if ( !mAttachedActors.empty() )
213 GestureDetectorActorContainer attachedActors(mAttachedActors);
215 // Clear mAttachedActors before we call OnActorDetach in case derived classes call a method which manipulates mAttachedActors.
216 mAttachedActors.clear();
218 for ( GestureDetectorActorContainer::iterator iter = attachedActors.begin(), endIter = attachedActors.end(); iter != endIter; ++iter )
222 // We no longer need to observe the actor's destruction
223 actor->RemoveObserver(*this);
225 // Remove detector from actor-gesture-data
226 actor->GetGestureData().RemoveGestureDetector( *this );
228 // Notification for derived classes
229 OnActorDetach(*actor);
232 // Guard to allow handle destruction after Core has been destroyed
233 if ( Stage::IsInstalled() )
235 // Unregister from gesture event processor
236 mGestureEventProcessor.RemoveGestureDetector(this);
241 size_t GestureDetector::GetAttachedActorCount() const
243 return mPendingAttachActors.size() + mAttachedActors.size();
246 Dali::Actor GestureDetector::GetAttachedActor(size_t index) const
250 if( index < mPendingAttachActors.size() )
252 actor = Dali::Actor( mPendingAttachActors[index] );
254 else if( index < mPendingAttachActors.size() + mAttachedActors.size() )
256 actor = Dali::Actor( mAttachedActors[index - mPendingAttachActors.size()] );
262 bool GestureDetector::IsAttached(Actor& actor) const
264 return ( find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) != mPendingAttachActors.end() ) ||
265 ( find(mAttachedActors.begin(), mAttachedActors.end(), &actor) != mAttachedActors.end() );
268 void GestureDetector::ObjectDestroyed(Object& object)
270 if ( !mPendingAttachActors.empty() )
272 GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &object);
274 if ( match != mPendingAttachActors.end() )
276 mPendingAttachActors.erase(match);
280 if ( !mAttachedActors.empty() )
282 GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &object);
284 if ( match != mAttachedActors.end() )
286 mAttachedActors.erase(match);
288 // Notification for derived classes
289 OnActorDestroyed(object);
291 // Unregister from gesture event processor if we do not have any actors
292 if ( mAttachedActors.empty() )
294 // Guard to allow handle destruction after Core has been destroyed
295 if ( Stage::IsInstalled() )
297 mGestureEventProcessor.RemoveGestureDetector(this);
304 } // namespace Internal