Add Inherited Visibility Changed signal 84/310084/12
authorSeungho Baek <sbsh.baek@samsung.com>
Mon, 22 Apr 2024 07:43:13 +0000 (16:43 +0900)
committerSeungho Baek <sbsh.baek@samsung.com>
Fri, 26 Apr 2024 10:20:58 +0000 (19:20 +0900)
Change-Id: I1d592e6a5c9f17b77b8ee9f8828586f424985699
Signed-off-by: Seungho Baek <sbsh.baek@samsung.com>
automated-tests/src/dali/utc-Dali-Actor.cpp
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h
dali/internal/event/actors/actor-parent-impl.cpp
dali/internal/event/actors/actor-parent-impl.h
dali/public-api/actors/actor.cpp
dali/public-api/actors/actor.h

index f08e19db1b9b1f61087463d16283046835dff78a..a245c5ccaf2eb1cf9cbafaed27898c06af5ad983 100644 (file)
@@ -276,6 +276,56 @@ struct VisibilityChangedVoidFunctor
   bool& mSignalCalled;
 };
 
+struct InheritedVisibilityChangedFunctorData
+{
+  InheritedVisibilityChangedFunctorData()
+  : actor(),
+    visible(false),
+    called(false)
+  {
+  }
+
+  void Reset()
+  {
+    actor.Reset();
+    visible = false;
+    called  = false;
+  }
+
+  void Check(bool compareCalled, Actor compareActor, bool compareVisible, const char* location)
+  {
+    DALI_TEST_EQUALS(called, compareCalled, TEST_INNER_LOCATION(location));
+    DALI_TEST_EQUALS(actor, compareActor, TEST_INNER_LOCATION(location));
+    DALI_TEST_EQUALS(visible, compareVisible, TEST_INNER_LOCATION(location));
+  }
+
+  void Check(bool compareCalled, const std::string& location)
+  {
+    DALI_TEST_EQUALS(called, compareCalled, TEST_INNER_LOCATION(location));
+  }
+
+  Actor                              actor;
+  bool                               visible;
+  bool                               called;
+};
+
+struct InheritedVisibilityChangedFunctor
+{
+  InheritedVisibilityChangedFunctor(InheritedVisibilityChangedFunctorData& dataVar)
+  : data(dataVar)
+  {
+  }
+
+  void operator()(Actor actor, bool visible)
+  {
+    data.actor   = actor;
+    data.visible = visible;
+    data.called  = true;
+  }
+
+  InheritedVisibilityChangedFunctorData& data;
+};
+
 struct ChildOrderChangedFunctor
 {
   ChildOrderChangedFunctor(bool& signalCalled, Actor& actor)
@@ -9811,6 +9861,284 @@ int utcDaliActorVisibilityChangeSignalByName(void)
   END_TEST;
 }
 
