Add Layout complex animation. 74/190274/15
authorAnton Obzhirov <a.obzhirov@samsung.com>
Mon, 17 Sep 2018 12:21:39 +0000 (13:21 +0100)
committerAnton Obzhirov <a.obzhirov@samsung.com>
Mon, 22 Oct 2018 15:35:31 +0000 (16:35 +0100)
Change-Id: I34a0fa03030b3e897f418982ea7b54eb8ea0e418

22 files changed:
CMakeLists.txt
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/utc-Dali-LayoutingAnimation.cpp [new file with mode: 0644]
dali-toolkit/devel-api/file.list
dali-toolkit/devel-api/layouting/layout-controller.cpp
dali-toolkit/devel-api/layouting/layout-controller.h
dali-toolkit/devel-api/layouting/layout-group-impl.cpp
dali-toolkit/devel-api/layouting/layout-group-impl.h
dali-toolkit/devel-api/layouting/layout-item-impl.cpp
dali-toolkit/devel-api/layouting/layout-item-impl.h
dali-toolkit/devel-api/layouting/layout-item.cpp
dali-toolkit/devel-api/layouting/layout-item.h
dali-toolkit/devel-api/layouting/layout-transition-data.cpp [new file with mode: 0644]
dali-toolkit/devel-api/layouting/layout-transition-data.h [new file with mode: 0644]
dali-toolkit/internal/controls/control/control-data-impl.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/layouting/layout-controller-impl.cpp
dali-toolkit/internal/layouting/layout-controller-impl.h
dali-toolkit/internal/layouting/layout-item-data-impl.cpp
dali-toolkit/internal/layouting/layout-item-data-impl.h
dali-toolkit/internal/layouting/layout-transition-data-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/layouting/layout-transition-data-impl.h [new file with mode: 0644]

