From 495b835ffa8550a23f11bb2140147c9c8846a3af Mon Sep 17 00:00:00 2001 From: Seungho Baek Date: Mon, 22 Apr 2024 16:43:13 +0900 Subject: [PATCH] Add Inherited Visibility Changed signal Change-Id: I1d592e6a5c9f17b77b8ee9f8828586f424985699 Signed-off-by: Seungho Baek --- automated-tests/src/dali/utc-Dali-Actor.cpp | 328 +++++++++++++++++++++++ dali/internal/event/actors/actor-impl.cpp | 89 +++++- dali/internal/event/actors/actor-impl.h | 44 ++- dali/internal/event/actors/actor-parent-impl.cpp | 16 ++ dali/internal/event/actors/actor-parent-impl.h | 7 + dali/public-api/actors/actor.cpp | 5 + dali/public-api/actors/actor.h | 57 ++-- 7 files changed, 507 insertions(+), 39 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-Actor.cpp b/automated-tests/src/dali/utc-Dali-Actor.cpp index f08e19d..a245c5c 100644 --- a/automated-tests/src/dali/utc-Dali-Actor.cpp +++ b/automated-tests/src/dali/utc-Dali-Actor.cpp @@ -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; diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp index 2aafb89..54ac552 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -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(); + 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(); + 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(); + 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); } } diff --git a/dali/internal/event/actors/actor-impl.h b/dali/internal/event/actors/actor-impl.h index cd71a09..9c9985c 100644 --- a/dali/internal/event/actors/actor-impl.h +++ b/dali/internal/event/actors/actor-impl.h @@ -1431,6 +1431,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. */ @@ -1526,6 +1532,14 @@ public: } /** + * @copydoc DevelActor::InheritedVisibilityChangedSignal + */ + Dali::Actor::InheritedVisibilityChangedSignalType& InheritedVisibilityChangedSignal() + { + return mInheritedVisibilityChangedSignal; + } + + /** * @copydoc LayoutDirectionChangedSignal */ Dali::Actor::LayoutDirectionChangedSignalType& LayoutDirectionChangedSignal() @@ -1873,6 +1887,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 */ void SetSiblingOrderOfChild(Actor& child, uint32_t order) override; @@ -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 diff --git a/dali/internal/event/actors/actor-parent-impl.cpp b/dali/internal/event/actors/actor-parent-impl.cpp index 6b535b7..8a03b02 100644 --- a/dali/internal/event/actors/actor-parent-impl.cpp +++ b/dali/internal/event/actors/actor-parent-impl.cpp @@ -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()) + { + child->mParentImpl.InheritVisibilityRecursively(inheritedVisibilityChangedList); + } + } + } +} + void ActorParentImpl::EmitChildAddedSignal(Actor& child) { EmitSignal(child, mChildAddedSignal); diff --git a/dali/internal/event/actors/actor-parent-impl.h b/dali/internal/event/actors/actor-parent-impl.h index c284953..c7fedb2 100644 --- a/dali/internal/event/actors/actor-parent-impl.h +++ b/dali/internal/event/actors/actor-parent-impl.h @@ -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 diff --git a/dali/public-api/actors/actor.cpp b/dali/public-api/actors/actor.cpp index 0c1b911..cb5b8e7 100644 --- a/dali/public-api/actors/actor.cpp +++ b/dali/public-api/actors/actor.cpp @@ -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) { diff --git a/dali/public-api/actors/actor.h b/dali/public-api/actors/actor.h index 0a58015..c12c6bc 100644 --- a/dali/public-api/actors/actor.h +++ b/dali/public-api/actors/actor.h @@ -218,14 +218,16 @@ using Padding = Rect; ///< 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; ///< Touch signal type @SINCE_1_1.37 - using HoverSignalType = Signal; ///< Hover signal type @SINCE_1_0.0 - using WheelEventSignalType = Signal; ///< Wheel signal type @SINCE_1_0.0 - using OnSceneSignalType = Signal; ///< Scene connection signal type @SINCE_1_9.24 - using OffSceneSignalType = Signal; ///< Scene disconnection signal type @SINCE_1_9.24 - using OnRelayoutSignalType = Signal; ///< Called when the actor is relaid out @SINCE_1_0.0 - using LayoutDirectionChangedSignalType = Signal; ///< Layout direction changes signal type. @SINCE_1_2.60 + using TouchEventSignalType = Signal; ///< Touch signal type @SINCE_1_1.37 + using HoverSignalType = Signal; ///< Hover signal type @SINCE_1_0.0 + using WheelEventSignalType = Signal; ///< Wheel signal type @SINCE_1_0.0 + using OnSceneSignalType = Signal; ///< Scene connection signal type @SINCE_1_9.24 + using OffSceneSignalType = Signal; ///< Scene disconnection signal type @SINCE_1_9.24 + using OnRelayoutSignalType = Signal; ///< Called when the actor is relaid out @SINCE_1_0.0 + using LayoutDirectionChangedSignalType = Signal; ///< Layout direction changes signal type. @SINCE_1_2.60 + using InheritedVisibilityChangedSignalType = Signal; ///< 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 /** -- 2.7.4