2 * Copyright (c) 2021 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/common/stage-impl.h>
27 #include <dali/internal/event/common/thread-local-storage.h>
28 #include <dali/internal/event/events/actor-gesture-data.h>
29 #include <dali/internal/event/events/gesture-event-processor.h>
35 GestureDetector::GestureDetector(GestureType::Value type, const SceneGraph::PropertyOwner* sceneObject)
36 : Object(sceneObject),
38 mGestureEventProcessor(ThreadLocalStorage::Get().GetGestureEventProcessor())
42 GestureDetector::~GestureDetector()
44 if(!mPendingAttachActors.empty())
46 for(GestureDetectorActorContainer::iterator iter = mPendingAttachActors.begin(), endIter = mPendingAttachActors.end(); iter != endIter; ++iter)
49 actor->RemoveObserver(*this);
50 actor->GetGestureData().RemoveGestureDetector(*this);
53 mPendingAttachActors.clear();
56 if(!mAttachedActors.empty())
58 for(GestureDetectorActorContainer::iterator iter = mAttachedActors.begin(), endIter = mAttachedActors.end(); iter != endIter; ++iter)
61 actor->RemoveObserver(*this);
62 actor->GetGestureData().RemoveGestureDetector(*this);
65 mAttachedActors.clear();
67 // Guard to allow handle destruction after Core has been destroyed
68 if(Stage::IsInstalled())
70 mGestureEventProcessor.RemoveGestureDetector(this);
75 void GestureDetector::Attach(Actor& actor)
77 if(!IsAttached(actor))
81 // Register with EventProcessor if first actor being added
82 if(mAttachedActors.empty())
84 mGestureEventProcessor.AddGestureDetector(this, actor.GetScene());
86 mAttachedActors.push_back(&actor);
87 // We need to observe the actor's destruction
88 actor.AddObserver(*this);
89 // Add the detector to the actor (so the actor knows it requires this gesture when going through hit-test algorithm)
90 actor.GetGestureData().AddGestureDetector(*this);
91 // Notification for derived classes
96 actor.AddObserver(*this);
97 // Add the detector to the actor (so the actor knows it requires this gesture when going through hit-test algorithm)
98 actor.GetGestureData().AddGestureDetector(*this);
100 mPendingAttachActors.push_back(&actor);
105 void GestureDetector::SceneObjectAdded(Object& object)
107 Actor& actor = dynamic_cast<Actor&>(object);
109 // Make sure the actor has not already been attached. Can't use IsAttached() as that checks the pending list as well
110 if(find(mAttachedActors.begin(), mAttachedActors.end(), &actor) == mAttachedActors.end())
112 GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
114 if(match != mPendingAttachActors.end())
116 mPendingAttachActors.erase(match);
118 // Register with EventProcessor if first actor being added
119 if(mAttachedActors.empty())
121 mGestureEventProcessor.AddGestureDetector(this, actor.GetScene());
123 mAttachedActors.push_back(&actor);
125 // Notification for derived classes
126 OnActorAttach(actor);
130 // Actor was not in the pending list
131 DALI_ASSERT_DEBUG(false);
136 // Check if actor has been attached and is still in the pending list - this would not be correct
137 DALI_ASSERT_DEBUG(find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) == mPendingAttachActors.end());
141 void GestureDetector::Detach(Actor& actor)
143 if(!mPendingAttachActors.empty())
145 GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor);
147 if(match != mPendingAttachActors.end())
149 // We no longer need to observe the actor's destruction
150 actor.RemoveObserver(*this);
152 // Remove detector from actor-gesture-data
153 actor.GetGestureData().RemoveGestureDetector(*this);
155 mPendingAttachActors.erase(match);
159 if(!mAttachedActors.empty())
161 GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &actor);
163 if(match != mAttachedActors.end())
165 // We no longer need to observe the actor's destruction
166 actor.RemoveObserver(*this);
168 // Remove detector from actor-gesture-data
169 actor.GetGestureData().RemoveGestureDetector(*this);
171 mAttachedActors.erase(match);
173 // Notification for derived classes
174 OnActorDetach(actor);
176 // Unregister from gesture event processor if we do not have any actors
177 if(mAttachedActors.empty())
179 // Guard to allow handle destruction after Core has been destroyed
180 if(Stage::IsInstalled())
182 mGestureEventProcessor.RemoveGestureDetector(this);
189 void GestureDetector::DetachAll()
191 if(!mPendingAttachActors.empty())
193 GestureDetectorActorContainer pendingActors(mPendingAttachActors);
195 mPendingAttachActors.clear();
197 for(GestureDetectorActorContainer::iterator iter = pendingActors.begin(), endIter = pendingActors.end(); iter != endIter; ++iter)
201 // We no longer need to observe the actor's destruction
202 actor->RemoveObserver(*this);
204 // Remove detector from actor-gesture-data
205 actor->GetGestureData().RemoveGestureDetector(*this);
209 if(!mAttachedActors.empty())
211 GestureDetectorActorContainer attachedActors(mAttachedActors);
213 // Clear mAttachedActors before we call OnActorDetach in case derived classes call a method which manipulates mAttachedActors.
214 mAttachedActors.clear();
216 for(GestureDetectorActorContainer::iterator iter = attachedActors.begin(), endIter = attachedActors.end(); iter != endIter; ++iter)
220 // We no longer need to observe the actor's destruction
221 actor->RemoveObserver(*this);
223 // Remove detector from actor-gesture-data
224 actor->GetGestureData().RemoveGestureDetector(*this);
226 // Notification for derived classes
227 OnActorDetach(*actor);
230 // Guard to allow handle destruction after Core has been destroyed
231 if(Stage::IsInstalled())
233 // Unregister from gesture event processor
234 mGestureEventProcessor.RemoveGestureDetector(this);
239 size_t GestureDetector::GetAttachedActorCount() const
241 return mPendingAttachActors.size() + mAttachedActors.size();
244 Dali::Actor GestureDetector::GetAttachedActor(size_t index) const
248 if(index < mPendingAttachActors.size())
250 actor = Dali::Actor(mPendingAttachActors[index]);
252 else if(index < mPendingAttachActors.size() + mAttachedActors.size())
254 actor = Dali::Actor(mAttachedActors[index - mPendingAttachActors.size()]);
260 bool GestureDetector::IsAttached(Actor& actor) const
262 return (find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) != mPendingAttachActors.end()) ||
263 (find(mAttachedActors.begin(), mAttachedActors.end(), &actor) != mAttachedActors.end());
266 void GestureDetector::ObjectDestroyed(Object& object)
268 if(!mPendingAttachActors.empty())
270 GestureDetectorActorContainer::iterator match = find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &object);
272 if(match != mPendingAttachActors.end())
274 mPendingAttachActors.erase(match);
278 if(!mAttachedActors.empty())
280 GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &object);
282 if(match != mAttachedActors.end())
284 mAttachedActors.erase(match);
286 // Notification for derived classes
287 OnActorDestroyed(object);
289 // Unregister from gesture event processor if we do not have any actors
290 if(mAttachedActors.empty())
292 // Guard to allow handle destruction after Core has been destroyed
293 if(Stage::IsInstalled())
295 mGestureEventProcessor.RemoveGestureDetector(this);
302 } // namespace Internal