+int utcDaliActorInheritedVisibilityChangeSignal1(void)
+{
+  TestApplication application;
+  tet_infoline("Check that the inherited visibility change signal is called when the visibility changes for the actor itself");
+
+  Actor parentActor = Actor::New();
+  Actor actor = Actor::New();
+
+  InheritedVisibilityChangedFunctorData data;
+  actor.InheritedVisibilityChangedSignal().Connect(&application, InheritedVisibilityChangedFunctor(data));
+
+  parentActor.Add(actor);
+  data.Check(false, TEST_LOCATION);
+
+  data.Reset();
+  application.GetScene().Add(parentActor);
+  data.Check(true, actor, true, TEST_LOCATION);
+
+  data.Reset();
+  actor.SetProperty(Actor::Property::VISIBLE, false);
+  data.Check(true, actor, false, TEST_LOCATION);
+
+  data.Reset();
+  actor.SetProperty(Actor::Property::VISIBLE, false);
+  data.Check(false, TEST_LOCATION);
+
+  data.Reset();
+  actor.SetProperty(Actor::Property::VISIBLE, true);
+  data.Check(true, actor, true, TEST_LOCATION);
+
+  data.Reset();
+  actor.SetProperty(Actor::Property::VISIBLE, true);
+  data.Check(false, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int utcDaliActorInheritedVisibilityChangeSignal2(void)
+{
+  TestApplication application;
+  tet_infoline("Check that the inherited visibility change signal is called when the actor or one of the parent become on scene or off scene");
+
+  Actor parentActor = Actor::New();
+  Actor childActor = Actor::New();
+
+  InheritedVisibilityChangedFunctorData dataP, dataC;
+  parentActor.InheritedVisibilityChangedSignal().Connect(&application, InheritedVisibilityChangedFunctor(dataP));
+  childActor.InheritedVisibilityChangedSignal().Connect(&application, InheritedVisibilityChangedFunctor(dataC));
+
+  dataP.Reset();
+  dataC.Reset();
+  parentActor.Add(childActor);
+  dataP.Check(false, TEST_LOCATION);
+  dataC.Check(false, TEST_LOCATION);
+
+  dataP.Reset();
+  dataC.Reset();
+  application.GetScene().Add(parentActor);
+  dataP.Check(true, parentActor, true, TEST_LOCATION);
+  dataC.Check(true, childActor, true, TEST_LOCATION);
+
+  dataP.Reset();
+  dataC.Reset();
+  childActor.Unparent();
+  dataP.Check(false, TEST_LOCATION);
+  dataC.Check(true, childActor, false, TEST_LOCATION);
+
+  dataP.Reset();
+  dataC.Reset();
+  childActor.SetProperty(Actor::Property::VISIBLE, false);
+  dataP.Check(false, TEST_LOCATION);
+  dataC.Check(false, TEST_LOCATION);
+
+  dataP.Reset();
+  dataC.Reset();
+  parentActor.Add(childActor);
+  dataP.Check(false, TEST_LOCATION);
+  dataC.Check(false, TEST_LOCATION);
+
+  dataP.Reset();
+  dataC.Reset();
+  childActor.SetProperty(Actor::Property::VISIBLE, true);
+  dataP.Check(false, TEST_LOCATION);
+  dataC.Check(true, childActor, true, TEST_LOCATION);
+
+  dataP.Reset();
+  dataC.Reset();
+  parentActor.SetProperty(Actor::Property::VISIBLE, false);
+  dataP.Check(true, parentActor, false, TEST_LOCATION);
+  dataC.Check(true, childActor, false, TEST_LOCATION);
+
+  dataP.Reset();
+  dataC.Reset();
+  childActor.Unparent();
+  dataP.Check(false, TEST_LOCATION);
+  dataC.Check(false, TEST_LOCATION);
+
+  dataP.Reset();
+  dataC.Reset();
+  parentActor.SetProperty(Actor::Property::VISIBLE, true);
+  dataP.Check(true, parentActor, true, TEST_LOCATION);
+  dataC.Check(false, TEST_LOCATION);
+
+  dataP.Reset();
+  dataC.Reset();
+  parentActor.Add(childActor);
+  dataP.Check(false, TEST_LOCATION);
+  dataC.Check(true, childActor, true, TEST_LOCATION);
+
+  dataP.Reset();
+  dataC.Reset();
+  parentActor.Remove(childActor);
+  dataP.Check(false, TEST_LOCATION);
+  dataC.Check(true, childActor, false, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int utcDaliActorInheritedVisibilityChangeSignal3(void)
+{
+  TestApplication application;
+  tet_infoline("Check that the inherited visibility change signal is called when the visibility changes for the parent actor");
+
+  Actor parentActor = Actor::New();
+  Actor actor = Actor::New();
+  parentActor.Add(actor);
+
+  InheritedVisibilityChangedFunctorData data;
+  actor.InheritedVisibilityChangedSignal().Connect(&application, InheritedVisibilityChangedFunctor(data));
+
+  application.GetScene().Add(parentActor);
+  data.Check(true, actor, true, TEST_LOCATION);
+
+  // Case 1
+  // Parent true -> false : called
+  // actor true -> false  : not called
+  // actor false -> true  : not called
+  data.Reset();
+  parentActor.SetProperty(Actor::Property::VISIBLE, false);
+  data.Check(true, actor, false, TEST_LOCATION);
+
+  data.Reset();
+  actor.SetProperty(Actor::Property::VISIBLE, false);
+  data.Check(false, TEST_LOCATION);
+
+  data.Reset();
+  actor.SetProperty(Actor::Property::VISIBLE, true);
+  data.Check(false, TEST_LOCATION);
+
+
+  // Prepare Case 2
+  // Parent : false
+  // actor : false
+  data.Reset();
+  actor.SetProperty(Actor::Property::VISIBLE, false);
+  data.Check(false, TEST_LOCATION);
+
+  // Case 2
+  // actor : false
+  // parent false -> true : not called
+  data.Reset();
+  parentActor.SetProperty(Actor::Property::VISIBLE, true);
+  data.Check(false, TEST_LOCATION);
+
+
+  // Prepare Case 3
+  // parent : false
+  // actor : true
+  data.Reset();
+  parentActor.SetProperty(Actor::Property::VISIBLE, false);
+  data.Check(false, TEST_LOCATION);
+
+  data.Reset();
+  actor.SetProperty(Actor::Property::VISIBLE, true);
+  data.Check(false, TEST_LOCATION);
+
+  // Case 3
+  // actor : true
+  // parent false -> true : called
+  parentActor.SetProperty(Actor::Property::VISIBLE, true);
+  data.Check(true, actor, true, TEST_LOCATION);
+
+  END_TEST;
+}
+
+namespace
+{
+  InheritedVisibilityChangedFunctorData dataPA, dataPB, dataCA, dataCB, dataCC;
+  void ResetInheritedVisibilityChangedFunctorData()
+  {
+    dataPA.Reset();
+    dataPB.Reset();
+    dataCA.Reset();
+    dataCB.Reset();
+    dataCC.Reset();
+  }
+}
+
+int utcDaliActorInheritedVisibilityChangeSignal4(void)
+{
+  TestApplication application;
+  tet_infoline("Check that the inherited visibility change signal is in tree");
+
+  /**
+   * ParentA
+   *    |
+   * ParentB
+   *    |
+   * ChildA   ChildB   ChildC
+   */
+
+  Actor parentA = Actor::New();
+  Actor parentB = Actor::New();
+  Actor childA = Actor::New();
+  Actor childB = Actor::New();
+  Actor childC = Actor::New();
+  parentA.Add(parentB);
+  parentB.Add(childA);
+  parentB.Add(childB);
+  parentB.Add(childC);
+
+  parentA.InheritedVisibilityChangedSignal().Connect(&application, InheritedVisibilityChangedFunctor(dataPA));
+  parentB.InheritedVisibilityChangedSignal().Connect(&application, InheritedVisibilityChangedFunctor(dataPB));
+  childA.InheritedVisibilityChangedSignal().Connect(&application, InheritedVisibilityChangedFunctor(dataCA));
+  childB.InheritedVisibilityChangedSignal().Connect(&application, InheritedVisibilityChangedFunctor(dataCB));
+  childC.InheritedVisibilityChangedSignal().Connect(&application, InheritedVisibilityChangedFunctor(dataCC));
+
+  ResetInheritedVisibilityChangedFunctorData();
+  application.GetScene().Add(parentA);
+  dataPA.Check(true, parentA, true, TEST_LOCATION);
+  dataPB.Check(true, parentB, true, TEST_LOCATION);
+  dataCA.Check(true, childA,  true, TEST_LOCATION);
+  dataCB.Check(true, childB,  true, TEST_LOCATION);
+  dataCC.Check(true, childC,  true, TEST_LOCATION);
+
+  ResetInheritedVisibilityChangedFunctorData();
+  parentA.SetProperty(Actor::Property::VISIBLE, false);
+  dataPA.Check(true, parentA, false, TEST_LOCATION);
+  dataPB.Check(true, parentB, false, TEST_LOCATION);
+  dataCA.Check(true, childA,  false, TEST_LOCATION);
+  dataCB.Check(true, childB,  false, TEST_LOCATION);
+  dataCC.Check(true, childC,  false, TEST_LOCATION);
+
+  ResetInheritedVisibilityChangedFunctorData();
+  childA.SetProperty(Actor::Property::VISIBLE, false);
+  dataPA.Check(false, TEST_LOCATION);
+  dataPB.Check(false, TEST_LOCATION);
+  dataCA.Check(false, TEST_LOCATION);
+  dataCB.Check(false, TEST_LOCATION);
+  dataCC.Check(false, TEST_LOCATION);
+
+  ResetInheritedVisibilityChangedFunctorData();
+  parentB.SetProperty(Actor::Property::VISIBLE, false);
+  dataPA.Check(false, TEST_LOCATION);
+  dataPB.Check(false, TEST_LOCATION);
+  dataCA.Check(false, TEST_LOCATION);
+  dataCB.Check(false, TEST_LOCATION);
+  dataCC.Check(false, TEST_LOCATION);
+
+  ResetInheritedVisibilityChangedFunctorData();
+  parentA.SetProperty(Actor::Property::VISIBLE, true);
+  dataPA.Check(true, parentA, true, TEST_LOCATION);
+  dataPB.Check(false, TEST_LOCATION);
+  dataCA.Check(false, TEST_LOCATION);
+  dataCB.Check(false, TEST_LOCATION);
+  dataCC.Check(false, TEST_LOCATION);
+
+  ResetInheritedVisibilityChangedFunctorData();
+  parentB.SetProperty(Actor::Property::VISIBLE, true);
+  dataPA.Check(false, TEST_LOCATION);
+  dataPB.Check(true, parentB, true, TEST_LOCATION);
+  dataCA.Check(false, TEST_LOCATION);
+  dataCB.Check(true, childB,  true, TEST_LOCATION);
+  dataCC.Check(true, childC,  true, TEST_LOCATION);
+
+  END_TEST;
+}
+
 static void LayoutDirectionChanged(Actor actor, LayoutDirection::Type type)
 {
   gLayoutDirectionType = type;
index 2aafb89dfa4ca71ae39ce9a88f3f3b5f0722bacc..54ac552b68ebc6c00c41013b6b62d4f822a6d109 100644 (file)
@@ -155,16 +155,17 @@ DALI_PROPERTY_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperti
 
 // Signals
 
-static constexpr std::string_view SIGNAL_HOVERED                  = "hovered";
-static constexpr std::string_view SIGNAL_WHEEL_EVENT              = "wheelEvent";
-static constexpr std::string_view SIGNAL_ON_SCENE                 = "onScene";
-static constexpr std::string_view SIGNAL_OFF_SCENE                = "offScene";
-static constexpr std::string_view SIGNAL_ON_RELAYOUT              = "onRelayout";
-static constexpr std::string_view SIGNAL_TOUCHED                  = "touched";
-static constexpr std::string_view SIGNAL_VISIBILITY_CHANGED       = "visibilityChanged";
-static constexpr std::string_view SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
-static constexpr std::string_view SIGNAL_CHILD_ADDED              = "childAdded";
-static constexpr std::string_view SIGNAL_CHILD_REMOVED            = "childRemoved";
+static constexpr std::string_view SIGNAL_HOVERED                      = "hovered";
+static constexpr std::string_view SIGNAL_WHEEL_EVENT                  = "wheelEvent";
+static constexpr std::string_view SIGNAL_ON_SCENE                     = "onScene";
+static constexpr std::string_view SIGNAL_OFF_SCENE                    = "offScene";
+static constexpr std::string_view SIGNAL_ON_RELAYOUT                  = "onRelayout";
+static constexpr std::string_view SIGNAL_TOUCHED                      = "touched";
+static constexpr std::string_view SIGNAL_VISIBILITY_CHANGED           = "visibilityChanged";
+static constexpr std::string_view SIGNAL_INHERITED_VISIBILITY_CHANGED = "inheritedVisibilityChanged";
+static constexpr std::string_view SIGNAL_LAYOUT_DIRECTION_CHANGED     = "layoutDirectionChanged";
+static constexpr std::string_view SIGNAL_CHILD_ADDED                  = "childAdded";
+static constexpr std::string_view SIGNAL_CHILD_REMOVED                = "childRemoved";
 
 // Actions
 
@@ -223,6 +224,10 @@ static bool DoConnectSignal(BaseObject*                 object,
   {
     actor->VisibilityChangedSignal().Connect(tracker, functor);
   }
+  else if(name == SIGNAL_INHERITED_VISIBILITY_CHANGED)
+  {
+    actor->InheritedVisibilityChangedSignal().Connect(tracker, functor);
+  }
   else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED)
   {
     actor->LayoutDirectionChangedSignal().Connect(tracker, functor);
@@ -285,9 +290,10 @@ SignalConnectorType signalConnector5(mType, std::string(SIGNAL_OFF_SCENE), &DoCo
 SignalConnectorType signalConnector6(mType, std::string(SIGNAL_ON_RELAYOUT), &DoConnectSignal);
 SignalConnectorType signalConnector7(mType, std::string(SIGNAL_TOUCHED), &DoConnectSignal);
 SignalConnectorType signalConnector8(mType, std::string(SIGNAL_VISIBILITY_CHANGED), &DoConnectSignal);
-SignalConnectorType signalConnector9(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &DoConnectSignal);
-SignalConnectorType signalConnector10(mType, std::string(SIGNAL_CHILD_ADDED), &DoConnectSignal);
-SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_REMOVED), &DoConnectSignal);
+SignalConnectorType signalConnector9(mType, std::string(SIGNAL_INHERITED_VISIBILITY_CHANGED), &DoConnectSignal);
+SignalConnectorType signalConnector10(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &DoConnectSignal);
+SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_ADDED), &DoConnectSignal);
+SignalConnectorType signalConnector12(mType, std::string(SIGNAL_CHILD_REMOVED), &DoConnectSignal);
 
 TypeAction a1(mType, std::string(ACTION_SHOW), &DoAction);
 TypeAction a2(mType, std::string(ACTION_HIDE), &DoAction);
@@ -1023,6 +1029,11 @@ void Actor::EmitVisibilityChangedSignal(bool visible, DevelActor::VisibilityChan
   EmitSignal(*this, mVisibilityChangedSignal, visible, type);
 }
 
+void Actor::EmitInheritedVisibilityChangedSignal(bool visible)
+{
+  EmitSignal(*this, mInheritedVisibilityChangedSignal, visible);
+}
+
 void Actor::EmitLayoutDirectionChangedSignal(LayoutDirection::Type type)
 {
   EmitSignal(*this, mLayoutDirectionChangedSignal, type);
@@ -1078,6 +1089,7 @@ Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
   mOffSceneSignal(),
   mOnRelayoutSignal(),
   mVisibilityChangedSignal(),
+  mInheritedVisibilityChangedSignal(),
   mLayoutDirectionChangedSignal(),
   mHitTestResultSignal(),
   mTargetOrientation(Quaternion::IDENTITY),
@@ -1488,6 +1500,8 @@ void Actor::LowerBelow(Internal::Actor& target)
 
 void Actor::SetParent(ActorParent* parent, bool notify)
 {
+  bool emitInheritedVisible = false;
+  bool visiblility = true;
   if(parent)
   {
     DALI_ASSERT_ALWAYS(!mParent && "Actor cannot have 2 parents");
@@ -1501,6 +1515,14 @@ void Actor::SetParent(ActorParent* parent, bool notify)
     {
       // Instruct each actor to create a corresponding node in the scene graph
       ConnectToScene(parentActor->GetHierarchyDepth(), parentActor->GetLayer3DParentCount(), notify);
+
+      Actor* actor         = this;
+      emitInheritedVisible = true;
+      while(emitInheritedVisible && actor)
+      {
+        emitInheritedVisible &= actor->GetProperty(Dali::Actor::Property::VISIBLE).Get<bool>();
+        actor = actor->GetParent();
+      }
     }
 
     // Resolve the name and index for the child properties if any
@@ -1510,6 +1532,19 @@ void Actor::SetParent(ActorParent* parent, bool notify)
   {
     DALI_ASSERT_ALWAYS(mParent != nullptr && "Actor should have a parent");
 
+    if(!EventThreadServices::IsShuttingDown() && // Don't emit signals or send messages during Core destruction
+       OnScene())
+    {
+      Actor* actor         = this;
+      emitInheritedVisible = true;
+      while(emitInheritedVisible && actor)
+      {
+        emitInheritedVisible &= actor->GetProperty(Dali::Actor::Property::VISIBLE).Get<bool>();
+        actor = actor->GetParent();
+      }
+      visiblility = false;
+    }
+
     mParent = nullptr;
 
     if(!EventThreadServices::IsShuttingDown() && // Don't emit signals or send messages during Core destruction
@@ -1524,6 +1559,11 @@ void Actor::SetParent(ActorParent* parent, bool notify)
 
     mScene = nullptr;
   }
+
+  if(emitInheritedVisible)
+  {
+    EmitInheritedVisibilityChangedSignalRecursively(visiblility);
+  }
 }
 
 Rect<> Actor::CalculateScreenExtents() const
@@ -1691,10 +1731,33 @@ void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage)
       RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
     }
 
+    Actor* actor = this->GetParent();
+    bool emitInheritedVisible = OnScene();
+    while(emitInheritedVisible && actor)
+    {
+      emitInheritedVisible &= actor->GetProperty(Dali::Actor::Property::VISIBLE).Get<bool>();
+      actor = actor->GetParent();
+    }
+
     mVisible = visible;
 
     // Emit the signal on this actor and all its children
     mParentImpl.EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::SELF);
+    if(emitInheritedVisible)
+    {
+      EmitInheritedVisibilityChangedSignalRecursively(visible);
+    }
+  }
+}
+
+void Actor::EmitInheritedVisibilityChangedSignalRecursively(bool visible)
+{
+  ActorContainer inheritedVisibilityChangedList;
+  mParentImpl.InheritVisibilityRecursively(inheritedVisibilityChangedList);
+  // Notify applications about the newly connected actors.
+  for(const auto& actor : inheritedVisibilityChangedList)
+  {
+    actor->EmitInheritedVisibilityChangedSignal(visible);
   }
 }
 
index cd71a09c7ebdc418b9c797aa77a0183aee328254..9c9985c868b78428aa216bcc92ee43da43f2e9c9 100644 (file)
@@ -1430,6 +1430,12 @@ public:
    */
   void EmitVisibilityChangedSignal(bool visible, DevelActor::VisibilityChange::Type type);
 
+  /**
+   * @brief Emits the inherited visibility change signal for this actor.
+   * @param[in] visible Whether the actor has become visible or not considering all parent Actors.
+   */
+  void EmitInheritedVisibilityChangedSignal(bool visible);
+
   /**
    * @brief Emits the layout direction change signal for this actor and all its children.
    * @param[in] type Whether the actor's layout direction property has changed or a parent's.
@@ -1525,6 +1531,14 @@ public:
     return mVisibilityChangedSignal;
   }
 
+  /**
+   * @copydoc DevelActor::InheritedVisibilityChangedSignal
+   */
+  Dali::Actor::InheritedVisibilityChangedSignalType& InheritedVisibilityChangedSignal()
+  {
+    return mInheritedVisibilityChangedSignal;
+  }
+
   /**
    * @copydoc LayoutDirectionChangedSignal
    */
@@ -1872,6 +1886,13 @@ private:
    */
   void SetVisibleInternal(bool visible, SendMessage::Type sendMessage);
 
+  /**
+   * Emits the visibility flag of an actor.
+   * @param[in] visible The new visibility flag.
+   * @param[in] sendMessage Whether to send a message to the update thread or not.
+   */
+  void EmitInheritedVisibilityChangedSignalRecursively(bool visible);
+
   /**
    * @copydoc ActorParent::SetSiblingOrderOfChild
    */
@@ -1944,17 +1965,18 @@ protected:
   ActorGestureData*  mGestureData;  ///< Optional Gesture data. Only created when actor requires gestures
 
   // Signals
-  Dali::Actor::TouchEventSignalType             mInterceptTouchedSignal;
-  Dali::Actor::TouchEventSignalType             mTouchedSignal;
-  Dali::Actor::HoverSignalType                  mHoveredSignal;
-  Dali::Actor::WheelEventSignalType             mInterceptWheelSignal;
-  Dali::Actor::WheelEventSignalType             mWheelEventSignal;
-  Dali::Actor::OnSceneSignalType                mOnSceneSignal;
-  Dali::Actor::OffSceneSignalType               mOffSceneSignal;
-  Dali::Actor::OnRelayoutSignalType             mOnRelayoutSignal;
-  DevelActor::VisibilityChangedSignalType       mVisibilityChangedSignal;
-  Dali::Actor::LayoutDirectionChangedSignalType mLayoutDirectionChangedSignal;
-  Dali::Actor::TouchEventSignalType             mHitTestResultSignal;
+  Dali::Actor::TouchEventSignalType                 mInterceptTouchedSignal;
+  Dali::Actor::TouchEventSignalType                 mTouchedSignal;
+  Dali::Actor::HoverSignalType                      mHoveredSignal;
+  Dali::Actor::WheelEventSignalType                 mInterceptWheelSignal;
+  Dali::Actor::WheelEventSignalType                 mWheelEventSignal;
+  Dali::Actor::OnSceneSignalType                    mOnSceneSignal;
+  Dali::Actor::OffSceneSignalType                   mOffSceneSignal;
+  Dali::Actor::OnRelayoutSignalType                 mOnRelayoutSignal;
+  DevelActor::VisibilityChangedSignalType           mVisibilityChangedSignal;
+  Dali::Actor::InheritedVisibilityChangedSignalType mInheritedVisibilityChangedSignal;
+  Dali::Actor::LayoutDirectionChangedSignalType     mLayoutDirectionChangedSignal;
+  Dali::Actor::TouchEventSignalType                 mHitTestResultSignal;
 
   Quaternion mTargetOrientation; ///< Event-side storage for orientation
   Vector4    mTargetColor;       ///< Event-side storage for color
index 6b535b798dd3483a04b438169034be5dd4d61dba..8a03b025bcc899beea18bb642fa01bc23458616e 100644 (file)
@@ -548,6 +548,22 @@ void ActorParentImpl::EmitVisibilityChangedSignalRecursively(
   }
 }
 
+void ActorParentImpl::InheritVisibilityRecursively(ActorContainer& inheritedVisibilityChangedList)
+{
+  inheritedVisibilityChangedList.push_back(ActorPtr(&mOwner));
+
+  if(mChildren)
+  {
+    for(const auto& child : *mChildren)
+    {
+      if(child->GetProperty(Dali::Actor::Property::VISIBLE).Get<bool>())
+      {
+        child->mParentImpl.InheritVisibilityRecursively(inheritedVisibilityChangedList);
+      }
+    }
+  }
+}
+
 void ActorParentImpl::EmitChildAddedSignal(Actor& child)
 {
   EmitSignal(child, mChildAddedSignal);
index c284953d8a0b44174688b12e9863e5fd8d694e38..c7fedb26f532628a9e51a41e29519b0da60d7e43 100644 (file)
@@ -239,6 +239,13 @@ public:
   void EmitVisibilityChangedSignalRecursively(bool                               visible,
                                               DevelActor::VisibilityChange::Type type);
 
+  /**
+   * @brief Propagates the actor's visibility on the actor tree, and retreives actor list to emit inherited-visibility-changed-signal.
+   *
+   * @param[out] inheritedVisibilityChangedList On return, the list of actors whose inherited visibility is changed.
+   */
+  void InheritVisibilityRecursively(ActorContainer& inheritedVisibilityChangedList);
+
 private:
   /**
    * @brief Emits the ChildAdded signal for this actor
index 0c1b911cdcc9938a86887fb03dfa2d74704e3695..cb5b8e7277acf40f5f6da447637dfa6052cfbe01 100644 (file)
@@ -259,6 +259,11 @@ Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
   return GetImplementation(*this).LayoutDirectionChangedSignal();
 }
 
+Actor::InheritedVisibilityChangedSignalType& Actor::InheritedVisibilityChangedSignal()
+{
+  return GetImplementation(*this).InheritedVisibilityChangedSignal();
+}
+
 Actor::Actor(Internal::Actor* internal)
 : Handle(internal)
 {
index 0a58015de268e8b27e51e13f595566ea718742ee..c12c6bc0880da7bc9c680e2eb246eba44ff73a98 100644 (file)
@@ -218,14 +218,16 @@ using Padding = Rect<float>; ///< Padding definition @SINCE_1_0.0
  * @nosubgrouping
  *
  * Signals
- * | %Signal Name      | Method                       |
- * |-------------------|------------------------------|
- * | touched           | @ref TouchedSignal()         |
- * | hovered           | @ref HoveredSignal()         |
- * | wheelEvent        | @ref WheelEventSignal()      |
- * | onScene           | @ref OnSceneSignal()         |
- * | offScene          | @ref OffSceneSignal()        |
- * | onRelayout        | @ref OnRelayoutSignal()      |
+ * | %Signal Name               | Method                                  |
+ * |----------------------------|-----------------------------------------|
+ * | touched                    | @ref TouchedSignal()                    |
+ * | hovered                    | @ref HoveredSignal()                    |
+ * | wheelEvent                 | @ref WheelEventSignal()                 |
+ * | onScene                    | @ref OnSceneSignal()                    |
+ * | offScene                   | @ref OffSceneSignal()                   |
+ * | onRelayout                 | @ref OnRelayoutSignal()                 |
+ * | layoutDirectionChanged     | @ref LayoutDirectionChangedSignal()     |
+ * | inheritedVisibilityChanged | @ref InheritedVisibilityChangedSignal() |
  *
  * Actions
  * | %Action Name      | %Actor method called         |
@@ -743,13 +745,14 @@ public:
 
   // Typedefs
 
-  using TouchEventSignalType             = Signal<bool(Actor, const TouchEvent&)>;     ///< Touch signal type @SINCE_1_1.37
-  using HoverSignalType                  = Signal<bool(Actor, const HoverEvent&)>;     ///< Hover signal type @SINCE_1_0.0
-  using WheelEventSignalType             = Signal<bool(Actor, const WheelEvent&)>;     ///< Wheel signal type @SINCE_1_0.0
-  using OnSceneSignalType                = Signal<void(Actor)>;                        ///< Scene connection signal type @SINCE_1_9.24
-  using OffSceneSignalType               = Signal<void(Actor)>;                        ///< Scene disconnection signal type @SINCE_1_9.24
-  using OnRelayoutSignalType             = Signal<void(Actor)>;                        ///< Called when the actor is relaid out @SINCE_1_0.0
-  using LayoutDirectionChangedSignalType = Signal<void(Actor, LayoutDirection::Type)>; ///< Layout direction changes signal type. @SINCE_1_2.60
+  using TouchEventSignalType                 = Signal<bool(Actor, const TouchEvent&)>;     ///< Touch signal type @SINCE_1_1.37
+  using HoverSignalType                      = Signal<bool(Actor, const HoverEvent&)>;     ///< Hover signal type @SINCE_1_0.0
+  using WheelEventSignalType                 = Signal<bool(Actor, const WheelEvent&)>;     ///< Wheel signal type @SINCE_1_0.0
+  using OnSceneSignalType                    = Signal<void(Actor)>;                        ///< Scene connection signal type @SINCE_1_9.24
+  using OffSceneSignalType                   = Signal<void(Actor)>;                        ///< Scene disconnection signal type @SINCE_1_9.24
+  using OnRelayoutSignalType                 = Signal<void(Actor)>;                        ///< Called when the actor is relaid out @SINCE_1_0.0
+  using LayoutDirectionChangedSignalType     = Signal<void(Actor, LayoutDirection::Type)>; ///< Layout direction changes signal type. @SINCE_1_2.60
+  using InheritedVisibilityChangedSignalType = Signal<void(Actor, bool)>;                  ///< Signal type of InheritedVisibilityChangedSignalType. @SINCE_2_3.22
 
   // Creation
 
@@ -1288,6 +1291,30 @@ public: // Signals
    */
   LayoutDirectionChangedSignalType& LayoutDirectionChangedSignal();
 
+  /**
+   * @brief This signal is emitted when the visible property of this actor or any of its parents (right up to the root layer) changes.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName( Actor actor, bool visible );
+   * @endcode
+   * actor: The actor whose inherited visibility has changed.
+   * visible: This is true if this actor's inherited VISIBLE property is true.
+   * If it is true, it denotes one of the 2 cases.
+   * One is VISIBLE property of this actor or only one of the parent actors were originally false and it becomes true now.
+   * Another is this actor is connected on Scene now with that the VISIBLE property of this actor and all of its parent were true.
+   * If it is false, it also denotes one of the 2 cases.
+   * One is that VISIBLE property of this actor and all of the parent actors were originally true but one of them becomes false now.
+   * Another is VISIBLE property of this actor and all of the parent actors are true and this actor is disconnected from the Scene now.
+   *
+   * @SINCE_2_3.22
+   * @return The signal to connect to
+   * @pre The Actor has been initialized.
+   * @note This signal is NOT emitted if the actor becomes transparent (or the reverse).
+   * @note For reference, an actor is only shown if it and it's parents (up to the root actor) are also visible, are not transparent, and this actor has a non-zero size.
+   */
+  DALI_CORE_API InheritedVisibilityChangedSignalType& InheritedVisibilityChangedSignal();
+
 public: // Not intended for application developers
   /// @cond internal
   /**