index 931b3e6..9114e20 100755 (executable)
@@ -104,6 +104,7 @@ SET( SOURCES ${SOURCES}
    ${internal_src_dir}/layouting/layout-group-data-impl.cpp\r
    ${internal_src_dir}/layouting/layout-controller-impl.cpp\r
    ${internal_src_dir}/layouting/layout-controller-debug.cpp\r
+   ${internal_src_dir}/layouting/layout-transition-data-impl.cpp\r
    ${internal_src_dir}/visuals/animated-image/animated-image-visual.cpp\r
    ${internal_src_dir}/visuals/animated-image/image-cache.cpp\r
    ${internal_src_dir}/visuals/animated-image/fixed-image-cache.cpp\r
index 369f9b0..6f1b55f 100755 (executable)
@@ -27,6 +27,7 @@ SET(TC_SOURCES
   utc-Dali-JsonParser.cpp
   utc-Dali-KeyInputFocusManager.cpp
   utc-Dali-Layouting.cpp
+  utc-Dali-LayoutingAnimation.cpp
   utc-Dali-LayoutingResizePolicy.cpp
   utc-Dali-LayoutingNesting.cpp
   utc-Dali-PageTurnView.cpp
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-LayoutingAnimation.cpp b/automated-tests/src/dali-toolkit/utc-Dali-LayoutingAnimation.cpp
new file mode 100644 (file)
index 0000000..ead839d
--- /dev/null
@@ -0,0 +1,1211 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+#include <dali-toolkit-test-suite-utils.h>
+#include <toolkit-event-thread-callback.h>
+
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/devel-api/layouting/absolute-layout.h>
+#include <dali-toolkit/devel-api/layouting/grid.h>
+#include <dali-toolkit/devel-api/layouting/linear-layout.h>
+#include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+
+#include <../custom-layout.h>
+
+#include <layout-utils.h>
+
+using namespace Dali;
+using namespace Toolkit;
+
+void utc_dali_toolkit_layouting_animation_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_toolkit_layouting_animation_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+// Functor to test whether a Finish signal is emitted
+struct LayoutTransitionFinishCheck
+{
+  LayoutTransitionFinishCheck( bool& signalReceived )
+  : mSignalReceived( signalReceived )
+  {
+  }
+
+  void operator()( LayoutTransitionData::LayoutTransitionType type, LayoutTransitionData& layoutTransitionData )
+  {
+    mSignalReceived = true;
+  }
+
+  void Reset()
+  {
+    mSignalReceived = false;
+  }
+
+  void CheckSignalReceived()
+  {
+    if (!mSignalReceived)
+    {
+      tet_printf("Expected Finish signal was not received\n");
+      tet_result(TET_FAIL);
+    }
+    else
+    {
+      tet_result(TET_PASS);
+    }
+  }
+
+  void CheckSignalNotReceived()
+  {
+    if (mSignalReceived)
+    {
+      tet_printf("Unexpected Finish signal was received\n");
+      tet_result(TET_FAIL);
+    }
+    else
+    {
+      tet_result(TET_PASS);
+    }
+  }
+
+  bool& mSignalReceived; // owned by individual tests
+};
+
+} // anon namespace
+
+int UtcDaliLayouting_LayoutTransitionDataConstructorP(void)
+{
+  TestApplication application;
+
+  LayoutTransitionData layoutTransitionData;
+
+  DALI_TEST_CHECK( !layoutTransitionData );
+  END_TEST;
+}
+
+int UtcDaliLayouting_LayoutTransitionDataNewP(void)
+{
+  TestApplication application;
+
+  LayoutTransitionData layoutTransitionData = LayoutTransitionData::New();
+
+  DALI_TEST_CHECK(layoutTransitionData);
+  END_TEST;
+}
+
+int UtcDaliLayouting_LayoutTransitionDataDownCastP(void)
+{
+  TestApplication application;
+
+  LayoutTransitionData layoutTransitionData = LayoutTransitionData::New();
+  BaseHandle object(layoutTransitionData);
+
+  LayoutTransitionData layoutTransitionData2 = LayoutTransitionData::DownCast(object);
+  DALI_TEST_CHECK(layoutTransitionData2);
+
+  LayoutTransitionData layoutTransitionData3 = DownCast< LayoutTransitionData >(object);
+  DALI_TEST_CHECK(layoutTransitionData2);
+  END_TEST;
+}
+
+int UtcDaliLayouting_LayoutTransitionDataDownCastN(void)
+{
+  TestApplication application;
+
+  BaseHandle unInitializedObject;
+
+  LayoutTransitionData layoutTransitionData1 = LayoutTransitionData::DownCast( unInitializedObject );
+  DALI_TEST_CHECK( !layoutTransitionData1 );
+
+  LayoutTransitionData layoutTransitionData2 = DownCast< LayoutTransitionData >( unInitializedObject );
+  DALI_TEST_CHECK( !layoutTransitionData2 );
+  END_TEST;
+}
+
+int UtcDaliLayouting_LayoutTransitionDataSetGetTransition(void)
+{
+  TestApplication application;
+
+  auto layout = LinearLayout::New();
+  auto layoutTransitionData = LayoutTransitionData::New();
+
+  layout.SetTransitionData( LayoutTransitionData::ON_OWNER_SET, layoutTransitionData );
+  DALI_TEST_CHECK( layout.GetTransitionData( LayoutTransitionData::ON_OWNER_SET ) == layoutTransitionData );
+  DALI_TEST_CHECK( layout.GetTransitionData( LayoutTransitionData::ON_CHILD_ADD ) == LayoutTransitionData() );
+  DALI_TEST_CHECK( layout.GetTransitionData( LayoutTransitionData::ON_CHILD_REMOVE ) == LayoutTransitionData() );
+
+  layout.SetTransitionData( LayoutTransitionData::ON_OWNER_SET, LayoutTransitionData() );
+  layout.SetTransitionData( LayoutTransitionData::ON_CHILD_ADD, layoutTransitionData );
+  DALI_TEST_CHECK( layout.GetTransitionData( LayoutTransitionData::ON_OWNER_SET ) == LayoutTransitionData() );
+  DALI_TEST_CHECK( layout.GetTransitionData( LayoutTransitionData::ON_CHILD_ADD ) == layoutTransitionData );
+  DALI_TEST_CHECK( layout.GetTransitionData( LayoutTransitionData::ON_CHILD_REMOVE ) == LayoutTransitionData() );
+
+  layout.SetTransitionData( LayoutTransitionData::ON_CHILD_ADD, LayoutTransitionData() );
+  layout.SetTransitionData( LayoutTransitionData::ON_CHILD_REMOVE, layoutTransitionData );
+  DALI_TEST_CHECK( layout.GetTransitionData( LayoutTransitionData::ON_OWNER_SET ) == LayoutTransitionData() );
+  DALI_TEST_CHECK( layout.GetTransitionData( LayoutTransitionData::ON_CHILD_ADD ) == LayoutTransitionData() );
+  DALI_TEST_CHECK( layout.GetTransitionData( LayoutTransitionData::ON_CHILD_REMOVE ) == layoutTransitionData );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_SetLayoutTransition01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_SetLayoutTransition01");
+
+  Stage stage = Stage::GetCurrent();
+  auto container = Control::New();
+  auto horizontalLayout = LinearLayout::New();
+  horizontalLayout.SetAnimateLayout( true );
+  horizontalLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
+
+  auto verticalLayout = LinearLayout::New();
+  verticalLayout.SetAnimateLayout( true );
+  verticalLayout.SetOrientation( LinearLayout::Orientation::VERTICAL );
+
+  DevelControl::SetLayout( container, horizontalLayout );
+  container.SetName( "Container");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  for( auto&& iter : controls )
+  {
+    container.Add( iter );
+  }
+
+  container.SetParentOrigin( ParentOrigin::CENTER );
+  container.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( container );
+
+  auto layoutTransitionData = LayoutTransitionData::New();
+  {
+    // Instant resize for parent
+    Property::Map map;
+    map["property"] = "size";
+    map["targetValue"] = Property::Value(); // capture from layout update
+    map["animator"] = Property::Map()
+      .Add("alphaFunction", "LINEAR")
+      .Add("timePeriod", Property::Map()
+        .Add("delay", 0.0f)
+        .Add("duration", 0.0f));
+    layoutTransitionData.AddPropertyAnimator( container, map );
+  }
+  {
+    Property::Map map;
+    map["property"] = "opacity";
+    map["initialValue"] = 0.0f;
+    map["targetValue"] = 1.0f;
+    map["animator"] = Property::Map()
+      .Add("alphaFunction", "LINEAR")
+      .Add("timePeriod", Property::Map()
+        .Add("delay", 0.0f)
+        .Add("duration", 0.5f));
+    layoutTransitionData.AddPropertyAnimator( container, map );
+  }
+  {
+    // Instant position for children
+    Property::Map map;
+    map["property"] = "position";
+    map["animator"] = Property::Map()
+       .Add("alphaFunction", "LINEAR")
+       .Add("timePeriod", Property::Map()
+         .Add("delay", 0.0f)
+         .Add("duration", 0.0f));
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  {
+    // Grow children from (0,0) size to full size (captured)
+    Property::Map map;
+    map["property"] = "size";
+    map["initialValue"] = Vector3( 0.0f, 0.0f, 0 );
+    map["animator"] = Property::Map()
+      .Add("alphaFunction", "LINEAR")
+      .Add("timePeriod", Property::Map()
+        .Add("delay", 0.0f)
+        .Add("duration", 0.5f));
+    layoutTransitionData.AddPropertyAnimator( Actor(), map );
+  }
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // First round, no animation
+  // TODO: container size (0, 0) after it is added to the stage should be fixed with HQ patch soon
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 100.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  bool signalReceived(false);
+  LayoutTransitionFinishCheck finishCheck(signalReceived);
+  layoutTransitionData.FinishedSignal().Connect(&application, finishCheck);
+
+  // Change a layout, start transition
+  verticalLayout.SetTransitionData( LayoutTransitionData::ON_OWNER_SET, layoutTransitionData );
+  DevelControl::SetLayout( container, verticalLayout );
+
+  application.SendNotification();
+  application.Render( 1u /*just very beginning of the animation*/ );
+
+  finishCheck.CheckSignalNotReceived();
+  // Second round, animation just started
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( container.GetCurrentOpacity(), 0.0f, 0.1f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 300.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetCurrentPosition(), Vector3( 0.0f, 400.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetCurrentSize(), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentSize(), Vector3( 0.0f, 0.0f, 0.0f ), 1.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetCurrentSize(), Vector3( 0.0f, 0.0f, 0.0f ), 1.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>( 0.5f * 1000.0f ) + 1u /*just after the end of the animation*/ );
+
+  // Third round, animation just finished
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( container.GetCurrentOpacity(), 1.0f, 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 300.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetCurrentPosition(), Vector3( 0.0f, 400.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetCurrentSize(), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render( 10u /* wait a bit more for a signal */ );
+
+  finishCheck.CheckSignalReceived();
+
+  // Now sizes and positions are finally set
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 300.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 400.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Transition back now with default transition
+  DevelControl::SetLayout( container, horizontalLayout );
+
+  application.SendNotification();
+  application.Render( 1u /*just very beginning of the animation*/ );
+
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( container.GetCurrentOpacity(), 1.0f, 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 300.0f, 0.0f ), 1.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetCurrentPosition(), Vector3( 0.0f, 400.0f, 0.0f ), 1.0f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetCurrentSize(), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>( 0.5f * 1000.0f ) + 1u /*just after the end of the animation*/ );
+
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( container.GetCurrentOpacity(), 1.0f, 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetCurrentPosition(), Vector3( 100.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetCurrentSize(), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render( 10u /* wait a bit more for complete default animation */ );
+
+  // Now sizes and positions are finally set
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 100.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_AddChildLayoutTransition01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_AddChildLayoutTransition01");
+
+  Stage stage = Stage::GetCurrent();
+  auto container = Control::New();
+  auto horizontalLayout = LinearLayout::New();
+  horizontalLayout.SetAnimateLayout( true );
+  horizontalLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
+
+  DevelControl::SetLayout( container, horizontalLayout );
+  container.SetName( "Container");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  container.SetParentOrigin( ParentOrigin::CENTER );
+  container.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( container );
+
+  auto layoutTransitionData = LayoutTransitionData::New();
+  {
+    // Instant resize for parent
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = "size";
+    map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Property::Value(); // capture from layout update
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR" )
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( container, map );
+  }
+  {
+    // Instant position for a child
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = "position";
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
+       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  {
+    // Grow a child from (0,0) size to full size (captured)
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = "size";
+    map[ LayoutTransitionData::AnimatorKey::INITIAL_VALUE ] = Vector3( 0.0f, 0.0f, 0 );
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f)
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f));
+    layoutTransitionData.AddPropertyAnimator( controls[0], map );
+  }
+
+  horizontalLayout.SetTransitionData( LayoutTransitionData::ON_CHILD_ADD, layoutTransitionData );
+  container.Add( controls[0] );
+
+  bool signalReceived(false);
+  LayoutTransitionFinishCheck finishCheck(signalReceived);
+  layoutTransitionData.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render( 1u /*just very beginning of the animation*/ );
+
+  finishCheck.CheckSignalNotReceived();
+  // The animation just started
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>( 0.5f * 1000.0f ) + 1u /*just after the end of the animation*/ );
+
+  // The animation just finished
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetCurrentSize(), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render( 10u /* wait a bit more for a signal */ );
+
+  // Now sizes and positions are finally set
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  finishCheck.CheckSignalReceived();
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_RemoveChildLayoutTransition01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_RemoveChildLayoutTransition01");
+
+  Stage stage = Stage::GetCurrent();
+  auto container = Control::New();
+  auto horizontalLayout = LinearLayout::New();
+  horizontalLayout.SetAnimateLayout( true );
+  horizontalLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
+
+  DevelControl::SetLayout( container, horizontalLayout );
+  container.SetName( "Container");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  container.SetParentOrigin( ParentOrigin::CENTER );
+  container.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( container );
+  container.Add( controls[0] );
+  container.Add( controls[1] );
+
+  // Initial rendering done
+  application.SendNotification();
+  application.Render();
+
+  auto layoutTransitionData = LayoutTransitionData::New();
+  {
+    // Instant resize for parent width
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE_WIDTH;
+    map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Property::Value(); // capture from layout update
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::TYPE, "ANIMATE_TO" )
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR" )
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( container, map );
+  }
+  {
+    // Instant resize for parent height
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE_HEIGHT;
+    map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Property::Value(); // capture from layout update
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::TYPE, "ANIMATE_TO" )
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR" )
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( container, map );
+  }
+  {
+    // Instant position for parent X position
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION_X;
+    map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Property::Value(); // capture from layout update
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::TYPE, "ANIMATE_TO" )
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR" )
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( container, map );
+  }
+  {
+    // Instant position for parent Y position
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION_Y;
+    map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Property::Value(); // capture from layout update
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::TYPE, "ANIMATE_TO" )
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR" )
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( container, map );
+  }
+  {
+    // Shrink the children
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE_WIDTH;
+    map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = 0.0f;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::TYPE, "ANIMATE_TO" )
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f)
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f));
+    layoutTransitionData.AddPropertyAnimator( Actor(), map );
+  }
+  {
+    // Shrink the children
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE_HEIGHT;
+    map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = 0.0f;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::TYPE, "ANIMATE_TO" )
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f)
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f));
+    layoutTransitionData.AddPropertyAnimator( Actor(), map );
+  }
+  {
+    // Instant position for a child
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION_X;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::TYPE, "ANIMATE_TO" )
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  {
+    // Instant position for a child
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION_Y;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::TYPE, "ANIMATE_TO" )
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+
+  horizontalLayout.SetTransitionData( LayoutTransitionData::ON_CHILD_REMOVE, layoutTransitionData );
+  container.Remove( controls[1] );
+
+  bool signalReceived(false);
+  LayoutTransitionFinishCheck finishCheck(signalReceived);
+  layoutTransitionData.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render( 1u /*just very beginning of the animation*/ );
+
+  finishCheck.CheckSignalNotReceived();
+  // Animation just started
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetCurrentPosition(), Vector3( 100.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetCurrentSize(), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentSize(), Vector3( 0.0f, 0.0f, 0.0f ), 1.0f, TEST_LOCATION );
+  // this control is already removed from the tree.
+  DALI_TEST_EQUALS( controls[1].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>( 0.5f * 1000.0f ) + 1u /*just after the end of the animation*/ );
+
+  // Animation just finished
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  // this control is already removed from the tree.
+  DALI_TEST_EQUALS( controls[1].GetCurrentPosition(), Vector3( 100.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetCurrentSize(), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentSize(), Vector3( 0.0f, 0.0f, 0.0f ), 1.0f, TEST_LOCATION );
+  // this control is already removed from the tree.
+  DALI_TEST_EQUALS( controls[1].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render( 10u /* wait a bit more for a signal */ );
+
+  // Now sizes and positions are finally set
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  // this control is already removed from the tree.
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 100.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  // this control is already removed from the tree.
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  finishCheck.CheckSignalReceived();
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_AddChildLayoutTransition02_KeyFrames(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_AddChildLayoutTransition02_KeyFrames");
+
+  Stage stage = Stage::GetCurrent();
+  auto container = Control::New();
+  auto horizontalLayout = LinearLayout::New();
+  horizontalLayout.SetAnimateLayout( true );
+  horizontalLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
+
+  DevelControl::SetLayout( container, horizontalLayout );
+  container.SetName( "Container");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  container.SetParentOrigin( ParentOrigin::CENTER );
+  container.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( container );
+
+  auto layoutTransitionData = LayoutTransitionData::New();
+  {
+    // Instant resize for parent
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
+    map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Property::Value(); // capture from layout update
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR" )
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( container, map );
+  }
+  {
+    // Instant position for a child
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
+       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  {
+    // Grow a child from (0,0) size to full size with key frames
+    KeyFrames keyFrames = KeyFrames::New();
+    keyFrames.Add( 0.0f, Vector3( 0.0f, 0.0f, 0 ) );
+    keyFrames.Add( 0.5f, Vector3( 100.0f, 100.0f, 0 ) );
+
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::TYPE, "ANIMATE_BETWEEN")
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f)
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f));
+    layoutTransitionData.AddPropertyAnimator( controls[0], map, keyFrames, Animation::Interpolation::Linear );
+  }
+
+  horizontalLayout.SetTransitionData( LayoutTransitionData::ON_CHILD_ADD, layoutTransitionData );
+  container.Add( controls[0] );
+
+  bool signalReceived(false);
+  LayoutTransitionFinishCheck finishCheck(signalReceived);
+  layoutTransitionData.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render( 1u /*just very beginning of the animation*/ );
+
+  finishCheck.CheckSignalNotReceived();
+  // The animation just started
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>( 0.5f * 1000.0f ) + 1u /*just after the end of the animation*/ );
+
+  // The animation just finished
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetCurrentSize(), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render( 10u /* wait a bit more for a signal */ );
+
+  // Now sizes and positions are finally set
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  finishCheck.CheckSignalReceived();
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_AddChildLayoutTransition03_Path(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_AddChildLayoutTransition03_Path");
+
+  Stage stage = Stage::GetCurrent();
+  auto container = Control::New();
+  auto horizontalLayout = LinearLayout::New();
+  horizontalLayout.SetAnimateLayout( true );
+  horizontalLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
+
+  DevelControl::SetLayout( container, horizontalLayout );
+  container.SetName( "Container");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  container.SetParentOrigin( ParentOrigin::CENTER );
+  container.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( container );
+
+  auto layoutTransitionData = LayoutTransitionData::New();
+  {
+    // Instant resize for parent
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
+    map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Property::Value(); // capture from layout update
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR" )
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( container, map );
+  }
+
+  Dali::Path path = Dali::Path::New();
+  {
+    // Curve position for a child
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+       .Add( LayoutTransitionData::AnimatorKey::TYPE, "ANIMATE_PATH")
+       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
+       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f ) );
+
+    // Build the path
+    Vector3 position0( 30.0,  80.0,  0.0 );
+    Vector3 position1( 70.0,  120.0, 0.0 );
+    Vector3 position2( 0.0, 350.0, 0.0 );
+
+    //Dali::Path path = Dali::Path::New();
+    path.AddPoint( position0 );
+    path.AddPoint( position1 );
+    path.AddPoint( position2 );
+
+    // Control points for first segment
+    path.AddControlPoint( Vector3( 39.0,  90.0, 0.0 ) );
+    path.AddControlPoint( Vector3( 56.0, 119.0, 0.0 ) );
+
+    // Control points for second segment
+    path.AddControlPoint( Vector3( 78.0, 120.0, 0.0 ) );
+    path.AddControlPoint( Vector3( 93.0, 104.0, 0.0 ) );
+
+    layoutTransitionData.AddPropertyAnimator( controls[0], map, path, Vector3::XAXIS );
+  }
+  {
+    // Grow a child from (0,0) size to full size (captured)
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = "size";
+    map[ LayoutTransitionData::AnimatorKey::INITIAL_VALUE ] = Vector3( 0.0f, 0.0f, 0 );
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f)
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f));
+    layoutTransitionData.AddPropertyAnimator( controls[0], map );
+  }
+
+  horizontalLayout.SetTransitionData( LayoutTransitionData::ON_CHILD_ADD, layoutTransitionData );
+  container.Add( controls[0] );
+
+  bool signalReceived(false);
+  LayoutTransitionFinishCheck finishCheck(signalReceived);
+  layoutTransitionData.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render( 0 );
+
+  finishCheck.CheckSignalNotReceived();
+  // The animation just started
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  Vector3 position, tangent;
+  Quaternion rotation;
+  path.Sample( 0.0f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), position,  0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentOrientation(), rotation, 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>( 0.5f * 1000.0f ) + 1u /*just after the end of the animation*/ );
+
+  path.Sample( 1.0f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), position, 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentOrientation(), rotation, 0.0001f, TEST_LOCATION );
+
+  // The animation just finished
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetCurrentSize(), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render( 10u /* wait a bit more for a signal */ );
+
+  // Now sizes and positions are finally set
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  finishCheck.CheckSignalReceived();
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_AddChildLayoutTransition04_AnimateBy(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_AddChildLayoutTransition04_AnimateBy");
+
+  Stage stage = Stage::GetCurrent();
+  auto container = Control::New();
+  auto horizontalLayout = LinearLayout::New();
+  horizontalLayout.SetAnimateLayout( true );
+  horizontalLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
+
+  DevelControl::SetLayout( container, horizontalLayout );
+  container.SetName( "Container");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  container.SetParentOrigin( ParentOrigin::CENTER );
+  container.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( container );
+
+  auto layoutTransitionData = LayoutTransitionData::New();
+  {
+    // Instant resize for parent
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
+    map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Property::Value(); // capture from layout update
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR" )
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( container, map );
+  }
+  {
+    // Instant position for a child
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+       .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
+       .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+         .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f )
+         .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  {
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
+    map[ LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Vector3( 0.0f, 350.0f, 0 );
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::TYPE, "ANIMATE_BY")
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR")
+      .Add( LayoutTransitionData::AnimatorKey::TIME_PERIOD, Property::Map()
+        .Add( LayoutTransitionData::AnimatorKey::DELAY, 0.0f)
+        .Add( LayoutTransitionData::AnimatorKey::DURATION, 0.5f));
+    layoutTransitionData.AddPropertyAnimator( controls[0], map );
+  }
+
+  horizontalLayout.SetTransitionData( LayoutTransitionData::ON_CHILD_ADD, layoutTransitionData );
+  container.Add( controls[0] );
+
+  bool signalReceived(false);
+  LayoutTransitionFinishCheck finishCheck(signalReceived);
+  layoutTransitionData.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render( 1u /*just very beginning of the animation*/ );
+
+  finishCheck.CheckSignalNotReceived();
+  // The animation just started
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render( static_cast<unsigned int>( 0.5f * 1000.0f ) + 1u /*just after the end of the animation*/ );
+
+  // The animation just finished
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetCurrentSize(), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render( 10u /* wait a bit more for a signal */ );
+
+  // Now sizes and positions are finally set
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  finishCheck.CheckSignalReceived();
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_AddChildLayoutTransition05(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_AddChildLayoutTransition05");
+
+  Stage stage = Stage::GetCurrent();
+  auto container = Control::New();
+  auto horizontalLayout = LinearLayout::New();
+  horizontalLayout.SetAnimateLayout( true );
+  horizontalLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
+
+  DevelControl::SetLayout( container, horizontalLayout );
+  container.SetName( "Container");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  container.SetParentOrigin( ParentOrigin::CENTER );
+  container.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( container );
+
+  auto layoutTransitionData = LayoutTransitionData::New();
+  {
+    // Instant resize for parent
+    Property::Map map;
+    map[ "property" ] = Actor::Property::SIZE;
+    map[ "targetValue" ] = Property::Value(); // capture from layout update
+    map[ "animator" ] = Property::Map()
+      .Add( "name", "InstantAnimator" )
+      .Add( "type", "ANIMATE_TO")
+      .Add( "alphaFunction", "LINEAR" )
+      .Add( "timePeriod", Property::Map()
+        .Add( "delay", 0.0f )
+        .Add( "duration", 0.0f ) );
+    layoutTransitionData.AddPropertyAnimator( container, map );
+  }
+  {
+    // Instant position for a child
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::COLOR_ALPHA;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = "InstantAnimator";
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  {
+    // Grow a child from (0,0) size to full size (captured)
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
+    map[ LayoutTransitionData::AnimatorKey::INITIAL_VALUE ] = Vector3( 0.0f, 0.0f, 0 );
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = std::string();
+    layoutTransitionData.AddPropertyAnimator( controls[0], map );
+  }
+  {
+    // Instant opacity for a child, for testing
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = "InstantAnimator";
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+
+  // Just throw all other alpha functions in
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "WRONG" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "LINEAR" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "REVERSE" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "EASE_IN_SQUARE" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "EASE_OUT_SQUARE" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "EASE_IN" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "EASE_IN" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "EASE_OUT" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "EASE_IN_OUT" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "EASE_IN_OUT_SINE" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "EASE_IN_SINE" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "EASE_OUT_SINE" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "BOUNCE" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "SIN" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, "EASE_OUT_BACK" );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, Vector4( 0.0f, 1.0f, 2.0f, 3.0f ) );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    // valid
+    Property::Array array;
+    array.Reserve( 4 );
+    array.PushBack( 0.0f );
+    array.PushBack( 1.0f );
+    array.PushBack( 2.0f );
+    array.PushBack( 3.0f );
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, array );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    // invalid
+    Property::Array array;
+    array.Reserve( 3 );
+    array.PushBack( 0.0f );
+    array.PushBack( 1.0f );
+    array.PushBack( 2.0f );
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, array );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    // invalid
+    Property::Array array;
+    array.Reserve( 4 );
+    array.PushBack( 0.0f );
+    array.PushBack( 10 );
+    array.PushBack( 2.0f );
+    array.PushBack( 3.0f );
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = Property::Map()
+      .Add( LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION, array );
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+  { // no property, not going to be used, but going to be parsed
+    Property::Map map;
+    map[ LayoutTransitionData::AnimatorKey::ANIMATOR ] = 0; // invalid
+    layoutTransitionData.AddPropertyAnimator( Actor(), map ); // apply to all children except parent
+  }
+
+  horizontalLayout.SetTransitionData( LayoutTransitionData::ON_CHILD_ADD, layoutTransitionData );
+  container.Add( controls[0] );
+
+  bool signalReceived(false);
+  LayoutTransitionFinishCheck finishCheck(signalReceived);
+  layoutTransitionData.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render( 1u /*just very beginning of the animation*/ );
+
+  finishCheck.CheckSignalNotReceived();
+  // The animation just started
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetCurrentSize(), Vector3( 480.0f, 800.0f, 0.0f ), 1.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentSize(), Vector3( 0.0f, 0.0f, 0.0f ), 1.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>( 0.5f * 1000.0f ) + 1u /*just after the end of the animation*/ );
+
+  // The animation just finished
+  DALI_TEST_EQUALS( container.GetCurrentPosition(), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentPosition(), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetCurrentSize(), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetCurrentSize(), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render( 10u /* wait a bit more for a signal */ );
+
+  // Now sizes and positions are finally set
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  finishCheck.CheckSignalReceived();
+
+  END_TEST;
+}
+
index c3f68aa..1cad2f5 100755 (executable)
@@ -44,6 +44,7 @@ devel_api_src_files = \
   $(devel_api_src_dir)/layouting/layout-group.cpp \
   $(devel_api_src_dir)/layouting/layout-group-impl.cpp \
   $(devel_api_src_dir)/layouting/linear-layout.cpp \
