Change layout item list order according to the actor's child list 25/185025/2
authorHeeyong Song <heeyong.song@samsung.com>
Wed, 25 Jul 2018 08:56:31 +0000 (17:56 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Thu, 26 Jul 2018 09:30:27 +0000 (18:30 +0900)
Change-Id: Ibffb65ec27cc5aea98a2736efb3dab9af4b66322

automated-tests/src/dali-toolkit/utc-Dali-Layouting.cpp
dali-toolkit/devel-api/layouting/layout-group-impl.cpp
dali-toolkit/devel-api/layouting/layout-group-impl.h
dali-toolkit/devel-api/layouting/layout-item-impl.cpp
dali-toolkit/devel-api/layouting/layout-parent-impl.h

index cd82d5e..76f9cf4 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali-toolkit/devel-api/layouting/linear-layout.h>
 #include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
 #include <dali-toolkit/devel-api/layouting/layout-group-impl.h>
+#include <dali/devel-api/actors/actor-devel.h>
 
 #include <../custom-layout.h>
 
 using namespace Dali;
 using namespace Toolkit;
 
+void TestLayoutItemOrder( std::vector< Control >& controls, LayoutGroup& layoutGroup )
+{
+  for( auto&& iter : controls )
+  {
+    unsigned int siblingOrder = static_cast< unsigned int>( iter.GetProperty< int >( DevelActor::Property::SIBLING_ORDER ) );
+    DALI_TEST_EQUALS( layoutGroup.GetChildAt( siblingOrder ), DevelControl::GetLayout( iter ), TEST_LOCATION );
+  }
+}
+
 void utc_dali_toolkit_layouting_startup(void)
 {
   test_return_value = TET_UNDEF;
@@ -1692,6 +1702,9 @@ int UtcDaliLayouting_LayoutChildren01(void)
   DALI_TEST_EQUALS( hboxLayout.GetOwner(), empty, TEST_LOCATION );
   DALI_TEST_EQUALS( (void*)hboxImpl.GetParent(), (void*)nullptr, TEST_LOCATION );
 
+  // For coverage
+  hboxImpl.SetLayoutRequested();
+
   END_TEST;
 }
 
@@ -1798,10 +1811,10 @@ int UtcDaliLayouting_LayoutChildren04(void)
   END_TEST;
 }
 
-int UtcDaliLayouting_SetLayoutOrder(void)
+int UtcDaliLayouting_SetLayoutOrder01(void)
 {
   ToolkitTestApplication application;
-  tet_infoline(" UtcDaliLayouting_SetLayoutOrder - Call SetLayout after adding the control to the root layout");
+  tet_infoline(" UtcDaliLayouting_SetLayoutOrder01 - Call SetLayout after adding the control to the root layout");
 
   Stage stage = Stage::GetCurrent();
 
@@ -1838,3 +1851,91 @@ int UtcDaliLayouting_SetLayoutOrder(void)
 
   END_TEST;
 }
+
+int UtcDaliLayouting_SetLayoutOrder02(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_SetLayoutOrder02 - Test the layout item order and the control order");
+
+  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();
+  hbox.SetName( "HBox");
+
+  rootControl.Add( hbox );
+
+  DevelControl::SetLayout( hbox, hboxLayout );
+
+  // Add child controls
+  std::vector< Control > controls;
+  controls.push_back( CreateLeafControl( 100, 100 ) );  // 0
+  controls.push_back( CreateLeafControl( 100, 100 ) );  // 1
+  controls.push_back( CreateLeafControl( 100, 100 ) );  // 2
+
+  for( auto&& iter : controls )
+  {
+    hbox.Add( iter );
+  }
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  TestLayoutItemOrder( controls, hboxLayout );
+
+  tet_infoline("RaiseToTop");
+
+  controls[0].RaiseToTop(); // 1 2 0
+
+  TestLayoutItemOrder( controls, hboxLayout );
+
+  tet_infoline("LowerToBottom");
+
+  controls[2].LowerToBottom();  // 2 1 0
+
+  TestLayoutItemOrder( controls, hboxLayout );
+
+  tet_infoline("Remove / Add");
+
+  hbox.Remove( controls[2] );  // 1 0
+  hbox.Add( controls[2] );     // 1 0 2
+
+  TestLayoutItemOrder( controls, hboxLayout );
+
+  tet_infoline("SetLayout");
+
+  auto vboxLayout = LinearLayout::New();
+  DevelControl::SetLayout( controls[0], vboxLayout );
+
+  TestLayoutItemOrder( controls, hboxLayout );
+
+  tet_infoline("Raise");
+
+  controls[0].Raise();  // 1 2 0
+
+  TestLayoutItemOrder( controls, hboxLayout );
+
+  tet_infoline("Lower");
+
+  controls[2].Lower();   // 2 1 0
+
+  TestLayoutItemOrder( controls, hboxLayout );
+
+  tet_infoline("SetLayout again");
+
+  auto vboxLayout1 = LinearLayout::New();
+  DevelControl::SetLayout( controls[2], vboxLayout1 );
+
+  TestLayoutItemOrder( controls, hboxLayout );
+
+  DevelControl::SetLayout( controls[2], vboxLayout );
+
+  END_TEST;
+}
index f3856de..69d268d 100644 (file)
@@ -122,6 +122,104 @@ void LayoutGroup::Remove( LayoutItem& child )
   RequestLayout();
 }
 
