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)
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;
// 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
{
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);
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);
EmitSignal(*this, mVisibilityChangedSignal, visible, type);
}
+void Actor::EmitInheritedVisibilityChangedSignal(bool visible)
+{
+ EmitSignal(*this, mInheritedVisibilityChangedSignal, visible);
+}
+
void Actor::EmitLayoutDirectionChangedSignal(LayoutDirection::Type type)
{
EmitSignal(*this, mLayoutDirectionChangedSignal, type);
mOffSceneSignal(),
mOnRelayoutSignal(),
mVisibilityChangedSignal(),
+ mInheritedVisibilityChangedSignal(),
mLayoutDirectionChangedSignal(),
mHitTestResultSignal(),
mTargetOrientation(Quaternion::IDENTITY),
void Actor::SetParent(ActorParent* parent, bool notify)
{
+ bool emitInheritedVisible = false;
+ bool visiblility = true;
if(parent)
{
DALI_ASSERT_ALWAYS(!mParent && "Actor cannot have 2 parents");
{
// 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
{
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
mScene = nullptr;
}
+
+ if(emitInheritedVisible)
+ {
+ EmitInheritedVisibilityChangedSignalRecursively(visiblility);
+ }
}
Rect<> Actor::CalculateScreenExtents() const
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);
}
}
* @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 |
// 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
*/
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
/**