+  $(devel_api_src_dir)/layouting/layout-transition-data.cpp \
   $(devel_api_src_dir)/scripting/script.cpp \
   $(devel_api_src_dir)/styling/style-manager-devel.cpp \
   $(devel_api_src_dir)/transition-effects/cube-transition-cross-effect.cpp \
@@ -101,6 +102,7 @@ devel_api_layouting_header_files = \
   $(devel_api_src_dir)/layouting/layout-length.h \
   $(devel_api_src_dir)/layouting/layout-parent-impl.h \
   $(devel_api_src_dir)/layouting/layout-size.h \
+  $(devel_api_src_dir)/layouting/layout-transition-data.h \
   $(devel_api_src_dir)/layouting/measured-size.h \
   $(devel_api_src_dir)/layouting/measure-spec.h
 
index 645fe48..ba87af2 100644 (file)
@@ -68,7 +68,12 @@ LayoutController LayoutController::Get()
 
 void LayoutController::RequestLayout( LayoutItem layout )
 {
-  GetImpl(*this).RequestLayout( GetImplementation( layout ) );
+  GetImpl( *this ).RequestLayout( GetImplementation( layout ), -1 );
+}
+
+void LayoutController::RequestLayout( LayoutItem layout, Dali::Toolkit::LayoutTransitionData::LayoutTransitionType layoutTransitionType  )
+{
+  GetImpl( *this ).RequestLayout( GetImplementation( layout ), layoutTransitionType );
 }
 
 LayoutController::LayoutController( Internal::LayoutController *impl )
index 2741829..062793d 100755 (executable)
@@ -62,10 +62,19 @@ public:
   static LayoutController Get();
 
   /**
-   * @brief Request for a particular layout (wrapping a control or a visual) to be measured and laid out.
+    * @brief Request for a particular layout (wrapping a control or a visual) to be measured and laid out. A specified layout transition
+    * will be triggered during the layout.
+    * @param[in] layout The layout to measure & relayout.
+    */
+  void RequestLayout( LayoutItem layout );
+
+  /**
+   * @brief Request for a particular layout (wrapping a control or a visual) to be measured and laid out. A specified layout transition
+   * will be triggered during the layout.
    * @param[in] layout The layout to measure & relayout.
+   * @param[in] layoutTransitionType The layout transition type.
    */
-  void RequestLayout( LayoutItem layout );
+  void RequestLayout( LayoutItem layout, Dali::Toolkit::LayoutTransitionData::LayoutTransitionType layoutTransitionType );
 
 public:
   /// @cond internal
index 35c682f..06305bd 100644 (file)
@@ -507,7 +507,7 @@ void LayoutGroup::OnInitialize()
     // Take ownership of existing children
     for( unsigned int childIndex = 0 ; childIndex < control.GetChildCount(); ++childIndex )
     {
-      ChildAddedToOwner( control.GetChildAt( childIndex ) );
+      ChildAddedToOwnerImpl( control.GetChildAt( childIndex ) );
     }
 
     DevelActor::ChildAddedSignal( control ).Connect( mSlotDelegate, &LayoutGroup::ChildAddedToOwner );
@@ -551,6 +551,8 @@ void LayoutGroup::OnInitialize()
         }
       }
     }
+
+    RequestLayout( Dali::Toolkit::LayoutTransitionData::LayoutTransitionType::ON_OWNER_SET );
   }
 }
 
@@ -582,6 +584,12 @@ void LayoutGroup::RemoveChild( LayoutItem& item )
 
 void LayoutGroup::ChildAddedToOwner( Actor child )
 {
+  ChildAddedToOwnerImpl( child );
+  RequestLayout( Dali::Toolkit::LayoutTransitionData::LayoutTransitionType::ON_CHILD_ADD );
+}
+
+void LayoutGroup::ChildAddedToOwnerImpl( Actor child )
+{
   LayoutItemPtr childLayout;
   Toolkit::Control control = Toolkit::Control::DownCast( child );
 
@@ -662,6 +670,7 @@ void LayoutGroup::ChildRemovedFromOwner( Actor child )
     if( childLayout )
     {
       Remove( *childLayout.Get() );
+      RequestLayout( Dali::Toolkit::LayoutTransitionData::LayoutTransitionType::ON_CHILD_REMOVE );
     }
   }
 }
index ee73c88..37aa90f 100644 (file)
@@ -294,6 +294,11 @@ private:
   void ChildAddedToOwner( Actor child );
 
   /**
+   * Implementation of ChildAddedToOwner
+   */
+  void ChildAddedToOwnerImpl( Actor child );
+
+  /**
    * Callback when child is removed from owner
    */
   void ChildRemovedFromOwner( Actor child );
index f70a5f1..cd4cf40 100644 (file)
 #include <dali/public-api/animation/animation.h>
 #include <dali/public-api/object/type-registry-helper.h>
 #include <dali-toolkit/public-api/controls/control.h>
+#include <dali/devel-api/object/handle-devel.h>
 #include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
 #include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+#include <dali-toolkit/internal/layouting/layout-transition-data-impl.h>
 #include <dali-toolkit/internal/layouting/layout-item-data-impl.h>
 
+#include <dali/devel-api/scripting/enum-helper.h>
+
 namespace
 {
 
@@ -33,7 +37,6 @@ Debug::Filter* gLayoutFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG
 const char* WIDTH_SPECIFICATION_NAME( "widthSpecification" );
 const char* HEIGHT_SPECIFICATION_NAME( "heightSpecification" );
 
-const float DEFAULT_TRANSITION_DURATION( 0.5f );
 }
 
 namespace Dali
@@ -66,7 +69,6 @@ void LayoutItem::Initialize( Handle& owner, const std::string& containerType )
   mImpl->mOwner = &(owner.GetBaseObject());
   RegisterChildProperties( containerType );
   OnInitialize(); // Ensure direct deriving class gets initialized
-  RequestLayout();
 }
 
 Handle LayoutItem::GetOwner() const
@@ -93,6 +95,35 @@ void LayoutItem::Unparent()
   mImpl->mOwner = NULL;
 }
 
