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.
18 #include <dali/internal/event/actors/actor-parent.h>
21 #include <dali/internal/event/actors/actor-impl.h>
22 #include <dali/internal/event/common/scene-impl.h>
23 #include <dali/public-api/common/vector-wrapper.h>
34 /// Helper for emitting signals with multiple parameters
35 template<typename Signal, typename... Param>
36 void EmitSignal(Actor& actor, Signal& signal, Param... params)
40 Dali::Actor handle(&actor);
41 signal.Emit(handle, params...);
45 } //anonymous namespace
47 ActorParentImpl::ActorParentImpl(Actor& owner)
50 mChildRemovedSignal(),
51 mChildOrderChangedSignal()
55 ActorParentImpl::~ActorParentImpl()
60 void ActorParentImpl::Add(Actor& child)
62 DALI_ASSERT_ALWAYS(&mOwner != &child && "Cannot add actor to itself");
63 DALI_ASSERT_ALWAYS(!child.IsRoot() && "Cannot add root actor");
67 mChildren = new ActorContainer;
70 Actor* oldParent = child.GetParent();
72 // child might already be ours
73 if(&mOwner != oldParent)
75 // if we already have parent, unparent us first
78 oldParent->Remove(child); // This causes OnChildRemove callback & ChildRemoved signal
80 // Old parent may need to readjust to missing child
81 if(oldParent->RelayoutDependentOnChildren())
83 oldParent->RelayoutRequest();
87 // Guard against Add() during previous OnChildRemove callback
88 if(!child.GetParent())
90 // Do this first, since user callbacks from within SetParent() may need to remove child
91 mChildren->push_back(ActorPtr(&child));
93 // SetParent asserts that child can be added
94 child.SetParent(&mOwner);
96 // Notification for derived classes
97 mOwner.OnChildAdd(child);
98 EmitChildAddedSignal(child);
100 child.InheritLayoutDirectionRecursively(mOwner.GetLayoutDirection());
102 // Only put in a relayout request if there is a suitable dependency
103 if(mOwner.RelayoutDependentOnChildren())
105 mOwner.RelayoutRequest();
111 void ActorParentImpl::Remove(Actor& child)
113 if((&mOwner == &child) || (!mChildren))
115 // no children or removing itself
121 // Find the child in mChildren, and unparent it
122 ActorIter end = mChildren->end();
123 for(ActorIter iter = mChildren->begin(); iter != end; ++iter)
125 ActorPtr actor = (*iter);
127 if(actor.Get() == &child)
129 // Keep handle for OnChildRemove notification
132 // Do this first, since user callbacks from within SetParent() may need to add the child
133 mChildren->erase(iter);
135 DALI_ASSERT_DEBUG(actor->GetParent() == &mOwner);
136 actor->SetParent(nullptr);
144 // Only put in a relayout request if there is a suitable dependency
145 if(mOwner.RelayoutDependentOnChildren())
147 mOwner.RelayoutRequest();
151 // Notification for derived classes
152 mOwner.OnChildRemove(child);
153 EmitChildRemovedSignal(child);
156 uint32_t ActorParentImpl::GetChildCount() const
158 return (nullptr != mChildren) ? static_cast<uint32_t>(mChildren->size()) : 0; // only 4,294,967,295 children per actor
161 ActorPtr ActorParentImpl::GetChildAt(uint32_t index) const
163 DALI_ASSERT_ALWAYS(index < GetChildCount());
165 return ((mChildren) ? (*mChildren)[index] : ActorPtr());
168 ActorPtr ActorParentImpl::FindChildByName(const std::string& actorName)
170 ActorPtr child = nullptr;
171 if(actorName == mOwner.GetName())
177 for(const auto& actor : *mChildren)
179 child = actor->FindChildByName(actorName);
190 ActorPtr ActorParentImpl::FindChildById(const uint32_t id)
192 ActorPtr child = nullptr;
193 if(id == mOwner.GetId())
199 for(const auto& actor : *mChildren)
201 child = actor->FindChildById(id);
212 void ActorParentImpl::UnparentChildren()
216 for(const auto& child : *mChildren)
218 child->SetParent(nullptr);
223 void ActorParentImpl::SetSiblingOrderOfChild(
229 uint32_t currentOrder = GetSiblingOrderOfChild(child);
230 if(order != currentOrder)
234 LowerChildToBottom(child);
236 else if(order < mChildren->size() - 1)
238 if(order > currentOrder)
240 RaiseChildAbove(child, *((*mChildren)[order]));
244 LowerChildBelow(child, *((*mChildren)[order]));
249 RaiseChildToTop(child);
255 uint32_t ActorParentImpl::GetSiblingOrderOfChild(const Actor& child) const
260 for(std::size_t i = 0; i < mChildren->size(); ++i)
262 if((*mChildren)[i] == &child)
264 order = static_cast<uint32_t>(i);
272 void ActorParentImpl::RaiseChild(Actor& child)
274 bool changed = false;
275 if(mChildren && mChildren->back() != &child) // If not already at end
277 for(std::size_t i = 0; i < mChildren->size(); ++i)
279 if((*mChildren)[i] == &child)
282 ActorPtr next = (*mChildren)[i + 1];
283 (*mChildren)[i + 1] = &child;
284 (*mChildren)[i] = next;
292 EmitOrderChangedAndRebuild(child);
296 void ActorParentImpl::LowerChild(Actor& child)
298 bool changed = false;
299 if(mChildren && mChildren->front() != &child) // If not already at beginning
301 for(std::size_t i = 1; i < mChildren->size(); ++i)
303 if((*mChildren)[i] == &child)
305 // Swap with previous
306 ActorPtr previous = (*mChildren)[i - 1];
307 (*mChildren)[i - 1] = &child;
308 (*mChildren)[i] = previous;
316 EmitOrderChangedAndRebuild(child);
320 void ActorParentImpl::RaiseChildToTop(Actor& child)
322 bool changed = false;
323 if(mChildren && mChildren->back() != &child) // If not already at end
325 auto iter = std::find(mChildren->begin(), mChildren->end(), &child);
326 if(iter != mChildren->end())
328 mChildren->erase(iter);
329 mChildren->push_back(ActorPtr(&child));
335 EmitOrderChangedAndRebuild(child);
339 void ActorParentImpl::LowerChildToBottom(Actor& child)
341 bool changed = false;
342 if(mChildren && mChildren->front() != &child) // If not already at bottom,
344 ActorPtr childPtr(&child); // ensure actor remains referenced.
346 auto iter = std::find(mChildren->begin(), mChildren->end(), &child);
347 if(iter != mChildren->end())
349 mChildren->erase(iter);
350 mChildren->insert(mChildren->begin(), childPtr);
356 EmitOrderChangedAndRebuild(child);
360 void ActorParentImpl::RaiseChildAbove(Actor& child, Actor& target)
363 if(mChildren && mChildren->back() != &child && target.GetParent() == child.GetParent()) // If not already at top
365 ActorPtr childPtr(&child); // ensure actor actor remains referenced.
367 auto targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
368 auto childIter = std::find(mChildren->begin(), mChildren->end(), &child);
369 if(childIter < targetIter)
371 mChildren->erase(childIter);
372 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
373 // invalidate actorIter)
374 targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
376 mChildren->insert(targetIter, childPtr);
382 EmitOrderChangedAndRebuild(child);
386 void ActorParentImpl::LowerChildBelow(Actor& child, Actor& target)
388 bool lowered = false;
390 // If not already at bottom
391 if(mChildren && mChildren->front() != &child && target.GetParent() == child.GetParent())
393 ActorPtr childPtr(&child); // ensure actor actor remains referenced.
395 auto targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
396 auto childIter = std::find(mChildren->begin(), mChildren->end(), &child);
398 if(childIter > targetIter)
400 mChildren->erase(childIter); // actor only invalidates iterators at or after actor point.
401 mChildren->insert(targetIter, childPtr);
407 EmitOrderChangedAndRebuild(child);
411 void ActorParentImpl::EmitChildAddedSignal(Actor& child)
413 EmitSignal(child, mChildAddedSignal);
416 void ActorParentImpl::EmitChildRemovedSignal(Actor& child)
418 EmitSignal(child, mChildRemovedSignal);
421 void ActorParentImpl::EmitOrderChangedAndRebuild(Actor& child)
423 EmitSignal(child, mChildOrderChangedSignal);
427 mOwner.GetScene().RequestRebuildDepthTree();
431 } // namespace Internal