Added ChildAdded and ChildRemoved signals to Actor 35/175935/4
authorDavid Steele <david.steele@samsung.com>
Fri, 13 Apr 2018 11:37:23 +0000 (12:37 +0100)
committerDavid Steele <david.steele@samsung.com>
Mon, 23 Apr 2018 13:33:24 +0000 (14:33 +0100)
Actor currently has OnChildAdded and OnChildRemoved to inform derived classes when
children are added to or removed from the actor. However, there is currently no
mechanism for another object to find out this information. Added signals so that
other objects can listen for this state change.

Note, these signals are sent after the callbacks; if the derived classes choose
to do something odd as a result of the callback, such as reparent the child, the
signal may not reflect truth in the derived parent.

Change-Id: I348bf0a3314baaa6f7b1a1c939e3ce9821f3485a
Signed-off-by: David Steele <david.steele@samsung.com>
automated-tests/src/dali/utc-Dali-Actor.cpp
dali/devel-api/actors/actor-devel.cpp
dali/devel-api/actors/actor-devel.h
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h

index 9a6f34f..ebdf66e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 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.
@@ -231,6 +231,21 @@ struct VisibilityChangedFunctor
   VisibilityChangedFunctorData& data;
 };
 
+
+struct VisibilityChangedVoidFunctor
+{
+  VisibilityChangedVoidFunctor(bool& signalCalled)
+  : mSignalCalled( signalCalled )
+  { }
+
+  void operator()()
+  {
+    mSignalCalled  = true;
+  }
+
+  bool& mSignalCalled;
+};
+
 } // anonymous namespace
 
 
@@ -6444,6 +6459,38 @@ int utcDaliActorVisibilityChangeSignalAfterAnimation(void)
 }
 
 
+int utcDaliActorVisibilityChangeSignalByName(void)
+{
+  TestApplication application;
+  tet_infoline( "Check that the visibility change signal is called when the visibility changes for the actor itself" );
+
+  Actor actor = Actor::New();
+
+  bool signalCalled=false;
+  actor.ConnectSignal( &application, "visibilityChanged", VisibilityChangedVoidFunctor(signalCalled) );
+  DALI_TEST_EQUALS( signalCalled, false, TEST_LOCATION );
+  actor.SetVisible( false );
+  DALI_TEST_EQUALS( signalCalled, true, TEST_LOCATION );
+
+  tet_infoline( "Ensure functor is not called if we attempt to change the visibility to what it already is at" );
+  signalCalled = false;
+  actor.SetVisible( false );
+  DALI_TEST_EQUALS( signalCalled, false, TEST_LOCATION );
+
+  tet_infoline( "Change the visibility using properties, ensure called" );
+  actor.SetProperty( Actor::Property::VISIBLE, true );
+  DALI_TEST_EQUALS( signalCalled, true, TEST_LOCATION );
+
+  tet_infoline( "Set the visibility to current using properties, ensure not called" );
+  signalCalled = false;
+
+  actor.SetProperty( Actor::Property::VISIBLE, true );
+  DALI_TEST_EQUALS( signalCalled, false, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
 static void LayoutDirectionChanged( Actor actor, LayoutDirection::Type type )
 {
   gLayoutDirectionType = type;
@@ -6536,3 +6583,343 @@ int UtcDaliActorLayoutDirectionProperty(void)
 
   END_TEST;
 }
+
+
+struct LayoutDirectionFunctor
+{
+  LayoutDirectionFunctor(bool& signalCalled)
+  : mSignalCalled( signalCalled )
+  {
+  }
+
+  LayoutDirectionFunctor(const LayoutDirectionFunctor& rhs)
+  : mSignalCalled( rhs.mSignalCalled )
+  {
+  }
+
+  void operator()()
+  {
+    mSignalCalled = true;
+  }
+
+  bool& mSignalCalled;
+};
+
+int UtcDaliActorLayoutDirectionSignal(void)
+{
+  TestApplication application;
+  tet_infoline( "Check changing layout direction property sends a signal" );
+
+  Actor actor = Actor::New();
+  DALI_TEST_EQUALS( actor.GetProperty< int >( Actor::Property::LAYOUT_DIRECTION ), static_cast< int >( LayoutDirection::LEFT_TO_RIGHT ), TEST_LOCATION );
+  Stage::GetCurrent().Add( actor );
+  bool signalCalled = false;
+  LayoutDirectionFunctor layoutDirectionFunctor(signalCalled);
+
+  actor.ConnectSignal( &application, "layoutDirectionChanged", layoutDirectionFunctor );
+  DALI_TEST_EQUALS( signalCalled, false, TEST_LOCATION );
+
+  // Test that writing the same value doesn't send a signal
+  actor.SetProperty( Actor::Property::LAYOUT_DIRECTION, LayoutDirection::LEFT_TO_RIGHT );
+  DALI_TEST_EQUALS( signalCalled, false, TEST_LOCATION );
+
+  // Test that writing a different value sends the signal
+  signalCalled = false;
+  actor.SetProperty( Actor::Property::LAYOUT_DIRECTION, LayoutDirection::RIGHT_TO_LEFT );
+  DALI_TEST_EQUALS( signalCalled, true, TEST_LOCATION );
+
+  signalCalled = false;
+  actor.SetProperty( Actor::Property::LAYOUT_DIRECTION, LayoutDirection::RIGHT_TO_LEFT );
+  DALI_TEST_EQUALS( signalCalled, false, TEST_LOCATION );
+
+  END_TEST;
+}
+
+struct ChildAddedSignalCheck
+{
+  ChildAddedSignalCheck( bool& signalReceived, Actor& childHandle )
+  : mSignalReceived( signalReceived ),
+    mChildHandle( childHandle )
+  {
+  }
+
+  void operator() ( Actor childHandle )
+  {
+    mSignalReceived = true;
+    mChildHandle = childHandle;
+  }
+  void operator() ()
+  {
+    mSignalReceived = true;
+    mChildHandle = Actor();
+  }
+
+  bool& mSignalReceived;
+  Actor& mChildHandle;
+};
+
+int UtcDaliChildAddedSignalP1(void)
+{
+  TestApplication application;
+  auto stage = Stage::GetCurrent();
+
+  bool signalReceived=false;
+  Actor childActor;
+
+  ChildAddedSignalCheck signal( signalReceived, childActor );
+  DevelActor::ChildAddedSignal( stage.GetRootLayer() ).Connect( &application, signal );
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+
+  auto actorA = Actor::New();
+  stage.Add( actorA );
+  DALI_TEST_EQUALS( signalReceived, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( childActor, actorA, TEST_LOCATION );
+  signalReceived = false;
+
+  auto actorB = Actor::New();
+  stage.Add( actorB );
+  DALI_TEST_EQUALS( signalReceived, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( childActor, actorB, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliChildAddedSignalP2(void)
+{
+  TestApplication application;
+  auto stage = Stage::GetCurrent();
+
+  bool signalReceived=false;
+  Actor childActor;
+
+  ChildAddedSignalCheck signal( signalReceived, childActor );
+  tet_infoline( "Connect to childAdded signal by name" );
+
+  stage.GetRootLayer().ConnectSignal( &application, "childAdded", signal );
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+
+  auto actorA = Actor::New();
+  stage.Add( actorA );
+  DALI_TEST_EQUALS( signalReceived, true, TEST_LOCATION );
+
+  // Can't test which actor was added; signal signature is void() when connecting via name.
+  signalReceived = false;
+
+  auto actorB = Actor::New();
+  stage.Add( actorB );
+  DALI_TEST_EQUALS( signalReceived, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliChildAddedSignalN(void)
+{
+  TestApplication application;
+  auto stage = Stage::GetCurrent();
+
+  bool signalReceived=false;
+  Actor childActor;
+
+  ChildAddedSignalCheck signal( signalReceived, childActor );
+  DevelActor::ChildAddedSignal( stage.GetRootLayer() ).Connect( &application, signal );
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+
+  auto actorA = Actor::New();
+  stage.Add( actorA );
+  DALI_TEST_EQUALS( signalReceived, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( childActor, actorA, TEST_LOCATION );
+  signalReceived = false;
+
+  auto actorB = Actor::New();
+  actorA.Add( actorB );
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+  END_TEST;
+}
+
+
+struct ChildRemovedSignalCheck
+{
+  ChildRemovedSignalCheck( bool& signalReceived, Actor& childHandle )
+  : mSignalReceived( signalReceived ),
+    mChildHandle( childHandle )
+  {
+  }
+
+  void operator() ( Actor childHandle )
+  {
+    mSignalReceived = true;
+    mChildHandle = childHandle;
+  }
+
+  void operator() ()
+  {
+    mSignalReceived = true;
+  }
+
+  bool& mSignalReceived;
+  Actor& mChildHandle;
+};
+
+int UtcDaliChildRemovedSignalP1(void)
+{
+  TestApplication application;
+  auto stage = Stage::GetCurrent();
+
+  bool signalReceived=false;
+  Actor childActor;
+
+  ChildRemovedSignalCheck signal( signalReceived, childActor );
+  DevelActor::ChildRemovedSignal( stage.GetRootLayer() ).Connect( &application, signal );
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+
+  auto actorA = Actor::New();
+  stage.Add( actorA );
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+  DALI_TEST_CHECK( !childActor );
+
+  stage.Remove( actorA );
+  DALI_TEST_EQUALS( childActor, actorA, TEST_LOCATION );
+  DALI_TEST_EQUALS( signalReceived, true, TEST_LOCATION );
+
+  signalReceived = false;
+  auto actorB = Actor::New();
+  stage.Add( actorB );
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+
+  stage.Remove( actorB );
+  DALI_TEST_EQUALS( signalReceived, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( childActor, actorB, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliChildRemovedSignalP2(void)
+{
+  TestApplication application;
+  auto stage = Stage::GetCurrent();
+
+  bool signalReceived=false;
+  Actor childActor;
+
+  ChildAddedSignalCheck signal( signalReceived, childActor );
+  tet_infoline( "Connect to childRemoved signal by name" );
+
+  stage.GetRootLayer().ConnectSignal( &application, "childRemoved", signal );
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+
+  auto actorA = Actor::New();
+  stage.Add( actorA );
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+
+  stage.Remove( actorA );
+  DALI_TEST_EQUALS( signalReceived, true, TEST_LOCATION );
+
+  signalReceived = false;
+  auto actorB = Actor::New();
+  stage.Add( actorB );
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+
+  stage.Remove( actorB );
+  DALI_TEST_EQUALS( signalReceived, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliChildRemovedSignalN(void)
+{
+  TestApplication application;
+  auto stage = Stage::GetCurrent();
+
+  bool signalReceived=false;
+  Actor childActor;
+
+  ChildRemovedSignalCheck signal( signalReceived, childActor );
+  DevelActor::ChildRemovedSignal( stage.GetRootLayer() ).Connect( &application, signal );
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+
+  auto actorA = Actor::New();
+  stage.Add( actorA );
+
+  auto actorB = Actor::New();
+  actorA.Add( actorB );
+
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+  DALI_TEST_CHECK( ! childActor );
+
+  actorA.Remove( actorB );
+  DALI_TEST_EQUALS( signalReceived, false, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliChildMovedSignalP(void)
+{
+  TestApplication application;
+  auto stage = Stage::GetCurrent();
+
+  bool addedASignalReceived   = false;
+  bool removedASignalReceived = false;
+  bool addedBSignalReceived   = false;
+  bool removedBSignalReceived = false;
+  Actor childActor;
+
+  auto actorA = Actor::New();
+  auto actorB = Actor::New();
+  stage.Add( actorA );
+  stage.Add( actorB );
+
+  ChildAddedSignalCheck addedSignalA( addedASignalReceived, childActor );
+  ChildRemovedSignalCheck removedSignalA( removedASignalReceived, childActor );
+  ChildAddedSignalCheck addedSignalB( addedBSignalReceived, childActor );
+  ChildRemovedSignalCheck removedSignalB( removedBSignalReceived, childActor );
+
+  DevelActor::ChildAddedSignal( actorA ).Connect( &application, addedSignalA );
+  DevelActor::ChildRemovedSignal( actorA ).Connect( &application, removedSignalA );
+  DevelActor::ChildAddedSignal( actorB ).Connect( &application, addedSignalB );
+  DevelActor::ChildRemovedSignal( actorB ).Connect( &application, removedSignalB );
+
+  DALI_TEST_EQUALS( addedASignalReceived, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( removedASignalReceived, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( addedBSignalReceived, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( removedBSignalReceived, false, TEST_LOCATION );
+
+  // Create a child of A
+
+  auto child = Actor::New();
+  actorA.Add( child );
+
+  DALI_TEST_EQUALS( addedASignalReceived, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( removedASignalReceived, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( addedBSignalReceived, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( removedBSignalReceived, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( childActor, child, TEST_LOCATION );
+
+  // Move child to B:
+  addedASignalReceived   = false;
+  addedBSignalReceived   = false;
+  removedASignalReceived = false;
+  removedBSignalReceived = false;
+
+  actorB.Add( child ); // Expect this child to be re-parented
+  DALI_TEST_EQUALS( addedASignalReceived, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( removedASignalReceived, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( addedBSignalReceived, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( removedBSignalReceived, false, TEST_LOCATION );
+
+  // Move child back to A:
+  addedASignalReceived   = false;
+  addedBSignalReceived   = false;
+  removedASignalReceived = false;
+  removedBSignalReceived = false;
+
+  actorA.Add( child ); // Expect this child to be re-parented
+  DALI_TEST_EQUALS( addedASignalReceived, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( removedASignalReceived, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( addedBSignalReceived, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( removedBSignalReceived, true, TEST_LOCATION );
+
+
+  END_TEST;
+}
index eabcb3a..591130c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 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.
@@ -30,6 +30,18 @@ VisibilityChangedSignalType& VisibilityChangedSignal( Actor actor )
   return GetImplementation( actor ).VisibilityChangedSignal();
 }
 
+ChildChangedSignalType& ChildAddedSignal( Actor actor )
+{
+  return GetImplementation( actor ).ChildAddedSignal();
+}
+
+ChildChangedSignalType& ChildRemovedSignal( Actor actor )
+{
+  return GetImplementation( actor ).ChildRemovedSignal();
+}
+
+
+
 } // namespace DevelActor
 
 } // namespace Dali
index 254ca39..054fe3e 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_ACTOR_DEVEL_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 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.
@@ -152,6 +152,50 @@ typedef Signal< void ( Actor, bool, VisibilityChange::Type ) > VisibilityChanged
  */
 DALI_IMPORT_API VisibilityChangedSignalType& VisibilityChangedSignal( Actor actor );
 
+
+typedef Signal< void (Actor) > ChildChangedSignalType; ///< Called when the actor has a child added or removed
+
+/**
+ * @brief This signal is emitted when a child is added to this actor.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ *   void MyCallbackName( Actor child );
+ * @endcode
+ * child: The child that has been added.
+ *
+ * @note Use this signal with caution. Changing the parent of the actor
+ * within this callback is possible, but DALi will prevent further signals
+ * being sent.
+ *
+ * @return The signal to connect to
+ * @pre The Actor has been initialized
+ */
+DALI_IMPORT_API ChildChangedSignalType& ChildAddedSignal( Actor actor );
+
+/**
+ * @brief This signal is emitted when a child is removed from this actor.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ *   void MyCallbackName( Actor child );
+ * @endcode
+ * child: The child that has been removed.
+ *
+ * @note Use this signal with caution. Changing the parent of the actor
+ * within this callback is possible, but DALi will prevent further signals
+ * being sent.
+ *
+ * @note If the child actor is moved from one actor to another, then
+ * this signal will be emitted followed immediately by an
+ * ChildAddedSignal() on the new parent.
+ *
+ * @return The signal to connect to
+ * @pre The Actor has been initialized
+ */
+DALI_IMPORT_API ChildChangedSignalType& ChildRemovedSignal( Actor actor );
+
+
 } // namespace DevelActor
 
 } // namespace Dali
index ca9fb9b..5428e97 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 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.
@@ -224,6 +224,10 @@ const char* const SIGNAL_ON_STAGE = "onStage";
 const char* const SIGNAL_OFF_STAGE = "offStage";
 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
 const char* const SIGNAL_TOUCH = "touch";
+const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
+const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
+const char* const SIGNAL_CHILD_ADDED = "childAdded";
+const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
 
 // Actions
 
@@ -244,6 +248,10 @@ SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectS
 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
+SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
+SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
+SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
+SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
 
 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
@@ -473,7 +481,7 @@ void Actor::Add( Actor& child )
     // if we already have parent, unparent us first
     if( oldParent )
     {
-      oldParent->Remove( child ); // This causes OnChildRemove callback
+      oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
 
       // Old parent may need to readjust to missing child
       if( oldParent->RelayoutDependentOnChildren() )
@@ -493,6 +501,7 @@ void Actor::Add( Actor& child )
 
       // Notification for derived classes
       OnChildAdd( child );
+      EmitChildAddedSignal( child );
 
       InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
 
@@ -547,6 +556,7 @@ void Actor::Remove( Actor& child )
 
   // Notification for derived classes
   OnChildRemove( child );
+  EmitChildRemovedSignal( child );
 }
 
 void Actor::Unparent()
@@ -2005,6 +2015,24 @@ void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
   }
 }
 
+void Actor::EmitChildAddedSignal( Actor& child )
+{
+  if( ! mChildAddedSignal.Empty() )
+  {
+    Dali::Actor handle( &child );
+    mChildAddedSignal.Emit( handle );
+  }
+}
+
+void Actor::EmitChildRemovedSignal( Actor& child )
+{
+  if( ! mChildRemovedSignal.Empty() )
+  {
+    Dali::Actor handle( &child );
+    mChildRemovedSignal.Emit( handle );
+  }
+}
+
 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
 {
   return mTouchedSignal;
@@ -2050,6 +2078,16 @@ Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSign
   return mLayoutDirectionChangedSignal;
 }
 
+DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
+{
+  return mChildAddedSignal;
+}
+
+DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
+{
+  return mChildRemovedSignal;
+}
+
 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
 {
   bool connected( true );
@@ -2083,6 +2121,22 @@ bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tra
   {
     actor->TouchSignal().Connect( tracker, functor );
   }
+  else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
+  {
+    actor->VisibilityChangedSignal().Connect( tracker, functor );
+  }
+  else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
+  {
+    actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
+  }
+  else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
+  {
+    actor->ChildAddedSignal().Connect( tracker, functor );
+  }
+  else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
+  {
+    actor->ChildRemovedSignal().Connect( tracker, functor );
+  }
   else
   {
     // signalName does not match any signal
@@ -2110,6 +2164,8 @@ Actor::Actor( DerivedType derivedType )
   mOnRelayoutSignal(),
   mVisibilityChangedSignal(),
   mLayoutDirectionChangedSignal(),
+  mChildAddedSignal(),
+  mChildRemovedSignal(),
   mTargetOrientation( Quaternion::IDENTITY ),
   mTargetColor( Color::WHITE ),
   mTargetSize( Vector3::ZERO ),
index b45b8a6..b9734c7 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_ACTOR_H
 
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 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.
@@ -1425,6 +1425,18 @@ public:
   void EmitLayoutDirectionChangedSignal( LayoutDirection::Type type );
 
   /**
+   * @brief Emits the ChildAdded signal for this actor
+   * @param[in] child The child actor that has been added
+   */
+  void EmitChildAddedSignal( Actor& child );
+
+  /**
+   * @brief Emits the ChildRemoved signal for this actor
+   * @param[in] child The child actor that has been removed
+   */
+  void EmitChildRemovedSignal( Actor& child );
+
+  /**
    * @copydoc Dali::Actor::TouchedSignal()
    */
   Dali::Actor::TouchSignalType& TouchedSignal();
@@ -1470,6 +1482,16 @@ public:
   Dali::Actor::LayoutDirectionChangedSignalType& LayoutDirectionChangedSignal();
 
   /**
+   * @copydoc DevelActor::ChildAddedSignal
+   */
+  DevelActor::ChildChangedSignalType& ChildAddedSignal();
+
+  /**
+   * @copydoc DevelActor::ChildRemovedSignal
+   */
+  DevelActor::ChildChangedSignalType& ChildRemovedSignal();
+
+  /**
    * Connects a callback function with the object's signals.
    * @param[in] object The object providing the signal.
    * @param[in] tracker Used to disconnect the signal.
@@ -1733,11 +1755,9 @@ private:
     };
   };
 
-  // Undefined
-  Actor();
-
-  // Undefined
-  Actor( const Actor& );
+  // Remove default constructor and copy constructor
+  Actor()=delete;
+  Actor( const Actor& )=delete;
 
   // Undefined
   Actor& operator=( const Actor& rhs );
@@ -1964,6 +1984,8 @@ protected:
   Dali::Actor::OnRelayoutSignalType        mOnRelayoutSignal;
   DevelActor::VisibilityChangedSignalType  mVisibilityChangedSignal;
   Dali::Actor::LayoutDirectionChangedSignalType  mLayoutDirectionChangedSignal;
+  DevelActor::ChildChangedSignalType       mChildAddedSignal;
+  DevelActor::ChildChangedSignalType       mChildRemovedSignal;
 
   Quaternion      mTargetOrientation; ///< Event-side storage for orientation
   Vector4         mTargetColor;       ///< Event-side storage for color