+LayoutTransitionDataPtr LayoutItem::GetDefaultTransition()
+{
+  DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::GetDefaultTransition\n" );
+  if ( !mImpl->mDefaultTransitionData.Get() )
+  {
+    auto owner = GetOwner();
+    auto actor = Actor::DownCast( owner );
+
+    mImpl->mDefaultTransitionData = LayoutTransitionData::New();
+    {
+      Property::Map map;
+      map[ Dali::Toolkit::LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::POSITION;
+      map[ Dali::Toolkit::LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Property::Value(); // capture from layout update
+      map[ Dali::Toolkit::LayoutTransitionData::AnimatorKey::ANIMATOR ] = std::string(); // default animator with default duration
+      // Capture calculated position after layout, apply default linear animation
+      mImpl->mDefaultTransitionData->AddPropertyAnimator( actor, map );
+    }
+    {
+      Property::Map map;
+      map[ Dali::Toolkit::LayoutTransitionData::AnimatorKey::PROPERTY ] = Actor::Property::SIZE;
+      map[ Dali::Toolkit::LayoutTransitionData::AnimatorKey::TARGET_VALUE ] = Property::Value(); // capture from layout update
+      map[ Dali::Toolkit::LayoutTransitionData::AnimatorKey::ANIMATOR ] = std::string(); // default animator with default duration
+      // Capture calculated size after layout, apply default linear animation
+      mImpl->mDefaultTransitionData->AddPropertyAnimator( actor, map );
+    }
+  }
+  return mImpl->mDefaultTransitionData;
+}
+
 void LayoutItem::SetAnimateLayout( bool animateLayout )
 {
   auto owner = GetOwner();
@@ -111,6 +142,39 @@ bool LayoutItem::IsLayoutAnimated() const
   return mImpl->mAnimated;
 }
 
+void LayoutItem::SetTransitionData( int layoutTransitionType, Internal::LayoutTransitionDataPtr layoutTransitionDataPtr )
+{
+  switch ( layoutTransitionType )
+  {
+  case Dali::Toolkit::LayoutTransitionData::ON_CHILD_ADD:
+    mImpl->mOnChildAddTransitionData = layoutTransitionDataPtr;
+    break;
+  case Dali::Toolkit::LayoutTransitionData::ON_CHILD_REMOVE:
+    mImpl->mOnChildRemoveTransitionData = layoutTransitionDataPtr;
+    break;
+  case Dali::Toolkit::LayoutTransitionData::ON_OWNER_SET:
+    mImpl->mOnOwnerSetTransitionData = layoutTransitionDataPtr;
+    break;
+  default:
+    break;
+  }
+}
+
+Internal::LayoutTransitionDataPtr LayoutItem::GetTransitionData( int layoutTransitionType ) const
+{
+  switch ( layoutTransitionType )
+  {
+  case Dali::Toolkit::LayoutTransitionData::ON_CHILD_ADD:
+    return mImpl->mOnChildAddTransitionData.Get();
+  case Dali::Toolkit::LayoutTransitionData::ON_CHILD_REMOVE:
+    return mImpl->mOnChildRemoveTransitionData.Get();
+  case Dali::Toolkit::LayoutTransitionData::ON_OWNER_SET:
+    return mImpl->mOnOwnerSetTransitionData.Get();
+  default:
+    return LayoutTransitionDataPtr();
+  }
+}
+
 void LayoutItem::RegisterChildProperties( const std::string& containerType )
 {
   // Call on derived types
@@ -198,14 +262,23 @@ void LayoutItem::Layout( LayoutLength l, LayoutLength t, LayoutLength r, LayoutL
     mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_MEASURE_NEEDED_BEFORE_LAYOUT );
   }
 
+  LayoutData& layoutData = *mImpl->sLayoutData;
+  size_t size = layoutData.childrenPropertyAnimators.size();
+
   bool changed = SetFrame( l, t, r, b );
 
   if( changed || mImpl->GetPrivateFlag( Impl::PRIVATE_FLAG_LAYOUT_REQUIRED ) )
   {
+
     OnLayout( changed, l, t, r, b );
     mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_LAYOUT_REQUIRED );
   }
 
+  if ( size != layoutData.childrenPropertyAnimators.size() )
+  {
+    layoutData.childrenPropertyAnimators.resize( size );
+  }
+
   mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
   mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_IS_LAID_OUT );
 }
@@ -333,14 +406,29 @@ LayoutParent* LayoutItem::GetParent()
 void LayoutItem::RequestLayout()
 {
   Toolkit::Control control = Toolkit::Control::DownCast( mImpl->mOwner );
+  if( control )
+  {
+    DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::RequestLayout control(%s)\n",
+        control.GetName().c_str() );
+  }
+  // @todo Enforce failure if called in Measure/Layout passes.
+  mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
+  Toolkit::LayoutController layoutController = Toolkit::LayoutController::Get();
+  layoutController.RequestLayout( Toolkit::LayoutItem( this ) );
+}
+
+void LayoutItem::RequestLayout( Dali::Toolkit::LayoutTransitionData::LayoutTransitionType layoutAnimationType )
+{
+  Toolkit::Control control = Toolkit::Control::DownCast( mImpl->mOwner );
   if ( control )
   {
-    DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::RequestLayout %s\n", control.GetName().c_str());
+    DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::RequestLayout control(%s) layoutTranstionType(%d)\n",
+        control.GetName().c_str(), (int)layoutAnimationType );
   }
   // @todo Enforce failure if called in Measure/Layout passes.
   mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
   Toolkit::LayoutController layoutController = Toolkit::LayoutController::Get();
-  layoutController.RequestLayout( Toolkit::LayoutItem(this) );
+  layoutController.RequestLayout( Toolkit::LayoutItem(this), layoutAnimationType );
 }
 
 bool LayoutItem::IsLayoutRequested() const
@@ -469,56 +557,65 @@ bool LayoutItem::SetFrame( LayoutLength left, LayoutLength top, LayoutLength rig
   if( mImpl->mLeft != left || mImpl->mRight != right || mImpl->mTop != top || mImpl->mBottom != bottom || mImpl->GetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_SET_FRAME ) )
   {
     changed = true;
-
-    LayoutLength oldWidth = mImpl->mRight - mImpl->mLeft;
-    LayoutLength oldHeight = mImpl->mBottom - mImpl->mTop;
-    LayoutLength newWidth = right - left;
-    LayoutLength newHeight = bottom - top;
-    bool sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
-
-    mImpl->mLeft = left;
-    mImpl->mTop = top;
-    mImpl->mRight = right;
-    mImpl->mBottom = bottom;
-
     mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_FORCE_SET_FRAME );
+  }
 
+  LayoutLength oldWidth = mImpl->mRight - mImpl->mLeft;
+  LayoutLength oldHeight = mImpl->mBottom - mImpl->mTop;
+  LayoutLength newWidth = right - left;
+  LayoutLength newHeight = bottom - top;
+  bool sizeChanged = ( newWidth != oldWidth ) || ( newHeight != oldHeight );
 
-    // Reflect up to parent control
-    auto owner = GetOwner();
-    auto actor = Actor::DownCast(owner);
-    if( actor )
-    {
-      DALI_LOG_STREAM( gLayoutFilter, Debug::Verbose, "LayoutItem::SetFrame owner(" << left << ", " << top << ", " << right << ", " << bottom << ")\n" );
+  mImpl->mLeft = left;
+  mImpl->mTop = top;
+  mImpl->mRight = right;
+  mImpl->mBottom = bottom;
 
-      if( mImpl->mAnimated )
-      {
-        auto animation = Animation::New( 0.5f );
-        animation.AnimateTo( Property( actor, Actor::Property::POSITION_X ), left.AsInteger() );
-        animation.AnimateTo( Property( actor, Actor::Property::POSITION_Y ), top.AsInteger() );
+  // Reflect up to parent control
+  auto owner = GetOwner();
+  auto actor = Actor::DownCast( owner );
+  LayoutData& layoutData = *mImpl->sLayoutData;
+  if( actor )
+  {
+    if( mImpl->mAnimated && !layoutData.speculativeLayout )
+    {
 
-        animation.AnimateTo( Property( actor, Actor::Property::SIZE_WIDTH ), newWidth.AsInteger() );
-        animation.AnimateTo( Property( actor, Actor::Property::SIZE_HEIGHT ), newHeight.AsInteger() );
+      LayoutItem* transitionOwner = layoutData.layoutTransition.layoutItem.Get();
+      LayoutTransitionDataPtr layoutTransitionDataPtr = GetTransitionData( layoutData.layoutTransition.layoutTransitionType );
 
-        animation.FinishedSignal().Connect( mSlotDelegate, &LayoutItem::OnLayoutAnimationFinished );
-        animation.Play();
+      // Found transition owner
+      if( transitionOwner == this && layoutTransitionDataPtr.Get() )
+      {
+        DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::SetFrame apply transition to (%s), transition type (%d)\n", actor.GetName().c_str(), layoutData.layoutTransition.layoutTransitionType );
+        layoutData.layoutPositionDataArray.push_back( LayoutPositionData( actor, left.AsDecimal(), top.AsDecimal(), right.AsDecimal(), bottom.AsDecimal(), true ) );
+        layoutTransitionDataPtr->ConvertToLayoutDataElements( actor, layoutData );
+        changed = true;
       }
       else
       {
-        // @todo Collate into list of Property & Property::Value pairs.
-        actor.SetX( left.AsInteger() );
-        actor.SetY( top.AsInteger() );
-        actor.SetProperty( Actor::Property::SIZE_WIDTH, newWidth.AsInteger() );
-        actor.SetProperty( Actor::Property::SIZE_HEIGHT, newHeight.AsInteger() );
+        if( changed )
+        {
+          DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::SetFrame apply default transition to (%s), transition type (%d)\n", actor.GetName().c_str(), layoutData.layoutTransition.layoutTransitionType );
+          layoutData.layoutPositionDataArray.push_back( LayoutPositionData( actor, left.AsDecimal(), top.AsDecimal(), right.AsDecimal(), bottom.AsDecimal(), true ) );
+          GetDefaultTransition()->ConvertToLayoutDataElements( actor, layoutData );
+        }
       }
     }
-
-    if( sizeChanged )
+    else
     {
-      SizeChange( LayoutSize( newWidth, newHeight ), LayoutSize( oldWidth, oldHeight ) );
+      if( changed )
+      {
+        layoutData.layoutPositionDataArray.push_back( LayoutPositionData( actor, left.AsDecimal(), top.AsDecimal(), right.AsDecimal(), bottom.AsDecimal(), false ) );
+      }
     }
   }
 
+  // TODO: do we need it
+  if( sizeChanged )
+  {
+    SizeChange( LayoutSize( newWidth, newHeight ), LayoutSize( oldWidth, oldHeight ) );
+  }
+
   DALI_LOG_STREAM( gLayoutFilter, Debug::Verbose, "LayoutItem::SetFrame  exit(" << left << ", " << top << ", " << right << ", " << bottom << ")\n" );
 
   return changed;
index 3850e5f..19b61d5 100644 (file)
 
 #include <dali/public-api/common/intrusive-ptr.h>
 #include <dali/public-api/object/base-object.h>
+#include <dali/public-api/object/property-map.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/public-api/actors/actor-enumerations.h>
+#include <dali/public-api/animation/animation.h>
 #include <dali-toolkit/devel-api/layouting/child-layout-data.h>
 #include <dali-toolkit/devel-api/layouting/layout-item.h>
 #include <dali-toolkit/devel-api/layouting/layout-child-impl.h>
@@ -37,9 +39,13 @@ namespace Toolkit
 namespace Internal
 {
 
+struct LayoutData;
+
 class LayoutItem;
 using LayoutItemPtr = IntrusivePtr<LayoutItem>;
 
+class LayoutTransitionData;
+using LayoutTransitionDataPtr = IntrusivePtr<LayoutTransitionData>;
 
 /**
  * Base class for layouts.
@@ -114,6 +120,28 @@ public:
   bool IsLayoutAnimated() const;
 
   /**
+   * @brief Get the default transition
+   *
+   * @return The default transition
+   */
+  LayoutTransitionDataPtr GetDefaultTransition();
+
+  /**
+   * @brief Set the layout transition data
+   * @param[in] layoutTransitionType The type of the transition
+   * @param[in] layoutTransitionDataPtr The transition data pointer
+   */
+  void SetTransitionData( int layoutTransitionType, LayoutTransitionDataPtr layoutTransitionDataPtr );
+
+  /**
+   * @brief Get the transition data
+   * @param[in] layoutTransitionType The type of the transition
+   *
+   * @return The transition
+   */
+  LayoutTransitionDataPtr GetTransitionData( int layoutTransitionType ) const;
+
+  /**
    * @brief  This is called to find out how big a layout should be.
    *
    * The parent supplies constraint information in the width and height parameters.
@@ -176,6 +204,14 @@ public:
   void RequestLayout();
 
   /**
+   * @brief Request that this layout is re-laid out with particular transition.
+   * @param[in] layoutTranstionType The transition type
+   *
+   * This will make this layout and all it's parent layouts dirty and set the transition queued.
+   */
+  void RequestLayout( Dali::Toolkit::LayoutTransitionData::LayoutTransitionType layoutTranstionType );
+
+  /**
    * @brief Predicate to determine if this layout has been requested to re-layout
    *
    * @return True if a layout request has occured on this layout
@@ -408,10 +444,9 @@ protected:
                                            MeasuredSize::State childMeasuredState );
 
   /**
-   * @brief Sets the frame (the size and position) of the layout onto it's owner
+   * @brief Sets the frame (the size and position) of the layout onto it's owner.
+   * Collect all properties to animate after the layout update.
    *
-   * @todo Consider instead, collating properties into LayoutCollector in order to set/animate them all
-   * in one block.
    * @param[in] left The horizontal position of the left edge of this frame within the parent layout
    * @param[in] top The vertical position of the top edge of this frame within the parent layout
    * @param[in] right The horizontal position of the right edge of this frame within the parent layout
@@ -466,7 +501,6 @@ private:
 public:
   class Impl; // Class declaration is public so we can add devel API's in the future
 
-
 private:
   std::unique_ptr<Impl> mImpl; ///< Implementation class holds all the data
   SlotDelegate<LayoutItem> mSlotDelegate;
index 153c134..a84b45d 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <dali-toolkit/devel-api/layouting/layout-item.h>
 #include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
+#include <dali-toolkit/devel-api/layouting/layout-transition-data.h>
+#include <dali-toolkit/internal/layouting/layout-transition-data-impl.h>
 
 namespace Dali
 {
@@ -53,6 +55,21 @@ bool LayoutItem::IsLayoutAnimated() const
   return GetImplementation( *this ).IsLayoutAnimated();
 }
 
+void LayoutItem::SetTransitionData( LayoutTransitionData::LayoutTransitionType layoutTransitionType, LayoutTransitionData layoutTransitionData )
+{
+  Toolkit::Internal::LayoutTransitionDataPtr layoutTransitionDataPtr = Toolkit::Internal::LayoutTransitionDataPtr();
+  if ( layoutTransitionData )
+  {
+    layoutTransitionDataPtr = Toolkit::Internal::LayoutTransitionDataPtr( &Toolkit::GetImplementation( layoutTransitionData ) );
+  }
+  GetImplementation( *this ).SetTransitionData( layoutTransitionType, layoutTransitionDataPtr );
+}
+
+LayoutTransitionData LayoutItem::GetTransitionData( LayoutTransitionData::LayoutTransitionType layoutTransitionType ) const
+{
+  return LayoutTransitionData( GetImplementation( *this ).GetTransitionData( layoutTransitionType ).Get() );
+}
+
 } // namespace Toolkit
 
 } // namespace Dali
index fc69e6d..1ad32ed 100755 (executable)
 #include <cstdint>
 #include <dali-toolkit/public-api/dali-toolkit-common.h>
 #include <dali/public-api/actors/actor-enumerations.h>
+#include <dali/public-api/animation/animation.h>
 #include <dali/public-api/object/base-handle.h>
 #include <dali/public-api/object/property-index-ranges.h>
+#include <dali/public-api/object/property-map.h>
 #include <dali-toolkit/devel-api/layouting/child-layout-data.h>
 #include <dali-toolkit/devel-api/layouting/measure-spec.h>
+#include <dali-toolkit/devel-api/layouting/layout-transition-data.h>
 #include <dali-toolkit/public-api/dali-toolkit-common.h>
 
 namespace Dali
@@ -38,7 +41,6 @@ class LayoutItem;
 
 using LayoutId = unsigned int;
 
-
 /**
  * Base class for layouts. It is used to layout a control (or visual).
  * It can be laid out by a LayoutGroup.
@@ -115,6 +117,23 @@ public:
    */
   bool IsLayoutAnimated() const;
 
+  /**
+   * @brief Set the layout transition data
+   *
+   * @param[in] layoutTransitionType The type of the layout transition
+   * @param[in] layoutTransitionData The layout transition data
+   */
+  void SetTransitionData( LayoutTransitionData::LayoutTransitionType layoutTransitionType, LayoutTransitionData layoutTransitionData );
+
+  /**
+   * @brief Get the layout transition data
+   *
+   * @param[in] layoutTransitionType The type of the layout transition
+   *
+   * @return The layout transition data
+   */
+  LayoutTransitionData GetTransitionData( LayoutTransitionData::LayoutTransitionType layoutTransitionType ) const;
+
 public:
   /// @cond internal
   /**
diff --git a/dali-toolkit/devel-api/layouting/layout-transition-data.cpp b/dali-toolkit/devel-api/layouting/layout-transition-data.cpp
new file mode 100644 (file)
index 0000000..c01b2dd
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali-toolkit/devel-api/layouting/layout-transition-data.h>
+#include <dali-toolkit/internal/layouting/layout-transition-data-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+LayoutTransitionData::LayoutTransitionData()
+: BaseHandle()
+{
+}
+
+LayoutTransitionData::LayoutTransitionData( Internal::LayoutTransitionData* layoutAnimationData )
+: BaseHandle( layoutAnimationData )
+{
+}
+
+LayoutTransitionData LayoutTransitionData::New()
+{
+  Internal::LayoutTransitionDataPtr layoutAnimationData = Internal::LayoutTransitionData::New();
+  return LayoutTransitionData( layoutAnimationData.Get() );
+}
+
+LayoutTransitionData LayoutTransitionData::DownCast( BaseHandle handle )
+{
+  return LayoutTransitionData( dynamic_cast<Internal::LayoutTransitionData*>(handle.GetObjectPtr()) );
+}
+
+void LayoutTransitionData::AddPropertyAnimator( Actor actor, Property::Map map )
+{
+  GetImplementation( *this ).AddPropertyAnimator( actor, map );
+}
+
+void LayoutTransitionData::AddPropertyAnimator(  Actor actor, Property::Map map, KeyFrames keyFrames, Animation::Interpolation interpolation )
+{
+  GetImplementation( *this ).AddPropertyAnimator( actor, map, keyFrames, interpolation );
+}
+
+void LayoutTransitionData::AddPropertyAnimator( Actor actor, Property::Map map, Path path, Vector3 forward )
+{
+  GetImplementation( *this ).AddPropertyAnimator( actor, map, path, forward );
+}
+
+LayoutTransitionData::LayoutTransitionSignalType& LayoutTransitionData::FinishedSignal()
+{
+  return GetImplementation(*this ).FinishedSignal();
+}
+
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/layouting/layout-transition-data.h b/dali-toolkit/devel-api/layouting/layout-transition-data.h
new file mode 100644 (file)
index 0000000..5bd509a
--- /dev/null
@@ -0,0 +1,151 @@
+#ifndef DALI_TOOLKIT_LAYOUTING_LAYOUT_TRANSITION_DATA_H
+#define DALI_TOOLKIT_LAYOUTING_LAYOUT_TRANSITION_DATA_H
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <cstdint>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/actors/actor-enumerations.h>
+#include <dali/public-api/animation/animation.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/property-index-ranges.h>
+#include <dali/public-api/object/property-map.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+namespace Internal
+{
+class LayoutTransitionData;
+}
+
+class DALI_TOOLKIT_API LayoutTransitionData final : public BaseHandle
+{
+public:
+
+  /**
+   * @brief Enumeration for property animator keys belonging to the LayoutTransitionData class.
+   */
+  struct AnimatorKey
+  {
+    enum Type
+    {
+      PROPERTY,           ///< A property to animate
+      INITIAL_VALUE,      ///< Initial value of an animated property
+      TARGET_VALUE,       ///< Target value of an animated property
+      ANIMATOR,           ///< Animator for an animated property
+      TYPE,               ///< Type of an animator
+      NAME,               ///< Name of an animator
+      TIME_PERIOD,        ///< Time period of an property animation
+      DURATION,           ///< Duration of an property animation
+      DELAY,              ///< Delay of an property animation
+      ALPHA_FUNCTION,     ///< Alpha function of a property animation
+    };
+  };
+
+  enum LayoutTransitionType
+  {
+    ON_CHILD_ADD,
+    ON_CHILD_REMOVE,
+    ON_OWNER_SET
+  };
+
+  typedef Signal< void (LayoutTransitionData::LayoutTransitionType, LayoutTransitionData&) > LayoutTransitionSignalType; ///< Transition finished signal
+
+  /**
+   * Create an uninitialized handle
+   *
+   * @SINCE_1_2.12
+   */
+  LayoutTransitionData();
+
+  /**
+   * Destructor - non virtual
+   *
+   * @SINCE_1_2.12
+   */
+  ~LayoutTransitionData() = default;
+
+  /**
+   * Create an initialized LayoutTransitionData
+   */
+  static LayoutTransitionData New();
+
+  /**
+   * @brief Downcasts a handle to LayoutTransitionData handle.
+   *
+   * If handle points to an LayoutTransitionData object, the downcast produces valid handle.
+   * If not, the returned handle is left uninitialized.
+   *
+   * @param[in] handle Handle to an object
+   * @return Handle to an LayoutTransitionData object or an uninitialized handle
+   */
+  static LayoutTransitionData DownCast( BaseHandle handle );
+
+  /**
+   * @brief Add a property animator for an actor
+   *
+   * @param[in] actor An owner of the animated property
+   * @param[in] map The animated property map including animator map
+   */
+  void AddPropertyAnimator( Actor actor, Property::Map map );
+
+  /**
+   * @brief Add a property animator for an actor
+   *
+   * @param[in] actor An owner of the animated property
+   * @param[in] map The properties map
+   * @param[in] keyFrames key frames
+   * @param[in] interpolation An interpolation
+   */
+  void AddPropertyAnimator( Actor actor, Property::Map map, KeyFrames keyFrames, Animation::Interpolation interpolation );
+
+  /**
+   * @brief Add a property animator for an actor
+   *
+   * @param[in] actor An owner of the animated property
+   * @param[in] map A properties map
+   * @param[in] path An animation path
+   * @param[in] forward A forward vector for the path
+   */
+  void AddPropertyAnimator( Actor actor, Property::Map map, Path path, Vector3 forward );
+
+  /**
+    * @brief Connects to this signal to be notified when a transition animation have finished.
+    *
+    * @return A signal object to connect with
+    */
+  LayoutTransitionSignalType& FinishedSignal();
+
+public:
+  /// @cond internal
+  /**
+   * @brief This constructor is used by LayoutTransitionData::New() method.
+   *
+   * @param[in] layoutTransitonData A pointer to a newly allocated transition data resource
+   */
+  DALI_INTERNAL explicit LayoutTransitionData( Internal::LayoutTransitionData* layoutTransitonData );
+  /// @endcond
+};
+
+}//namespace Toolkit
+}//namespace Dali
+
+#endif // DALI_TOOLKIT_LAYOUTING_LAYOUT_TRANSITION_DATA_H
index 6468ad5..fcfb147 100755 (executable)
@@ -1457,6 +1457,7 @@ void Control::Impl::SetLayout( Toolkit::Internal::LayoutItem& layout )
 
 void Control::Impl::RemoveLayout()
 {
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Control::Impl::RemoveLayout\n");
   if( mLayout )
   {
     mLayout->Unparent();
index 6df2e9f..8fab9fd 100755 (executable)
@@ -21,6 +21,7 @@ toolkit_src_files = \
    $(toolkit_src_dir)/layouting/layout-controller-debug.cpp \
    $(toolkit_src_dir)/layouting/layout-controller-impl.cpp \
    $(toolkit_src_dir)/layouting/linear-layout-impl.cpp \
+   $(toolkit_src_dir)/layouting/layout-transition-data-impl.cpp \
    $(toolkit_src_dir)/layouting/size-negotiation-mapper.cpp \
    $(toolkit_src_dir)/visuals/animated-image/animated-image-visual.cpp \
    $(toolkit_src_dir)/visuals/animated-image/image-cache.cpp \
index f912810..17a75a6 100644 (file)
@@ -17,6 +17,7 @@
 #include <dali/public-api/common/stage.h>
 #include <dali/public-api/actors/layer.h>
 #include <dali-toolkit/internal/layouting/layout-controller-impl.h>
+#include <dali-toolkit/internal/layouting/layout-item-data-impl.h>
 #include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
 #include <dali-toolkit/public-api/controls/control.h>
 #include <dali-toolkit/public-api/controls/control-impl.h>
@@ -42,7 +43,8 @@ namespace Internal
 {
 
 LayoutController::LayoutController()
-: mLayoutRequested(false)
+: mLayoutRequested( false ),
+  mSlotDelegate( this )
 {
 }
 
@@ -52,15 +54,33 @@ LayoutController::~LayoutController()
 
 void LayoutController::Initialize()
 {
+  mAnimation = Animation::New( 0.0f );
 }
 
-void LayoutController::RequestLayout( LayoutItem& LayoutItem )
+void LayoutController::RequestLayout( LayoutItem& layoutItem, int layoutTransitionType )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::RequestLayout\n" );
+  auto actor = Actor::DownCast( layoutItem.GetOwner() );
+  if ( actor )
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::RequestLayout owner[%s] layoutItem[%p] layoutAnimationType(%d)\n", actor.GetName().c_str(), &layoutItem, layoutTransitionType );
+  }
+  else
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::RequestLayout layoutItem[%p] layoutAnimationType(%d)\n", &layoutItem, layoutTransitionType );
+  }
+
   mLayoutRequested = true;
+  if( layoutTransitionType != -1 )
+  {
+    LayoutTransition layoutTransition = LayoutTransition( layoutItem, layoutTransitionType );
+    if( std::find( mLayoutTransitions.begin(), mLayoutTransitions.end(), layoutTransition ) == mLayoutTransitions.end() && layoutItem.GetTransitionData( layoutTransitionType ).Get() )
+    {
+      mLayoutTransitions.push_back( layoutTransition );
+    }
+  }
 
   // Go up the tree and mark all parents to relayout
-  LayoutParent* layoutParent = LayoutItem.GetParent();
+  LayoutParent* layoutParent = layoutItem.GetParent();
   if( layoutParent )
   {
     LayoutGroup& layoutGroup = static_cast< LayoutGroup& >( *layoutParent );
@@ -74,11 +94,10 @@ void LayoutController::RequestLayout( LayoutItem& LayoutItem )
 void LayoutController::Process()
 {
   // Perform the full process.
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, "LayoutController::Process\n" );
 
   if( mLayoutRequested )
   {
-    mLayoutRequested = false;
-
     // If window size has changed, expect stage to have already been updated
     Stage stage = Stage::GetCurrent();
     auto stageWidth  = stage.GetSize().width;
@@ -91,8 +110,34 @@ void LayoutController::Process()
     MeasureHierarchy( stage.GetRootLayer(), widthSpec, heightSpec );
 
     LAYOUT_DEBUG_MEASURE_STATES( stage.GetRootLayer() );
+
+    LayoutTransition layoutTransition;
+    LayoutPositionDataArray layoutPositionDataArray;
+    LayoutDataArray layoutDataArray;
+    LayoutAnimatorArray layoutAnimatorArray;
+    layoutAnimatorArray.push_back( LayoutDataAnimator() );
+    PropertyAnimatorArray childrenPropertiesAnimators;
+
+    if ( mLayoutTransitions.size() )
+    {
+      layoutTransition = mLayoutTransitions.front();
+      mLayoutTransitions.pop_front();
+      mLayoutRequested = ( mLayoutTransitions.size() != 0 );
+    }
+    else
+    {
+      mLayoutRequested = false;
+    }
+
+    LayoutData layoutData( layoutTransition, layoutPositionDataArray, layoutDataArray, layoutAnimatorArray, childrenPropertiesAnimators );
+    LayoutItem::Impl::sLayoutData = &layoutData;
     PerformLayout( stage.GetRootLayer(), 0, 0, stageWidth, stageHeight );
 
+    PerformLayoutPositioning( layoutPositionDataArray, false );
+
+    PerformLayoutAnimation( layoutTransition, layoutPositionDataArray, layoutDataArray, layoutAnimatorArray );
+    LayoutItem::Impl::sLayoutData = nullptr;
+
     LAYOUT_DEBUG_AFTER_LAYOUT( stage.GetRootLayer() );
   }
 }
@@ -145,7 +190,6 @@ void LayoutController::PerformLayout( Actor root, int left, int top, int right,
 
     if( layout )
     {
-      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutController::PerformLayout on layout\n" );
       layout->Layout( left, top, right, bottom );
     }
   }
@@ -161,6 +205,142 @@ void LayoutController::PerformLayout( Actor root, int left, int top, int right,
   }
 }
 
