Fix WIDTH_SPECIFICATION & HEIGHT_SPECIFICATION bug. 88/181288/7
authorAnton Obzhirov <a.obzhirov@samsung.com>
Mon, 11 Jun 2018 18:04:29 +0000 (19:04 +0100)
committerAnton Obzhirov <a.obzhirov@samsung.com>
Wed, 13 Jun 2018 14:45:59 +0000 (15:45 +0100)
Change-Id: I10b5faacc51491fdd2cf3ca6c9181a526c0f271c

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

index 49bb007..6abc0c7 100644 (file)
@@ -389,6 +389,54 @@ 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 = HboxLayout::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;
+}
+
 // Padding tests
 
 int UtcDaliLayouting_HboxLayout_Padding01(void)
index 9df05c6..10bfe2d 100644 (file)
@@ -182,7 +182,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\n");
 
   if ( ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) &&
          ( index <= CHILD_PROPERTY_REGISTRATION_MAX_INDEX ) )
@@ -191,6 +191,14 @@ void LayoutGroup::OnSetChildProperties( Handle& handle, Property::Index index, P
   {
     // If any child properties are set, must perform relayout
     RequestLayout();
+    for( auto&& child : mImpl->mChildren )
+    {
+      if( child.child->GetOwner() == handle )
+      {
+        child.child->SetLayoutRequested();
+        break;
+      }
+    }
   }
 }
 
@@ -226,36 +234,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 +265,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,
@@ -451,15 +436,13 @@ 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().
     }
 
     Add( *childLayout.Get() );
index be5b0ed..217ffa6 100644 (file)
@@ -140,7 +140,7 @@ void LayoutItem::Measure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasur
 
   const bool needsLayout = specChanged && ( !isSpecExactly || !matchesSpecSize );
 
-  if( forceLayout || needsLayout)
+  if( forceLayout || needsLayout )
   {
     mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_MEASURED_DIMENSION_SET );
 
@@ -246,6 +246,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;
@@ -272,6 +284,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 +300,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..e59ca96 100644 (file)
@@ -187,6 +187,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.
index ebbf330..7bba696 100644 (file)
@@ -286,6 +286,8 @@ YGSize FlexLayout::OnChildMeasure( YGNodeRef node,
                               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 );
@@ -348,8 +350,20 @@ YGSize FlexLayout::OnChildMeasure( YGNodeRef node,
   }
 
   // Measure for Yoga
-  MeasureSpec ygWidthMeasureSpec = MeasureSpec( desiredWidth, static_cast<MeasureSpec::Mode>(widthMode) );
-  MeasureSpec ygHeightMeasureSpec = MeasureSpec( desiredHeight, static_cast<MeasureSpec::Mode>(heightMode) );
+  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;