2 * Copyright (c) 2024 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/devel-api/actors/layer-devel.h>
22 #include <dali/internal/event/actors/actor-impl.h>
23 #include <dali/internal/event/common/scene-impl.h>
24 #include <dali/public-api/common/vector-wrapper.h>
35 /// Helper for emitting signals with multiple parameters
36 template<typename Signal, typename... Param>
37 void EmitSignal(Actor& actor, Signal& signal, Param... params)
41 Dali::Actor handle(&actor);
42 signal.Emit(handle, params...);
46 } //anonymous namespace
48 ActorParentImpl::ActorParentImpl(Actor& owner)
51 mChildRemovedSignal(),
52 mChildOrderChangedSignal()
56 ActorParentImpl::~ActorParentImpl()
61 void ActorParentImpl::Add(Actor& child, bool notify)
63 DALI_ASSERT_ALWAYS(&mOwner != &child && "Cannot add actor to itself");
64 DALI_ASSERT_ALWAYS(!child.IsRoot() && "Cannot add root actor");
68 mChildren = new ActorContainer;
71 Actor* oldParent = child.GetParent();
73 // child might already be ours
74 if(&mOwner != oldParent)
76 // if we already have parent, unparent us first
79 oldParent->Remove(child, notify); // This causes OnChildRemove callback & ChildRemoved signal
81 // Old parent may need to readjust to missing child
82 if(oldParent->RelayoutDependentOnChildren())
84 oldParent->RelayoutRequest();
88 // Guard against Add() during previous OnChildRemove callback
89 if(!child.GetParent())
91 // Do this first, since user callbacks from within SetParent() may need to remove child
92 mChildren->push_back(ActorPtr(&child));
94 // SetParent asserts that child can be added
95 child.SetParent(&mOwner, notify);
99 // Notification for derived classes
100 mOwner.OnChildAdd(child);
101 EmitChildAddedSignal(child);
104 child.mParentImpl.InheritLayoutDirectionRecursively(mOwner.GetLayoutDirection());
106 // Only put in a relayout request if there is a suitable dependency
107 if(mOwner.RelayoutDependentOnChildren())
109 mOwner.RelayoutRequest();
115 void ActorParentImpl::Remove(Actor& child, bool notify)
117 if((&mOwner == &child) || (!mChildren))
119 // no children or removing itself
125 // Find the child in mChildren, and unparent it
126 ActorIter end = mChildren->end();
127 for(ActorIter iter = mChildren->begin(); iter != end; ++iter)
129 if((*iter).Get() == &child)
131 // Keep handle for OnChildRemove notification
134 // Do this first, since user callbacks from within SetParent() may need to add the child
135 mChildren->erase(iter);
137 DALI_ASSERT_DEBUG(removed->GetParent() == &mOwner);
138 removed->SetParent(nullptr, notify);
146 // Only put in a relayout request if there is a suitable dependency
147 if(mOwner.RelayoutDependentOnChildren())
149 mOwner.RelayoutRequest();
155 // Notification for derived classes
156 mOwner.OnChildRemove(child);
157 EmitChildRemovedSignal(child);
161 uint32_t ActorParentImpl::GetChildCount() const
163 return (nullptr != mChildren) ? static_cast<uint32_t>(mChildren->size()) : 0; // only 4,294,967,295 children per actor
166 ActorPtr ActorParentImpl::GetChildAt(uint32_t index) const
168 DALI_ASSERT_ALWAYS(index < GetChildCount());
170 return ((mChildren) ? (*mChildren)[index] : ActorPtr());
173 ActorPtr ActorParentImpl::FindChildByName(const std::string_view& actorName)
175 ActorPtr child = nullptr;
176 if(actorName == mOwner.GetName())
182 for(const auto& actor : *mChildren)
184 child = actor->FindChildByName(actorName);
195 ActorPtr ActorParentImpl::FindChildById(const uint32_t id)
197 ActorPtr child = nullptr;
198 if(id == mOwner.GetId())
204 for(const auto& actor : *mChildren)
206 child = actor->FindChildById(id);
217 void ActorParentImpl::UnparentChildren()
221 for(const auto& child : *mChildren)
223 child->SetParent(nullptr);
228 void ActorParentImpl::SetSiblingOrderOfChild(
232 if(mChildren && !mChildren->empty())
234 uint32_t currentOrder = GetSiblingOrderOfChild(child);
235 if(order != currentOrder)
239 LowerChildToBottom(child);
241 else if(order < mChildren->size() - 1)
243 if(order > currentOrder)
245 RaiseChildAbove(child, *((*mChildren)[order]));
249 LowerChildBelow(child, *((*mChildren)[order]));
254 RaiseChildToTop(child);
260 uint32_t ActorParentImpl::GetSiblingOrderOfChild(const Actor& child) const
263 if(mChildren && !mChildren->empty())
265 for(std::size_t i = 0; i < mChildren->size(); ++i)
267 if((*mChildren)[i] == &child)
269 order = static_cast<uint32_t>(i);
277 void ActorParentImpl::RaiseChild(Actor& child)
279 bool changed = false;
280 if(mChildren && !mChildren->empty() && mChildren->back() != &child) // If not already at end
282 for(std::size_t i = 0; i + 1 < mChildren->size(); ++i)
284 if((*mChildren)[i] == &child)
287 ActorPtr next = std::move((*mChildren)[i + 1]);
288 (*mChildren)[i + 1] = &child;
289 (*mChildren)[i] = std::move(next);
297 EmitOrderChangedAndRebuild(child);
301 void ActorParentImpl::LowerChild(Actor& child)
303 bool changed = false;
304 if(mChildren && !mChildren->empty() && mChildren->front() != &child) // If not already at beginning
306 for(std::size_t i = 1; i < mChildren->size(); ++i)
308 if((*mChildren)[i] == &child)
310 // Swap with previous
311 ActorPtr previous = std::move((*mChildren)[i - 1]);
312 (*mChildren)[i - 1] = &child;
313 (*mChildren)[i] = std::move(previous);
321 EmitOrderChangedAndRebuild(child);
325 void ActorParentImpl::RaiseChildToTop(Actor& child)
327 bool changed = false;
328 if(mChildren && !mChildren->empty() && mChildren->back() != &child) // If not already at end
330 auto iter = std::find(mChildren->begin(), mChildren->end(), &child);
331 if(iter != mChildren->end())
333 ActorPtr childPtr(&child); // ensure actor remains referenced.
335 mChildren->erase(iter);
336 mChildren->push_back(childPtr);
342 EmitOrderChangedAndRebuild(child);
346 void ActorParentImpl::LowerChildToBottom(Actor& child)
348 bool changed = false;
349 if(mChildren && !mChildren->empty() && mChildren->front() != &child) // If not already at bottom,
351 auto iter = std::find(mChildren->begin(), mChildren->end(), &child);
352 if(iter != mChildren->end())
354 ActorPtr childPtr(&child); // ensure actor remains referenced.
356 mChildren->erase(iter);
357 mChildren->insert(mChildren->begin(), childPtr);
363 EmitOrderChangedAndRebuild(child);
367 void ActorParentImpl::RaiseChildAbove(Actor& child, Actor& target)
370 if(mChildren && !mChildren->empty() && mChildren->back() != &child && target.GetParent() == child.GetParent()) // If not already at top
372 auto targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
373 auto childIter = std::find(mChildren->begin(), mChildren->end(), &child);
374 if(childIter < targetIter)
376 ActorPtr childPtr(&child); // ensure actor actor remains referenced.
378 mChildren->erase(childIter);
379 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
380 // invalidate actorIter)
381 targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
383 mChildren->insert(targetIter, childPtr);
389 EmitOrderChangedAndRebuild(child);
393 void ActorParentImpl::LowerChildBelow(Actor& child, Actor& target)
395 bool lowered = false;
397 // If not already at bottom
398 if(mChildren && !mChildren->empty() && mChildren->front() != &child && target.GetParent() == child.GetParent())
400 auto targetIter = std::find(mChildren->begin(), mChildren->end(), &target);
401 auto childIter = std::find(mChildren->begin(), mChildren->end(), &child);
403 if(childIter > targetIter)
405 ActorPtr childPtr(&child); // ensure actor actor remains referenced.
407 mChildren->erase(childIter); // actor only invalidates iterators at or after actor point.
408 mChildren->insert(targetIter, childPtr);
414 EmitOrderChangedAndRebuild(child);
418 void ActorParentImpl::DepthTraverseActorTree(OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths,
421 uint32_t sortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
422 mOwner.SetSortingDepth(sortedDepth);
423 sceneGraphNodeDepths->Add(const_cast<SceneGraph::Node*>(&mOwner.GetNode()), sortedDepth);
425 // Create/add to children of this node
428 for(const auto& actor : *mChildren)
431 actor->mParentImpl.DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
436 void ActorParentImpl::RecursiveConnectToScene(ActorContainer& connectionList, uint32_t layer3DParentsCount, uint32_t depth)
438 DALI_ASSERT_ALWAYS(!mOwner.OnScene());
442 if(static_cast<Dali::Internal::Layer*>(&mOwner)->GetBehavior() == Dali::Layer::Behavior::LAYER_3D)
444 // This is 3d layer. Propagate it to all children.
445 ++layer3DParentsCount;
449 mOwner.mIsOnScene = true;
450 mOwner.mDepth = static_cast<uint16_t>(depth); // overflow ignored, not expected in practice
451 mOwner.mLayer3DParentsCount = static_cast<uint16_t>(layer3DParentsCount); // overflow ignored, not expected in practice
452 mOwner.ConnectToSceneGraph();
454 // Notification for internal derived classes
455 mOwner.OnSceneConnectionInternal();
457 // This stage is atomic; avoid emitting callbacks until all Actors are connected
458 connectionList.push_back(ActorPtr(&mOwner));
460 // Recursively connect children
463 for(const auto& actor : *mChildren)
465 actor->SetScene(*mOwner.mScene);
466 actor->mParentImpl.RecursiveConnectToScene(connectionList, layer3DParentsCount, depth + 1);
471 void ActorParentImpl::RecursiveDisconnectFromScene(ActorContainer& disconnectionList)
473 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
474 mOwner.mIsOnScene = false;
475 mOwner.mScene = nullptr;
476 mOwner.mLayer3DParentsCount = 0;
478 // Recursively disconnect children
481 for(const auto& actor : *mChildren)
483 actor->mParentImpl.RecursiveDisconnectFromScene(disconnectionList);
487 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
488 disconnectionList.push_back(ActorPtr(&mOwner));
490 // Notification for internal derived classes
491 mOwner.OnSceneDisconnectionInternal();
492 mOwner.DisconnectFromSceneGraph();
495 void ActorParentImpl::RecursiveChangeLayer3dCount(int32_t layer3DParentsCountDiff)
497 mOwner.mLayer3DParentsCount += layer3DParentsCountDiff; // overflow ignored, not expected in practice
499 // Recursively change the value
502 for(const auto& actor : *mChildren)
504 actor->mParentImpl.RecursiveChangeLayer3dCount(layer3DParentsCountDiff);
509 void ActorParentImpl::InheritLayoutDirectionRecursively(Dali::LayoutDirection::Type direction, bool set)
511 if(mOwner.mInheritLayoutDirection || set)
513 if(mOwner.mLayoutDirection != direction)
515 mOwner.mLayoutDirection = direction;
516 mOwner.EmitLayoutDirectionChangedSignal(direction);
517 mOwner.RelayoutRequest();
522 for(const auto& child : *mChildren)
524 child->mParentImpl.InheritLayoutDirectionRecursively(direction);
530 void ActorParentImpl::EmitVisibilityChangedSignalRecursively(
532 DevelActor::VisibilityChange::Type type)
534 if(!visible && mOwner.OnScene())
536 //The actor should receive an interrupted event when it is hidden.
537 mOwner.GetScene().SendInterruptedEvents(&mOwner);
540 mOwner.EmitVisibilityChangedSignal(visible, type);
544 for(const auto& child : *mChildren)
546 child->mParentImpl.EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::PARENT);
551 void ActorParentImpl::InheritVisibilityRecursively(ActorContainer& inheritedVisibilityChangedList)
553 inheritedVisibilityChangedList.push_back(ActorPtr(&mOwner));
557 for(const auto& child : *mChildren)
559 if(child->GetProperty(Dali::Actor::Property::VISIBLE).Get<bool>())
561 child->mParentImpl.InheritVisibilityRecursively(inheritedVisibilityChangedList);
567 void ActorParentImpl::EmitChildAddedSignal(Actor& child)
569 EmitSignal(child, mChildAddedSignal);
572 void ActorParentImpl::EmitChildRemovedSignal(Actor& child)
574 EmitSignal(child, mChildRemovedSignal);
577 void ActorParentImpl::EmitOrderChangedAndRebuild(Actor& child)
579 EmitSignal(child, mChildOrderChangedSignal);
583 mOwner.GetScene().RequestRebuildDepthTree();
587 } // namespace Internal