[Tizen] Make mScene nullptr when the Actor is disconnected from Scene recursively
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-parent-impl.cpp
index bd50549..f5311df 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
 #include <dali/internal/event/actors/actor-parent.h>
 
 // INTERNAL INCLUDES
+#include <dali/devel-api/actors/layer-devel.h>
 #include <dali/internal/event/actors/actor-impl.h>
 #include <dali/internal/event/common/scene-impl.h>
 #include <dali/public-api/common/vector-wrapper.h>
@@ -57,7 +58,7 @@ ActorParentImpl::~ActorParentImpl()
   delete mChildren;
 }
 
-void ActorParentImpl::Add(Actor& child)
+void ActorParentImpl::Add(Actor& child, bool notify)
 {
   DALI_ASSERT_ALWAYS(&mOwner != &child && "Cannot add actor to itself");
   DALI_ASSERT_ALWAYS(!child.IsRoot() && "Cannot add root actor");
@@ -75,7 +76,7 @@ void ActorParentImpl::Add(Actor& child)
     // if we already have parent, unparent us first
     if(oldParent)
     {
-      oldParent->Remove(child); // This causes OnChildRemove callback & ChildRemoved signal
+      oldParent->Remove(child, notify); // This causes OnChildRemove callback & ChildRemoved signal
 
       // Old parent may need to readjust to missing child
       if(oldParent->RelayoutDependentOnChildren())
@@ -91,13 +92,16 @@ void ActorParentImpl::Add(Actor& child)
       mChildren->push_back(ActorPtr(&child));
 
       // SetParent asserts that child can be added
-      child.SetParent(&mOwner);
+      child.SetParent(&mOwner, notify);
 
-      // Notification for derived classes
-      mOwner.OnChildAdd(child);
-      EmitChildAddedSignal(child);
+      if(notify)
+      {
+        // Notification for derived classes
+        mOwner.OnChildAdd(child);
+        EmitChildAddedSignal(child);
+      }
 
-      child.InheritLayoutDirectionRecursively(mOwner.GetLayoutDirection());
+      child.mParentImpl.InheritLayoutDirectionRecursively(mOwner.GetLayoutDirection());
 
       // Only put in a relayout request if there is a suitable dependency
       if(mOwner.RelayoutDependentOnChildren())
@@ -108,7 +112,7 @@ void ActorParentImpl::Add(Actor& child)
   }
 }
 
-void ActorParentImpl::Remove(Actor& child)
+void ActorParentImpl::Remove(Actor& child, bool notify)
 {
   if((&mOwner == &child) || (!mChildren))
   {
@@ -133,7 +137,7 @@ void ActorParentImpl::Remove(Actor& child)
       mChildren->erase(iter);
 
       DALI_ASSERT_DEBUG(actor->GetParent() == &mOwner);
-      actor->SetParent(nullptr);
+      actor->SetParent(nullptr, notify);
 
       break;
     }
@@ -148,9 +152,12 @@ void ActorParentImpl::Remove(Actor& child)
     }
   }
 
-  // Notification for derived classes
-  mOwner.OnChildRemove(child);
-  EmitChildRemovedSignal(child);
+  if(notify)
+  {
+    // Notification for derived classes
+    mOwner.OnChildRemove(child);
+    EmitChildRemovedSignal(child);
+  }
 }
 
 uint32_t ActorParentImpl::GetChildCount() const
@@ -165,10 +172,10 @@ ActorPtr ActorParentImpl::GetChildAt(uint32_t index) const
   return ((mChildren) ? (*mChildren)[index] : ActorPtr());
 }
 
-ActorPtr ActorParentImpl::FindChildByName(const std::string& actorName)
+ActorPtr ActorParentImpl::FindChildByName(ConstString actorName)
 {
   ActorPtr child = nullptr;
-  if(actorName == mOwner.GetName())
+  if(actorName.GetStringView() == mOwner.GetName())
   {
     child = &mOwner;
   }
@@ -408,6 +415,108 @@ void ActorParentImpl::LowerChildBelow(Actor& child, Actor& target)
   }
 }
 
+void ActorParentImpl::DepthTraverseActorTree(OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths,
+                                             int32_t&                              depthIndex)
+{
+  uint32_t sortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
+  mOwner.SetSortingDepth(sortedDepth);
+  sceneGraphNodeDepths->Add(const_cast<SceneGraph::Node*>(&mOwner.GetNode()), sortedDepth);
+
+  // Create/add to children of this node
+  if(mChildren)
+  {
+    for(const auto& actor : *mChildren)
+    {
+      ++depthIndex;
+      actor->mParentImpl.DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
+    }
+  }
+}
+
+void ActorParentImpl::RecursiveConnectToScene(ActorContainer& connectionList, uint32_t depth)
+{
+  DALI_ASSERT_ALWAYS(!mOwner.OnScene());
+
+  mOwner.mIsOnScene = true;
+  mOwner.mDepth     = static_cast<uint16_t>(depth); // overflow ignored, not expected in practice
+  mOwner.ConnectToSceneGraph();
+
+  // Notification for internal derived classes
+  mOwner.OnSceneConnectionInternal();
+
+  // This stage is atomic; avoid emitting callbacks until all Actors are connected
+  connectionList.push_back(ActorPtr(&mOwner));
+
+  // Recursively connect children
+  if(mChildren)
+  {
+    for(const auto& actor : *mChildren)
+    {
+      actor->SetScene(*mOwner.mScene);
+      actor->mParentImpl.RecursiveConnectToScene(connectionList, depth + 1);
+    }
+  }
+}
+
+void ActorParentImpl::RecursiveDisconnectFromScene(ActorContainer& disconnectionList)
+{
+  // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
+  mOwner.mIsOnScene = false;
+  mOwner.mScene     = nullptr;
+
+  // Recursively disconnect children
+  if(mChildren)
+  {
+    for(const auto& actor : *mChildren)
+    {
+      actor->mParentImpl.RecursiveDisconnectFromScene(disconnectionList);
+    }
+  }
+
+  // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
+  disconnectionList.push_back(ActorPtr(&mOwner));
+
+  // Notification for internal derived classes
+  mOwner.OnSceneDisconnectionInternal();
+  mOwner.DisconnectFromSceneGraph();
+}
+
+void ActorParentImpl::InheritLayoutDirectionRecursively(Dali::LayoutDirection::Type direction, bool set)
+{
+  if(mOwner.mInheritLayoutDirection || set)
+  {
+    if(mOwner.mLayoutDirection != direction)
+    {
+      mOwner.mLayoutDirection = direction;
+      mOwner.EmitLayoutDirectionChangedSignal(direction);
+      mOwner.RelayoutRequest();
+    }
+
+    if(mChildren)
+    {
+      for(const auto& child : *mChildren)
+      {
+        child->mParentImpl.InheritLayoutDirectionRecursively(direction);
+      }
+    }
+  }
+}
+
+void ActorParentImpl::EmitVisibilityChangedSignalRecursively(
+  bool                               visible,
+  DevelActor::VisibilityChange::Type type)
+{
+  mOwner.EmitVisibilityChangedSignal(visible, type);
+
+  if(mChildren)
+  {
+    for(const auto& child : *mChildren)
+    {
+      child->mParentImpl.EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::PARENT);
+    }
+  }
+}
+
 void ActorParentImpl::EmitChildAddedSignal(Actor& child)
 {
   EmitSignal(child, mChildAddedSignal);