+void LayoutController::PerformLayoutPositioning( LayoutPositionDataArray& layoutPositionDataArray, bool all ) const
+{
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutController::PerformLayoutPositioning %d\n", (int)all );
+
+  for( auto layoutPositionData : layoutPositionDataArray )
+  {
+    Actor actor = Actor::DownCast( layoutPositionData.handle );
+    if( actor && ( !layoutPositionData.animated || all ) )
+    {
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutController::PerformLayoutPositioning %s\n", actor.GetName().c_str() );
+      actor.SetPosition( layoutPositionData.left, layoutPositionData.top );
+      actor.SetSize( layoutPositionData.right - layoutPositionData.left, layoutPositionData.bottom - layoutPositionData.top );
+    }
+  }
+}
+
+void LayoutController::PerformLayoutAnimation( LayoutTransition& layoutTransition, LayoutPositionDataArray& layoutPositionDataArray, LayoutDataArray& layoutDataArray, LayoutAnimatorArray& layoutAnimatorArray )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutController::PerformLayoutAnimation\n" );
+  Animation animation = Animation::New( 0 );
+  bool isAnimatorAdded = false;
+
+  for( auto layoutDataElement : layoutDataArray )
+  {
+    if ( layoutDataElement.animatorIndex >= 0 )
+    {
+      Actor actor = Actor::DownCast( layoutDataElement.handle );
+      if ( actor )
+      {
+        LayoutDataAnimator animator = layoutAnimatorArray[ layoutDataElement.animatorIndex ];
+        TimePeriod timePeriod = TimePeriod( 0, animation.GetDuration() );
+        if (animator.timePeriod.durationSeconds >= 0)
+        {
+          timePeriod = animator.timePeriod;
+        }
+
+        Property::Value value = layoutDataElement.targetValue;
+        // Capture calculated position and size values after layout if target values are not set.
+        // Other values are set to current actor ones.
+        if( value.GetType() == Property::NONE )
+        {
+          if ( layoutDataElement.positionDataIndex < 0)
+          {
+            auto result = std::find_if( layoutPositionDataArray.begin(), layoutPositionDataArray.end(), [&actor](const LayoutPositionData& iter)
+                          { return iter.handle == actor; } );
+            if( result == layoutPositionDataArray.end() )
+            {
+              continue;
+            }
+            layoutDataElement.positionDataIndex = std::distance(layoutPositionDataArray.begin(), result);
+          }
+
+          LayoutPositionData& positionData = layoutPositionDataArray[ layoutDataElement.positionDataIndex ];
+
+          switch ( layoutDataElement.propertyIndex )
+          {
+          case Actor::Property::POSITION:
+            value = Vector3( positionData.left, positionData.top, 0.0f );
+            break;
+          case Actor::Property::POSITION_X:
+            value = positionData.left;
+            break;
+          case Actor::Property::POSITION_Y:
+            value = positionData.top;
+            break;
+          case Actor::Property::SIZE:
+            value = Vector3( positionData.right - positionData.left, positionData.bottom - positionData.top, 0.0f );
+            break;
+          case Actor::Property::SIZE_WIDTH:
+            value = positionData.right - positionData.left;
+            break;
+          case Actor::Property::SIZE_HEIGHT:
+            value = positionData.bottom - positionData.top;
+            break;
+          default:
+            value = actor.GetProperty( layoutDataElement.propertyIndex );
+          }
+        }
+
+        // Failed to get target value, just move the next one
+        if( value.GetType() == Property::NONE )
+        {
+          continue;
+        }
+
+        // Set initial value
+        Property::Value initialValue = layoutDataElement.initialValue;
+        if( initialValue.GetType() != Property::NONE )
+        {
+          actor.SetProperty( layoutDataElement.propertyIndex, initialValue );
+        }
+
+        // Create an animator for the property
+        switch (animator.animatorType)
+        {
+        case LayoutDataAnimator::AnimatorType::ANIMATE_TO:
+        {
+          animation.AnimateTo( Property( actor, layoutDataElement.propertyIndex ), value, animator.alphaFunction, timePeriod );
+          break;
+        }
+        case LayoutDataAnimator::AnimatorType::ANIMATE_BY:
+        {
+          animation.AnimateBy( Property( actor, layoutDataElement.propertyIndex ), value, animator.alphaFunction, timePeriod );
+          break;
+        }
+        case LayoutDataAnimator::AnimatorType::ANIMATE_BETWEEN:
+        {
+          animation.AnimateBetween( Property( actor, layoutDataElement.propertyIndex ), animator.keyFrames, animator.alphaFunction, animator.interpolation );
+          break;
+        }
+        case LayoutDataAnimator::AnimatorType::ANIMATE_PATH:
+          animation.Animate( actor, animator.path, animator.forward, animator.alphaFunction, timePeriod );
+          break;
+        }
+      }
+      isAnimatorAdded = true;
+    }
+  }
+
+  if( isAnimatorAdded )
+  {
+    if( mAnimation.GetState() == Animation::PLAYING )
+    {
+      mAnimation.Clear();
+      if( mAnimationFinishedFunctors.size() != 0 )
+      {
+        mAnimationFinishedFunctors.front()( mAnimation );
+      }
+    }
+
+    mAnimation = animation;
+    mAnimationFinishedFunctors.push_back( AnimationFinishedFunctor( *this, layoutTransition, layoutPositionDataArray ) );
+    mAnimation.FinishedSignal().Connect( mSlotDelegate.GetConnectionTracker(), mAnimationFinishedFunctors.back() );
+    mAnimation.Play();
+  }
+}
 
 } // namespace Internal
 } // namespace Toolkit
