#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;
DALI_TEST_EQUALS( hboxLayout.GetOwner(), empty, TEST_LOCATION );
DALI_TEST_EQUALS( (void*)hboxImpl.GetParent(), (void*)nullptr, TEST_LOCATION );
+ // For coverage
+ hboxImpl.SetLayoutRequested();
+
END_TEST;
}
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();
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;
+}
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() ; )
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 );
+ }
}
}
}
}
}
-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 );
+ }
}
}
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
/**
* 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
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 )
*/
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()
{