+Toolkit::LayoutGroup::LayoutId LayoutGroup::Insert( LayoutItem& target, LayoutItem& child )
+{
+  LayoutParent* oldParent = child.GetParent();
+  if( oldParent )
+  {
+    LayoutGroupPtr parentGroup( dynamic_cast< LayoutGroup* >( oldParent ) );
+    if( parentGroup )
+    {
+      parentGroup->Remove( child );
+    }
+  }
+
+  // Find target position
+  std::vector< Impl::ChildLayout >::iterator position;
+  for( auto iter = mImpl->mChildren.begin(); iter != mImpl->mChildren.end(); ++iter )
+  {
+    if( iter->child.Get() == &target )
+    {
+      position = iter;
+      break;
+    }
+  }
+
+  Impl::ChildLayout childLayout;
+  childLayout.layoutId = mImpl->mNextLayoutId++;
+  childLayout.child = &child;
+  mImpl->mChildren.insert( position, childLayout );
+
+  child.SetParent( this );
+
+  auto owner = child.GetOwner();
+
+  // Inform deriving classes that this child has been added
+  OnChildAdd( *childLayout.child.Get() );
+
+  // Now listen to future changes to the child properties.
+  DevelHandle::PropertySetSignal(owner).Connect( this, &LayoutGroup::OnSetChildProperties );
+
+  RequestLayout();
+
+  return childLayout.layoutId;
+}
+
+Toolkit::LayoutGroup::LayoutId LayoutGroup::Move( LayoutItem& target, LayoutItem& child )
+{
+  // Remove child from the previous position
+  for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; ++iter )
+  {
+    if( iter->child.Get() == &child )
+    {
+      mImpl->mChildren.erase( iter );
+      break;
+    }
+  }
+
+  // Find target position
+  std::vector< Impl::ChildLayout >::iterator position;
+  for( auto iter = mImpl->mChildren.begin(); iter != mImpl->mChildren.end(); ++iter )
+  {
+    if( iter->child.Get() == &target )
+    {
+      position = iter;
+      break;
+    }
+  }
+
+  Impl::ChildLayout childLayout;
+  childLayout.layoutId = mImpl->mNextLayoutId++;
+  childLayout.child = &child;
+  mImpl->mChildren.insert( position, childLayout );
+
+  RequestLayout();
+
+  return childLayout.layoutId;
+}
+
+Toolkit::LayoutGroup::LayoutId LayoutGroup::MoveBack( LayoutItem& child )
+{
+  // Remove child from the previous position
+  for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; ++iter )
+  {
+    if( iter->child.Get() == &child )
+    {
+      mImpl->mChildren.erase( iter );
+      break;
+    }
+  }
+
+  Impl::ChildLayout childLayout;
+  childLayout.layoutId = mImpl->mNextLayoutId++;
+  childLayout.child = &child;
+  mImpl->mChildren.emplace_back( childLayout );
+
+  RequestLayout();
+
+  return childLayout.layoutId;
+}
+
 void LayoutGroup::RemoveAll()
 {
   for( auto iter = mImpl->mChildren.begin() ; iter != mImpl->mChildren.end() ; )
@@ -418,7 +516,30 @@ void LayoutGroup::OnInitialize()
         if( parentLayout )
         {
           Internal::LayoutGroup& parentLayoutImpl = GetImplementation( parentLayout );
-          parentLayoutImpl.Add( *this );
+
+          unsigned int count = parent.GetChildCount();
+          unsigned int index = static_cast< unsigned int >( control.GetProperty< int >( DevelActor::Property::SIBLING_ORDER ) );
+
+          // Find insertion position
+          while( ++index < count )
+          {
+            auto sibling = Toolkit::Control::DownCast( parent.GetChildAt( index ) );
+            if( sibling )
+            {
+              auto siblingLayout = DevelControl::GetLayout( sibling );
+              if( siblingLayout )
+              {
+                Internal::LayoutItem& siblingLayoutImpl = GetImplementation( siblingLayout );
+                parentLayoutImpl.Insert( siblingLayoutImpl, *this );
+                break;
+              }
+            }
+          }
+
+          if( index >= count )
+          {
+            parentLayoutImpl.Add( *this );
+          }
         }
       }
     }
@@ -509,13 +630,39 @@ void LayoutGroup::ChildRemovedFromOwner( Actor child )
   }
 }
 
-void LayoutGroup::ChildOrderChanged()
+void LayoutGroup::ChildOrderChanged( Actor child )
 {
-  RequestLayout();
-  // Force Children to be relaid out:
-  for( auto&& child : mImpl->mChildren )
+  Toolkit::Control childControl = Toolkit::Control::DownCast( child );
+  if( childControl )
   {
-    child.child->SetLayoutRequested();
+    Internal::Control& childControlImpl = GetImplementation( childControl );
+    Internal::Control::Impl& childControlDataImpl = Internal::Control::Impl::Get( childControlImpl );
+
+    auto childLayout = childControlDataImpl.GetLayout();
+    if( childLayout )
+    {
+      Toolkit::Control control = Toolkit::Control::DownCast( GetOwner() );
+      unsigned int count = control.GetChildCount();
+      unsigned int index = static_cast< unsigned int >( childControl.GetProperty< int >( DevelActor::Property::SIBLING_ORDER ) );
+
+      // Find insertion position
+      while( ++index < count )
+      {
+        auto sibling = Toolkit::Control::DownCast( control.GetChildAt( index ) );
+        if( sibling )
+        {
+          auto siblingLayout = DevelControl::GetLayout( sibling );
+          if( siblingLayout )
+          {
+            Internal::LayoutItem& siblingLayoutImpl = GetImplementation( siblingLayout );
+            Move( siblingLayoutImpl, *childLayout );
+            return;
+          }
+        }
+      }
+
+      MoveBack( *childLayout );
+    }
   }
 }
 
index 36e0312..3039125 100644 (file)
@@ -96,6 +96,26 @@ public:
   void Remove( LayoutItem& child ) override;
 
   /**
+   * @brief Insert a child to the parent
+   * @param[in] target The target item
+   * @param[in] child The item to insert to this layout parent
+   */
+  Toolkit::LayoutGroup::LayoutId Insert( LayoutItem& target, LayoutItem& child ) override;
+
+  /**
+   * @brief Move a child to another position
+   * @param[in] target The target item
+   * @param[in] child The item to move
+   */
+  Toolkit::LayoutGroup::LayoutId Move( LayoutItem& target, LayoutItem& child ) override;
+
+  /**
+   * @brief Move a child to back
+   * @param[in] child The item to move
+   */
+  Toolkit::LayoutGroup::LayoutId MoveBack( LayoutItem& child ) override;
+
+  /**
    * @brief Remove all layout children.
    *
    * @note This will not unparent owner's children
@@ -264,7 +284,7 @@ private:
   /**
    * Callback when child order is changed
    */
-  void ChildOrderChanged();
+  void ChildOrderChanged( Actor child );
 
   /**
    * Callback when an owner property is set. Triggers a relayout if it's a child property
index 4c1e6b9..a0350e3 100644 (file)
@@ -327,7 +327,7 @@ bool LayoutItem::IsLayoutRequested() const
 
 void LayoutItem::SetLayoutRequested()
 {
-  return mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
+  mImpl->SetPrivateFlag( Impl::PRIVATE_FLAG_FORCE_LAYOUT );
 }
 
 void LayoutItem::SetMeasuredDimensions( MeasuredSize measuredWidth, MeasuredSize measuredHeight )
index 677a8ff..7c9414f 100644 (file)
@@ -52,6 +52,26 @@ public:
    */
   virtual void Remove( LayoutItem& item ) = 0;
 
+  /**
+   * @brief Insert a child to the parent
+   * @param[in] target The target item
+   * @param[in] item The item to insert to this layout parent
+   */
+  virtual Toolkit::LayoutGroup::LayoutId Insert( LayoutItem& target, LayoutItem& item ) = 0;
+
+  /**
+   * @brief Move a child to another position
+   * @param[in] target The target item
+   * @param[in] item The item to move
+   */
+  virtual Toolkit::LayoutGroup::LayoutId Move( LayoutItem& target, LayoutItem& item ) = 0;
+
+  /**
+   * @brief Move a child to back
+   * @param[in] item The item to move
+   */
+  virtual Toolkit::LayoutGroup::LayoutId MoveBack( LayoutItem& item ) = 0;
+
 protected:
   virtual ~LayoutParent()
   {