index 08db259..1c3130d 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+#include <list>
 #include <dali/public-api/object/base-object.h>
 #include <dali/integration-api/core.h>
 #include <dali-toolkit/public-api/controls/control.h>
 #include <dali-toolkit/devel-api/layouting/layout-controller.h>
 #include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
 #include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+#include <dali-toolkit/internal/layouting/layout-transition-data-impl.h>
 
 namespace Dali
 {
@@ -54,9 +55,9 @@ public:
   void Initialize();
 
   /**
-   * This marks the given layout and all its parents as dirty.
+   * This marks the given layout and all its parents as dirty and triggers a transition if set.
    */
-  void RequestLayout( LayoutItem& layout );
+  void RequestLayout( LayoutItem& layout, int layoutTransitionType );
 
   /**
    * Measures next level of layouts in the actor hierarchy.
@@ -68,6 +69,16 @@ public:
    */
   void PerformLayout( Actor root, int left, int top, int right, int bottom );
 
+  /**
+   * Perform positioning of actors after layout update
+   */
+  void PerformLayoutPositioning( LayoutPositionDataArray& layoutPositionDataArray, bool all ) const;
+
+  /**
+   * Perform animation of actors properties after layout update
+   */
+  void PerformLayoutAnimation( LayoutTransition& layoutTransition, LayoutPositionDataArray& layoutPositionDataArray, LayoutDataArray& layoutDataArray, LayoutAnimatorArray& layoutAnimatorArray );
+
 protected: // Implementation of Processor
 
   /**
@@ -76,7 +87,40 @@ protected: // Implementation of Processor
   virtual void Process();
 
 private:
+  std::list< LayoutTransition > mLayoutTransitions;
+  struct AnimationFinishedFunctor
+  {
+    AnimationFinishedFunctor( LayoutController& layoutController, LayoutTransition& layoutTransition, LayoutPositionDataArray& array )
+    : layoutController( layoutController ),
+      layoutDataPositionArray(),
+      layoutItem( layoutTransition.layoutItem ),
+      layoutTransitionType( layoutTransition.layoutTransitionType )
+    {
+      layoutDataPositionArray.swap( array );
+    }
+
+    void operator()( Animation& animation )
+    {
+      layoutController.PerformLayoutPositioning( layoutDataPositionArray, true );
+      layoutController.mAnimationFinishedFunctors.pop_front();
+      if (layoutTransitionType != -1)
+      {
+        LayoutTransitionDataPtr layoutTransitionDataPtr = layoutItem->GetTransitionData( layoutTransitionType );
+        layoutTransitionDataPtr->EmitSignalFinish( layoutTransitionType );
+      }
+    }
+
+    LayoutController& layoutController;
+    LayoutPositionDataArray layoutDataPositionArray;
+    LayoutItemPtr layoutItem;
+    int layoutTransitionType;
+  };
+
   bool mLayoutRequested;
+  Animation mAnimation;
+  std::list< AnimationFinishedFunctor > mAnimationFinishedFunctors;
+
+  SlotDelegate<LayoutController> mSlotDelegate;
 };
 
 } // namespace Internal
index 0833b3b..c97a8df 100644 (file)
@@ -24,8 +24,10 @@ namespace Toolkit
 namespace Internal
 {
 
-bool LayoutItem::Impl::sUseZeroUnspecifiedMeasureSpec = false;
+class LayoutData;
 
+bool LayoutItem::Impl::sUseZeroUnspecifiedMeasureSpec = false;
+LayoutData* LayoutItem::Impl::sLayoutData = nullptr;
 
 LayoutItem::Impl::Impl()
 : mOwner( nullptr ),
index 2347d28..0e68977 100644 (file)
@@ -20,6 +20,7 @@
 #include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
 #include <dali-toolkit/devel-api/layouting/layout-controller.h>
 #include <dali-toolkit/devel-api/layouting/layout-size.h>
+#include <dali-toolkit/internal/layouting/layout-transition-data-impl.h>
 
 namespace Dali
 {
@@ -27,8 +28,6 @@ namespace Toolkit
 {
 namespace Internal
 {
-class LayoutParent;
-
 
 class LayoutItem::Impl
 {
@@ -81,6 +80,13 @@ public:
 
   static bool sUseZeroUnspecifiedMeasureSpec;
 
+  LayoutTransitionDataPtr mOnChildAddTransitionData;
+  LayoutTransitionDataPtr mOnChildRemoveTransitionData;
+  LayoutTransitionDataPtr mOnOwnerSetTransitionData;
+  LayoutTransitionDataPtr mDefaultTransitionData;
+
+  // To pass layout data during perform layout
+  static LayoutData* sLayoutData;
 };
 
 } // namespace Internal
diff --git a/dali-toolkit/internal/layouting/layout-transition-data-impl.cpp b/dali-toolkit/internal/layouting/layout-transition-data-impl.cpp
new file mode 100644 (file)
index 0000000..f43ee79
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/integration-api/debug.h>
+
+#include <dali/public-api/animation/animation.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/type-registry-helper.h>
+#include <dali-toolkit/public-api/controls/control.h>
+#include <dali/devel-api/object/handle-devel.h>
+#include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+#include <dali-toolkit/internal/layouting/layout-transition-data-impl.h>
+#include <dali-toolkit/internal/layouting/layout-item-data-impl.h>
+
+#include <dali/devel-api/scripting/enum-helper.h>
+
+namespace
+{
+// Key tokens
+const char* TOKEN_PROPERTY("property");
+const char* TOKEN_INITIAL_VALUE("initialValue");
+const char* TOKEN_TARGET_VALUE("targetValue");
+const char* TOKEN_ANIMATOR("animator");
+const char* TOKEN_TYPE("type");
+const char* TOKEN_NAME("name");
+const char* TOKEN_TIME_PERIOD("timePeriod");
+const char* TOKEN_DURATION("duration");
+const char* TOKEN_DELAY("delay");
+const char* TOKEN_ALPHA_FUNCTION("alphaFunction");
+
+DALI_ENUM_TO_STRING_TABLE_BEGIN( ALPHA_FUNCTION_BUILTIN )
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, LINEAR)
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, REVERSE)
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_IN)
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_OUT)
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_IN_OUT)
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_IN_SQUARE)
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_OUT_SQUARE)
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_IN_SINE)
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_OUT_SINE)
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_IN_OUT_SINE)
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, EASE_OUT_BACK)
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, BOUNCE)
+DALI_ENUM_TO_STRING_WITH_SCOPE(Dali::AlphaFunction, SIN)
+DALI_ENUM_TO_STRING_TABLE_END( ALPHA_FUNCTION_BUILTIN )
+
+}
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+LayoutTransitionData::LayoutTransitionData()
+{
+}
+
+LayoutTransitionData::~LayoutTransitionData()
+{
+}
+
+LayoutTransitionDataPtr LayoutTransitionData::New()
+{
+  LayoutTransitionDataPtr layoutAnimationData( new LayoutTransitionData() );
+  return layoutAnimationData;
+}
+
+LayoutTransitionData::PropertyAnimator::PropertyAnimator( )
+  : handle( Actor( ) )
+  , map()
+  , interpolation( Animation::Linear )
+{
+}
+
+LayoutTransitionData::PropertyAnimator::PropertyAnimator( Actor actor, Property::Map map )
+  : handle( actor )
+  , map( map )
+  , interpolation( Animation::Linear )
+{
+}
+
+LayoutTransitionData::PropertyAnimator::PropertyAnimator( Actor actor,  Property::Map map, Path path, Vector3 forward )
+  : handle( actor )
+  , map( map )
+  , interpolation( Animation::Linear )
+  , path( path )
+  , forward( forward )
+{
+}
+
+LayoutTransitionData::PropertyAnimator::PropertyAnimator( Actor actor, Property::Map map, KeyFrames keyFrames, Animation::Interpolation interpolation  )
+  : handle( actor )
+  , map( map )
+  , keyFrames( keyFrames )
+  , interpolation( interpolation )
+{
+}
+
+void LayoutTransitionData::AddPropertyAnimator( Actor actor, Property::Map map )
+{
+  mPropertyAnimators.push_back( PropertyAnimator( actor, map ) );
+}
+
+void LayoutTransitionData::AddPropertyAnimator( Actor actor, Property::Map map, KeyFrames keyFrames, Animation::Interpolation interpolation )
+{
+  mPropertyAnimators.push_back( PropertyAnimator( actor, map, keyFrames, interpolation ) );
+}
+
+void LayoutTransitionData::AddPropertyAnimator( Actor actor, Property::Map map, Path path, Vector3 forward )
+{
+  mPropertyAnimators.push_back( PropertyAnimator( actor, map, path, forward ) );
+}
+
+bool LayoutTransitionData::ConvertToLayoutAnimator( const Property::Map& animatorMap, const PropertyAnimator& propertyAnimator, LayoutDataAnimator& layoutDataAnimator )
+{
+  bool valid = true;
+
+  for ( size_t animatorMapIdx = 0; animatorMapIdx < animatorMap.Count(); ++animatorMapIdx )
+  {
+    const KeyValuePair pair( animatorMap.GetKeyValue( animatorMapIdx ) );
+
+    Property::Index indexKey = Property::INVALID_INDEX;
+    if ( pair.first.type == Property::Key::STRING )
+    {
+      const std::string& key(pair.first.stringKey);
+      if( key == TOKEN_TYPE )
+      {
+        indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::TYPE;
+      }
+      else if( key == TOKEN_NAME )
+      {
+        indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::NAME;
+      }
+      else if( key == TOKEN_TIME_PERIOD )
+      {
+        indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::TIME_PERIOD;
+      }
+      else if( key == TOKEN_ALPHA_FUNCTION )
+      {
+        indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION;
+      }
+    }
+    else
+    {
+      indexKey = pair.first.indexKey;
+    }
+
+    const Property::Value& value( pair.second );
+
+    if ( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::ALPHA_FUNCTION )
+    {
+      if ( value.GetType() == Property::ARRAY )
+      {
+        valid = true;
+        Vector4 controlPoints;
+        Property::Array *array = value.GetArray();
+        if ( array && array->Count() >= 4 )
+        {
+          for ( size_t vecIdx = 0; vecIdx < 4; ++vecIdx )
+          {
+            Property::Value& v = array->GetElementAt( vecIdx );
+            if ( v.GetType() == Property::FLOAT )
+            {
+              controlPoints[vecIdx] = v.Get<float>();
+            }
+            else
+            {
+              valid = false;
+              break;
+            }
+          }
+        }
+        else
+        {
+          valid = false;
+        }
+
+        if ( valid )
+        {
+          Vector2 controlPoint1( controlPoints.x, controlPoints.y );
+          Vector2 controlPoint2( controlPoints.z, controlPoints.w );
+          layoutDataAnimator.alphaFunction = AlphaFunction( controlPoint1, controlPoint2 );
+        }
+        else
+        {
+          valid = false;
+        }
+      }
+      else if ( value.GetType() == Property::VECTOR4 )
+      {
+        Vector4 controlPoints = value.Get<Vector4>();
+        Vector2 controlPoint1( controlPoints.x, controlPoints.y );
+        Vector2 controlPoint2( controlPoints.z, controlPoints.w );
+        layoutDataAnimator.alphaFunction = AlphaFunction( controlPoint1, controlPoint2 );
+      }
+      else if ( value.GetType() == Property::STRING )
+      {
+        std::string alphaFunctionValue = value.Get<std::string>();
+
+        if ( alphaFunctionValue == "LINEAR" )
+        {
+          layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::LINEAR );
+        }
+        else if ( !alphaFunctionValue.compare( 0, 5, "EASE_" ) )
+        {
+          if ( alphaFunctionValue == "EASE_IN" )
+          {
+            layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_IN );
+          }
+          else if ( alphaFunctionValue == "EASE_OUT" )
+          {
+            layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_OUT );
+          }
+          else if ( !alphaFunctionValue.compare( 5, 3, "IN_" ) )
+          {
+            if ( !alphaFunctionValue.compare( 8, -1, "SQUARE" ) )
+            {
+              layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_IN_SQUARE );
+            }
+            else if ( !alphaFunctionValue.compare( 8, -1, "OUT" ) )
+            {
+              layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_IN_OUT );
+            }
+            else if ( !alphaFunctionValue.compare( 8, -1, "OUT_SINE" ) )
+            {
+              layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_IN_OUT_SINE );
+            }
+            else if ( !alphaFunctionValue.compare( 8, -1, "SINE" ) )
+            {
+              layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_IN_SINE );
+            }
+          }
+          else if ( !alphaFunctionValue.compare( 5, 4, "OUT_" ) )
+          {
+            if ( !alphaFunctionValue.compare( 9, -1, "SQUARE" ) )
+            {
+              layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_OUT_SQUARE );
+            }
+            else if ( !alphaFunctionValue.compare( 9, -1, "SINE" ) )
+            {
+              layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_OUT_SINE );
+            }
+            else if ( !alphaFunctionValue.compare( 9, -1, "BACK" ) )
+            {
+              layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::EASE_OUT_BACK );
+            }
+          }
+        }
+        else if ( alphaFunctionValue == "REVERSE" )
+        {
+          layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::REVERSE );
+        }
+        else if ( alphaFunctionValue == "BOUNCE" )
+        {
+          layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::BOUNCE );
+        }
+        else if ( alphaFunctionValue == "SIN" )
+        {
+          layoutDataAnimator.alphaFunction = AlphaFunction( AlphaFunction::SIN );
+        }
+        else
+        {
+          valid = false;
+        }
+      }
+      else
+      {
+        valid = false;
+      }
+    }
+    else if ( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::NAME )
+    {
+      if( value.GetType() == Property::STRING )
+      {
+        layoutDataAnimator.name = value.Get<std::string>();
+      }
+    }
+    else if ( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::TYPE )
+    {
+      if( value.GetType() == Property::STRING )
+      {
+        std::string animatorType = value.Get<std::string>();
+        if( animatorType == "ANIMATE_TO" )
+        {
+          layoutDataAnimator.animatorType = LayoutDataAnimator::AnimatorType::ANIMATE_TO;
+        }
+        else if( animatorType == "ANIMATE_BY" )
+        {
+          layoutDataAnimator.animatorType = LayoutDataAnimator::AnimatorType::ANIMATE_BY;
+        }
+        else if( animatorType == "ANIMATE_BETWEEN" )
+        {
+          layoutDataAnimator.animatorType = LayoutDataAnimator::AnimatorType::ANIMATE_BETWEEN;
+          layoutDataAnimator.keyFrames = propertyAnimator.keyFrames;
+        }
+        else if( animatorType == "ANIMATE_PATH" )
+        {
+          layoutDataAnimator.animatorType = LayoutDataAnimator::AnimatorType::ANIMATE_PATH;
+          layoutDataAnimator.path = propertyAnimator.path;
+          layoutDataAnimator.forward = propertyAnimator.forward;
+        }
+      }
+    }
+    else if ( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::TIME_PERIOD )
+    {
+      Property::Map timeMap = value.Get<Property::Map>();
+      for ( size_t timeMapIdx = 0; timeMapIdx < timeMap.Count(); ++timeMapIdx )
+      {
+        const KeyValuePair pair( timeMap.GetKeyValue( timeMapIdx ) );
+        indexKey = Property::INVALID_INDEX;
+
+        if ( pair.first.type == Property::Key::STRING)
+        {
+          const std::string& key( pair.first.stringKey );
+          if( key == TOKEN_DURATION )
+          {
+            indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::DURATION;
+          }
+          else if( key == TOKEN_DELAY )
+          {
+            indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::DELAY;
+          }
+        }
+        else
+        {
+          indexKey = pair.first.indexKey;
+        }
+
+        if ( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::DELAY )
+        {
+          layoutDataAnimator.timePeriod.delaySeconds = pair.second.Get<float>();
+        }
+        else if ( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::DURATION )
+        {
+          layoutDataAnimator.timePeriod.durationSeconds = pair.second.Get<float>();
+        }
+      }
+    }
+  }
+
+  return valid;
+}
+
+bool LayoutTransitionData::ConvertToLayoutDataElement( const PropertyAnimator& propertyAnimator, LayoutDataElement& layoutDataElement, LayoutData& layoutData )
+{
+  const Property::Map& map = propertyAnimator.map;
+  bool propertyFound = false;
+
+  for( unsigned int mapIdx = 0; mapIdx < map.Count(); ++mapIdx )
+  {
+    const KeyValuePair pair( map.GetKeyValue( mapIdx ) );
+    const Property::Value& value( pair.second );
+    Property::Index indexKey = Property::INVALID_INDEX;
+
+    if ( pair.first.type == Property::Key::STRING )
+    {
+      const std::string& key( pair.first.stringKey );
+      if ( key == TOKEN_PROPERTY )
+      {
+        indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::PROPERTY;
+      }
+      else if( key == TOKEN_INITIAL_VALUE )
+      {
+        indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::INITIAL_VALUE;
+      }
+      else if( key == TOKEN_TARGET_VALUE )
+      {
+        indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::TARGET_VALUE;
+      }
+      else if( key == TOKEN_ANIMATOR )
+      {
+        indexKey = Dali::Toolkit::LayoutTransitionData::AnimatorKey::ANIMATOR;
+      }
+    }
+    else
+    {
+      indexKey = pair.first.indexKey;
+    }
+
+    if( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::PROPERTY )
+    {
+      if( value.GetType() == Property::STRING )
+      {
+        Actor actor = Actor::DownCast( layoutDataElement.handle );
+        layoutDataElement.propertyIndex = DevelHandle::GetPropertyIndex( actor, Property::Key( value.Get<std::string>() ) );
+      }
+      else
+      {
+        layoutDataElement.propertyIndex = value.Get<int>();
+      }
+      propertyFound = true;
+    }
+    else if( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::INITIAL_VALUE )
+    {
+      layoutDataElement.initialValue = value;
+    }
+    else if( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::TARGET_VALUE )
+    {
+      layoutDataElement.targetValue = value;
+    }
+    else if( indexKey == Dali::Toolkit::LayoutTransitionData::AnimatorKey::ANIMATOR )
+    {
+      if( value.GetType() == Property::STRING )
+      {
+        std::string animatorName = value.Get<std::string>();
+        if ( animatorName.empty() )
+        {
+          layoutDataElement.animatorIndex = 0;
+        }
+        else
+        {
+          auto animator = std::find_if( layoutData.layoutAnimatorArray.begin(), layoutData.layoutAnimatorArray.end(), [&animatorName](const LayoutDataAnimator& iter) {
+            return (iter.name == animatorName); } );
+          if( animator != layoutData.layoutAnimatorArray.end() )
+          {
+            layoutDataElement.animatorIndex = std::distance( layoutData.layoutAnimatorArray.begin(), animator );
+          }
+        }
+      }
+      else if ( value.GetType() == Property::MAP )
+      {
+        Property::Map animatorMap = value.Get< Property::Map >();
+        LayoutDataAnimator layoutDataAnimator;
+        if( ConvertToLayoutAnimator( animatorMap, propertyAnimator, layoutDataAnimator ) )
+        {
+          layoutData.layoutAnimatorArray.push_back( layoutDataAnimator );
+          layoutDataElement.animatorIndex = layoutData.layoutAnimatorArray.size()-1;
+        }
+      }
+    }
+  }
+
+  return propertyFound;
+}
+
+void LayoutTransitionData::ConvertToLayoutDataElements( Actor owner, LayoutData& layoutData )
+{
+  LayoutDataArray& layoutDataArray = layoutData.layoutDataArray;
+  // Add the children animators
+  for( const PropertyAnimator& iter : layoutData.childrenPropertyAnimators )
+  {
+    LayoutDataElement layoutDataElement;
+    layoutDataElement.handle = owner;
+    layoutDataElement.positionDataIndex = layoutData.layoutPositionDataArray.size() - 1;
+
+    if( ConvertToLayoutDataElement( iter, layoutDataElement, layoutData ) )
+    {
+      layoutDataArray.push_back( layoutDataElement );
+    }
+  }
+
+  // Add the transition animators
+  for( const PropertyAnimator& iter : mPropertyAnimators )
+  {
+    if( iter.handle == nullptr )
+    {
+      layoutData.childrenPropertyAnimators.push_back( iter );
+      continue;
+    }
+
+    LayoutDataElement layoutDataElement;
+    layoutDataElement.handle = iter.handle;
+    if( ConvertToLayoutDataElement( iter, layoutDataElement, layoutData ) )
+    {
+      layoutDataArray.push_back( layoutDataElement );
+    }
+  }
+}
+
+Dali::Toolkit::LayoutTransitionData::LayoutTransitionSignalType& LayoutTransitionData::FinishedSignal()
+{
+  return mFinishedSignal;
+}
+
+void LayoutTransitionData::EmitSignalFinish( int layoutTransitionType )
+{
+  if ( !mFinishedSignal.Empty() )
+  {
+    Dali::Toolkit::LayoutTransitionData handle( this );
+    mFinishedSignal.Emit( static_cast<Dali::Toolkit::LayoutTransitionData::LayoutTransitionType>(layoutTransitionType), handle );
+  }
+}
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/internal/layouting/layout-transition-data-impl.h b/dali-toolkit/internal/layouting/layout-transition-data-impl.h
new file mode 100644 (file)
index 0000000..eb9e9d9
--- /dev/null
@@ -0,0 +1,246 @@
+#ifndef DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_TRANSITION_DATA_IMPL_H
+#define DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_TRANSITION_DATA_IMPL_H
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/object/property-map.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/actors/actor-enumerations.h>
+#include <dali/public-api/animation/animation.h>
+
+#include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
+#include <dali-toolkit/devel-api/layouting/layout-transition-data.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+struct LayoutTransition
+{
+  LayoutTransition( LayoutItem& layoutItem, int layoutTransitionType )
+  : layoutItem( &layoutItem )
+  , layoutTransitionType( layoutTransitionType )
+  {
+  }
+
+  LayoutTransition()
+  : layoutTransitionType( -1 )
+  {
+  }
+
+  bool operator==( const LayoutTransition& rhs )
+  {
+    return ( ( layoutItem.Get() == rhs.layoutItem.Get() ) && layoutTransitionType == rhs.layoutTransitionType );
+  }
+
+  LayoutItemPtr layoutItem;
+  int layoutTransitionType;
+};
+
+const float DEFAULT_TRANSITION_DURATION( 0.5f );
+
+struct LayoutDataAnimator
+{
+   enum class AnimatorType
+   {
+     ANIMATE_TO,
+     ANIMATE_BY,
+     ANIMATE_BETWEEN,
+     ANIMATE_PATH
+   };
+
+   LayoutDataAnimator()
+   : animatorType( AnimatorType::ANIMATE_TO ),
+     alphaFunction( AlphaFunction::LINEAR ),
+     timePeriod( 0.0f, DEFAULT_TRANSITION_DURATION ),
+     interpolation( Animation::Linear )
+   {
+   }
+
+   std::string name;
+   AnimatorType animatorType;
+   AlphaFunction alphaFunction;
+   TimePeriod timePeriod;
+
+   KeyFrames keyFrames;
+   Animation::Interpolation interpolation;
+
+   Path path;
+   Vector3 forward;
+};
+
+using LayoutAnimatorArray = std::vector< LayoutDataAnimator >;
+
+struct LayoutPositionData
+{
+  LayoutPositionData( Handle handle, float left, float top, float right, float bottom, bool animated ) :
+      handle( handle ), left( left ), top( top ), right( right ), bottom( bottom ), animated( animated )
+  {
+  };
+
+  BaseHandle handle;
+  float left;
+  float top;
+  float right;
+  float bottom;
+  bool animated;
+};
+
+using LayoutPositionDataArray = std::vector< LayoutPositionData >;
+
+struct LayoutDataElement
+{
+  LayoutDataElement()
+  : propertyIndex( Property::INVALID_KEY ), animatorIndex( -1 ), positionDataIndex(-1 )
+  {
+  };
+
+  LayoutDataElement( Actor actor, Property::Index propertyIndex, Property::Value value )
+  : handle( actor ),
+    propertyIndex( propertyIndex ),
+    targetValue( value ),
+    animatorIndex( -1 ),
+    positionDataIndex( -1 )
+  {
+  };
+
+  BaseHandle handle;
+  Property::Index propertyIndex;
+  Property::Value initialValue;
+  Property::Value targetValue;
+  int animatorIndex;
+  int positionDataIndex;
+};
+
+class LayoutTransitionData;
+using LayoutTransitionDataPtr = IntrusivePtr<LayoutTransitionData>;
+
+/**
+ * LayoutTransitionData implementation class.
+ */
+class DALI_TOOLKIT_API LayoutTransitionData : public BaseObject
+{
+public:
+  struct PropertyAnimator
+  {
+    PropertyAnimator();
+    PropertyAnimator( Actor actor, Property::Map map );
+    PropertyAnimator( Actor actor, Property::Map map, Path path, Vector3 forward );
+    PropertyAnimator( Actor actor, Property::Map map, KeyFrames keyFrames, Animation::Interpolation interpolation );
+
+    BaseHandle handle;
+
+    Property::Map map;
+
+    KeyFrames keyFrames;
+    Animation::Interpolation interpolation;
+
+    Path path;
+    Vector3 forward;
+  };
+
+  using PropertyAnimatorArray = std::vector< PropertyAnimator >;
+
+  static LayoutTransitionDataPtr New();
+
+  LayoutTransitionData( const LayoutTransitionData& ) = delete;
+  LayoutTransitionData& operator=( const LayoutTransitionData& ) = delete;
+
+  void AddPropertyAnimator( Actor actor, Property::Map map );
+  void AddPropertyAnimator( Actor actor, Property::Map map, KeyFrames keyFrames, Animation::Interpolation interpolation );
+  void AddPropertyAnimator( Actor actor, Property::Map map, Path path, Vector3 forward );
+
+  void ConvertToLayoutDataElements( Actor, LayoutData& layoutData );
+
+  /**
+   * @copydoc Dali::Animation::FinishedSignal()
+   */
+  Dali::Toolkit::LayoutTransitionData::LayoutTransitionSignalType& FinishedSignal();
+
+  void EmitSignalFinish( int layoutTransitionType );
+
+private:
+  bool ConvertToLayoutAnimator( const Property::Map& animatorData, const PropertyAnimator& propertyAnimator, LayoutDataAnimator& layoutAnimator );
+  bool ConvertToLayoutDataElement( const PropertyAnimator& propertyAnimator, LayoutDataElement& layoutDataElement, LayoutData& layoutData );
+
+  PropertyAnimatorArray mPropertyAnimators;
+
+  /**
+   * Ref counted object - Only allow construction via New().
+   */
+  LayoutTransitionData();
+
+protected:
+  /**
+   *  A ref counted object may only be deleted by calling Unreference
+   */
+  virtual ~LayoutTransitionData();
+
+  Dali::Toolkit::LayoutTransitionData::LayoutTransitionSignalType mFinishedSignal;
+};
+
+using PropertyAnimatorArray = std::vector< LayoutTransitionData::PropertyAnimator >;
+using LayoutTransitionDataArray = std::vector< LayoutTransitionDataPtr >;
+using LayoutDataArray = std::vector< LayoutDataElement >;
+
+struct LayoutData
+{
+  LayoutData( LayoutTransition& layoutTransition, LayoutPositionDataArray& layoutPositionDataArray, LayoutDataArray& layoutDataArray,
+      LayoutAnimatorArray& layoutAnimatorArray, PropertyAnimatorArray& childrenPropertyAnimators )
+  : speculativeLayout( false ),
+    layoutTransition( layoutTransition ),
+    layoutPositionDataArray( layoutPositionDataArray ),
+    layoutDataArray( layoutDataArray),
+    layoutAnimatorArray( layoutAnimatorArray ),
+    childrenPropertyAnimators( childrenPropertyAnimators )
+  {
+  };
+
+  bool speculativeLayout;
+  LayoutTransition& layoutTransition;
+  LayoutPositionDataArray& layoutPositionDataArray;
+  LayoutDataArray& layoutDataArray;
+  LayoutAnimatorArray& layoutAnimatorArray;
+  PropertyAnimatorArray& childrenPropertyAnimators;
+};
+
+} //namespace Internal
+
+inline Internal::LayoutTransitionData& GetImplementation( Dali::Toolkit::LayoutTransitionData& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "LayoutTransitionData handle is empty" );
+  BaseObject& object = handle.GetBaseObject();
+  return static_cast< Internal::LayoutTransitionData& >( object );
+}
+
+inline const Internal::LayoutTransitionData& GetImplementation( const Dali::Toolkit::LayoutTransitionData& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "LayoutTransitionData handle is empty" );
+  const BaseObject& object = handle.GetBaseObject();
+  return static_cast< const Internal::LayoutTransitionData& >( object );
+}
+
+} //namespace Toolkit
+} //namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_TRANSITION_DATA_IMPL_H