[dali_1.3.29] Merge branch 'devel/master' 65/182365/1
authorVictor Cebollada <v.cebollada@samsung.com>
Fri, 22 Jun 2018 07:55:57 +0000 (08:55 +0100)
committerVictor Cebollada <v.cebollada@samsung.com>
Fri, 22 Jun 2018 07:55:57 +0000 (08:55 +0100)
Change-Id: I784d42cf5036496ecd37705173228c220b9f648e

42 files changed:
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/layout-utils.cpp [new file with mode: 0755]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/layout-utils.h [new file with mode: 0644]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-adaptor.cpp
automated-tests/src/dali-toolkit/utc-Dali-AbsoluteLayout.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/utc-Dali-FlexLayout.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/utc-Dali-Layouting.cpp
dali-toolkit/devel-api/file.list
dali-toolkit/devel-api/layouting/absolute-layout.cpp [moved from dali-toolkit/devel-api/layouting/hbox-layout.cpp with 51% similarity]
dali-toolkit/devel-api/layouting/absolute-layout.h [new file with mode: 0644]
dali-toolkit/devel-api/layouting/flex-layout.cpp [new file with mode: 0644]
dali-toolkit/devel-api/layouting/flex-layout.h [new file with mode: 0644]
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-group.cpp
dali-toolkit/devel-api/layouting/layout-group.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.h
dali-toolkit/devel-api/layouting/layout-parent-impl.h
dali-toolkit/devel-api/layouting/linear-layout.cpp [new file with mode: 0644]
dali-toolkit/devel-api/layouting/linear-layout.h [moved from dali-toolkit/devel-api/layouting/hbox-layout.h with 59% similarity]
dali-toolkit/devel-api/layouting/measure-spec.h
dali-toolkit/devel-api/layouting/measured-size.h
dali-toolkit/devel-api/layouting/vbox-layout.h
dali-toolkit/devel-api/toolkit-property-index-ranges.h
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/layouting/absolute-layout-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/layouting/absolute-layout-impl.h [moved from dali-toolkit/internal/layouting/hbox-layout-impl.h with 50% similarity]
dali-toolkit/internal/layouting/flex-layout-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/layouting/flex-layout-impl.h [new file with mode: 0644]
dali-toolkit/internal/layouting/hbox-layout-impl.cpp [deleted file]
dali-toolkit/internal/layouting/layout-controller-debug.cpp
dali-toolkit/internal/layouting/layout-controller-impl.cpp
dali-toolkit/internal/layouting/linear-layout-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/layouting/linear-layout-impl.h [new file with mode: 0644]
dali-toolkit/internal/layouting/vbox-layout-impl.cpp
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index a839b3f..c3bbf75 100755 (executable)
@@ -7,7 +7,7 @@ SET(CAPI_LIB "dali-toolkit")
 
 # List of test case sources (Only these get parsed for test cases)
 SET(TC_SOURCES
-  utc-Dali-Layouting.cpp
+  utc-Dali-AbsoluteLayout.cpp
   utc-Dali-Alignment.cpp
   utc-Dali-AnimatedImageVisual.cpp
   utc-Dali-BloomView.cpp
@@ -18,11 +18,13 @@ SET(TC_SOURCES
   utc-Dali-CubeTransitionEffect.cpp
   utc-Dali-EffectsView.cpp
   utc-Dali-FlexContainer.cpp
+  utc-Dali-FlexLayout.cpp
   utc-Dali-GaussianBlurView.cpp
   utc-Dali-ImageView.cpp
   utc-Dali-ImageVisual.cpp
   utc-Dali-JsonParser.cpp
   utc-Dali-KeyInputFocusManager.cpp
+  utc-Dali-Layouting.cpp
   utc-Dali-PageTurnView.cpp
   utc-Dali-Script.cpp
   utc-Dali-ScrollBar.cpp
@@ -89,6 +91,7 @@ LIST(APPEND TC_SOURCES
   dali-toolkit-test-utils/toolkit-trigger-event-factory.cpp
   dali-toolkit-test-utils/dali-test-suite-utils.cpp
   dali-toolkit-test-utils/dummy-control.cpp
+  dali-toolkit-test-utils/layout-utils.cpp
   dali-toolkit-test-utils/mesh-builder.cpp
   dali-toolkit-test-utils/test-actor-utils.cpp
   dali-toolkit-test-utils/test-animation-data.cpp
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/layout-utils.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/layout-utils.cpp
new file mode 100755 (executable)
index 0000000..54ff302
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ *
+ */
+
+// FILE HEADER
+#include "layout-utils.h"
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
+#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/devel-api/layouting/flex-layout.h>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+Control CreateLeafControl( int width, int height )
+{
+  auto control = Control::New();
+  control.SetName( "Leaf" );
+
+  auto pixelBuffer = Devel::PixelBuffer::New( 1, 1, Pixel::RGB888 );
+  unsigned char* pixels = pixelBuffer.GetBuffer();
+  pixels[0] = 0xff;
+  pixels[1] = 0x00;
+  pixels[2] = 0x00;
+  auto texture = Texture::New( TextureType::TEXTURE_2D, Pixel::RGB888, 1, 1 );
+  auto pixelData = Devel::PixelBuffer::Convert( pixelBuffer );
+  texture.Upload( pixelData );
+  std::string url = TextureManager::AddTexture( texture );
+
+  Property::Map map;
+  map[ Visual::Property::TYPE ] = Visual::IMAGE;
+  map[ ImageVisual::Property::URL ] = url;
+  map[ ImageVisual::Property::DESIRED_WIDTH ] = (float) width;
+  map[ ImageVisual::Property::DESIRED_HEIGHT ] = (float) height;
+  control.SetProperty( Control::Property::BACKGROUND, map );
+  return control;
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/layout-utils.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/layout-utils.h
new file mode 100644 (file)
index 0000000..c0ef58f
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef __DALI_TOOLKIT_LAYOUT_UTILS_H__
+#define __DALI_TOOLKIT_LAYOUT_UTILS_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 <dali-toolkit/dali-toolkit.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+/**
+ * @brief Creates an empty leaf control filled with red color for layout tests
+ *
+ * @param[in] width The width of the control.
+ * @param[in] height The height of the control.
+ * @param[out] Control The control.
+ */
+Control CreateLeafControl( int width, int height );
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_LAYOUT_UTILS_H__
index 3ff177c..eb1f2b8 100644 (file)
@@ -97,7 +97,7 @@ void Adaptor::Stop()
 {
 }
 
-bool Adaptor::AddIdle( CallbackBase* callback )
+bool Adaptor::AddIdle( CallbackBase* callback, bool hasReturnValue )
 {
   const bool isAvailable = IsAvailable();
 
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AbsoluteLayout.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AbsoluteLayout.cpp
new file mode 100644 (file)
index 0000000..e443b7e
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * 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 <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/devel-api/layouting/absolute-layout.h>
+
+#include <layout-utils.h>
+
+using namespace Dali;
+using namespace Toolkit;
+
+void utc_dali_toolkit_absolute_layout_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_toolkit_absolute_layoutg_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+int UtcDaliLayouting_AbsoluteLayoutDownCast(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliLayouting_AbsoluteLayoutDownCast - Testing Downcast");
+
+  AbsoluteLayout absoluteLayout = AbsoluteLayout::New();
+
+  LayoutGroup layoutGroup( absoluteLayout );
+
+  AbsoluteLayout absoluteLayoutCandidate = AbsoluteLayout::DownCast( layoutGroup );
+  DALI_TEST_CHECK( absoluteLayoutCandidate );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_AbsoluteLayoutAssignment(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliLayouting_AbsoluteLayoutAssignment - Testing operator=");
+
+  AbsoluteLayout absoluteLayout = AbsoluteLayout::New();
+  AbsoluteLayout absoluteLayout2;
+
+  absoluteLayout2 = absoluteLayout;
+
+  DALI_TEST_CHECK( absoluteLayout2 == absoluteLayout );
+
+  END_TEST;
+}
+
+
+int UtcDaliLayouting_AbsoluteLayout01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_AbsoluteLayout01 - Position an item with Actor::Property::POSITION");
+
+  Stage stage = Stage::GetCurrent();
+  auto absoluteLayout = Control::New();
+  auto layout = AbsoluteLayout::New();
+  DevelControl::SetLayout( absoluteLayout, layout );
+  absoluteLayout.SetName( "AsoluteLayout");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+
+  // Position one of the  controls using the actor property.
+  controls[1].SetProperty(Actor::Property::POSITION, Vector3( 100.0f, 0.0f, 0.0f) );
+
+  for( auto&& iter : controls )
+  {
+    absoluteLayout.Add( iter );
+  }
+  absoluteLayout.SetParentOrigin( ParentOrigin::CENTER );
+  absoluteLayout.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( absoluteLayout );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // AbsoluteLayout renders items at the positions given by their Actor::Property::POSITION relative to the top left of the container.
+  // Items can overlap or spill out of their parent container.
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // The controls[1] was the only control to have a defiend position
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 100.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Items size should not change regardless of parent's size.
+  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 );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
\ No newline at end of file
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-FlexLayout.cpp b/automated-tests/src/dali-toolkit/utc-Dali-FlexLayout.cpp
new file mode 100644 (file)
index 0000000..8317361
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ * 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 <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/devel-api/controls/control-devel.h>
+#include <dali-toolkit/devel-api/layouting/flex-layout.h>
+
+#include <layout-utils.h>
+
+using namespace Dali;
+using namespace Toolkit;
+
+void utc_dali_toolkit_flexlayout_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_toolkit_flexlayout_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliLayouting_FlexLayout01(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_FlexLayout01");
+
+  Stage stage = Stage::GetCurrent();
+  auto flexBox = Control::New();
+  auto flexLayout = FlexLayout::New();
+  flexLayout.SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection::ROW );
+  flexLayout.SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::CENTER );
+  DevelControl::SetLayout( flexBox, flexLayout );
+  flexBox.SetName( "Flexbox");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 60 ) );
+  controls.push_back( CreateLeafControl( 80, 80 ) );
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+
+  const Extents CONTROL_MARGIN = Extents( 0, 10, 0, 0 );
+  for( auto&& iter : controls )
+  {
+    iter.SetProperty(Toolkit::Control::Property::MARGIN, CONTROL_MARGIN );
+    flexBox.Add( iter );
+  }
+  flexBox.SetParentOrigin( ParentOrigin::CENTER );
+  flexBox.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( flexBox );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // To see goto https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjIsImFsaWduQ29udGVudCI6MSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsInBhZGRpbmciOnsidG9wIjoiIiwicmlnaHQiOiIiLCJib3R0b20iOiIiLCJsZWZ0IjoiIn0sIm1hcmdpbiI6eyJyaWdodCI6IjEwIn0sInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH19LHsid2lkdGgiOiI2MCIsImhlaWdodCI6IjYwIiwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwiYWxpZ25JdGVtcyI6MCwiYWxpZ25Db250ZW50IjowLCJwYWRkaW5nIjp7InRvcCI6IiIsInJpZ2h0IjoiIiwiYm90dG9tIjoiIiwibGVmdCI6IiJ9LCJtYXJnaW4iOnsicmlnaHQiOiIxMCJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fSx7IndpZHRoIjoiODAiLCJoZWlnaHQiOiI4MCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjAsImFsaWduQ29udGVudCI6MCwicGFkZGluZyI6eyJ0b3AiOiIiLCJyaWdodCI6IiIsImJvdHRvbSI6IiIsImxlZnQiOiIifSwibWFyZ2luIjp7InJpZ2h0IjoiMTAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6MTAwLCJoZWlnaHQiOjEwMCwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwiYWxpZ25JdGVtcyI6MCwiYWxpZ25Db250ZW50IjowLCJwYWRkaW5nIjp7InRvcCI6IiIsInJpZ2h0IjoiIiwiYm90dG9tIjoiIiwibGVmdCI6IiJ9LCJtYXJnaW4iOnsicmlnaHQiOiIxMCJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fV19
+  DALI_TEST_EQUALS( flexBox.GetProperty<Vector3>(Actor::Property::POSITION), Vector3( 0, 0, 0 ),TEST_LOCATION);
+  DALI_TEST_EQUALS( flexBox.GetProperty<Vector3>(Actor::Property::SIZE), Vector3( 480, 800, 0 ),TEST_LOCATION);
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 50.0f, 370.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 120.0f, 360.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 210.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 80.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  const Extents CONTROL_PADDING = Extents( 5, 10, 15, 15 );
+  for( auto&& iter : controls )
+  {
+    iter.SetProperty(Toolkit::Control::Property::PADDING, CONTROL_PADDING );
+    flexBox.Add( iter );
+  }
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // To see go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjIsImFsaWduQ29udGVudCI6MSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsInBhZGRpbmciOnsidG9wIjoiMTUiLCJyaWdodCI6IjEwIiwiYm90dG9tIjoiMTUiLCJsZWZ0IjoiNSJ9LCJtYXJnaW4iOnsicmlnaHQiOiIxMCJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fSx7IndpZHRoIjoiNjAiLCJoZWlnaHQiOiI2MCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjAsImFsaWduQ29udGVudCI6MCwicGFkZGluZyI6eyJ0b3AiOiIxNSIsInJpZ2h0IjoiMTAiLCJib3R0b20iOiIxNSIsImxlZnQiOiI1In0sIm1hcmdpbiI6eyJyaWdodCI6IjEwIn0sInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH19LHsid2lkdGgiOiI4MCIsImhlaWdodCI6IjgwIiwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwiYWxpZ25JdGVtcyI6MCwiYWxpZ25Db250ZW50IjowLCJwYWRkaW5nIjp7InRvcCI6IjE1IiwicmlnaHQiOiIxMCIsImJvdHRvbSI6IjE1IiwibGVmdCI6IjUifSwibWFyZ2luIjp7InJpZ2h0IjoiMTAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6MTAwLCJoZWlnaHQiOjEwMCwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwiYWxpZ25JdGVtcyI6MCwiYWxpZ25Db250ZW50IjowLCJwYWRkaW5nIjp7InRvcCI6IjE1IiwicmlnaHQiOiIxMCIsImJvdHRvbSI6IjE1IiwibGVmdCI6IjUifSwibWFyZ2luIjp7InJpZ2h0IjoiMTAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 365.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 65.0f, 355.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 150.0f, 345.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 255.0f, 335.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 55.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 75.0f, 90.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 95.0f, 110.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 115.0f, 130.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  const Extents FLEXBOX_PADDING = Extents( 25, 25, 25, 25 );
+  flexBox.SetProperty(Toolkit::Control::Property::PADDING, FLEXBOX_PADDING );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // To see go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjIsImFsaWduQ29udGVudCI6MSwicGFkZGluZyI6eyJ0b3AiOiIyNSIsInJpZ2h0IjoiMjUiLCJib3R0b20iOiIyNSIsImxlZnQiOiIyNSJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9LCJmbGV4V3JhcCI6MSwiY2hpbGRyZW4iOlt7IndpZHRoIjoiNDAiLCJoZWlnaHQiOiI0MCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjAsImFsaWduQ29udGVudCI6MCwicGFkZGluZyI6eyJ0b3AiOiIxNSIsInJpZ2h0IjoiMTAiLCJib3R0b20iOiIxNSIsImxlZnQiOiI1In0sIm1hcmdpbiI6eyJyaWdodCI6IjEwIn0sInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH19LHsid2lkdGgiOiI2MCIsImhlaWdodCI6IjYwIiwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwiYWxpZ25JdGVtcyI6MCwiYWxpZ25Db250ZW50IjowLCJwYWRkaW5nIjp7InRvcCI6IjE1IiwicmlnaHQiOiIxMCIsImJvdHRvbSI6IjE1IiwibGVmdCI6IjUifSwibWFyZ2luIjp7InJpZ2h0IjoiMTAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjgwIiwiaGVpZ2h0IjoiODAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsInBhZGRpbmciOnsidG9wIjoiMTUiLCJyaWdodCI6IjEwIiwiYm90dG9tIjoiMTUiLCJsZWZ0IjoiNSJ9LCJtYXJnaW4iOnsicmlnaHQiOiIxMCJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fSx7IndpZHRoIjoxMDAsImhlaWdodCI6MTAwLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsInBhZGRpbmciOnsidG9wIjoiMTUiLCJyaWdodCI6IjEwIiwiYm90dG9tIjoiMTUiLCJsZWZ0IjoiNSJ9LCJtYXJnaW4iOnsicmlnaHQiOiIxMCJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fV19
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 25.0f, 365.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 90.0f, 355.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 175.0f, 345.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 280.0f, 335.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 55.0f, 70.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 75.0f, 90.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 95.0f, 110.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 115.0f, 130.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_FlexLayout02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_FlexLayout02");
+
+  Stage stage = Stage::GetCurrent();
+  auto flexBox = Control::New();
+  auto flexLayout = FlexLayout::New();
+  flexLayout.SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection::ROW );
+  flexLayout.SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::CENTER );
+
+  DevelControl::SetLayout( flexBox, flexLayout );
+  flexBox.SetName( "Flexbox");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 60 ) );
+  controls.push_back( CreateLeafControl( 80, 80 ) );
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+
+  const Extents CONTROL_MARGIN = Extents( 0, 10, 0, 0 );
+  for( auto&& iter : controls )
+  {
+    iter.SetProperty( Toolkit::Control::Property::MARGIN, CONTROL_MARGIN );
+    flexBox.Add( iter );
+  }
+
+  controls[1].SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  controls[1].SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+
+  flexBox.SetParentOrigin( ParentOrigin::CENTER );
+  flexBox.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( flexBox );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // flexbox centers elements vertically, it fills test harness stage, which is 480x800.
+  DALI_TEST_EQUALS( flexBox.GetProperty<Vector3>(Actor::Property::POSITION), Vector3( 0, 0, 0 ),TEST_LOCATION);
+  DALI_TEST_EQUALS( flexBox.GetProperty<Vector3>(Actor::Property::SIZE), Vector3( 480, 800, 0 ),TEST_LOCATION);
+
+  DALI_TEST_EQUALS( controls[1].GetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION ), Property::Value( ChildLayoutData::WRAP_CONTENT ), TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION ), Property::Value( ChildLayoutData::MATCH_PARENT ), TEST_LOCATION );
+
+  // left aligned elements with right margin 10
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 50.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 120.0f, 360.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 210.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 80.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_FlexLayout03(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_FlexLayout03 Test nested flex boxes");
+
+  Stage stage = Stage::GetCurrent();
+
+  auto flexbox1 = Control::New();
+  auto flexLayout1 = FlexLayout::New();
+  DevelControl::SetLayout( flexbox1, flexLayout1 );
+  flexbox1.SetName( "Flexbox1");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 20, 20 ) );
+  controls.push_back( CreateLeafControl( 30, 30 ) );
+  flexbox1.Add( controls[0] );
+  flexbox1.Add( controls[1] );
+  flexbox1.SetParentOrigin( ParentOrigin::CENTER );
+  flexbox1.SetAnchorPoint( AnchorPoint::CENTER );
+
+  flexLayout1.SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection::ROW );
+  flexLayout1.SetFlexWrap(Dali::Toolkit::FlexLayout::WrapType::NO_WRAP);
+  flexLayout1.SetFlexAlignment( Dali::Toolkit::FlexLayout::Alignment::FLEX_START );
+  flexLayout1.SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::FLEX_START );
+  flexLayout1.SetFlexJustification( Dali::Toolkit::FlexLayout::Justification::FLEX_START );
+
+  auto flexbox2 = Control::New();
+  auto flexLayout2 = FlexLayout::New();
+  DevelControl::SetLayout( flexbox2, flexLayout2 );
+  flexbox2.SetName( "Flexbox2");
+
+  controls.push_back( CreateLeafControl( 25, 25 ) );
+  controls.push_back( CreateLeafControl( 35, 35 ) );
+  flexbox2.Add( controls[2] );
+  flexbox2.Add( controls[3] );
+  flexbox2.SetParentOrigin( ParentOrigin::CENTER );
+  flexbox2.SetAnchorPoint( AnchorPoint::CENTER );
+
+  flexLayout2.SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection::COLUMN );
+  flexLayout2.SetFlexWrap(Dali::Toolkit::FlexLayout::WrapType::NO_WRAP);
+  flexLayout2.SetFlexAlignment( Dali::Toolkit::FlexLayout::Alignment::FLEX_START );
+  flexLayout2.SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::FLEX_START );
+  flexLayout2.SetFlexJustification( Dali::Toolkit::FlexLayout::Justification::FLEX_START );
+
+  auto flexbox3 = Control::New();
+  auto flexLayout3 = FlexLayout::New();
+  DevelControl::SetLayout( flexbox3, flexLayout3 );
+  flexbox3.SetParentOrigin( ParentOrigin::CENTER );
+  flexbox3.SetName( "Flexbox3");
+  flexbox3.Add( flexbox1 );
+  flexbox3.Add( flexbox2 );
+  stage.Add( flexbox3 );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 20.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 30.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 55.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 20.0f, 20.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 30.0f, 30.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 25.0f, 25.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 35.0f, 35.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Test flexbox1,2 are sized to wrap their content
+  DALI_TEST_EQUALS( flexbox1.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 50.0f, 30.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( flexbox2.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 35.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( flexbox1.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( flexbox2.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 30.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Test flexbox3 matches parent (root layer)
+  DALI_TEST_EQUALS( flexbox3.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( flexbox3.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_FlexLayout04(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_FlexLayout04");
+
+  Stage stage = Stage::GetCurrent();
+  auto flexBox = Control::New();
+  auto flexLayout = FlexLayout::New();
+  flexLayout.SetFlexAlignment( Dali::Toolkit::FlexLayout::Alignment::FLEX_START );
+  flexLayout.SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::FLEX_START );
+  flexLayout.SetFlexWrap(Dali::Toolkit::FlexLayout::WrapType::NO_WRAP);
+  flexLayout.SetFlexJustification( Dali::Toolkit::FlexLayout::Justification::FLEX_START );
+  flexLayout.SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection::COLUMN );
+  DevelControl::SetLayout( flexBox, flexLayout );
+  flexBox.SetName( "Flexbox");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 60 ) );
+  for( auto&& iter : controls )
+  {
+    flexBox.Add( iter );
+  }
+  flexBox.SetParentOrigin( ParentOrigin::CENTER );
+  flexBox.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( flexBox );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsImFsaWduQ29udGVudCI6MSwiZmxleERpcmVjdGlvbiI6MCwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJtYXJnaW4iOnsicmlnaHQiOiIwIn0sInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH19LHsid2lkdGgiOiI2MCIsImhlaWdodCI6IjYwIiwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwibWFyZ2luIjp7InJpZ2h0IjoiMTAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Ensure layouting happens
+  flexLayout.SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection::COLUMN_REVERSE );
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsImFsaWduQ29udGVudCI6MSwiZmxleERpcmVjdGlvbiI6MSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJtYXJnaW4iOnsicmlnaHQiOiIwIn0sInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH19LHsid2lkdGgiOiI2MCIsImhlaWdodCI6IjYwIiwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwibWFyZ2luIjp7InJpZ2h0IjoiMTAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 760.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 700.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Ensure layouting happens
+  flexLayout.SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection::ROW );
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsImFsaWduQ29udGVudCI6MSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJtYXJnaW4iOnsicmlnaHQiOiIwIn0sInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH19LHsid2lkdGgiOiI2MCIsImhlaWdodCI6IjYwIiwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwibWFyZ2luIjp7InJpZ2h0IjoiMTAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 40.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Ensure layouting happens
+  flexLayout.SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection::ROW_REVERSE );
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsImFsaWduQ29udGVudCI6MSwiZmxleERpcmVjdGlvbiI6MywicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJtYXJnaW4iOnsicmlnaHQiOiIwIn0sInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH19LHsid2lkdGgiOiI2MCIsImhlaWdodCI6IjYwIiwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwibWFyZ2luIjp7InJpZ2h0IjoiMTAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 440.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 380.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Ensure layouting happens
+  flexLayout.SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection::ROW );
+  flexLayout.SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::CENTER );
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjIsImFsaWduQ29udGVudCI6MSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiY2hpbGRyZW4iOlt7IndpZHRoIjoiNDAiLCJoZWlnaHQiOiI0MCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjYwIiwiaGVpZ2h0IjoiNjAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJtYXJnaW4iOnsicmlnaHQiOiIxMCJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fV19
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 40.0f, 370.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Ensure layouting happens
+  flexLayout.SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::FLEX_END );
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjMsImFsaWduQ29udGVudCI6MSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiY2hpbGRyZW4iOlt7IndpZHRoIjoiNDAiLCJoZWlnaHQiOiI0MCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjYwIiwiaGVpZ2h0IjoiNjAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJtYXJnaW4iOnsicmlnaHQiOiIxMCJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fV19
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 760.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 40.0f, 740.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Ensure layouting happens
+  flexLayout.SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::STRETCH );
+  controls[0].SetProperty( Actor::Property::MAXIMUM_SIZE, Vector2(40.f, 40.f) );
+  controls[1].SetProperty( Actor::Property::MAXIMUM_SIZE, Vector2(60.f, 60.f) );
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsImFsaWduQ29udGVudCI6MSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiY2hpbGRyZW4iOlt7IndpZHRoIjoiNDAiLCJoZWlnaHQiOiI0MCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjAsImFsaWduQ29udGVudCI6MCwibWFyZ2luIjp7InJpZ2h0IjoiMCJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fSx7IndpZHRoIjoiNjAiLCJoZWlnaHQiOiI2MCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjAsImFsaWduQ29udGVudCI6MCwibWFyZ2luIjp7InJpZ2h0IjoiMCJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fV19
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 40.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  flexLayout.SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::FLEX_START );
+  flexLayout.SetFlexJustification( Dali::Toolkit::FlexLayout::Justification::FLEX_START );
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsImFsaWduQ29udGVudCI6MSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiY2hpbGRyZW4iOlt7IndpZHRoIjoiNDAiLCJoZWlnaHQiOiI0MCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjAsImFsaWduQ29udGVudCI6MCwibWFyZ2luIjp7InJpZ2h0IjoiMCJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fSx7IndpZHRoIjoiNjAiLCJoZWlnaHQiOiI2MCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjAsImFsaWduQ29udGVudCI6MCwibWFyZ2luIjp7InJpZ2h0IjoiMCJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fV19
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 40.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  flexLayout.SetFlexJustification( Dali::Toolkit::FlexLayout::Justification::CENTER );
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImp1c3RpZnlDb250ZW50IjoxLCJhbGlnbkl0ZW1zIjoxLCJhbGlnbkNvbnRlbnQiOjEsInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH0sImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjYwIiwiaGVpZ2h0IjoiNjAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 190.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 230.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  flexLayout.SetFlexJustification( Dali::Toolkit::FlexLayout::Justification::FLEX_END );
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImp1c3RpZnlDb250ZW50IjoyLCJhbGlnbkl0ZW1zIjoxLCJhbGlnbkNvbnRlbnQiOjEsInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH0sImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjYwIiwiaGVpZ2h0IjoiNjAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 380.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 420.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  flexLayout.SetFlexJustification( Dali::Toolkit::FlexLayout::Justification::SPACE_BETWEEN );
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImp1c3RpZnlDb250ZW50IjozLCJhbGlnbkl0ZW1zIjoxLCJhbGlnbkNvbnRlbnQiOjEsInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH0sImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjYwIiwiaGVpZ2h0IjoiNjAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 420.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  flexLayout.SetFlexJustification( Dali::Toolkit::FlexLayout::Justification::SPACE_AROUND );
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImp1c3RpZnlDb250ZW50Ijo0LCJhbGlnbkl0ZW1zIjoxLCJhbGlnbkNvbnRlbnQiOjEsInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH0sImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjYwIiwiaGVpZ2h0IjoiNjAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 95.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 325.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_FlexLayout05(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_FlexLayout05");
+
+  Stage stage = Stage::GetCurrent();
+  auto flexBox = Control::New();
+  auto flexLayout = FlexLayout::New();
+  flexLayout.SetFlexAlignment( Dali::Toolkit::FlexLayout::Alignment::FLEX_START );
+  flexLayout.SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::FLEX_START );
+  flexLayout.SetFlexWrap(Dali::Toolkit::FlexLayout::WrapType::NO_WRAP);
+  flexLayout.SetFlexJustification( Dali::Toolkit::FlexLayout::Justification::FLEX_START );
+  flexLayout.SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection::ROW );
+  DevelControl::SetLayout( flexBox, flexLayout );
+  flexBox.SetName( "Flexbox");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 200, 200 ) );
+  controls.push_back( CreateLeafControl( 400, 400 ) );
+  for( auto&& iter : controls )
+  {
+    flexBox.Add( iter );
+  }
+  flexBox.SetParentOrigin( ParentOrigin::CENTER );
+  flexBox.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( flexBox );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // Shrink is off
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 200.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 200.0f, 200.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 400.0f, 400.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  flexLayout.SetFlexWrap(Dali::Toolkit::FlexLayout::WrapType::WRAP);
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsImFsaWduQ29udGVudCI6MSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjIwMCIsImhlaWdodCI6IjIwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjQwMCIsImhlaWdodCI6IjQwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 200.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 200.0f, 200.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 400.0f, 400.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  flexLayout.SetFlexAlignment(Dali::Toolkit::FlexLayout::Alignment::CENTER);
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsImFsaWduQ29udGVudCI6MiwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjIwMCIsImhlaWdodCI6IjIwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjQwMCIsImhlaWdodCI6IjQwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 300.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 200.0f, 200.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 400.0f, 400.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  flexLayout.SetFlexAlignment(Dali::Toolkit::FlexLayout::Alignment::FLEX_END);
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsImFsaWduQ29udGVudCI6MiwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjIwMCIsImhlaWdodCI6IjIwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjQwMCIsImhlaWdodCI6IjQwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 200.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( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 200.0f, 200.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 400.0f, 400.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  flexLayout.SetFlexAlignment(Dali::Toolkit::FlexLayout::Alignment::STRETCH);
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // To see the test go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsImFsaWduQ29udGVudCI6MiwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjIwMCIsImhlaWdodCI6IjIwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjQwMCIsImhlaWdodCI6IjQwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX1dfQ==
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 300.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 200.0f, 200.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 400.0f, 400.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_FlexLayout06(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_FlexLayout06");
+
+  Stage stage = Stage::GetCurrent();
+  auto flexBox = Control::New();
+  auto flexLayout = FlexLayout::New();
+  flexLayout.SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection::COLUMN );
+  flexLayout.SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::FLEX_START );
+  DevelControl::SetLayout( flexBox, flexLayout );
+  flexBox.SetName( "Flexbox");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 60 ) );
+  controls.push_back( CreateLeafControl( 80, 80 ) );
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+  for( auto&& iter : controls )
+  {
+    flexBox.Add( iter );
+  }
+  flexBox.SetParentOrigin( ParentOrigin::CENTER );
+  flexBox.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( flexBox );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // flexbox centers elements vertically, it fills test harness stage, which is 480x800.
+  // left aligned elements with right margin 10
+  // To see goto https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsImFsaWduQ29udGVudCI6MSwiZmxleERpcmVjdGlvbiI6MCwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjYwIiwiaGVpZ2h0IjoiNjAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjgwIiwiaGVpZ2h0IjoiODAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6MTAwLCJoZWlnaHQiOjEwMCwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwiYWxpZ25JdGVtcyI6MCwiYWxpZ25Db250ZW50IjowLCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fV19
+  DALI_TEST_EQUALS( flexBox.GetProperty<Vector3>(Actor::Property::POSITION), Vector3(0, 0, 0),TEST_LOCATION);
+  DALI_TEST_EQUALS( flexBox.GetProperty<Vector3>(Actor::Property::SIZE), Vector3(480, 800, 0),TEST_LOCATION);
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 180.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 80.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  flexBox.Remove( controls[1] );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // To see goto https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjEsImFsaWduQ29udGVudCI6MSwiZmxleERpcmVjdGlvbiI6MCwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjgwIiwiaGVpZ2h0IjoiODAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6MTAwLCJoZWlnaHQiOjEwMCwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwiYWxpZ25JdGVtcyI6MCwiYWxpZ25Db250ZW50IjowLCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fV19
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 120.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 80.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_FlexLayout07(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_FlexLayout07");
+
+  Stage stage = Stage::GetCurrent();
+  auto flexBox = Control::New();
+  auto flexLayout = FlexLayout::New();
+  flexLayout.SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection::ROW );
+  flexLayout.SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::CENTER );
+  DevelControl::SetLayout( flexBox, flexLayout );
+  flexBox.SetName( "Flexbox");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 60 ) );
+  controls.push_back( CreateLeafControl( 80, 80 ) );
+  controls.push_back( CreateLeafControl( 100, 100 ) );
+
+  for( auto&& iter : controls )
+  {
+    iter.SetProperty( Toolkit::FlexLayout::ChildProperty::FLEX, 0.f );
+    iter.SetProperty( Toolkit::FlexLayout::ChildProperty::ALIGN_SELF, Dali::Toolkit::FlexLayout::Alignment::AUTO );
+    flexBox.Add( iter );
+  }
+  flexBox.SetParentOrigin( ParentOrigin::CENTER );
+  flexBox.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( flexBox );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // To see goto https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjIsImFsaWduQ29udGVudCI6MSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjYwIiwiaGVpZ2h0IjoiNjAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjgwIiwiaGVpZ2h0IjoiODAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6MTAwLCJoZWlnaHQiOjEwMCwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwiYWxpZ25JdGVtcyI6MCwiYWxpZ25Db250ZW50IjowLCJtYXJnaW4iOnsicmlnaHQiOiIwIn0sInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH19XX0=
+  DALI_TEST_EQUALS( flexBox.GetProperty<Vector3>(Actor::Property::POSITION), Vector3( 0, 0, 0 ),TEST_LOCATION);
+  DALI_TEST_EQUALS( flexBox.GetProperty<Vector3>(Actor::Property::SIZE), Vector3( 480, 800, 0 ),TEST_LOCATION);
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 40.0f, 370.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 100.0f, 360.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 180.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 80.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  for( auto&& iter : controls )
+  {
+    iter.SetProperty( Toolkit::FlexLayout::ChildProperty::FLEX, 0.25f );
+    iter.SetProperty( Toolkit::FlexLayout::ChildProperty::ALIGN_SELF, Toolkit::FlexLayout::Alignment::AUTO );
+  }
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // To see go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjIsImFsaWduQ29udGVudCI6MSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleEdyb3ciOiIwLjI1In0seyJ3aWR0aCI6IjYwIiwiaGVpZ2h0IjoiNjAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleEdyb3ciOiIwLjI1In0seyJ3aWR0aCI6IjgwIiwiaGVpZ2h0IjoiODAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleEdyb3ciOiIwLjI1In0seyJ3aWR0aCI6MTAwLCJoZWlnaHQiOjEwMCwibWluV2lkdGgiOm51bGwsIm1pbkhlaWdodCI6bnVsbCwibWF4V2lkdGgiOm51bGwsIm1heEhlaWdodCI6bnVsbCwiYWxpZ25JdGVtcyI6MCwiYWxpZ25Db250ZW50IjowLCJtYXJnaW4iOnsicmlnaHQiOiIwIn0sInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH0sImZsZXhHcm93IjoiMC4yNSJ9XX0=
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 120.0f, 370.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 240.0f, 360.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 360.0f, 350.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 120.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 120.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 120.0f, 80.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 120.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  for( auto&& iter : controls )
+  {
+    iter.SetProperty( Toolkit::FlexLayout::ChildProperty::FLEX, 0.f );
+  }
+  controls[0].SetProperty( Toolkit::FlexLayout::ChildProperty::ALIGN_SELF, Toolkit::FlexLayout::Alignment::CENTER );
+  controls[1].SetProperty( Toolkit::FlexLayout::ChildProperty::ALIGN_SELF, Toolkit::FlexLayout::Alignment::FLEX_START );
+  controls[2].SetProperty( Toolkit::FlexLayout::ChildProperty::ALIGN_SELF, Toolkit::FlexLayout::Alignment::FLEX_END );
+  controls[3].SetProperty( Toolkit::FlexLayout::ChildProperty::ALIGN_SELF, Toolkit::FlexLayout::Alignment::STRETCH );
+  controls[3].SetProperty( Actor::Property::MAXIMUM_SIZE, Vector2(100.f, 100.f) );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // To see go to https://yogalayout.com/playground/#eyJ3aWR0aCI6IjQ4MCIsImhlaWdodCI6IjgwMCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjIsImFsaWduQ29udGVudCI6MSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfSwiZmxleFdyYXAiOjEsImNoaWxkcmVuIjpbeyJ3aWR0aCI6IjQwIiwiaGVpZ2h0IjoiNDAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnbkNvbnRlbnQiOjAsIm1hcmdpbiI6eyJyaWdodCI6IjAifSwicG9zaXRpb24iOnsidG9wIjpudWxsLCJyaWdodCI6bnVsbCwiYm90dG9tIjpudWxsLCJsZWZ0IjpudWxsfX0seyJ3aWR0aCI6IjYwIiwiaGVpZ2h0IjoiNjAiLCJtaW5XaWR0aCI6bnVsbCwibWluSGVpZ2h0IjpudWxsLCJtYXhXaWR0aCI6bnVsbCwibWF4SGVpZ2h0IjpudWxsLCJhbGlnbkl0ZW1zIjowLCJhbGlnblNlbGYiOjEsImFsaWduQ29udGVudCI6MCwibWFyZ2luIjp7InJpZ2h0IjoiMCJ9LCJwb3NpdGlvbiI6eyJ0b3AiOm51bGwsInJpZ2h0IjpudWxsLCJib3R0b20iOm51bGwsImxlZnQiOm51bGx9fSx7IndpZHRoIjoiODAiLCJoZWlnaHQiOiI4MCIsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjAsImFsaWduU2VsZiI6MywiYWxpZ25Db250ZW50IjowLCJtYXJnaW4iOnsicmlnaHQiOiIwIn0sInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH19LHsid2lkdGgiOjEwMCwiaGVpZ2h0IjoxMDAsIm1pbldpZHRoIjpudWxsLCJtaW5IZWlnaHQiOm51bGwsIm1heFdpZHRoIjpudWxsLCJtYXhIZWlnaHQiOm51bGwsImFsaWduSXRlbXMiOjAsImFsaWduU2VsZiI6NCwiYWxpZ25Db250ZW50IjowLCJtYXJnaW4iOnsicmlnaHQiOiIwIn0sInBvc2l0aW9uIjp7InRvcCI6bnVsbCwicmlnaHQiOm51bGwsImJvdHRvbSI6bnVsbCwibGVmdCI6bnVsbH19XX0=
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 40.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 100.0f, 720.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 180.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 60.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 80.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 100.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_FlexLayout08(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_FlexLayout08");
+
+  Stage stage = Stage::GetCurrent();
+
+  auto flexbox1 = Control::New();
+  auto flexLayout1 = FlexLayout::New();
+  DevelControl::SetLayout( flexbox1, flexLayout1 );
+  flexbox1.SetName( "Flexbox1");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 20, 20 ) );
+  flexbox1.Add( controls[0] );
+  flexbox1.SetParentOrigin( ParentOrigin::CENTER );
+  flexbox1.SetAnchorPoint( AnchorPoint::CENTER );
+  const Extents CONTROL_MARGIN = Extents( 10, 10, 10, 10 );
+  const Extents CONTROL_PADDING = Extents( 5, 5, 5, 5 );
+  flexbox1.SetProperty( Toolkit::Control::Property::MARGIN, CONTROL_MARGIN );
+  flexbox1.SetProperty( Toolkit::Control::Property::PADDING, CONTROL_PADDING );
+  flexbox1.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  flexbox1.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+
+  auto flexbox2 = Control::New();
+  auto flexLayout2 = FlexLayout::New();
+  DevelControl::SetLayout( flexbox2, flexLayout2 );
+  flexbox2.SetParentOrigin( ParentOrigin::CENTER );
+  flexbox2.SetName( "Flexbox2");
+  flexbox2.Add( flexbox1 );
+  stage.Add( flexbox2 );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 15.0f, 15.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 20.0f, 20.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( flexbox1.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 30.0f, 30.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( flexbox2.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( flexbox1.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 10.0f, 10.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( flexbox2.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
index deb8eb8..4246d16 100644 (file)
 #include <iostream>
 #include <stdlib.h>
 #include <dali-toolkit-test-suite-utils.h>
+
 #include <dali-toolkit/dali-toolkit.h>
-#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
-#include <dali-toolkit/devel-api/image-loader/texture-manager.h>
 #include <dali-toolkit/devel-api/controls/control-devel.h>
-#include <dali-toolkit/devel-api/layouting/hbox-layout.h>
-#include <dali-toolkit/devel-api/layouting/vbox-layout.h>
-//#include <dali-toolkit/internal/controls/control/control-data-impl-debug.h>
+#include <dali-toolkit/devel-api/layouting/absolute-layout.h>
+#include <dali-toolkit/devel-api/layouting/linear-layout.h>
+
+#include <layout-utils.h>
 
 using namespace Dali;
 using namespace Toolkit;
@@ -39,31 +39,6 @@ void utc_dali_toolkit_layouting_cleanup(void)
   test_return_value = TET_PASS;
 }
 
-
-Control CreateLeafControl( int width, int height )
-{
-  auto control = Control::New();
-  control.SetName( "Leaf" );
-
-  auto pixelBuffer = Devel::PixelBuffer::New( 1, 1, Pixel::RGB888 );
-  unsigned char* pixels = pixelBuffer.GetBuffer();
-  pixels[0] = 0xff;
-  pixels[1] = 0x00;
-  pixels[2] = 0x00;
-  auto texture = Texture::New( TextureType::TEXTURE_2D, Pixel::RGB888, 1, 1 );
-  auto pixelData = Devel::PixelBuffer::Convert( pixelBuffer );
-  texture.Upload( pixelData );
-  std::string url = TextureManager::AddTexture( texture );
-
-  Property::Map map;
-  map[ Visual::Property::TYPE ] = Visual::IMAGE;
-  map[ ImageVisual::Property::URL ] = url;
-  map[ ImageVisual::Property::DESIRED_WIDTH ] = (float) width;
-  map[ ImageVisual::Property::DESIRED_HEIGHT ] = (float) height;
-  control.SetProperty( Control::Property::BACKGROUND, map );
-  return control;
-}
-
 int UtcDaliLayouting_HboxLayout01(void)
 {
   ToolkitTestApplication application;
@@ -71,7 +46,7 @@ int UtcDaliLayouting_HboxLayout01(void)
 
   Stage stage = Stage::GetCurrent();
   auto hbox = Control::New();
-  auto hboxLayout = HboxLayout::New();
+  auto hboxLayout = LinearLayout::New();
   hboxLayout.SetCellPadding( LayoutSize( 10, 0 ) );
   DevelControl::SetLayout( hbox, hboxLayout );
   hbox.SetName( "HBox");
@@ -106,6 +81,19 @@ int UtcDaliLayouting_HboxLayout01(void)
   DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
   DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
 
+  // Change a layout
+  auto newHBoxLayout = LinearLayout::New();
+  newHBoxLayout.SetCellPadding( LayoutSize( 10, 0 ) );
+  DevelControl::SetLayout( hbox, newHBoxLayout );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 50.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 120.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 210.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
   END_TEST;
 }
 
@@ -117,11 +105,11 @@ int UtcDaliLayouting_HboxLayout02(void)
   Stage stage = Stage::GetCurrent();
 
   auto hbox1 = Control::New();
-  auto hboxLayout1 = HboxLayout::New();
+  auto hboxLayout1 = LinearLayout::New();
   DevelControl::SetLayout( hbox1, hboxLayout1 );
 
   auto hbox2 = Control::New();
-  auto hboxLayout2 = HboxLayout::New();
+  auto hboxLayout2 = LinearLayout::New();
   DevelControl::SetLayout( hbox2, hboxLayout2 );
 
   hbox1.SetName( "HBox1");
@@ -157,7 +145,7 @@ int UtcDaliLayouting_HboxLayout02(void)
   hbox2.SetAnchorPoint( AnchorPoint::CENTER );
 
   auto hbox3 = Control::New();
-  auto hboxLayout3 = HboxLayout::New();
+  auto hboxLayout3 = LinearLayout::New();
   DevelControl::SetLayout( hbox3, hboxLayout3 );
 
   hbox3.SetParentOrigin( ParentOrigin::CENTER );
@@ -217,11 +205,11 @@ int UtcDaliLayouting_HboxLayout03(void)
   Stage stage = Stage::GetCurrent();
 
   auto hbox1 = Control::New();
-  auto hboxLayout1 = HboxLayout::New();
+  auto hboxLayout1 = LinearLayout::New();
   DevelControl::SetLayout( hbox1, hboxLayout1 );
 
   auto hbox2 = Control::New();
-  auto hboxLayout2 = HboxLayout::New();
+  auto hboxLayout2 = LinearLayout::New();
   DevelControl::SetLayout( hbox2, hboxLayout2 );
 
   hbox1.SetName( "HBox1");
@@ -261,7 +249,7 @@ int UtcDaliLayouting_HboxLayout03(void)
   hbox2.SetAnchorPoint( AnchorPoint::CENTER );
 
   auto hbox3 = Control::New();
-  auto hboxLayout3 = HboxLayout::New();
+  auto hboxLayout3 = LinearLayout::New();
   DevelControl::SetLayout( hbox3, hboxLayout3);
 
   hbox3.SetParentOrigin( ParentOrigin::CENTER );
@@ -322,11 +310,11 @@ int UtcDaliLayouting_HboxLayout04(void)
   Stage stage = Stage::GetCurrent();
 
   auto hbox1 = Control::New();
-  auto hboxLayout1 = HboxLayout::New();
+  auto hboxLayout1 = LinearLayout::New();
   DevelControl::SetLayout( hbox1, hboxLayout1 );
 
   auto hbox2 = Control::New();
-  auto hboxLayout2 = HboxLayout::New();
+  auto hboxLayout2 = LinearLayout::New();
   DevelControl::SetLayout( hbox2, hboxLayout2 );
 
   hbox1.SetName( "HBox1"); // Default spec is to wrap content
@@ -363,7 +351,7 @@ int UtcDaliLayouting_HboxLayout04(void)
 
   controls[6].SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
   auto hbox3 = Control::New();
-  auto hboxLayout3 = HboxLayout::New();
+  auto hboxLayout3 = LinearLayout::New();
   DevelControl::SetLayout( hbox3, hboxLayout3 );
 
   hbox3.SetParentOrigin( ParentOrigin::CENTER );
@@ -414,6 +402,243 @@ int UtcDaliLayouting_HboxLayout04(void)
   END_TEST;
 }
 
+int UtcDaliLayouting_HboxLayout05(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_HboxLayout05 - Set children size explicitly via width & height specification");
+
+  Stage stage = Stage::GetCurrent();
+  auto hbox = Control::New();
+  auto hboxLayout = LinearLayout::New();
+  hboxLayout.SetCellPadding( LayoutSize( 10, 0 ) );
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetName( "HBox");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 40 ) );
+  controls.push_back( CreateLeafControl( 80, 40 ) );
+  controls.push_back( CreateLeafControl( 100, 40 ) );
+
+  for( auto&& iter : controls )
+  {
+    hbox.Add( iter );
+    iter.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, 100 );
+    iter.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, 50 );
+  }
+
+  hbox.SetParentOrigin( ParentOrigin::CENTER );
+  hbox.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( hbox );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // hbox centers elements vertically, it fills test harness stage, which is 480x800.
+  // hbox left justifies elements
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 375.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 110.0f, 375.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 220.0f, 375.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 330.0f, 375.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 50.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 50.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 50.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 50.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_HboxLayout06(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_HboxLayout06 - Test nested layouts");
+
+  Stage stage = Stage::GetCurrent();
+
+  auto rootControl = Control::New();
+  auto absoluteLayout = AbsoluteLayout::New();
+  DevelControl::SetLayout( rootControl, absoluteLayout );
+  rootControl.SetName( "AbsoluteLayout" );
+  stage.Add( rootControl );
+
+  auto hbox = Control::New();
+  auto hboxLayout = LinearLayout::New();
+  hboxLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetName( "HBox" );
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 40 ) );
+
+  for( auto&& iter : controls )
+  {
+    hbox.Add( iter );
+  }
+  hbox.SetParentOrigin( ParentOrigin::CENTER );
+  hbox.SetAnchorPoint( AnchorPoint::CENTER );
+  rootControl.Add( hbox );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // hbox centers elements vertically, it fills test harness stage, which is 480x800.
+  // hbox left justifies elements
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 40.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( hbox.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Change a layout
+  auto newHBoxLayout = LinearLayout::New();
+  newHBoxLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
+  DevelControl::SetLayout( hbox, newHBoxLayout );
+
+  hbox.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  hbox.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( hbox.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Change size specification
+  hbox.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+  hbox.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( hbox.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  // Use WRAP_CONTENT again
+  hbox.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  hbox.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( hbox.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliLayouting_HboxLayout07(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_HboxLayout07 - Set LTR/RTL direction");
+
+  Stage stage = Stage::GetCurrent();
+  auto hbox = Control::New();
+  auto hboxLayout = LinearLayout::New();
+  hboxLayout.SetCellPadding( LayoutSize( 10, 0 ) );
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetName( "HBox");
+
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 40, 40 ) );
+  controls.push_back( CreateLeafControl( 60, 40 ) );
+  controls.push_back( CreateLeafControl( 80, 40 ) );
+  controls.push_back( CreateLeafControl( 100, 40 ) );
+
+  for( auto&& iter : controls )
+  {
+    hbox.Add( iter );
+  }
+  hbox.SetParentOrigin( ParentOrigin::CENTER );
+  hbox.SetAnchorPoint( AnchorPoint::CENTER );
+  stage.Add( hbox );
+
+  hbox.SetProperty( Actor::Property::LAYOUT_DIRECTION, LayoutDirection::LEFT_TO_RIGHT );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  // hbox centers elements vertically, it fills test harness stage, which is 480x800 from left to right.
+  // hbox left justifies elements
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 50.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 120.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 210.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  hbox.SetProperty( Actor::Property::LAYOUT_DIRECTION, LayoutDirection::RIGHT_TO_LEFT );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 470.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 400.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 310.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 200.0f, 380.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( controls[0].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 40.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[1].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 60.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[2].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 80.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( controls[3].GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 100.0f, 40.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_HboxLayout08(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_HboxLayout08 - Test layout animation");
+
+  Stage stage = Stage::GetCurrent();
+
+  auto rootControl = Control::New();
+  auto absoluteLayout = AbsoluteLayout::New();
+  absoluteLayout.SetAnimateLayout( true );
+  DevelControl::SetLayout( rootControl, absoluteLayout );
+  rootControl.SetName( "AbsoluteLayout" );
+  stage.Add( rootControl );
+
+  Control control1 = CreateLeafControl( 40, 40 );
+  rootControl.Add( control1 );
+
+  auto hbox = Control::New();
+  auto hboxLayout = LinearLayout::New();
+  hboxLayout.SetOrientation( LinearLayout::Orientation::HORIZONTAL );
+  DevelControl::SetLayout( hbox, hboxLayout );
+  hbox.SetName( "HBox" );
+
+  Control control2 = CreateLeafControl( 40, 40 );
+  hbox.Add( control2 );
+
+  hbox.SetParentOrigin( ParentOrigin::CENTER );
+  hbox.SetAnchorPoint( AnchorPoint::CENTER );
+  rootControl.Add( hbox );
+
+  DALI_TEST_EQUALS( absoluteLayout.IsLayoutAnimated(), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( DevelControl::GetLayout( control1 ).IsLayoutAnimated(), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( hboxLayout.IsLayoutAnimated(), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( DevelControl::GetLayout( control2 ).IsLayoutAnimated(), false, TEST_LOCATION );
+
+  hboxLayout.SetAnimateLayout( true );
+  absoluteLayout.SetAnimateLayout( false );
+
+  DALI_TEST_EQUALS( absoluteLayout.IsLayoutAnimated(), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( DevelControl::GetLayout( control1 ).IsLayoutAnimated(), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( hboxLayout.IsLayoutAnimated(), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( DevelControl::GetLayout( control2 ).IsLayoutAnimated(), true, TEST_LOCATION );
+
+  END_TEST;
+}
+
 // Padding tests
 
 int UtcDaliLayouting_HboxLayout_Padding01(void)
@@ -423,7 +648,7 @@ int UtcDaliLayouting_HboxLayout_Padding01(void)
 
   Stage stage = Stage::GetCurrent();
   auto hbox = Control::New();
-  auto hboxLayout = HboxLayout::New();
+  auto hboxLayout = LinearLayout::New();
   DevelControl::SetLayout( hbox, hboxLayout );
   hbox.SetName( "HBox");
 
@@ -488,7 +713,7 @@ int UtcDaliLayouting_HboxLayout_Padding02(void)
 
   Stage stage = Stage::GetCurrent();
   auto hbox = Control::New();
-  auto hboxLayout = HboxLayout::New();
+  auto hboxLayout = LinearLayout::New();
   DevelControl::SetLayout( hbox, hboxLayout );
   hbox.SetName( "HBox");
 
@@ -567,7 +792,7 @@ int UtcDaliLayouting_HboxLayout_Padding03(void)
 
   Stage stage = Stage::GetCurrent();
   auto hbox = Control::New();
-  auto hboxLayout = HboxLayout::New();
+  auto hboxLayout = LinearLayout::New();
   DevelControl::SetLayout( hbox, hboxLayout );
   hbox.SetName( "HBox");
 
@@ -653,7 +878,7 @@ int UtcDaliLayouting_HboxLayout_Margin01(void)
 
   Stage stage = Stage::GetCurrent();
   auto hbox = Control::New();
-  auto hboxLayout = HboxLayout::New();
+  auto hboxLayout = LinearLayout::New();
   DevelControl::SetLayout( hbox, hboxLayout );
   hbox.SetName( "HBox");
 
@@ -715,7 +940,8 @@ int UtcDaliLayouting_VboxLayout01(void)
 
   Stage stage = Stage::GetCurrent();
   auto vbox = Control::New();
-  auto vboxLayout = VboxLayout::New();
+  auto vboxLayout = LinearLayout::New();
+  vboxLayout.SetOrientation( LinearLayout::Orientation::VERTICAL );
   DevelControl::SetLayout( vbox, vboxLayout );
   vbox.SetName( "Vbox");
 
@@ -767,17 +993,18 @@ int UtcDaliLayouting_VboxLayout02(void)
   // LayoutGroup for this to happen automatically.
   //
   // For this test, add an hbox instead
-  auto hbox = Control::New();
-  auto hboxLayout = HboxLayout::New();
-  DevelControl::SetLayout( hbox, hboxLayout );
-  hbox.SetName( "Hbox");
-  stage.Add( hbox );
+  auto rootControl = Control::New();
+  auto absoluteLayout = AbsoluteLayout::New();
+  DevelControl::SetLayout( rootControl, absoluteLayout );
+  rootControl.SetName( "AbsoluteLayout");
+  stage.Add( rootControl );
 
   auto vbox = Control::New();
-  auto vboxLayout = VboxLayout::New();
+  auto vboxLayout = LinearLayout::New();
+  vboxLayout.SetOrientation( LinearLayout::Orientation::VERTICAL );
   DevelControl::SetLayout( vbox, vboxLayout );
   vbox.SetName( "Vbox");
-  hbox.Add( vbox );
+  rootControl.Add( vbox );
 
   vbox.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
   vbox.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::MATCH_PARENT );
@@ -804,8 +1031,8 @@ int UtcDaliLayouting_VboxLayout02(void)
   application.SendNotification();
   application.Render();
 
-  DALI_TEST_EQUALS( hbox.GetProperty<Vector3>(Actor::Property::POSITION), Vector3(0,0,0),TEST_LOCATION);
-  DALI_TEST_EQUALS( hbox.GetProperty<Vector3>(Actor::Property::SIZE), Vector3(480,800,0),TEST_LOCATION);
+  DALI_TEST_EQUALS( rootControl.GetProperty<Vector3>(Actor::Property::POSITION), Vector3(0,0,0),TEST_LOCATION);
+  DALI_TEST_EQUALS( rootControl.GetProperty<Vector3>(Actor::Property::SIZE), Vector3(480,800,0),TEST_LOCATION);
 
   // vbox centers elements horizontally, it should wrap it's content horizontally, i.e. it should take the width of the largest element (100)
   DALI_TEST_EQUALS( vbox.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
@@ -838,14 +1065,15 @@ int UtcDaliLayouting_VboxLayout03(void)
   //
   // For this test, add an hbox instead
   auto hbox = Control::New();
-  auto hboxLayout = HboxLayout::New();
+  auto hboxLayout = LinearLayout::New();
   DevelControl::SetLayout( hbox, hboxLayout );
   hbox.SetName( "Hbox");
   stage.Add( hbox );
 
   auto vbox = Control::New();
-  auto vboxLayout = VboxLayout::New();
+  auto vboxLayout = LinearLayout::New();
   vboxLayout.SetCellPadding( LayoutSize( 0, 10 ) );
+  vboxLayout.SetOrientation( LinearLayout::Orientation::VERTICAL );
 
   DALI_TEST_EQUALS( vboxLayout.GetCellPadding(), LayoutSize( 0, 10 ), TEST_LOCATION );
 
index 86d2fc0..dadce6e 100755 (executable)
@@ -31,8 +31,9 @@ devel_api_src_files = \
   $(devel_api_src_dir)/image-loader/atlas-upload-observer.cpp \
   $(devel_api_src_dir)/image-loader/image-atlas.cpp \
   $(devel_api_src_dir)/image-loader/texture-manager.cpp \
-  $(devel_api_src_dir)/layouting/hbox-layout.cpp \
-  $(devel_api_src_dir)/layouting/vbox-layout.cpp \
+  $(devel_api_src_dir)/layouting/flex-layout.cpp \
+  $(devel_api_src_dir)/layouting/absolute-layout.cpp \
+  $(devel_api_src_dir)/layouting/linear-layout.cpp \
   $(devel_api_src_dir)/layouting/layout-item.cpp \
   $(devel_api_src_dir)/layouting/layout-item-impl.cpp \
   $(devel_api_src_dir)/layouting/layout-controller.cpp \
@@ -80,9 +81,10 @@ devel_api_effects_view_header_files = \
   $(devel_api_src_dir)/controls/effects-view/effects-view.h
 
 devel_api_layouting_header_files = \
+  $(devel_api_src_dir)/layouting/absolute-layout.h \
   $(devel_api_src_dir)/layouting/child-layout-data.h \
-  $(devel_api_src_dir)/layouting/hbox-layout.h \
-  $(devel_api_src_dir)/layouting/vbox-layout.h \
+  $(devel_api_src_dir)/layouting/flex-layout.h \
+  $(devel_api_src_dir)/layouting/linear-layout.h \
   $(devel_api_src_dir)/layouting/layout-item.h \
   $(devel_api_src_dir)/layouting/layout-item-impl.h \
   $(devel_api_src_dir)/layouting/layout-controller.h \
  */
 
 //CLASS HEADER
-#include <dali-toolkit/devel-api/layouting/hbox-layout.h>
+#include <dali-toolkit/devel-api/layouting/absolute-layout.h>
 
-//EXTERNAL HEADERS
 //INTERNAL HEADERS
-#include <dali-toolkit/internal/layouting/hbox-layout-impl.h>
+#include <dali-toolkit/internal/layouting/absolute-layout-impl.h>
 
 namespace Dali
 {
 namespace Toolkit
 {
 
-HboxLayout::HboxLayout()
+AbsoluteLayout::AbsoluteLayout()
 {
 }
 
-HboxLayout HboxLayout::New()
+AbsoluteLayout AbsoluteLayout::New()
 {
-  Internal::HboxLayoutPtr internal = Internal::HboxLayout::New();
-  return HboxLayout( internal.Get() );
+  Internal::AbsoluteLayoutPtr internal = Internal::AbsoluteLayout::New();
+  return AbsoluteLayout( internal.Get() );
 }
 
-HboxLayout HboxLayout::DownCast( BaseHandle handle )
+AbsoluteLayout AbsoluteLayout::DownCast( BaseHandle handle )
 {
-  return HboxLayout( dynamic_cast< Dali::Toolkit::Internal::HboxLayout*>( handle.GetObjectPtr() ) );
+  return AbsoluteLayout( dynamic_cast< Dali::Toolkit::Internal::AbsoluteLayout*>( handle.GetObjectPtr() ) );
 }
 
-HboxLayout::HboxLayout( const HboxLayout& other )
+AbsoluteLayout::AbsoluteLayout( const AbsoluteLayout& other )
 : LayoutGroup( other )
 {
 }
 
-HboxLayout& HboxLayout::operator=( const HboxLayout& other )
+AbsoluteLayout& AbsoluteLayout::operator=( const AbsoluteLayout& other )
 {
   if( &other != this )
   {
@@ -55,17 +54,7 @@ HboxLayout& HboxLayout::operator=( const HboxLayout& other )
   return *this;
 }
 
-void HboxLayout::SetCellPadding( LayoutSize size )
-{
-  GetImplementation(*this).SetCellPadding( size );
-}
-
-LayoutSize HboxLayout::GetCellPadding()
-{
-  return GetImplementation(*this).GetCellPadding();
-}
-
-HboxLayout::HboxLayout( Dali::Toolkit::Internal::HboxLayout* object )
+AbsoluteLayout::AbsoluteLayout( Dali::Toolkit::Internal::AbsoluteLayout* object )
 : LayoutGroup( object )
 {
 }
diff --git a/dali-toolkit/devel-api/layouting/absolute-layout.h b/dali-toolkit/devel-api/layouting/absolute-layout.h
new file mode 100644 (file)
index 0000000..5face16
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef DALI_TOOLKIT_LAYOUTING_ABSOLUTE_LAYOUT_H
+#define DALI_TOOLKIT_LAYOUTING_ABSOLUTE_LAYOUT_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 <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali-toolkit/devel-api/layouting/layout-group.h>
+#include <dali-toolkit/devel-api/layouting/layout-size.h>
+#include <dali-toolkit/public-api/toolkit-property-index-ranges.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+namespace Internal DALI_INTERNAL
+{
+class AbsoluteLayout;
+}
+
+/**
+ * This class implements a absolute layout, allowing explict positioning of
+ * children.
+ * Positions are from the top left of the layout and can be set using the
+ * Actor::Property::POSITION and alike.
+ */
+class DALI_TOOLKIT_API AbsoluteLayout : public LayoutGroup
+{
+public:
+
+  enum PropertyRange
+  {
+    CHILD_PROPERTY_START_INDEX = ABSOLUTE_LAYOUT_CHILD_PROPERTY_START_INDEX,
+    CHILD_PROPERTY_END_INDEX   = ABSOLUTE_LAYOUT_CHILD_PROPERTY_END_INDEX
+  };
+
+  /**
+   * @brief Creates an uninitialized AbsoluteLayout handle.
+   *
+   * Initialize it using AbsoluteLayout::New().
+   * Calling member functions with an uninitialized handle is not allowed.
+   */
+  AbsoluteLayout();
+
+  /**
+   * @brief Creates a AbsoluteLayout object.
+   */
+  static AbsoluteLayout New();
+
+  /**
+   * @brief Downcasts a handle to a AbsoluteLayout handle.
+   *
+   * If handle points to a AbsoluteLayout, the downcast produces a valid handle.
+   * If not, the returned handle is left uninitialized.
+
+   * @param[in] handle to an object
+   * @return Handle to a AbsoluteLayout or an uninitialized handle
+   */
+  static AbsoluteLayout DownCast( BaseHandle handle );
+
+  /**
+   * @brief Copy constructor
+   */
+  AbsoluteLayout( const AbsoluteLayout& other );
+
+  /**
+   * @brief Assigment operator
+   */
+  AbsoluteLayout& operator=( const AbsoluteLayout& other );
+
+  /**
+   * @brief Default destructor.
+   *
+   * This is non-virtual, since derived Handle types must not contain data or virtual methods
+   */
+  ~AbsoluteLayout()=default;
+
+
+public: // Not intended for application developers
+
+  /// @cond internal
+  /**
+   * @brief This constructor is used by AbsoluteLayout::New() methods.
+   *
+   * @param[in] actor A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL AbsoluteLayout( Internal::AbsoluteLayout* body );
+  /// @endcond
+};
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_LAYOUTING_ABSOLUTE_LAYOUT_H
diff --git a/dali-toolkit/devel-api/layouting/flex-layout.cpp b/dali-toolkit/devel-api/layouting/flex-layout.cpp
new file mode 100644 (file)
index 0000000..084182b
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+//CLASS HEADER
+#include "flex-layout.h"
+
+//INTERNAL INCLUDES
+#include <dali-toolkit/internal/layouting/flex-layout-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+FlexLayout::FlexLayout()
+{
+}
+
+FlexLayout FlexLayout::New()
+{
+  Internal::FlexLayoutPtr internal = Internal::FlexLayout::New();
+  return FlexLayout( internal.Get() );
+}
+
+FlexLayout FlexLayout::DownCast( BaseHandle handle )
+{
+  return FlexLayout( dynamic_cast< Dali::Toolkit::Internal::FlexLayout*>( handle.GetObjectPtr() ) );
+}
+
+FlexLayout::FlexLayout( const FlexLayout& other )
+: LayoutGroup( other )
+{
+}
+
+FlexLayout& FlexLayout::operator=( const FlexLayout& other )
+{
+  if( &other != this )
+  {
+    LayoutGroup::operator=( other );
+  }
+  return *this;
+}
+
+void FlexLayout::SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection flexDirection )
+{
+  if( GetImplementation(*this).GetFlexDirection() != flexDirection )
+  {
+    GetImplementation(*this).SetFlexDirection( flexDirection );
+    GetImplementation(*this).RequestLayout();
+  }
+}
+
+Dali::Toolkit::FlexLayout::FlexDirection FlexLayout::GetFlexDirection() const
+{
+  return GetImplementation(*this).GetFlexDirection();
+}
+
+void FlexLayout::SetFlexJustification( Dali::Toolkit::FlexLayout::Justification flexJustification )
+{
+  if( GetImplementation(*this).GetFlexJustification() != flexJustification )
+  {
+    GetImplementation(*this).SetFlexJustification( flexJustification );
+    GetImplementation(*this).RequestLayout();
+  }
+}
+
+Dali::Toolkit::FlexLayout::Justification FlexLayout::GetFlexJustification() const
+{
+  return GetImplementation(*this).GetFlexJustification();
+}
+
+void FlexLayout::SetFlexWrap( Dali::Toolkit::FlexLayout::WrapType flexWrap )
+{
+  if( GetImplementation(*this).GetFlexWrap() != flexWrap )
+  {
+    GetImplementation(*this).SetFlexWrap( flexWrap );
+    GetImplementation(*this).RequestLayout();
+  }
+}
+
+Dali::Toolkit::FlexLayout::WrapType FlexLayout::GetFlexWrap() const
+{
+  return GetImplementation(*this).GetFlexWrap();
+}
+
+void FlexLayout::SetFlexAlignment( Dali::Toolkit::FlexLayout::Alignment::Type flexAlignment )
+{
+  if( GetImplementation(*this).GetFlexAlignment() != flexAlignment )
+  {
+    GetImplementation(*this).SetFlexAlignment( flexAlignment );
+    GetImplementation(*this).RequestLayout();
+  }
+}
+
+Dali::Toolkit::FlexLayout::Alignment::Type FlexLayout::GetFlexAlignment() const
+{
+  return GetImplementation(*this).GetFlexAlignment();
+}
+
+void FlexLayout::SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::Type flexAlignment )
+{
+  if( GetImplementation(*this).GetFlexItemsAlignment() != flexAlignment )
+  {
+    GetImplementation(*this).SetFlexItemsAlignment( flexAlignment );
+    GetImplementation(*this).RequestLayout();
+  }
+}
+
+Dali::Toolkit::FlexLayout::Alignment::Type FlexLayout::GetFlexItemsAlignment() const
+{
+  return GetImplementation(*this).GetFlexItemsAlignment();
+}
+
+FlexLayout::FlexLayout( Dali::Toolkit::Internal::FlexLayout* object )
+: LayoutGroup( object )
+{
+}
+
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/layouting/flex-layout.h b/dali-toolkit/devel-api/layouting/flex-layout.h
new file mode 100644 (file)
index 0000000..881478b
--- /dev/null
@@ -0,0 +1,241 @@
+#ifndef DALI_TOOLKIT_LAYOUTING_FLEX_LAYOUT_H
+#define DALI_TOOLKIT_LAYOUTING_FLEX_LAYOUT_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 <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+#include <dali-toolkit/devel-api/layouting/layout-group.h>
+#include <dali-toolkit/devel-api/layouting/layout-size.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+namespace Internal DALI_INTERNAL
+{
+class FlexLayout;
+}
+
+/**
+ * This class implements a flex layout.
+ *
+ * The flex layout implementation is based on open source Facebook Yoga layout engine.
+ * For more information about the flex layout API and how to use it please refer to
+ * https://yogalayout.com/docs/
+ * We implement the subset of the API in the class below.
+ */
+class DALI_TOOLKIT_API FlexLayout : public LayoutGroup
+{
+public:
+
+  enum PropertyRange
+  {
+    CHILD_PROPERTY_START_INDEX = FLEX_LAYOUT_CHILD_PROPERTY_START_INDEX,
+    CHILD_PROPERTY_END_INDEX   = FLEX_LAYOUT_CHILD_PROPERTY_END_INDEX
+  };
+
+  /**
+   * @brief Enumeration for the direction of the main axis in the flex container. This determines
+   * the direction that flex items are laid out in the flex container.
+   */
+  enum class FlexDirection
+  {
+    COLUMN,                  ///< The flexible items are displayed vertically as a column
+    COLUMN_REVERSE,          ///< The flexible items are displayed vertically as a column, but in reverse order
+    ROW,                     ///< The flexible items are displayed horizontally as a row
+    ROW_REVERSE              ///< The flexible items are displayed horizontally as a row, but in reverse order
+  };
+
+  /**
+   * @brief Enumeration for the alignment of the flex items when the items do not use all available
+   * space on the main-axis.
+   */
+  enum class Justification
+  {
+    FLEX_START,              ///< Items are positioned at the beginning of the container
+    CENTER,                  ///< Items are positioned at the center of the container
+    FLEX_END,                ///< Items are positioned at the end of the container
+    SPACE_BETWEEN,           ///< Items are positioned with equal space between the lines
+    SPACE_AROUND             ///< Items are positioned with equal space before, between, and after the lines
+  };
+
+  /**
+   * @brief Enumeration for the alignment of the flex items or lines when the items or lines do not
+   * use all the available space on the cross-axis.
+   */
+  struct Alignment
+  {
+    enum Type
+    {
+      AUTO,                  ///< Inherits the same alignment from the parent (only valid for "alignSelf" property)
+      FLEX_START,            ///< At the beginning of the container
+      CENTER,                ///< At the center of the container
+      FLEX_END,              ///< At the end of the container
+      STRETCH                ///< Stretch to fit the container
+    };
+  };
+
+  /**
+   * @brief Enumeration for the wrap type of the flex container when there is no enough room for
+   * all the items on one flex line.
+   */
+  enum class WrapType
+  {
+    NO_WRAP,                 ///< Flex items laid out in single line (shrunk to fit the flex container along the main axis)
+    WRAP                     ///< Flex items laid out in multiple lines if needed
+  };
+
+  struct ChildProperty
+  {
+    enum
+    {
+      FLEX = CHILD_PROPERTY_START_INDEX, ///< name "flex",      The proportion of the free space in the container the flex item will receive. If all items in the container set this property, their sizes will be proportional to the specified flex factor,  type FLOAT
+      ALIGN_SELF                         ///< name "alignSelf", The alignment of the flex item along the cross axis, which, if set, overrides the default alignment for all items in the container, type INTEGER
+    };
+  };
+
+  /**
+   * @brief Creates an uninitialized FlexLayout handle.
+   *
+   * Initialize it using FlexLayout::New().
+   * Calling member functions with an uninitialized handle is not allowed.
+   */
+  FlexLayout();
+
+  /**
+   * @brief Creates a FlexLayout object.
+   */
+  static FlexLayout New();
+
+  /**
+   * @brief Downcasts a handle to a FlexLayout handle.
+   *
+   * If handle points to a FlexLayout, the downcast produces a valid handle.
+   * If not, the returned handle is left uninitialized.
+
+   * @param[in] handle to an object
+   * @return Handle to a FlexLayout or an uninitialized handle
+   */
+  static FlexLayout DownCast( BaseHandle handle );
+
+  /**
+   * @brief Copy constructor
+   */
+  FlexLayout( const FlexLayout& other );
+
+  /**
+   * @brief Assigment operator
+   */
+  FlexLayout& operator=( const FlexLayout& other );
+
+  /**
+   * @brief Default destructor.
+   *
+   * This is non-virtual, since derived Handle types must not contain data or virtual methods
+   */
+  ~FlexLayout()=default;
+
+  /**
+    * @brief Set the flex direction in the layout.
+    * The direction of the main-axis which determines the direction that flex items are laid out.
+    *
+    * @param[in] flexDirection The flex direction.
+    */
+  void SetFlexDirection( FlexDirection flexDirection );
+
+  /**
+    * @brief Get the flex direction in the layout.
+    *
+    * @return The flex direction.
+    */
+  FlexDirection GetFlexDirection() const;
+
+  /**
+    * @brief Set the justification in the layout.
+    *
+    * @param[in] flexJustification The flex justification.
+    */
+  void SetFlexJustification( Justification flexJustification );
+
+  /**
+    * @brief Get the flex justification in the layout.
+    *
+    * @return The flex justification.
+    */
+  Justification GetFlexJustification() const;
+
+  /**
+    * @brief Set the wrap in the layout.
+    *
+    * @param[in] flexWrap The flex wrap.
+    */
+  void SetFlexWrap( WrapType flexWrap );
+
+  /**
+    * @brief Get the flex wrap in the layout.
+    *
+    * @return The flex wrap.
+    */
+  WrapType GetFlexWrap() const;
+
+  /**
+    * @brief Set the alignment of the layout content.
+    *
+    * @param[in] flexAlignment The alignment of the content.
+    */
+  void SetFlexAlignment( Alignment::Type flexAlignment );
+
+  /**
+    * @brief Get the alignment of the layout content.
+    *
+    * @return The flex content alignment.
+    */
+  Alignment::Type GetFlexAlignment() const;
+
+  /**
+    * @brief Set the alignment of the layout items.
+    *
+    * @param[in] flexAlignment The alignment of the items.
+    */
+  void SetFlexItemsAlignment( Alignment::Type flexAlignment );
+
+  /**
+    * @brief Get the alignment of the layout items.
+    *
+    * @return The flex items alignment.
+    */
+  Alignment::Type GetFlexItemsAlignment() const;
+
+public: // Not intended for application developers
+
+  /// @cond internal
+  /**
+   * @brief This constructor is used by FlexLayout::New() methods.
+   *
+   * @param[in] actor A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL FlexLayout( Internal::FlexLayout* body );
+  /// @endcond
+};
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_LAYOUTING_FLEX_LAYOUT_H
index db5cc5b..fe955a4 100644 (file)
@@ -36,7 +36,7 @@ class LayoutController;
  * @brief Controls the process of layouting the control tree. It provides methods to enable
  * controls to re-layout and internal systems to separately measure and layout controls.
  */
-class DALI_IMPORT_API LayoutController : public BaseHandle
+class DALI_TOOLKIT_API LayoutController : public BaseHandle
 {
 public:
   /**
index 9df05c6..428ac89 100644 (file)
@@ -31,7 +31,7 @@
 namespace
 {
 #if defined(DEBUG_ENABLED)
-Debug::Filter* gLogFilter = Debug::Filter::New( Debug::Concise, false, "LOG_LAYOUT" );
+Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT" );
 #endif
 }
 
@@ -71,6 +71,8 @@ Toolkit::LayoutGroup::LayoutId LayoutGroup::Add( LayoutItem& child )
   childLayout.child = &child;
   mImpl->mChildren.emplace_back( childLayout );
 
+  child.SetParent( this );
+
   auto owner = child.GetOwner();
 
   // If the owner does not have any LayoutItem child properties, add them
@@ -122,7 +124,7 @@ void LayoutGroup::Remove( LayoutItem& child )
 
 void LayoutGroup::RemoveAll()
 {
-  for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; ++iter )
+  for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; )
   {
     OnChildRemove( *iter->child.Get() );
     iter = mImpl->mChildren.erase(iter);
@@ -182,7 +184,7 @@ void LayoutGroup::DoRegisterChildProperties( const std::string& containerType )
 
 void LayoutGroup::OnSetChildProperties( Handle& handle, Property::Index index, Property::Value value )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::OnSetChildProperties");
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::OnSetChildProperties property(%s)\n", handle.GetPropertyName(index).c_str());
 
   if ( ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) &&
          ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
@@ -190,7 +192,14 @@ void LayoutGroup::OnSetChildProperties( Handle& handle, Property::Index index, P
        ( index == Toolkit::Control::Property::MARGIN || index == Toolkit::Control::Property::PADDING ) )
   {
     // If any child properties are set, must perform relayout
-    RequestLayout();
+    for( auto&& child : mImpl->mChildren )
+    {
+      if( child.child->GetOwner() == handle )
+      {
+        child.child->RequestLayout();
+        break;
+      }
+    }
   }
 }
 
@@ -226,36 +235,14 @@ void LayoutGroup::MeasureChild( LayoutItemPtr child,
 #if defined( DEBUG_ENABLED )
   if ( control )
   {
-    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChildWithMargins naturalSizewidth(%f)\n",  control.GetNaturalSize().width );
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChild natural size(%f, %f)\n",  control.GetNaturalSize().width, control.GetNaturalSize().height );
   }
 #endif
 
   // Get last stored width and height specifications for the child
   auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
   auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
-
-  // The size of the control could have changed due to padding being altered, the XXX_SPECIFICATIONs will not have been updated.
-  // So GetNaturalSize is called, if the control's natural size includes padding then th size will be updated.
-  if ( control )
-  {
-    auto desiredSize = control.GetNaturalSize();  // Get's child control's size which could include new padding values.
-
-    // Check if WIDTH_SPECIFICATION was a size value, if so then get update to child controls's width.
-    if ( desiredWidth > 0  )
-    {
-      desiredWidth = desiredSize.width;
-      childOwner.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, LayoutLength::IntType( desiredWidth ) );
-    }
-
-    // Check if HEIGHT_SPECIFICATION was a size value, if so then get update to child controls's height.
-    if ( desiredHeight > 0)
-    {
-      desiredHeight = desiredSize.height;
-      childOwner.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, LayoutLength::IntType( desiredHeight ) );
-    }
-  }
-
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChild desiredWidth(%d)\n",  desiredWidth );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChild desiredWidth(%d) desiredHeight(%d)\n", desiredWidth, desiredHeight );
 
   auto padding = GetPadding(); // Padding of this layout's owner, not of the child being measured.
 
@@ -279,7 +266,6 @@ void LayoutGroup::MeasureChildWithMargins( LayoutItemPtr child,
 
   auto padding = GetPadding(); // Padding of this layout's owner, not of the child being measured.
 
-
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChildWithMargins desiredWidth(%d)\n",  desiredWidth );
 
   MeasureSpec childWidthMeasureSpec = GetChildMeasureSpec( parentWidthMeasureSpec,
@@ -421,6 +407,20 @@ void LayoutGroup::OnInitialize()
     DevelActor::ChildAddedSignal( control ).Connect( mSlotDelegate, &LayoutGroup::ChildAddedToOwner );
     DevelActor::ChildRemovedSignal( control ).Connect( mSlotDelegate, &LayoutGroup::ChildRemovedFromOwner );
     DevelHandle::PropertySetSignal( control ).Connect( mSlotDelegate, &LayoutGroup::OnOwnerPropertySet );
+
+    if( control.GetParent() )
+    {
+      auto parent = Toolkit::Control::DownCast( control.GetParent() );
+      if( parent )
+      {
+        auto parentLayout = Toolkit::LayoutGroup::DownCast( DevelControl::GetLayout( parent ) );
+        if( parentLayout )
+        {
+          Internal::LayoutGroup& parentLayoutImpl = GetImplementation( parentLayout );
+          parentLayoutImpl.Add( *this );
+        }
+      }
+    }
   }
 }
 
@@ -431,7 +431,19 @@ void LayoutGroup::OnRegisterChildProperties( const std::string& containerType )
 
 void LayoutGroup::OnUnparent()
 {
+  // Remove children
   RemoveAll();
+
+  // Remove myself from parent
+  LayoutParent* parent = GetParent();
+  if( parent )
+  {
+    LayoutGroupPtr parentGroup( dynamic_cast< LayoutGroup* >( parent ) );
+    if( parentGroup )
+    {
+      parentGroup->Remove( *this );
+    }
+  }
 }
 
 void LayoutGroup::ChildAddedToOwner( Actor child )
@@ -451,15 +463,22 @@ void LayoutGroup::ChildAddedToOwner( Actor child )
       // If the child doesn't already have a layout, then create a LayoutItem for it.
       childLayout = LayoutItem::New( control );
       childLayout->SetAnimateLayout( IsLayoutAnimated() ); // @todo this essentially forces animation inheritance. Bad?
-
+#if defined(DEBUG_ENABLED)
       auto desiredSize = control.GetNaturalSize();
       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::ChildAddedToOwner desiredSize(%f,%f) (naturalSize)\n", desiredSize.width, desiredSize.height );
-
+#endif
       childControlDataImpl.SetLayout( *childLayout.Get() );
 
-      // Default layout data for this object
-      child.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, LayoutLength::IntType( desiredSize.width ) );
-      child.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, LayoutLength::IntType( desiredSize.height ) );
+      // Default layout data will be generated by Add().
+    }
+    else
+    {
+      LayoutGroupPtr layoutGroup( dynamic_cast< LayoutGroup* >( childLayout.Get() ) );
+      if( !layoutGroup )
+      {
+        // Set only in case of leaf children
+        childLayout->SetAnimateLayout( IsLayoutAnimated() );
+      }
     }
 
     Add( *childLayout.Get() );
@@ -497,6 +516,20 @@ void LayoutGroup::OnOwnerPropertySet( Handle& handle, Property::Index index, Pro
   }
 }
 
+void LayoutGroup::OnAnimationStateChanged( bool animateLayout )
+{
+  // Change children's animation state
+  for( auto&& child : mImpl->mChildren )
+  {
+    LayoutGroupPtr parentGroup( dynamic_cast< LayoutGroup* >( child.child.Get() ) );
+    if( !parentGroup )
+    {
+      // Change state only in case of leaf children
+      child.child->SetAnimateLayout( animateLayout );
+    }
+  }
+}
+
 } // namespace Internal
 } // namespace Toolkit
 } // namespace Dali
index 025950c..27363aa 100644 (file)
@@ -54,8 +54,8 @@ using LayoutGroupPtr = IntrusivePtr<LayoutGroup>;
  * OnLayout should use it's own layout parameters and the measured children's size to determine the children's
  * position and size; it should then call Layout() on the child layout to layout the child and it's hierarchy.
  */
-class DALI_IMPORT_API LayoutGroup : public LayoutItem,
-                                    public ConnectionTracker
+class DALI_TOOLKIT_API LayoutGroup : public LayoutItem,
+                                     public ConnectionTracker
 {
 public:
   /**
@@ -267,6 +267,11 @@ private:
    */
   void OnSetChildProperties( Handle& handle, Property::Index index, Property::Value value );
 
+  /**
+   * @brief Called when a layer animation state is changed.
+   */
+  void OnAnimationStateChanged( bool animateLayout ) override final;
+
 public:
   class Impl; // Class declaration is public so we can add devel API's in the future
 
index dd36ddc..b13da31 100644 (file)
@@ -27,6 +27,11 @@ LayoutGroup::LayoutGroup()
 {
 }
 
+LayoutGroup LayoutGroup::DownCast( BaseHandle handle )
+{
+  return LayoutGroup( dynamic_cast< Dali::Toolkit::Internal::LayoutGroup* >( handle.GetObjectPtr() ) );
+}
+
 LayoutGroup::LayoutId LayoutGroup::Add( LayoutItem& child )
 {
   return GetImplementation( *this ).Add( GetImplementation(child) );
index c6b777b..1d9ad5d 100644 (file)
@@ -49,7 +49,7 @@ class LayoutGroup;
  * To write a new layout, inherit from both LayoutGroup handle and Internal::LayoutGroup body.
  *
  */
-class DALI_IMPORT_API LayoutGroup : public LayoutItem
+class DALI_TOOLKIT_API LayoutGroup : public LayoutItem
 {
 public:
   using LayoutId = unsigned int;
@@ -59,7 +59,6 @@ public:
   {
     enum
     {
-      MARGIN_SPECIFICATION = LAYOUT_GROUP_CHILD_PROPERTY_START_INDEX,
     };
   };
 
index be5b0ed..4213cd8 100644 (file)
@@ -26,7 +26,7 @@ namespace
 {
 
 #if defined(DEBUG_ENABLED)
-Debug::Filter* gLayoutFilter = Debug::Filter::New( Debug::Verbose, false, "LOG_LAYOUT" );
+Debug::Filter* gLayoutFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT" );
 #endif
 
 const char* WIDTH_SPECIFICATION_NAME( "widthSpecification" );
@@ -85,6 +85,8 @@ void LayoutItem::Unparent()
 void LayoutItem::SetAnimateLayout( bool animateLayout )
 {
   mImpl->mAnimated = animateLayout;
+
+  OnAnimationStateChanged( animateLayout );
 }
 
 bool LayoutItem::IsLayoutAnimated() const
@@ -140,11 +142,18 @@ void LayoutItem::Measure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasur
 
   const bool needsLayout = specChanged && ( !isSpecExactly || !matchesSpecSize );
 
-  if( forceLayout || needsLayout)
+  DALI_LOG_STREAM( gLayoutFilter, Debug::Verbose, "LayoutItem::Measure("<<widthMeasureSpec<<", "<<heightMeasureSpec<<") Owner:"<<Actor::DownCast(GetOwner()).GetName() <<"  forceLayout="<<forceLayout<<", specChanged="<<specChanged<<", isSpecExactly="<<isSpecExactly<<", matchesSpecSize="<<matchesSpecSize<<", needsLayout="<<needsLayout <<std::endl <<(forceLayout||needsLayout?"  Remeasuring":"  NoChange"));
+
+  if( forceLayout || needsLayout )
   {
     mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_MEASURED_DIMENSION_SET );
 
     // measure ourselves, this should set the measured dimension flag back
+#if defined(DEBUG_ENABLED)
+    std::ostringstream o;
+    o<<widthMeasureSpec<<","<<heightMeasureSpec;
+    DALI_LOG_INFO( gLayoutFilter, Debug::Concise, "Calling %s OnMeasure( %s )\n", Actor::DownCast(GetOwner()).GetName().c_str(), o.str().c_str());
+#endif
     OnMeasure( widthMeasureSpec, heightMeasureSpec );
     mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_MEASURE_NEEDED_BEFORE_LAYOUT );
 
@@ -246,6 +255,18 @@ LayoutLength LayoutItem::GetDefaultSize( LayoutLength size, MeasureSpec measureS
       break;
     }
     case MeasureSpec::Mode::AT_MOST:
+    {
+      LayoutLength tmp = specSize;
+      if( size < tmp )
+      {
+        result = size;
+      }
+      else
+      {
+        result = specSize;
+      }
+      break;
+    }
     case MeasureSpec::Mode::EXACTLY:
     {
       result = specSize;
@@ -265,6 +286,11 @@ void LayoutItem::OnLayout( bool changed, LayoutLength left, LayoutLength top, La
 {
 }
 
+void LayoutItem::SetParent( LayoutParent* parent )
+{
+  mImpl->mLayoutParent = parent;
+}
+
 LayoutParent* LayoutItem::GetParent()
 {
   return mImpl->mLayoutParent;
@@ -272,6 +298,11 @@ LayoutParent* LayoutItem::GetParent()
 
 void LayoutItem::RequestLayout()
 {
+  Toolkit::Control control = Toolkit::Control::DownCast( mImpl->mOwner );
+  if ( control )
+  {
+    DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::RequestLayout %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();
@@ -283,6 +314,11 @@ bool LayoutItem::IsLayoutRequested() const
   return mImpl->GetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
 }
 
+void LayoutItem::SetLayoutRequested()
+{
+  return mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
+}
+
 void LayoutItem::SetMeasuredDimensions( MeasuredSize measuredWidth, MeasuredSize measuredHeight )
 {
   DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutBase::SetMeasuredDimensions width(%d) height(%d) \n",
index e91e7f9..ce5250a 100644 (file)
@@ -44,8 +44,8 @@ using LayoutItemPtr = IntrusivePtr<LayoutItem>;
 /**
  * Base class for layouts.
  */
-class DALI_IMPORT_API LayoutItem : public BaseObject,
-                                   public LayoutParent
+class DALI_TOOLKIT_API LayoutItem : public BaseObject,
+                                    public LayoutParent
 {
 public:
   /**
@@ -113,16 +113,6 @@ public:
   bool IsLayoutAnimated() const;
 
   /**
-   * @brief Register child properties of layout with owner type.
-   *
-   * The Actor hierarchy uses these registered properties in the type
-   * system to ensure child custom properties are properly initialized.
-   *
-   * @param[in] containerType The type of the containing view (owner)
-   */
-  void RegisterChildProperties( const std::string& containerType );
-
-  /**
    * @brief  This is called to find out how big a layout should be.
    *
    * The parent supplies constraint information in the width and height parameters.
@@ -168,6 +158,11 @@ public:
   static LayoutLength GetDefaultSize( LayoutLength size, MeasureSpec measureSpec );
 
   /**
+   * @copydoc LayoutParent::SetParent
+   */
+  virtual void SetParent( LayoutParent* parent ) override;
+
+  /**
    * @copydoc LayoutParent::GetParent
    */
   virtual LayoutParent* GetParent() override;
@@ -187,6 +182,11 @@ public:
   bool IsLayoutRequested() const;
 
   /**
+   * @brief Set layout requested flag (mark the layout dirty).
+   */
+  void SetLayoutRequested();
+
+  /**
    * @brief Get the measured width (without any measurement flags).
    *
    * This method should be used only during measurement and layout calculations.
@@ -419,6 +419,11 @@ protected:
    */
   virtual void OnInitialize();
 
+  /**
+   * @brief Called when a layer animation state is changed.
+   */
+  virtual void OnAnimationStateChanged( bool animateLayout ) {}
+
 private:
   /**
    * @brief Called to change the size of the layout.
@@ -435,6 +440,16 @@ private:
    */
   void OnLayoutAnimationFinished( Animation& animation );
 
+  /**
+   * @brief Register child properties of layout with owner type.
+   *
+   * The Actor hierarchy uses these registered properties in the type
+   * system to ensure child custom properties are properly initialized.
+   *
+   * @param[in] containerType The type of the containing view (owner)
+   */
+  void RegisterChildProperties( const std::string& containerType );
+
 public:
   class Impl; // Class declaration is public so we can add devel API's in the future
 
index 3bb96bb..5b042c6 100644 (file)
@@ -24,6 +24,7 @@
 #include <dali/public-api/object/property-index-ranges.h>
 #include <dali-toolkit/devel-api/layouting/child-layout-data.h>
 #include <dali-toolkit/devel-api/layouting/measure-spec.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 
 namespace Dali
 {
@@ -42,7 +43,7 @@ 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.
  */
-class DALI_IMPORT_API LayoutItem : public BaseHandle
+class DALI_TOOLKIT_API LayoutItem : public BaseHandle
 {
 public:
 
@@ -121,7 +122,7 @@ public:
    *
    * @param[in] actor A pointer to a newly allocated Dali resource
    */
-  explicit DALI_INTERNAL LayoutItem( Internal::LayoutItem* LayoutItem );
+  explicit LayoutItem( Internal::LayoutItem* LayoutItem );
   /// @endcond
 };
 
index 392a2ab..d55fb42 100644 (file)
@@ -17,6 +17,8 @@
  * limitations under the License.
  */
 
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+
 namespace Dali
 {
 namespace Toolkit
@@ -30,10 +32,15 @@ namespace Internal
  * Needed to prevent circular inheritance - most LayoutBases have a parent,
  * but parenting is provided by LayoutGroup, which is a sub-class of LayoutBase.
  */
-class DALI_IMPORT_API LayoutParent
+class DALI_TOOLKIT_API LayoutParent
 {
 public:
   /**
+   * Set the parent of this layout.
+   */
+  virtual void SetParent( LayoutParent* parent ) = 0;
+
+  /**
    * Get the parent of this layout.
    */
   virtual LayoutParent* GetParent() = 0;
diff --git a/dali-toolkit/devel-api/layouting/linear-layout.cpp b/dali-toolkit/devel-api/layouting/linear-layout.cpp
new file mode 100644 (file)
index 0000000..e9e7e5b
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+//CLASS HEADER
+#include "linear-layout.h"
+
+//INTERNAL INCLUDES
+#include <dali-toolkit/internal/layouting/linear-layout-impl.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+
+LinearLayout::LinearLayout()
+{
+}
+
+LinearLayout LinearLayout::New()
+{
+  Internal::LinearLayoutPtr internal = Internal::LinearLayout::New();
+  return LinearLayout( internal.Get() );
+}
+
+LinearLayout LinearLayout::DownCast( BaseHandle handle )
+{
+  return LinearLayout( dynamic_cast< Dali::Toolkit::Internal::LinearLayout*>( handle.GetObjectPtr() ) );
+}
+
+LinearLayout::LinearLayout( const LinearLayout& other )
+: LayoutGroup( other )
+{
+}
+
+LinearLayout& LinearLayout::operator=( const LinearLayout& other )
+{
+  if( &other != this )
+  {
+    LayoutGroup::operator=( other );
+  }
+  return *this;
+}
+
+void LinearLayout::SetCellPadding( LayoutSize size )
+{
+  GetImplementation(*this).SetCellPadding( size );
+  GetImplementation(*this).RequestLayout();
+}
+
+LayoutSize LinearLayout::GetCellPadding()
+{
+  return GetImplementation(*this).GetCellPadding();
+  GetImplementation(*this).RequestLayout();
+}
+
+void LinearLayout::SetOrientation( LinearLayout::Orientation orientation )
+{
+  GetImplementation(*this).SetOrientation( orientation );
+  GetImplementation(*this).RequestLayout();
+}
+
+LinearLayout::Orientation LinearLayout::GetOrientation()
+{
+  return GetImplementation(*this).GetOrientation();
+  GetImplementation(*this).RequestLayout();
+}
+
+LinearLayout::LinearLayout( Dali::Toolkit::Internal::LinearLayout* object )
+: LayoutGroup( object )
+{
+}
+
+} // namespace Toolkit
+} // namespace Dali
@@ -1,5 +1,5 @@
-#ifndef DALI_TOOLKIT_LAYOUTING_HBOX_LAYOUT_H
-#define DALI_TOOLKIT_LAYOUTING_HBOX_LAYOUT_H
+#ifndef DALI_TOOLKIT_LAYOUTING_LINEAR_LAYOUT_H
+#define DALI_TOOLKIT_LAYOUTING_LINEAR_LAYOUT_H
 
 /*
  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
@@ -30,14 +30,14 @@ namespace Toolkit
 
 namespace Internal DALI_INTERNAL
 {
-class HboxLayout;
+class LinearLayout;
 }
 
 /**
- * This class implements a horizontal box layout, automatically handling
+ * This class implements a linear box layout, automatically handling
  * right to left or left to right direction change.
  */
-class DALI_IMPORT_API HboxLayout : public LayoutGroup
+class DALI_TOOLKIT_API LinearLayout : public LayoutGroup
 {
 public:
 
@@ -47,63 +47,55 @@ public:
     CHILD_PROPERTY_END_INDEX   = LINEAR_LAYOUT_CHILD_PROPERTY_END_INDEX
   };
 
-  struct Property
-  {
-    // @todo When we can have event-only properties for BaseObject, this will be useful.
-    enum
-    {
-      CELL_PADDING = PROPERTY_REGISTRATION_START_INDEX + 2000
-    };
-  };
-
-  struct ChildProperty
+  /**
+   * @brief Enumeration for the direction in which the content is laid out
+   */
+  enum class Orientation
   {
-    enum
-    {
-      WEIGHT = CHILD_PROPERTY_START_INDEX
-    };
+    HORIZONTAL,                 ///< Horizontal (row)
+    VERTICAL                    ///< Vertical (column)
   };
 
   /**
-   * @brief Creates an uninitialized HboxLayout handle.
+   * @brief Creates an uninitialized LinearLayout handle.
    *
-   * Initialize it using HboxLayout::New().
+   * Initialize it using LinearLayout::New().
    * Calling member functions with an uninitialized handle is not allowed.
    */
-  HboxLayout();
+  LinearLayout();
 
   /**
-   * @brief Creates a HboxLayout object.
+   * @brief Creates a LinearLayout object.
    */
-  static HboxLayout New();
+  static LinearLayout New();
 
   /**
-   * @brief Downcasts a handle to a HboxLayout handle.
+   * @brief Downcasts a handle to a LinearLayout handle.
    *
-   * If handle points to a HboxLayout, the downcast produces a valid handle.
+   * If handle points to a LinearLayout, the downcast produces a valid handle.
    * If not, the returned handle is left uninitialized.
 
    * @param[in] handle to an object
-   * @return Handle to a HboxLayout or an uninitialized handle
+   * @return Handle to a LinearLayout or an uninitialized handle
    */
-  static HboxLayout DownCast( BaseHandle handle );
+  static LinearLayout DownCast( BaseHandle handle );
 
   /**
    * @brief Copy constructor
    */
-  HboxLayout( const HboxLayout& other );
+  LinearLayout( const LinearLayout& other );
 
   /**
    * @brief Assigment operator
    */
-  HboxLayout& operator=( const HboxLayout& other );
+  LinearLayout& operator=( const LinearLayout& other );
 
   /**
    * @brief Default destructor.
    *
    * This is non-virtual, since derived Handle types must not contain data or virtual methods
    */
-  ~HboxLayout()=default;
+  ~LinearLayout()=default;
 
   /**
    * @brief Set the padding between cells in the layout
@@ -119,19 +111,33 @@ public:
    */
   LayoutSize GetCellPadding();
 
+  /**
+   * @brief Set the orientation in the layout
+   *
+   * @param[in] orientation The orientation.
+   */
+  void SetOrientation( Orientation orientation );
+
+  /**
+   * @brief Get the orientation in the layout
+   *
+   * @return The orientation.
+   */
+  Orientation GetOrientation();
+
 public: // Not intended for application developers
 
   /// @cond internal
   /**
-   * @brief This constructor is used by HboxLayout::New() methods.
+   * @brief This constructor is used by LinearLayout::New() methods.
    *
    * @param[in] actor A pointer to a newly allocated Dali resource
    */
-  explicit DALI_INTERNAL HboxLayout( Internal::HboxLayout* body );
+  explicit DALI_INTERNAL LinearLayout( Internal::LinearLayout* body );
   /// @endcond
 };
 
 } // namespace Toolkit
 } // namespace Dali
 
-#endif // DALI_TOOLKIT_LAYOUTING_HBOX_LAYOUT_H
+#endif // DALI_TOOLKIT_LAYOUTING_LINEAR_LAYOUT_H
index 92a03f2..04c4d01 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <dali/public-api/common/dali-common.h>
 #include <dali-toolkit/devel-api/layouting/layout-length.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 
 #include <sstream>
 
@@ -32,7 +33,7 @@ namespace Toolkit
  * how to be measured. For instance, it may measure a child with an exact width and an unspecified
  * height in order to determine height for width.
  */
-class DALI_IMPORT_API MeasureSpec
+class DALI_TOOLKIT_API MeasureSpec
 {
 public:
   using IntType = LayoutLength::IntType;
index 3e38a1e..4acdd70 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <dali/public-api/common/dali-common.h>
 #include <dali-toolkit/devel-api/layouting/layout-length.h>
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
 
 namespace Dali
 {
@@ -28,7 +29,7 @@ namespace Toolkit
 /**
  * Class that encodes a measurement and a measure state, which is set if the measured size is too small.
  */
-class DALI_IMPORT_API MeasuredSize
+class DALI_TOOLKIT_API MeasuredSize
 {
 public:
 
index f04a4bd..220872e 100644 (file)
@@ -36,7 +36,7 @@ class VboxLayout;
  * This class implements a vertical box layout, automatically handling
  * right to left or left to right direction change.
  */
-class DALI_IMPORT_API VboxLayout : public LayoutGroup
+class DALI_TOOLKIT_API VboxLayout : public LayoutGroup
 {
 public:
 
index c5db50c..1861a93 100644 (file)
@@ -32,14 +32,16 @@ namespace Toolkit
  */
 enum DevelPropertyRanges
 {
-  LAYOUT_GROUP_CHILD_PROPERTY_START_INDEX = CHILD_PROPERTY_REGISTRATION_START_INDEX + 1000,   ///< Layout Group Property Start Index.
-  LAYOUT_GROUP_CHILD_PROPERTY_END_INDEX   = LAYOUT_GROUP_CHILD_PROPERTY_START_INDEX + 999,    ///< Layout Group Property End Index.
-  LINEAR_LAYOUT_CHILD_PROPERTY_START_INDEX = LAYOUT_GROUP_CHILD_PROPERTY_END_INDEX + 1,       ///< Linear Layout Property Start Index.
-  LINEAR_LAYOUT_CHILD_PROPERTY_END_INDEX   = LINEAR_LAYOUT_CHILD_PROPERTY_START_INDEX + 999,  ///< Linear Layout Property End Index.
-  GRID_LAYOUT_CHILD_PROPERTY_START_INDEX = LINEAR_LAYOUT_CHILD_PROPERTY_END_INDEX + 1,        ///< Grid Layout Property Start Index.
-  GRID_LAYOUT_CHILD_PROPERTY_END_INDEX   = GRID_LAYOUT_CHILD_PROPERTY_START_INDEX + 999,      ///< Grid Layout Property End Index.
-  FLEX_LAYOUT_CHILD_PROPERTY_START_INDEX = GRID_LAYOUT_CHILD_PROPERTY_END_INDEX + 1,          ///< Flex Layout Property Start Index.
-  FLEX_LAYOUT_CHILD_PROPERTY_END_INDEX   = FLEX_LAYOUT_CHILD_PROPERTY_START_INDEX + 999,      ///< Flex Layout Property End Index.
+  LAYOUT_GROUP_CHILD_PROPERTY_START_INDEX = CHILD_PROPERTY_REGISTRATION_START_INDEX + 1000,     ///< Layout Group Property Start Index.
+  LAYOUT_GROUP_CHILD_PROPERTY_END_INDEX   = LAYOUT_GROUP_CHILD_PROPERTY_START_INDEX + 999,      ///< Layout Group Property End Index.
+  LINEAR_LAYOUT_CHILD_PROPERTY_START_INDEX = LAYOUT_GROUP_CHILD_PROPERTY_END_INDEX + 1,         ///< Linear Layout Property Start Index.
+  LINEAR_LAYOUT_CHILD_PROPERTY_END_INDEX   = LINEAR_LAYOUT_CHILD_PROPERTY_START_INDEX + 999,    ///< Linear Layout Property End Index.
+  GRID_LAYOUT_CHILD_PROPERTY_START_INDEX = LINEAR_LAYOUT_CHILD_PROPERTY_END_INDEX + 1,          ///< Grid Layout Property Start Index.
+  GRID_LAYOUT_CHILD_PROPERTY_END_INDEX   = GRID_LAYOUT_CHILD_PROPERTY_START_INDEX + 999,        ///< Grid Layout Property End Index.
+  FLEX_LAYOUT_CHILD_PROPERTY_START_INDEX = GRID_LAYOUT_CHILD_PROPERTY_END_INDEX + 1,            ///< Flex Layout Property Start Index.
+  FLEX_LAYOUT_CHILD_PROPERTY_END_INDEX   = FLEX_LAYOUT_CHILD_PROPERTY_START_INDEX + 999,        ///< Flex Layout Property End Index.
+  ABSOLUTE_LAYOUT_CHILD_PROPERTY_START_INDEX = FLEX_LAYOUT_CHILD_PROPERTY_END_INDEX +1,         ///< Absolute Layout Property Start Index.
+  ABSOLUTE_LAYOUT_CHILD_PROPERTY_END_INDEX = ABSOLUTE_LAYOUT_CHILD_PROPERTY_START_INDEX + 999,  ///< Absolute Layout Property End Index.
 };
 
 } // namespace Toolkit
index 80e884a..3360256 100755 (executable)
@@ -1387,7 +1387,7 @@ void TextEditor::OnRelayout( const Vector2& size, RelayoutContainer& container )
       {
         // @note: The callback manager takes the ownership of the callback object.
         mIdleCallback = MakeCallback( this, &TextEditor::OnIdleSignal );
-        adaptor.AddIdle( mIdleCallback );
+        adaptor.AddIdle( mIdleCallback, false );
       }
     }
   }
index d92be64..dd34031 100755 (executable)
@@ -1433,7 +1433,7 @@ void TextField::OnRelayout( const Vector2& size, RelayoutContainer& container )
       {
         // @note: The callback manager takes the ownership of the callback object.
         mIdleCallback = MakeCallback( this, &TextField::OnIdleSignal );
-        adaptor.AddIdle( mIdleCallback );
+        adaptor.AddIdle( mIdleCallback, false );
       }
     }
   }
index 00121b8..328d1d6 100755 (executable)
@@ -11,8 +11,9 @@ toolkit_src_files = \
    $(toolkit_src_dir)/builder/style.cpp \
    $(toolkit_src_dir)/builder/tree-node-manipulator.cpp \
    $(toolkit_src_dir)/builder/replacement.cpp \
-   $(toolkit_src_dir)/layouting/hbox-layout-impl.cpp \
-   $(toolkit_src_dir)/layouting/vbox-layout-impl.cpp \
+   $(toolkit_src_dir)/layouting/flex-layout-impl.cpp \
+   $(toolkit_src_dir)/layouting/absolute-layout-impl.cpp \
+   $(toolkit_src_dir)/layouting/linear-layout-impl.cpp \
    $(toolkit_src_dir)/layouting/layout-item-data-impl.cpp \
    $(toolkit_src_dir)/layouting/layout-group-data-impl.cpp \
    $(toolkit_src_dir)/layouting/layout-controller-debug.cpp \
diff --git a/dali-toolkit/internal/layouting/absolute-layout-impl.cpp b/dali-toolkit/internal/layouting/absolute-layout-impl.cpp
new file mode 100644 (file)
index 0000000..3f499ef
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+//CLASS HEADER
+#include <dali-toolkit/internal/layouting/absolute-layout-impl.h>
+
+//INTERNAL HEADERS
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/extents.h>
+#include <dali/public-api/actors/actor.h>
+#include <dali-toolkit/devel-api/layouting/layout-item.h>
+#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT" );
+#endif
+}
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+AbsoluteLayoutPtr AbsoluteLayout::New()
+{
+  AbsoluteLayoutPtr layout( new AbsoluteLayout() );
+  return layout;
+}
+
+AbsoluteLayout::AbsoluteLayout()
+: LayoutGroup()
+{
+}
+
+AbsoluteLayout::~AbsoluteLayout()
+{
+}
+
+void AbsoluteLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
+{
+#if defined(DEBUG_ENABLED)
+  auto actor = Actor::DownCast(GetOwner());
+
+  std::ostringstream oss;
+  oss << "AbsoluteLayout::OnMeasure  ";
+  if( actor )
+  {
+    oss << "Actor Id:" << actor.GetId() << " Name:" << actor.GetName() << "  ";
+  }
+  oss << "widthMeasureSpec:" << widthMeasureSpec << " heightMeasureSpec:" << heightMeasureSpec << std::endl;
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, oss.str().c_str() );
+#endif
+
+  LayoutLength totalHeight( 0 );
+  LayoutLength totalWidth( 0 );
+
+  struct
+  {
+    MeasuredSize::State widthState;
+    MeasuredSize::State heightState;
+  } childState = { MeasuredSize::State::MEASURED_SIZE_OK, MeasuredSize::State::MEASURED_SIZE_OK };
+
+  auto minPosition = Vector3( Vector3::ZERO );
+  auto maxPosition = Vector3( Vector3::ZERO );
+
+  // measure children
+  for( unsigned int i=0; i<GetChildCount(); ++i )
+  {
+    auto childLayout = GetChildAt( i );
+    if( childLayout )
+    {
+      auto childOwner = childLayout->GetOwner();
+
+      // Get size of child
+      MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
+      auto childWidth = childLayout->GetMeasuredWidth();
+      auto childHeight = childLayout->GetMeasuredHeight();
+
+      // Determine the width and height needed by the children using their given position and size.
+      // Children could overlap so find the left most and right most child.
+      auto childPosition = childOwner.GetProperty< Vector3 >( Actor::Property::POSITION );
+      minPosition.x = std::min( minPosition.x, childPosition.x );
+      maxPosition.x = std::max( maxPosition.x, childPosition.x + childWidth );
+      // Children could overlap so find the highest and lowest child.
+      minPosition.y = std::min( minPosition.y, childPosition.y );
+      maxPosition.y = std::max( maxPosition.y, childPosition.y + childHeight );
+
+      // Store current width and height needed to contain all children.
+      totalWidth = maxPosition.x - minPosition.x;
+      totalHeight = maxPosition.y - minPosition.y;
+      DALI_LOG_INFO( gLogFilter, Debug::Concise, "AbsoluteLayout::OnMeasure child width(%f) height(%f) \n", (float)totalWidth, (float)totalHeight  );
+
+      if( childLayout->GetMeasuredWidthAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
+      {
+        childState.widthState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
+      }
+      if( childLayout->GetMeasuredHeightAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
+      {
+        childState.heightState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
+      }
+    }
+  }
+
+  MeasuredSize widthSizeAndState = ResolveSizeAndState( totalWidth, widthMeasureSpec, MeasuredSize::State::MEASURED_SIZE_OK);
+  MeasuredSize heightSizeAndState = ResolveSizeAndState( totalHeight, heightMeasureSpec, MeasuredSize::State::MEASURED_SIZE_OK);
+  totalWidth = widthSizeAndState.GetSize();
+  totalHeight = heightSizeAndState.GetSize();
+
+  // Ensure layout respects it's given minimum size
+  totalWidth = std::max( totalWidth, GetSuggestedMinimumWidth() );
+  totalHeight = std::max( totalHeight, GetSuggestedMinimumHeight() );
+
+  widthSizeAndState.SetState( childState.widthState );
+  heightSizeAndState.SetState( childState.heightState );
+
+  SetMeasuredDimensions( ResolveSizeAndState( totalWidth, widthMeasureSpec, childState.widthState ),
+                         ResolveSizeAndState( totalHeight, heightMeasureSpec, childState.heightState ) );
+
+}
+
+void AbsoluteLayout::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
+{
+  // Absolute layout positions it's children at their Actor positions.
+  // Children could overlap or spill outside the parent, as is the nature of absolute positions.
+  auto count = GetChildCount();
+
+  for( unsigned int i = 0; i < count; i++)
+  {
+    LayoutItemPtr childLayout = GetChildAt( i );
+    if( childLayout != nullptr )
+    {
+      auto childOwner = childLayout->GetOwner();
+      auto childWidth = childLayout->GetMeasuredWidth();
+      auto childHeight = childLayout->GetMeasuredHeight();
+
+      auto childPosition = childOwner.GetProperty< Vector3 >( Actor::Property::POSITION );
+
+      auto childTop = childPosition.y;
+      auto childLeft = childPosition.x;
+
+      childLayout->Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
+    }
+  }
+}
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
@@ -1,5 +1,5 @@
-#ifndef DALI_TOOLKIT_INTERNAL_LAYOUTING_HBOX_LAYOUT_H
-#define DALI_TOOLKIT_INTERNAL_LAYOUTING_HBOX_LAYOUT_H
+#ifndef DALI_TOOLKIT_INTERNAL_ABSOLUTE_LAYOUT_H
+#define DALI_TOOLKIT_INTERNAL_ABSOLUTE_LAYOUT_H
 
 /*
  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
@@ -20,7 +20,7 @@
 #include <dali/public-api/common/intrusive-ptr.h>
 #include <dali/public-api/object/base-object.h>
 #include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
-#include <dali-toolkit/devel-api/layouting/hbox-layout.h>
+#include <dali-toolkit/devel-api/layouting/absolute-layout.h>
 
 namespace Dali
 {
@@ -29,36 +29,25 @@ namespace Toolkit
 namespace Internal
 {
 
-class HboxLayout;
-using HboxLayoutPtr = IntrusivePtr<HboxLayout>;
+class AbsoluteLayout;
+using AbsoluteLayoutPtr = IntrusivePtr<AbsoluteLayout>;
 
-class HboxLayout final : public LayoutGroup
+class AbsoluteLayout final : public LayoutGroup
 {
 public:
-  static HboxLayoutPtr New();
-
-public:
-  void SetCellPadding( LayoutSize size );
-  LayoutSize GetCellPadding();
+  static AbsoluteLayoutPtr New();
 
 protected:
-  HboxLayout();
-  virtual ~HboxLayout();
-
-  /**
-   * @copydoc LayoutItem::DoInitialize
-   */
-  virtual void DoInitialize() override;
 
   /**
-   * @copydoc LayoutItem::DoRegisterChildProperties()
+   * Constructor
    */
-  virtual void DoRegisterChildProperties( const std::string& containerType ) override;
+  AbsoluteLayout();
 
   /**
-   * @copydoc LayoutItem::OnChildAdd
+   * Destructor
    */
-  virtual void OnChildAdd( LayoutItem& child ) override;
+  virtual ~AbsoluteLayout();
 
   /**
    * @copydoc LayoutItem::OnMeasure
@@ -71,33 +60,30 @@ protected:
   virtual void OnLayout( bool changed, LayoutLength l, LayoutLength t, LayoutLength r, LayoutLength b ) override;
 
 private:
-  HboxLayout( const HboxLayout& other ) = delete;
-  HboxLayout& operator=( const HboxLayout& other ) = delete;
+  AbsoluteLayout( const AbsoluteLayout& other ) = delete;
+  AbsoluteLayout& operator=( const AbsoluteLayout& other ) = delete;
 
   void ForceUniformHeight( int count, MeasureSpec widthMeasureSpec );
 
-private:
-  LayoutSize mCellPadding;
-  LayoutLength mTotalLength;
 };
 
 } // namespace Internal
 
-inline Internal::HboxLayout& GetImplementation( Dali::Toolkit::HboxLayout& handle )
+inline Internal::AbsoluteLayout& GetImplementation( Dali::Toolkit::AbsoluteLayout& handle )
 {
-  DALI_ASSERT_ALWAYS( handle && "HboxLayout handle is empty" );
+  DALI_ASSERT_ALWAYS( handle && "AbsoluteLayout handle is empty" );
   BaseObject& object = handle.GetBaseObject();
-  return static_cast<Internal::HboxLayout&>( object );
+  return static_cast<Internal::AbsoluteLayout&>( object );
 }
 
-inline const Internal::HboxLayout& GetImplementation( const Dali::Toolkit::HboxLayout& handle )
+inline const Internal::AbsoluteLayout& GetImplementation( const Dali::Toolkit::AbsoluteLayout& handle )
 {
-  DALI_ASSERT_ALWAYS( handle && "HboxLayout handle is empty" );
+  DALI_ASSERT_ALWAYS( handle && "AbsoluteLayout handle is empty" );
   const BaseObject& object = handle.GetBaseObject();
-  return static_cast<const Internal::HboxLayout&>( object );
+  return static_cast<const Internal::AbsoluteLayout&>( object );
 }
 
 } // namespace Toolkit
 } // namespace Dali
 
-#endif // DALI_TOOLKIT_INTERNAL_LAYOUTING_HBOX_LAYOUT_H
+#endif // DALI_TOOLKIT_INTERNAL_ABSOLUTE_LAYOUT_H
diff --git a/dali-toolkit/internal/layouting/flex-layout-impl.cpp b/dali-toolkit/internal/layouting/flex-layout-impl.cpp
new file mode 100644 (file)
index 0000000..8766c58
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * 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.
+ */
+
+//CLASS HEADER
+#include "flex-layout-impl.h"
+
+//EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/extents.h>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/object/handle-devel.h>
+
+//INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/layouting/layout-item.h>
+#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+#include <dali-toolkit/third-party/yoga/YGNode.h>
+
+#if defined(DEBUG_ENABLED)
+static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT" );
+#endif
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+FlexLayoutPtr FlexLayout::New()
+{
+  FlexLayoutPtr layout( new FlexLayout() );
+  return layout;
+}
+
+void FlexLayout::SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection flexDirection )
+{
+  YGNodeStyleSetFlexDirection( mRoot, static_cast<YGFlexDirection>(flexDirection) );
+}
+
+Dali::Toolkit::FlexLayout::FlexDirection FlexLayout::GetFlexDirection() const
+{
+  return static_cast<Dali::Toolkit::FlexLayout::FlexDirection>(YGNodeStyleGetFlexDirection( mRoot ));
+}
+
+void FlexLayout::SetFlexJustification( Dali::Toolkit::FlexLayout::Justification flexJustification )
+{
+  YGNodeStyleSetJustifyContent( mRoot, static_cast<YGJustify>(flexJustification) );
+}
+
+Dali::Toolkit::FlexLayout::Justification FlexLayout::GetFlexJustification() const
+{
+  return static_cast<Dali::Toolkit::FlexLayout::Justification>(YGNodeStyleGetJustifyContent( mRoot ));
+}
+
+void FlexLayout::SetFlexWrap( Dali::Toolkit::FlexLayout::WrapType wrapType )
+{
+  YGNodeStyleSetFlexWrap( mRoot, static_cast<YGWrap>(wrapType) );
+}
+
+Dali::Toolkit::FlexLayout::WrapType FlexLayout::GetFlexWrap() const
+{
+  return static_cast<Dali::Toolkit::FlexLayout::WrapType>(YGNodeStyleGetFlexWrap( mRoot ));
+}
+
+void FlexLayout::SetFlexAlignment( Dali::Toolkit::FlexLayout::Alignment::Type flexAlignment )
+{
+  YGNodeStyleSetAlignContent( mRoot, static_cast<YGAlign>(flexAlignment) );
+}
+
+Dali::Toolkit::FlexLayout::Alignment::Type FlexLayout::GetFlexAlignment() const
+{
+  return static_cast<Dali::Toolkit::FlexLayout::Alignment::Type>(YGNodeStyleGetAlignContent( mRoot ));
+}
+
+void FlexLayout::SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::Type flexAlignment )
+{
+  YGNodeStyleSetAlignItems( mRoot, static_cast<YGAlign>(flexAlignment) );
+}
+
+Dali::Toolkit::FlexLayout::Alignment::Type FlexLayout::GetFlexItemsAlignment() const
+{
+  return static_cast<Dali::Toolkit::FlexLayout::Alignment::Type>(YGNodeStyleGetAlignItems( mRoot ));
+}
+
+FlexLayout::FlexLayout()
+: LayoutGroup(),
+  mRoot( nullptr )
+{
+  mRoot = YGNodeNew();
+  YGNodeSetContext( mRoot, this );
+
+  // Set default style
+  YGNodeStyleSetFlexDirection( mRoot, YGFlexDirectionColumn );
+  YGNodeStyleSetFlexWrap( mRoot, YGWrapNoWrap );
+  YGNodeStyleSetJustifyContent( mRoot, YGJustifyFlexStart );
+  YGNodeStyleSetAlignContent( mRoot, YGAlignFlexStart );
+  YGNodeStyleSetAlignItems( mRoot, YGAlignFlexStart );
+}
+
+FlexLayout::~FlexLayout()
+{
+  if( mRoot )
+  {
+    YGNodeFreeRecursive( mRoot );
+  }
+}
+
+void FlexLayout::DoInitialize()
+{
+}
+
+void FlexLayout::DoRegisterChildProperties( const std::string& containerType )
+{
+  auto typeInfo = Dali::TypeRegistry::Get().GetTypeInfo( containerType );
+  if( typeInfo )
+  {
+    Property::IndexContainer indices;
+    typeInfo.GetChildPropertyIndices( indices );
+
+    if( std::find( indices.Begin(), indices.End(), Toolkit::FlexLayout::ChildProperty::FLEX ) ==
+        indices.End() )
+    {
+      ChildPropertyRegistration( typeInfo.GetName(), "flex", Toolkit::FlexLayout::ChildProperty::FLEX, Property::FLOAT );
+    }
+
+    if( std::find( indices.Begin(), indices.End(), Toolkit::FlexLayout::ChildProperty::ALIGN_SELF ) ==
+        indices.End() )
+    {
+      ChildPropertyRegistration( typeInfo.GetName(), "alignSelf", Toolkit::FlexLayout::ChildProperty::ALIGN_SELF, Property::INTEGER );
+    }
+  }
+}
+
+void FlexLayout::OnChildAdd( LayoutItem& child )
+{
+  auto owner = child.GetOwner();
+  if(!DevelHandle::DoesCustomPropertyExist(owner, Toolkit::FlexLayout::ChildProperty::FLEX ))
+  {
+    owner.SetProperty( Toolkit::FlexLayout::ChildProperty::FLEX, 0 );
+  }
+  if(!DevelHandle::DoesCustomPropertyExist(owner, Toolkit::FlexLayout::ChildProperty::ALIGN_SELF ))
+  {
+    owner.SetProperty( Toolkit::FlexLayout::ChildProperty::ALIGN_SELF, YGAlignAuto );
+  }
+
+  YGNodeRef node = YGNodeNew();
+  YGNodeSetContext( node, &child );
+  YGNodeSetMeasureFunc( node, OnChildMeasure );
+  YGNodeMarkDirty( node );
+  YGNodeInsertChild( mRoot, node, GetChildCount()-1 );
+}
+
+void FlexLayout::OnChildRemove( LayoutItem& child )
+{
+  auto count = GetChildCount();
+  for( unsigned int childIndex = 0; childIndex < count; childIndex++)
+  {
+    LayoutItemPtr childLayout = GetChildAt( childIndex );
+    if( &child == childLayout.Get() )
+    {
+      YGNodeRef node = YGNodeGetChild( mRoot, childIndex );
+      YGNodeRemoveChild( mRoot, node );
+      break;
+    }
+  }
+}
+
+void FlexLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
+{
+  auto actor = Actor::DownCast(GetOwner());
+  bool isLayoutRtl = actor ? actor.GetProperty<int>( Actor::Property::LAYOUT_DIRECTION ) == LayoutDirection::RIGHT_TO_LEFT: false;
+  Extents padding = GetPadding();
+  Extents margin = GetMargin();
+
+#if defined(DEBUG_ENABLED)
+  std::ostringstream oss;
+  oss << "FlexLayout::OnMeasure  ";
+  if( actor )
+  {
+    oss << "Actor Id:" << actor.GetId() << " Name:" << actor.GetName() << " Layout direction:" << actor.GetProperty( Actor::Property::LAYOUT_DIRECTION ).Get<int>() << " ";
+  }
+  oss << "widthMeasureSpec:" << widthMeasureSpec << " heightMeasureSpec:" << heightMeasureSpec << std::endl;
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, oss.str().c_str() );
+#endif
+
+  YGNodeStyleSetMargin( mRoot, YGEdgeLeft, margin.start );
+  YGNodeStyleSetMargin( mRoot, YGEdgeTop, margin.top );
+  YGNodeStyleSetMargin( mRoot, YGEdgeRight, margin.end );
+  YGNodeStyleSetMargin( mRoot, YGEdgeBottom, margin.bottom );
+  YGNodeStyleSetPadding( mRoot, YGEdgeLeft, padding.start );
+  YGNodeStyleSetPadding( mRoot, YGEdgeTop, padding.top );
+  YGNodeStyleSetPadding( mRoot, YGEdgeRight, padding.end );
+  YGNodeStyleSetPadding( mRoot, YGEdgeBottom, padding.bottom );
+
+  float width = YGUndefined;
+  float height = YGUndefined;
+
+  YGNodeStyleSetWidth( mRoot, YGUndefined );
+  YGNodeStyleSetHeight( mRoot, YGUndefined );
+  YGNodeStyleSetMinWidth( mRoot, YGUndefined );
+  YGNodeStyleSetMinHeight( mRoot, YGUndefined );
+  YGNodeStyleSetMaxWidth( mRoot, YGUndefined );
+  YGNodeStyleSetMaxHeight( mRoot, YGUndefined );
+
+  if( widthMeasureSpec.GetMode() == MeasureSpec::Mode::EXACTLY )
+  {
+    width = widthMeasureSpec.GetSize();
+    YGNodeStyleSetWidth( mRoot, width );
+  }
+  else if( widthMeasureSpec.GetMode() == MeasureSpec::Mode::AT_MOST )
+  {
+    width = widthMeasureSpec.GetSize();
+    YGNodeStyleSetMaxWidth( mRoot, width );
+  }
+
+  if (heightMeasureSpec.GetMode() == MeasureSpec::Mode::EXACTLY)
+  {
+    height = heightMeasureSpec.GetSize();
+    YGNodeStyleSetHeight( mRoot, height );
+  }
+  else if (widthMeasureSpec.GetMode() == MeasureSpec::Mode::AT_MOST)
+  {
+    height = heightMeasureSpec.GetSize();
+    YGNodeStyleSetMaxHeight( mRoot, height );
+  }
+
+  SetChildrenStyle();
+  YGNodeCalculateLayout( mRoot, width, height, isLayoutRtl ? YGDirectionRTL : YGDirectionLTR );
+  SetMeasuredDimensions( GetDefaultSize( YGNodeLayoutGetWidth(mRoot), widthMeasureSpec ),
+                         GetDefaultSize( YGNodeLayoutGetHeight(mRoot), heightMeasureSpec ) );
+}
+
+void FlexLayout::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
+{
+  auto owner = GetOwner();
+  auto actor = Actor::DownCast(owner);
+  bool isLayoutRtl = actor ? actor.GetProperty( Actor::Property::LAYOUT_DIRECTION ).Get<int>() == LayoutDirection::RIGHT_TO_LEFT: false;
+  auto width = right - left;
+  auto height = bottom - top;
+
+#if defined(DEBUG_ENABLED)
+  std::ostringstream oss;
+  oss << "FlexLayout::OnLayout  ";
+  if( actor )
+  {
+    oss << "Actor Id:" << actor.GetId() << " Name:" << actor.GetName() << " Layout direction:" << actor.GetProperty( Actor::Property::LAYOUT_DIRECTION ).Get<int>() << " ";
+  }
+  oss << "changed:" << (int)changed << " left:" << left << " top:" << top << " right:" << right << " bottom:" << bottom << " isLayoutRtl:" << (int)isLayoutRtl << std::endl;
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, oss.str().c_str() );
+#endif
+
+  YGNodeCalculateLayout( mRoot, width, height, isLayoutRtl ? YGDirectionRTL : YGDirectionLTR );
+
+  auto count = GetChildCount();
+  for( unsigned int childIndex = 0; childIndex < count; childIndex++)
+  {
+    LayoutItemPtr childLayout = GetChildAt( childIndex );
+    if( childLayout != nullptr )
+    {
+      YGNodeRef node = YGNodeGetChild(mRoot, childIndex);
+      auto childLeft = YGNodeLayoutGetLeft( node ) + left;
+      auto childTop = YGNodeLayoutGetTop( node ) + top;
+      auto childWidth = YGNodeLayoutGetWidth( node );
+      auto childHeight = YGNodeLayoutGetHeight( node );
+      childLayout->Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
+    }
+  }
+}
+
+YGSize FlexLayout::OnChildMeasure( YGNodeRef node,
+                              float innerWidth,
+                              YGMeasureMode widthMode,
+                              float innerHeight,
+                              YGMeasureMode heightMode ) {
+  // TODO: this function should try to get use of LayoutGroup::GetChildMeasureSpec
+  // or LayoutGroup::MeasureChild somehow since it is fixed now
+  LayoutItem* childLayout = static_cast<LayoutItem*>(node->getContext());
+  auto childOwner = childLayout->GetOwner();
+  auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
+  auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
+
+  MeasureSpec::Mode measureWidthMode = MeasureSpec::Mode::AT_MOST;
+  MeasureSpec::Mode measureHeightMode = MeasureSpec::Mode::AT_MOST;
+  if( desiredWidth == Toolkit::ChildLayoutData::MATCH_PARENT )
+  {
+    if( innerWidth != YGUndefined)
+    {
+      desiredWidth = innerWidth;
+    }
+    measureWidthMode = MeasureSpec::Mode::EXACTLY;
+  }
+
+  if( desiredHeight == Toolkit::ChildLayoutData::MATCH_PARENT )
+  {
+    if( innerWidth != YGUndefined)
+    {
+      desiredHeight = innerHeight;
+    }
+    measureHeightMode = MeasureSpec::Mode::EXACTLY;
+  }
+
+  if( desiredWidth == Toolkit::ChildLayoutData::WRAP_CONTENT )
+  {
+    measureWidthMode = MeasureSpec::Mode::UNSPECIFIED;
+  }
+
+  if( desiredHeight == Toolkit::ChildLayoutData::WRAP_CONTENT )
+  {
+    measureHeightMode = MeasureSpec::Mode::UNSPECIFIED;
+  }
+
+  MeasureSpec widthMeasureSpec = MeasureSpec( desiredWidth, measureWidthMode );
+  MeasureSpec heightMeasureSpec = MeasureSpec( desiredHeight, measureHeightMode );
+  if( measureWidthMode == MeasureSpec::Mode::UNSPECIFIED ||
+      measureHeightMode == MeasureSpec::Mode::UNSPECIFIED )
+  {
+    // A measure just to get the size if the wrapped content
+    childLayout->Measure( widthMeasureSpec, heightMeasureSpec );
+    desiredWidth = childLayout->GetMeasuredWidth();
+    desiredHeight = childLayout->GetMeasuredHeight();
+    // Remove padding here since the second measure will add it back
+    Extents padding = childLayout->GetPadding();
+    desiredWidth = desiredWidth - padding.end - padding.start;
+    desiredHeight = desiredHeight - padding.bottom - padding.top;
+  }
+
+  // Safety check to avoid going out of boundary
+  if( (innerWidth != YGUndefined && innerWidth != 0) && innerWidth < desiredWidth )
+  {
+    desiredWidth = innerWidth;
+  }
+
+  if( (innerHeight != YGUndefined && innerHeight != 0) && innerHeight < desiredHeight )
+  {
+    desiredHeight = innerHeight;
+  }
+
+  // Measure for Yoga
+  MeasureSpec::Mode ygWidthMode = static_cast<MeasureSpec::Mode>(widthMode);
+  if( measureWidthMode == MeasureSpec::Mode::EXACTLY )
+  {
+    ygWidthMode = MeasureSpec::Mode::EXACTLY;
+  }
+
+  MeasureSpec::Mode ygHeightMode = static_cast<MeasureSpec::Mode>(heightMode);
+  if( measureHeightMode == MeasureSpec::Mode::EXACTLY )
+  {
+    ygHeightMode = MeasureSpec::Mode::EXACTLY;
+  }
+
+  MeasureSpec ygWidthMeasureSpec = MeasureSpec( desiredWidth, ygWidthMode );
+  MeasureSpec ygHeightMeasureSpec = MeasureSpec( desiredHeight, ygHeightMode );
+#if defined(DEBUG_ENABLED)
+  auto actor = Actor::DownCast(childOwner);
+  std::ostringstream oss;
+  oss << "FlexLayout::OnChildMeasure  ";
+  if( actor )
+  {
+    oss << "Actor Id:" << actor.GetId() << " Name:" << actor.GetName() << " ";
+  }
+  oss << "innerWidth:" << ((innerWidth == YGUndefined) ? "YGUndefined " : "") << innerWidth <<
+         " innerHeight:" << ((innerHeight == YGUndefined) ? "YGUndefined " : "") << innerHeight <<
+         " desiredWidth:" << desiredWidth << " desiredHeight:" << desiredHeight <<
+         " widthMeasureSpec:" << widthMeasureSpec << " heightMeasureSpec:" << heightMeasureSpec <<
+         " ygWidthMeasureSpec:" << ygWidthMeasureSpec << " ygHeightMeasureSpec:" << ygHeightMeasureSpec << std::endl;
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, oss.str().c_str() );
+#endif
+
+  if( measureWidthMode == MeasureSpec::Mode::UNSPECIFIED ||
+      measureHeightMode == MeasureSpec::Mode::UNSPECIFIED )
+  {
+    if( ygWidthMeasureSpec == widthMeasureSpec && ygHeightMeasureSpec == heightMeasureSpec )
+    {
+      return YGSize{
+        .width = childLayout->GetMeasuredWidth(),
+        .height = childLayout->GetMeasuredHeight(),
+      };
+    }
+  }
+
+  childLayout->Measure( ygWidthMeasureSpec, ygHeightMeasureSpec );
+  return YGSize{
+    .width = childLayout->GetMeasuredWidth(),
+    .height = childLayout->GetMeasuredHeight(),
+  };
+}
+
+void FlexLayout::SetChildrenStyle()
+{
+  if( mRoot )
+  {
+    auto count = GetChildCount();
+    for( unsigned int childIndex = 0; childIndex < count; childIndex++)
+    {
+      LayoutItemPtr childLayout = GetChildAt( childIndex );
+      if( childLayout != nullptr )
+      {
+        Extents padding = childLayout->GetPadding();
+        Extents margin = childLayout->GetMargin();
+        auto childOwner = childLayout->GetOwner();
+        auto childActor = Actor::DownCast(childOwner);
+        auto flex = childOwner.GetProperty<float>( Toolkit::FlexLayout::ChildProperty::FLEX );
+        auto alignSelf = static_cast<YGAlign>( childOwner.GetProperty<int>( Toolkit::FlexLayout::ChildProperty::ALIGN_SELF ));
+
+        YGNodeRef childNode = YGNodeGetChild( mRoot, childIndex );
+        // Initialise the style of the child.
+        YGNodeStyleSetMargin( childNode, YGEdgeLeft, margin.start );
+        YGNodeStyleSetMargin( childNode, YGEdgeTop, margin.top );
+        YGNodeStyleSetMargin( childNode, YGEdgeRight, margin.end );
+        YGNodeStyleSetMargin( childNode, YGEdgeBottom, margin.bottom );
+
+        YGNodeStyleSetPadding( childNode, YGEdgeLeft, padding.start );
+        YGNodeStyleSetPadding( childNode, YGEdgeTop, padding.top );
+        YGNodeStyleSetPadding( childNode, YGEdgeRight, padding.end );
+        YGNodeStyleSetPadding( childNode, YGEdgeBottom, padding.bottom );
+
+        YGNodeStyleSetWidth( childNode, YGUndefined );
+        YGNodeStyleSetHeight( childNode, YGUndefined );
+        // TODO: check if we are supposed to use actor properties here, max/min is needed for stretch
+        YGNodeStyleSetMinWidth( childNode, childActor.GetMinimumSize().x );
+        YGNodeStyleSetMinHeight( childNode, childActor.GetMinimumSize().y );
+        if( childActor.GetMaximumSize().x == FLT_MAX )
+        {
+          YGNodeStyleSetMaxWidth( childNode, YGUndefined );
+        }
+        else
+        {
+          YGNodeStyleSetMaxWidth( childNode, childActor.GetMaximumSize().x );
+        }
+        if( childActor.GetMaximumSize().y == FLT_MAX )
+        {
+          YGNodeStyleSetMaxHeight( childNode, YGUndefined );
+        }
+        else
+        {
+          YGNodeStyleSetMaxHeight( childNode, childActor.GetMaximumSize().y );
+        }
+
+        YGNodeStyleSetFlex( childNode, flex );
+        YGNodeStyleSetAlignSelf( childNode, alignSelf );
+
+        // Have to do manually for nodes with custom measure function
+        // TODO: check the style is changed before marking the node
+        YGNodeMarkDirty( childNode );
+      }
+    }
+  }
+}
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/internal/layouting/flex-layout-impl.h b/dali-toolkit/internal/layouting/flex-layout-impl.h
new file mode 100644 (file)
index 0000000..b2bd236
--- /dev/null
@@ -0,0 +1,165 @@
+#ifndef DALI_TOOLKIT_INTERNAL_LAYOUTING_FLEX_LAYOUT_H
+#define DALI_TOOLKIT_INTERNAL_LAYOUTING_FLEX_LAYOUT_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.
+ */
+
+//EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+
+//INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/layouting/flex-layout.h>
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+#include <dali-toolkit/third-party/yoga/Yoga.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+class FlexLayout;
+using FlexLayoutPtr = IntrusivePtr<FlexLayout>;
+
+class FlexLayout final : public LayoutGroup
+{
+public:
+  static FlexLayoutPtr New();
+
+public:
+  /**
+   * @copydoc FlexLayout::SetFlexDirection
+   */
+  void SetFlexDirection( Dali::Toolkit::FlexLayout::FlexDirection flexDirection );
+
+  /**
+   * @copydoc FlexLayout::GetFlexDirection
+   */
+  Dali::Toolkit::FlexLayout::FlexDirection GetFlexDirection() const;
+
+  /**
+   * @copydoc FlexLayout::SetFlexJustification
+   */
+  void SetFlexJustification( Dali::Toolkit::FlexLayout::Justification flexJustification );
+
+  /**
+   * @copydoc FlexLayout::GetFlexJustification
+   */
+  Dali::Toolkit::FlexLayout::Justification GetFlexJustification() const;
+
+  /**
+   * @copydoc FlexLayout::SetFlexWrap
+   */
+  void SetFlexWrap( Dali::Toolkit::FlexLayout::WrapType wrap );
+
+  /**
+   * @copydoc FlexLayout::GetFlexWrap
+   */
+  Dali::Toolkit::FlexLayout::WrapType GetFlexWrap() const;
+
+  /**
+   * @copydoc FlexLayout::SetFlexAlignment
+   */
+  void SetFlexAlignment( Dali::Toolkit::FlexLayout::Alignment::Type flexAlignment );
+  /**
+   * @copydoc FlexLayout::GetFlexAlignment
+   */
+  Dali::Toolkit::FlexLayout::Alignment::Type GetFlexAlignment() const;
+
+  /**
+   * @copydoc FlexLayout::SetFlexItemsAlignment
+   */
+  void SetFlexItemsAlignment( Dali::Toolkit::FlexLayout::Alignment::Type flexAlignment );
+
+  /**
+   * @copydoc FlexLayout::GetFlexItemsAlignment
+   */
+  Dali::Toolkit::FlexLayout::Alignment::Type GetFlexItemsAlignment() const;
+
+protected:
+  /**
+   * Constructor
+   */
+  FlexLayout();
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~FlexLayout();
+
+  /**
+   * @copydoc LayoutItem::DoInitialize
+   */
+  virtual void DoInitialize() override;
+
+  /**
+   * @copydoc LayoutItem::DoRegisterChildProperties()
+   */
+  virtual void DoRegisterChildProperties( const std::string& containerType ) override;
+
+  /**
+   * @copydoc LayoutItem::OnChildAdd
+   */
+  virtual void OnChildAdd( LayoutItem& child ) override;
+
+  /**
+   * @copydoc LayoutItem::OnChildRemove
+   */
+  virtual void OnChildRemove( LayoutItem& child ) override;
+
+  /**
+   * @copydoc LayoutItem::OnMeasure
+   */
+  virtual void OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec ) override;
+
+  /**
+   * @copydoc LayoutItem::OnLayout
+   */
+  virtual void OnLayout( bool changed, LayoutLength l, LayoutLength t, LayoutLength r, LayoutLength b ) override;
+
+private:
+  FlexLayout( const FlexLayout& other ) = delete;
+  FlexLayout& operator=( const FlexLayout& other ) = delete;
+
+  static YGSize OnChildMeasure( YGNodeRef node, float width, YGMeasureMode widthMode, float height, YGMeasureMode heightMode );
+  void SetChildrenStyle();
+
+private:
+  YGNodeRef mRoot;
+};
+
+} // namespace Internal
+
+inline Internal::FlexLayout& GetImplementation( Dali::Toolkit::FlexLayout& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "FboxLayout handle is empty" );
+  BaseObject& object = handle.GetBaseObject();
+  return static_cast<Internal::FlexLayout&>( object );
+}
+
+inline const Internal::FlexLayout& GetImplementation( const Dali::Toolkit::FlexLayout& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "FboxLayout handle is empty" );
+  const BaseObject& object = handle.GetBaseObject();
+  return static_cast<const Internal::FlexLayout&>( object );
+}
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_LAYOUTING_FLEX_LAYOUT_H
diff --git a/dali-toolkit/internal/layouting/hbox-layout-impl.cpp b/dali-toolkit/internal/layouting/hbox-layout-impl.cpp
deleted file mode 100644 (file)
index 0caf08d..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * 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.
- */
-
-//CLASS HEADER
-#include <dali-toolkit/internal/layouting/hbox-layout-impl.h>
-
-//EXTERNAL HEADERS
-//INTERNAL HEADERS
-#include <dali/integration-api/debug.h>
-#include <dali/public-api/common/extents.h>
-#include <dali/public-api/actors/actor.h>
-#include <dali-toolkit/devel-api/layouting/layout-item.h>
-#include <dali-toolkit/public-api/controls/control-impl.h>
-#include <dali-toolkit/internal/controls/control/control-data-impl.h>
-
-namespace
-{
-#if defined(DEBUG_ENABLED)
-static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::Concise, false, "LOG_LAYOUT" );
-#endif
-}
-
-namespace Dali
-{
-namespace Toolkit
-{
-namespace Internal
-{
-
-HboxLayoutPtr HboxLayout::New()
-{
-  HboxLayoutPtr layout( new HboxLayout() );
-  return layout;
-}
-
-HboxLayout::HboxLayout()
-: LayoutGroup(),
-  mCellPadding( 0, 0 ),
-  mTotalLength( 0 )
-{
-}
-
-HboxLayout::~HboxLayout()
-{
-}
-
-void HboxLayout::DoInitialize()
-{
-}
-
-void HboxLayout::DoRegisterChildProperties( const std::string& containerType )
-{
-  auto typeInfo = Dali::TypeRegistry::Get().GetTypeInfo( containerType );
-  if( typeInfo )
-  {
-    Property::IndexContainer indices;
-    typeInfo.GetChildPropertyIndices( indices );
-
-    if( std::find( indices.Begin(), indices.End(), Toolkit::HboxLayout::ChildProperty::WEIGHT ) == indices.End() )
-    {
-      ChildPropertyRegistration( typeInfo.GetName(), "weight",
-                                 Toolkit::HboxLayout::ChildProperty::WEIGHT, Property::FLOAT );
-    }
-  }
-}
-
-void HboxLayout::OnChildAdd( LayoutItem& child )
-{
-  auto owner = child.GetOwner();
-  owner.SetProperty( Toolkit::HboxLayout::ChildProperty::WEIGHT, 1.0f );
-}
-
-void HboxLayout::SetCellPadding( LayoutSize size )
-{
-  mCellPadding = size;
-}
-
-LayoutSize HboxLayout::GetCellPadding()
-{
-  return mCellPadding;
-}
-
-void HboxLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
-{
-#if defined(DEBUG_ENABLED)
-  auto actor = Actor::DownCast(GetOwner());
-
-  std::ostringstream oss;
-  oss << "HBoxLayout::OnMeasure  ";
-  if( actor )
-  {
-    oss << "Actor Id:" << actor.GetId() << " Name:" << actor.GetName() << "  ";
-  }
-  oss << "widthMeasureSpec:" << widthMeasureSpec << " heightMeasureSpec:" << heightMeasureSpec << std::endl;
-  DALI_LOG_INFO( gLogFilter, Debug::Concise, oss.str().c_str() );
-#endif
-
-  DALI_LOG_INFO( gLogFilter, Debug::Concise, "HboxLayout::OnMeasure widthSize(%d) \n", widthMeasureSpec.GetSize());
-
-  auto widthMode = widthMeasureSpec.GetMode();
-  auto heightMode = heightMeasureSpec.GetMode();
-  bool isExactly = (widthMode == MeasureSpec::Mode::EXACTLY);
-  bool matchHeight = false;
-  bool allFillParent = true;
-  LayoutLength maxHeight = 0;
-  LayoutLength alternativeMaxHeight = 0;
-  struct
-  {
-    MeasuredSize::State widthState;
-    MeasuredSize::State heightState;
-  } childState = { MeasuredSize::State::MEASURED_SIZE_OK, MeasuredSize::State::MEASURED_SIZE_OK };
-
-  // measure children, and determine if further resolution is required
-  for( unsigned int i=0; i<GetChildCount(); ++i )
-  {
-    auto childLayout = GetChildAt( i );
-    if( childLayout )
-    {
-      auto childOwner = childLayout->GetOwner();
-      auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
-
-      MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
-      auto childWidth = childLayout->GetMeasuredWidth();
-      auto childMargin = childLayout->GetMargin();
-
-      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "HboxLayout::OnMeasure childWidth(%d)\n", MeasureSpec::IntType( childWidth ) );
-
-      auto length = childWidth + LayoutLength::IntType(childMargin.start + childMargin.end);
-
-      auto cellPadding = i<GetChildCount()-1 ? mCellPadding.width: 0;
-
-      if( isExactly )
-      {
-        mTotalLength += length;
-      }
-      else
-      {
-        auto totalLength = mTotalLength;
-        mTotalLength = std::max( totalLength, totalLength + length + cellPadding );
-      }
-
-      bool matchHeightLocally = false;
-      if( heightMode != MeasureSpec::Mode::EXACTLY && desiredHeight == Toolkit::ChildLayoutData::MATCH_PARENT )
-      {
-        // Will have to re-measure at least this child when we know exact height.
-        matchHeight = true;
-        matchHeightLocally = true;
-      }
-
-      auto marginHeight = LayoutLength( childMargin.top + childMargin.bottom );
-      auto childHeight = childLayout->GetMeasuredHeight() + marginHeight;
-
-      if( childLayout->GetMeasuredWidthAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
-      {
-        childState.widthState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
-      }
-      if( childLayout->GetMeasuredHeightAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
-      {
-        childState.heightState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
-      }
-
-      maxHeight = std::max( maxHeight, childHeight );
-      allFillParent = ( allFillParent && desiredHeight == Toolkit::ChildLayoutData::MATCH_PARENT );
-      alternativeMaxHeight = std::max( alternativeMaxHeight, matchHeightLocally ? marginHeight : childHeight );
-    }
-  }
-
-  Extents padding = GetPadding();
-  mTotalLength += padding.start + padding.end;
-  auto widthSize = mTotalLength;
-  widthSize = std::max( widthSize, GetSuggestedMinimumWidth() );
-  MeasuredSize widthSizeAndState = ResolveSizeAndState( widthSize, widthMeasureSpec, MeasuredSize::State::MEASURED_SIZE_OK);
-  widthSize = widthSizeAndState.GetSize();
-
-  if( !allFillParent && heightMode != MeasureSpec::Mode::EXACTLY )
-  {
-    maxHeight = alternativeMaxHeight;
-  }
-  maxHeight += padding.top + padding.bottom;
-  maxHeight = std::max( maxHeight, GetSuggestedMinimumHeight() );
-
-  widthSizeAndState.SetState( childState.widthState );
-
-  SetMeasuredDimensions( widthSizeAndState,
-                         ResolveSizeAndState( maxHeight, heightMeasureSpec, childState.heightState ) );
-
-  if( matchHeight )
-  {
-    ForceUniformHeight( GetChildCount(), widthMeasureSpec );
-  }
-}
-
-void HboxLayout::ForceUniformHeight( int count, MeasureSpec widthMeasureSpec )
-{
-  // Pretend that the linear layout has an exact size. This is the measured height of
-  // ourselves. The measured height should be the max height of the children, changed
-  // to accommodate the heightMeasureSpec from the parent
-  auto uniformMeasureSpec = MeasureSpec( GetMeasuredHeight(), MeasureSpec::Mode::EXACTLY );
-  for (int i = 0; i < count; ++i)
-  {
-    LayoutItemPtr childLayout = GetChildAt(i);
-    if( childLayout != nullptr )
-    {
-      auto childOwner = childLayout->GetOwner();
-      auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
-      auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
-
-      if( desiredHeight == Toolkit::ChildLayoutData::MATCH_PARENT )
-      {
-        // Temporarily force children to reuse their old measured width
-        int oldWidth = desiredWidth;
-        childOwner.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, childLayout->GetMeasuredWidth().mValue );
-
-        // Remeasure with new dimensions
-        MeasureChildWithMargins( childLayout, widthMeasureSpec, 0, uniformMeasureSpec, 0);
-
-        childOwner.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, oldWidth );
-      }
-    }
-  }
-}
-
-void HboxLayout::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
-{
-  auto owner = GetOwner();
-  auto actor = Actor::DownCast(owner);
-  bool isLayoutRtl = actor ? actor.GetProperty<bool>( Actor::Property::LAYOUT_DIRECTION ) : false;
-
-  Extents padding = GetPadding();
-
-  LayoutLength childTop( 0 );
-  LayoutLength childLeft( padding.start );
-
-  // Where bottom of child should go
-  auto height = bottom - top;
-
-  // Space available for child
-  auto childSpace = height - padding.top - padding.bottom;
-
-  auto count = GetChildCount();
-
-  int start = 0;
-  int dir = 1;
-
-  // In case of RTL, start drawing from the last child.
-  // @todo re-work to draw the first child from the right edge, and move leftwards.
-  // (Should have an alignment also)
-  if( isLayoutRtl ) {
-    start = count - 1;
-    dir = -1;
-  }
-
-  for( unsigned int i = 0; i < count; i++)
-  {
-    int childIndex = start + dir * i;
-    LayoutItemPtr childLayout = GetChildAt( childIndex );
-    if( childLayout != nullptr )
-    {
-      auto childWidth = childLayout->GetMeasuredWidth();
-      auto childHeight = childLayout->GetMeasuredHeight();
-
-      auto childMargin = childLayout->GetMargin();
-
-      childTop = LayoutLength(padding.top) + ((childSpace - childHeight) / 2) + childMargin.top - childMargin.bottom;
-
-      childLeft += childMargin.start;
-      childLayout->Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
-      childLeft += childWidth + childMargin.end + mCellPadding.width;
-    }
-  }
-}
-
-} // namespace Internal
-} // namespace Toolkit
-} // namespace Dali
index 85057c1..4b8f63e 100644 (file)
@@ -27,7 +27,7 @@ namespace Internal
 {
 
 #if defined( DEBUG_ENABLED )
-Debug::Filter* gLogFilter = Debug::Filter::New( Debug::Verbose, false, "LOG_LAYOUT_TREE" );
+Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT_TREE" );
 
 
 void GetLayoutMeasureStateString( std::ostringstream& oss, LayoutItemPtr layout )
index 0ca1847..1f12c3f 100644 (file)
@@ -29,7 +29,7 @@ namespace
 {
 
 #if defined(DEBUG_ENABLED)
-static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::Concise, false, "LOG_LAYOUT" );
+static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT" );
 #endif
 
 }
diff --git a/dali-toolkit/internal/layouting/linear-layout-impl.cpp b/dali-toolkit/internal/layouting/linear-layout-impl.cpp
new file mode 100644 (file)
index 0000000..6b91bc0
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ * 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.
+ */
+
+//CLASS HEADER
+#include "linear-layout-impl.h"
+
+//PUBLIC INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/extents.h>
+#include <dali/public-api/actors/actor.h>
+
+//INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/layouting/layout-item.h>
+#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT" );
+#endif
+}
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+LinearLayoutPtr LinearLayout::New()
+{
+  LinearLayoutPtr layout( new LinearLayout() );
+  return layout;
+}
+
+LinearLayout::LinearLayout()
+: LayoutGroup(),
+  mCellPadding( 0, 0 ),
+  mOrientation( Dali::Toolkit::LinearLayout::Orientation::HORIZONTAL ),
+  mTotalLength( 0 )
+{
+}
+
+LinearLayout::~LinearLayout()
+{
+}
+
+void LinearLayout::SetCellPadding( LayoutSize size )
+{
+  mCellPadding = size;
+}
+
+LayoutSize LinearLayout::GetCellPadding()
+{
+  return mCellPadding;
+}
+
+void LinearLayout::SetOrientation( Dali::Toolkit::LinearLayout::Orientation orientation )
+{
+  mOrientation = orientation;
+}
+
+Dali::Toolkit::LinearLayout::Orientation LinearLayout::GetOrientation()
+{
+  return mOrientation;
+}
+
+void LinearLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
+{
+#if defined(DEBUG_ENABLED)
+  auto actor = Actor::DownCast(GetOwner());
+
+  std::ostringstream oss;
+  oss << "LinearLayout::OnMeasure  ";
+  if( actor )
+  {
+    oss << "Actor Id:" << actor.GetId() << " Name:" << actor.GetName() << "  ";
+  }
+  oss << "widthMeasureSpec:" << widthMeasureSpec << " heightMeasureSpec:" << heightMeasureSpec << std::endl;
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, oss.str().c_str() );
+#endif
+
+  if( mOrientation == Dali::Toolkit::LinearLayout::Orientation::HORIZONTAL )
+  {
+    MeasureHorizontal( widthMeasureSpec, heightMeasureSpec );
+  }
+  else
+  {
+    MeasureVertical( widthMeasureSpec, heightMeasureSpec );
+  }
+}
+
+void LinearLayout::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
+{
+#if defined(DEBUG_ENABLED)
+  auto actor = Actor::DownCast(GetOwner());
+
+  std::ostringstream oss;
+  oss << "LinearLayout::OnLayout  ";
+  if( actor )
+  {
+    oss << "Actor Id:" << actor.GetId() << " Name:" << actor.GetName() << "  ";
+  }
+  oss << "left:" << left << " top:" << top << " right:" << right << " bottom:" << bottom << std::endl;
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, oss.str().c_str() );
+#endif
+
+  if( mOrientation == Dali::Toolkit::LinearLayout::Orientation::HORIZONTAL )
+  {
+    LayoutHorizontal( left, top, right, bottom );
+  }
+  else
+  {
+    LayoutVertical( left, top, right, bottom );
+  }
+}
+
+void LinearLayout::MeasureHorizontal( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
+{
+  auto widthMode = widthMeasureSpec.GetMode();
+  auto heightMode = heightMeasureSpec.GetMode();
+  bool isExactly = (widthMode == MeasureSpec::Mode::EXACTLY);
+  bool matchHeight = false;
+  bool allFillParent = true;
+  LayoutLength maxHeight = 0;
+  LayoutLength alternativeMaxHeight = 0;
+  struct
+  {
+    MeasuredSize::State widthState;
+    MeasuredSize::State heightState;
+  } childState = { MeasuredSize::State::MEASURED_SIZE_OK, MeasuredSize::State::MEASURED_SIZE_OK };
+
+  // Reset total length
+  mTotalLength = 0;
+
+  // measure children, and determine if further resolution is required
+  for( unsigned int i=0; i<GetChildCount(); ++i )
+  {
+    auto childLayout = GetChildAt( i );
+    if( childLayout )
+    {
+      auto childOwner = childLayout->GetOwner();
+      auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
+
+      MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
+      auto childWidth = childLayout->GetMeasuredWidth();
+      auto childMargin = childLayout->GetMargin();
+
+      DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LinearLayout::OnMeasure childWidth(%d)\n", MeasureSpec::IntType( childWidth ) );
+
+      auto length = childWidth + LayoutLength::IntType(childMargin.start + childMargin.end);
+
+      auto cellPadding = i<GetChildCount()-1 ? mCellPadding.width: 0;
+
+      if( isExactly )
+      {
+        mTotalLength += length;
+      }
+      else
+      {
+        auto totalLength = mTotalLength;
+        mTotalLength = std::max( totalLength, totalLength + length + cellPadding );
+      }
+
+      bool matchHeightLocally = false;
+      if( heightMode != MeasureSpec::Mode::EXACTLY && desiredHeight == Toolkit::ChildLayoutData::MATCH_PARENT )
+      {
+        // Will have to re-measure at least this child when we know exact height.
+        matchHeight = true;
+        matchHeightLocally = true;
+      }
+
+      auto marginHeight = LayoutLength( childMargin.top + childMargin.bottom );
+      auto childHeight = childLayout->GetMeasuredHeight() + marginHeight;
+
+      if( childLayout->GetMeasuredWidthAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
+      {
+        childState.widthState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
+      }
+      if( childLayout->GetMeasuredHeightAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
+      {
+        childState.heightState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
+      }
+
+      maxHeight = std::max( maxHeight, childHeight );
+      allFillParent = ( allFillParent && desiredHeight == Toolkit::ChildLayoutData::MATCH_PARENT );
+      alternativeMaxHeight = std::max( alternativeMaxHeight, matchHeightLocally ? marginHeight : childHeight );
+    }
+  }
+
+  Extents padding = GetPadding();
+  mTotalLength += padding.start + padding.end;
+  auto widthSize = mTotalLength;
+  widthSize = std::max( widthSize, GetSuggestedMinimumWidth() );
+  MeasuredSize widthSizeAndState = ResolveSizeAndState( widthSize, widthMeasureSpec, MeasuredSize::State::MEASURED_SIZE_OK);
+  widthSize = widthSizeAndState.GetSize();
+
+  if( !allFillParent && heightMode != MeasureSpec::Mode::EXACTLY )
+  {
+    maxHeight = alternativeMaxHeight;
+  }
+  maxHeight += padding.top + padding.bottom;
+  maxHeight = std::max( maxHeight, GetSuggestedMinimumHeight() );
+
+  widthSizeAndState.SetState( childState.widthState );
+
+  SetMeasuredDimensions( widthSizeAndState,
+                         ResolveSizeAndState( maxHeight, heightMeasureSpec, childState.heightState ) );
+
+  if( matchHeight )
+  {
+    ForceUniformHeight( GetChildCount(), widthMeasureSpec );
+  }
+}
+
+void LinearLayout::ForceUniformHeight( int count, MeasureSpec widthMeasureSpec )
+{
+  // Pretend that the linear layout has an exact size. This is the measured height of
+  // ourselves. The measured height should be the max height of the children, changed
+  // to accommodate the heightMeasureSpec from the parent
+  auto uniformMeasureSpec = MeasureSpec( GetMeasuredHeight(), MeasureSpec::Mode::EXACTLY );
+  for (int i = 0; i < count; ++i)
+  {
+    LayoutItemPtr childLayout = GetChildAt(i);
+    if( childLayout != nullptr )
+    {
+      auto childOwner = childLayout->GetOwner();
+      auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
+      auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
+
+      if( desiredHeight == Toolkit::ChildLayoutData::MATCH_PARENT )
+      {
+        // Temporarily force children to reuse their old measured width
+        int oldWidth = desiredWidth;
+        childOwner.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, childLayout->GetMeasuredWidth().mValue );
+
+        // Remeasure with new dimensions
+        MeasureChildWithMargins( childLayout, widthMeasureSpec, 0, uniformMeasureSpec, 0);
+
+        childOwner.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, oldWidth );
+      }
+    }
+  }
+}
+
+void LinearLayout::LayoutHorizontal( LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
+{
+  auto owner = GetOwner();
+  auto actor = Actor::DownCast(owner);
+  bool isLayoutRtl = actor ? actor.GetProperty<bool>( Actor::Property::LAYOUT_DIRECTION ) : false;
+
+  Extents padding = GetPadding();
+
+  LayoutLength childTop( 0 );
+  LayoutLength childLeft( padding.start );
+
+  // Where bottom of child should go
+  auto height = bottom - top;
+
+  // Space available for child
+  auto childSpace = height - padding.top - padding.bottom;
+
+  auto count = GetChildCount();
+
+  int start = 0;
+  int dir = 1;
+
+  // In case of RTL, start drawing from the last child and apply right alignment.
+  // @TODO Should we have also support Actor HorizontalAlignment|VerticalAlignment in general for LinearLayout?
+  if( isLayoutRtl ) {
+    start = count - 1;
+    dir = -1;
+    childLeft = padding.start + right - left - mTotalLength;
+  }
+
+  for( unsigned int i = 0; i < count; i++)
+  {
+    int childIndex = start + dir * i;
+    LayoutItemPtr childLayout = GetChildAt( childIndex );
+    if( childLayout != nullptr )
+    {
+      auto childWidth = childLayout->GetMeasuredWidth();
+      auto childHeight = childLayout->GetMeasuredHeight();
+      auto childMargin = childLayout->GetMargin();
+
+      childTop = LayoutLength(padding.top) + ((childSpace - childHeight) / 2) + childMargin.top - childMargin.bottom;
+
+      childLeft += childMargin.start;
+      childLayout->Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
+      childLeft += childWidth + childMargin.end + mCellPadding.width;
+    }
+  }
+}
+
+void LinearLayout::MeasureVertical( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
+{
+  auto widthMode = widthMeasureSpec.GetMode();
+
+  bool matchWidth = false;
+  bool allFillParent = true;
+  LayoutLength maxWidth = 0;
+  LayoutLength alternativeMaxWidth = 0;
+
+  struct
+  {
+    MeasuredSize::State widthState;
+    MeasuredSize::State heightState;
+  } childState = { MeasuredSize::State::MEASURED_SIZE_OK, MeasuredSize::State::MEASURED_SIZE_OK };
+
+  // Reset total length
+  mTotalLength = 0;
+
+  // measure children, and determine if further resolution is required
+  for( unsigned int i=0; i<GetChildCount(); ++i )
+  {
+    auto childLayout = GetChildAt( i );
+    if( childLayout )
+    {
+      auto childOwner = childLayout->GetOwner();
+      auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
+
+      MeasureChildWithMargins( childLayout, widthMeasureSpec, 0, heightMeasureSpec, 0 );
+      auto childHeight = childLayout->GetMeasuredHeight();
+      auto childMargin = childLayout->GetMargin();
+      auto length = childHeight + LayoutLength::IntType(childMargin.top + childMargin.bottom );
+
+      auto cellPadding = i<GetChildCount()-1 ? mCellPadding.height : 0;
+      auto totalLength = mTotalLength;
+      mTotalLength = std::max( totalLength, totalLength + length + cellPadding);
+
+      bool matchWidthLocally = false;
+      if( widthMode != MeasureSpec::Mode::EXACTLY && desiredWidth == Toolkit::ChildLayoutData::MATCH_PARENT )
+      {
+        // Will have to re-measure at least this child when we know exact height.
+        matchWidth = true;
+        matchWidthLocally = true;
+      }
+
+      auto marginWidth = LayoutLength( childMargin.start + childMargin.end );
+      auto childWidth = childLayout->GetMeasuredWidth() + marginWidth;
+
+      // was combineMeasuredStates()
+      if( childLayout->GetMeasuredWidthAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
+      {
+        childState.widthState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
+      }
+      if( childLayout->GetMeasuredHeightAndState().GetState() == MeasuredSize::State::MEASURED_SIZE_TOO_SMALL )
+      {
+        childState.heightState = MeasuredSize::State::MEASURED_SIZE_TOO_SMALL;
+      }
+
+      maxWidth = std::max( maxWidth, childWidth );
+      allFillParent = ( allFillParent && desiredWidth == Toolkit::ChildLayoutData::MATCH_PARENT );
+      alternativeMaxWidth = std::max( alternativeMaxWidth, matchWidthLocally ? marginWidth : childWidth );
+    }
+  }
+  Extents padding = GetPadding();
+  mTotalLength += padding.top + padding.bottom;
+  auto heightSize = mTotalLength;
+  heightSize = std::max( heightSize, GetSuggestedMinimumHeight() );
+  MeasuredSize heightSizeAndState = ResolveSizeAndState( heightSize, heightMeasureSpec, MeasuredSize::State::MEASURED_SIZE_OK);
+  heightSize = heightSizeAndState.GetSize();
+
+  if( !allFillParent && widthMode != MeasureSpec::Mode::EXACTLY )
+  {
+    maxWidth = alternativeMaxWidth;
+  }
+  maxWidth += padding.start + padding.end;
+  maxWidth = std::max( maxWidth, GetSuggestedMinimumWidth() );
+
+  heightSizeAndState.SetState( childState.heightState );
+
+  SetMeasuredDimensions( ResolveSizeAndState( maxWidth, widthMeasureSpec, childState.widthState ),
+                         heightSizeAndState );
+
+  if( matchWidth )
+  {
+    ForceUniformWidth( GetChildCount(), heightMeasureSpec );
+  }
+}
+
+void LinearLayout::ForceUniformWidth( int count, MeasureSpec heightMeasureSpec )
+{
+  // Pretend that the linear layout has an exact size.
+  auto uniformMeasureSpec = MeasureSpec( GetMeasuredWidth(), MeasureSpec::Mode::EXACTLY );
+  for (int i = 0; i < count; ++i)
+  {
+    LayoutItemPtr childLayout = GetChildAt(i);
+    if( childLayout != nullptr )
+    {
+      auto childOwner = childLayout->GetOwner();
+      auto desiredWidth = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION );
+      auto desiredHeight = childOwner.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION );
+
+      if( desiredWidth == Toolkit::ChildLayoutData::MATCH_PARENT )
+      {
+        // Temporarily force children to reuse their old measured height
+        int oldHeight = desiredHeight;
+        childOwner.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, childLayout->GetMeasuredHeight().mValue );
+
+        // Remeasure with new dimensions
+        MeasureChildWithMargins( childLayout, uniformMeasureSpec, 0, heightMeasureSpec, 0 );
+
+        childOwner.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, oldHeight );
+      }
+    }
+  }
+}
+
+void LinearLayout::LayoutVertical( LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
+{
+  Extents padding = GetPadding();
+
+  LayoutLength childTop( 0 );
+  LayoutLength childLeft( padding.start );
+
+  // Where bottom of child should go
+  auto width = right - left;
+
+  // Space available for child
+  auto childSpace = width - padding.start - padding.end;
+  auto count = GetChildCount();
+
+  for( unsigned int childIndex = 0; childIndex < count; childIndex++)
+  {
+    LayoutItemPtr childLayout = GetChildAt( childIndex );
+    if( childLayout != nullptr )
+    {
+      auto childWidth = childLayout->GetMeasuredWidth();
+      auto childHeight = childLayout->GetMeasuredHeight();
+      auto childMargin = childLayout->GetMargin();
+
+      childTop += childMargin.top;
+      childLeft = ( childSpace - childWidth ) / 2 + childMargin.start - childMargin.end;
+
+      childLayout->Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
+      childTop += childHeight + childMargin.bottom + mCellPadding.height;
+    }
+  }
+}
+
+} // namespace Internal
+} // namespace Toolkit
+} // namespace Dali
diff --git a/dali-toolkit/internal/layouting/linear-layout-impl.h b/dali-toolkit/internal/layouting/linear-layout-impl.h
new file mode 100644 (file)
index 0000000..d9fb90a
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef DALI_TOOLKIT_INTERNAL_LAYOUTING_LINEAR_LAYOUT_H
+#define DALI_TOOLKIT_INTERNAL_LAYOUTING_LINEAR_LAYOUT_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 <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+#include <dali-toolkit/devel-api/layouting/linear-layout.h>
+
+namespace Dali
+{
+namespace Toolkit
+{
+namespace Internal
+{
+
+class LinearLayout;
+using LinearLayoutPtr = IntrusivePtr<LinearLayout>;
+
+class LinearLayout final : public LayoutGroup
+{
+public:
+  static LinearLayoutPtr New();
+
+public:
+  void SetCellPadding( LayoutSize size );
+  LayoutSize GetCellPadding();
+  void SetOrientation( Dali::Toolkit::LinearLayout::Orientation orientation );
+  Dali::Toolkit::LinearLayout::Orientation GetOrientation();
+
+protected:
+  LinearLayout();
+  virtual ~LinearLayout();
+
+  /**
+   * @copydoc LayoutItem::OnMeasure
+   */
+  virtual void OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec ) override;
+
+  /**
+   * @copydoc LayoutItem::OnLayout
+   */
+  virtual void OnLayout( bool changed, LayoutLength l, LayoutLength t, LayoutLength r, LayoutLength b ) override;
+
+private:
+  LinearLayout( const LinearLayout& other ) = delete;
+  LinearLayout& operator=( const LinearLayout& other ) = delete;
+
+ /**
+  * Measure children for horizontal orientation
+  */
+  void MeasureHorizontal( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec );
+
+ /**
+  * Apply a uniform height to the children
+  */
+  void ForceUniformHeight( int count, MeasureSpec widthMeasureSpec );
+
+ /**
+  * Layout the children horizontally
+  */
+  void LayoutHorizontal( LayoutLength l, LayoutLength t, LayoutLength r, LayoutLength b );
+
+ /**
+  * Measure children for horizontal orientation
+  */
+  void MeasureVertical( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec );
+
+ /**
+  * Apply a uniform width to the children
+  */
+  void ForceUniformWidth( int count, MeasureSpec heightMeasureSpec );
+
+ /**
+  * Layout the children vertically
+  */
+  void LayoutVertical( LayoutLength l, LayoutLength t, LayoutLength r, LayoutLength b );
+
+private:
+  LayoutSize mCellPadding;
+  Dali::Toolkit::LinearLayout::Orientation mOrientation;
+  LayoutLength mTotalLength;
+};
+
+} // namespace Internal
+
+inline Internal::LinearLayout& GetImplementation( Dali::Toolkit::LinearLayout& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "LinearLayout handle is empty" );
+  BaseObject& object = handle.GetBaseObject();
+  return static_cast<Internal::LinearLayout&>( object );
+}
+
+inline const Internal::LinearLayout& GetImplementation( const Dali::Toolkit::LinearLayout& handle )
+{
+  DALI_ASSERT_ALWAYS( handle && "LinearLayout handle is empty" );
+  const BaseObject& object = handle.GetBaseObject();
+  return static_cast<const Internal::LinearLayout&>( object );
+}
+
+} // namespace Toolkit
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_INTERNAL_LAYOUTING_LINEAR_LAYOUT_H
index 3097a21..22fba16 100644 (file)
@@ -29,7 +29,7 @@
 namespace
 {
 #if defined(DEBUG_ENABLED)
-static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::Concise, false, "LOG_LAYOUT" );
+static Debug::Filter* gLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_LAYOUT" );
 #endif
 }
 
@@ -133,7 +133,8 @@ void VboxLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeas
 
       MeasureChildWithMargins( childLayout, widthMeasureSpec, 0, heightMeasureSpec, 0 );
       auto childHeight = childLayout->GetMeasuredHeight();
-      auto childMargin = childOwner.GetProperty<Extents>( Toolkit::LayoutGroup::ChildProperty::MARGIN_SPECIFICATION );
+      auto childMargin = childLayout->GetMargin();
+
       auto length = childHeight + LayoutLength::IntType(childMargin.top + childMargin.bottom );
 
       auto cellPadding = i<GetChildCount()-1 ? mCellPadding.height : 0;
@@ -244,7 +245,7 @@ void VboxLayout::OnLayout( bool changed, LayoutLength left, LayoutLength top, La
       auto childHeight = childLayout->GetMeasuredHeight();
 
       auto childOwner = childLayout->GetOwner();
-      auto childMargin = childOwner.GetProperty<Extents>( Toolkit::LayoutGroup::ChildProperty::MARGIN_SPECIFICATION );
+      auto childMargin = childLayout->GetMargin();
 
       childTop += childMargin.top;
       childLeft = ( childSpace - childWidth ) / 2 + childMargin.start - childMargin.end;
index 24d48e3..425d60c 100644 (file)
@@ -31,7 +31,7 @@ namespace Toolkit
 
 const unsigned int TOOLKIT_MAJOR_VERSION = 1;
 const unsigned int TOOLKIT_MINOR_VERSION = 3;
-const unsigned int TOOLKIT_MICRO_VERSION = 28;
+const unsigned int TOOLKIT_MICRO_VERSION = 29;
 const char * const TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index a8511e5..9f4ca1b 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    1.3.28
+Version:    1.3.29
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT