[Tizen] Store LayoutItem target size when set explictly 96/195496/1
authoragnelo vaz <agnelo.vaz@samsung.com>
Wed, 5 Dec 2018 17:35:52 +0000 (17:35 +0000)
committerSeoyeon Kim <seoyeon2.kim@samsung.com>
Fri, 14 Dec 2018 02:45:23 +0000 (11:45 +0900)
MinimumWidth and height were used to store the set size of LayoutItems,
this was a problem if the ResizePolicy changed and the size set was no longer
needed as it was still stored.

If the resize policy size was less than the minimum size stored then it would
not be updated.  Hence Actor would not re-draw it after SetFrame called.

TargetSize has been added to the LayoutItem now.  It can be set to zero when no
longer needed and we can still have Minimum size working.

Change-Id: Id3f0cec1d4b1e991f2dd7034c2895ed7d8decd6c

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/layout-item-data-impl.cpp
dali-toolkit/internal/layouting/layout-item-data-impl.h
dali-toolkit/public-api/controls/control-impl.cpp

index 23cc93a..0ee5a23 100644 (file)
@@ -3341,6 +3341,117 @@ int UtcDaliLayouting_SetLayout(void)
   END_TEST;
 }
 
+int UtcDaliLayouting_SetSizeExplictFollowedByWrapContent(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_SetSizeExplictFollowedByWrapContent");
+
+  Stage stage = Stage::GetCurrent();
+
+  AbsoluteLayout absoluteLayout = AbsoluteLayout::New();
+  Control container = Control::New();
+  container.SetName( "Container" );
+  DevelControl::SetLayout( container, absoluteLayout );
+  container.SetAnchorPoint( Dali::AnchorPoint::CENTER );
+  container.SetParentOrigin( Dali::ParentOrigin::CENTER );
+
+  TextLabel textLabel = CreateTextLabel( "W" );
+  tet_infoline("SetSize explicitly then set WRAP_CONTENT");
+  textLabel.SetSize( 300.0f, 200.0f );
+  textLabel.SetProperty( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  textLabel.SetProperty( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION, ChildLayoutData::WRAP_CONTENT );
+  textLabel.SetName( "text-label" );
+  tet_infoline("Adding child to container");
+  container.Add( textLabel );
+
+  tet_infoline("Adding container stage");
+  stage.Add( container );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION ); // Not re-laid out
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 54.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  textLabel.SetProperty( TextLabel::Property::TEXT, "WWW" );
+
+  application.SendNotification();
+  application.Render();
+
+  // Add container to stage here
+  // Should call RequestLayout() to measure and layout
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION ); // Stage Size
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 162.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLayouting_SetSizeExplictFollowedByResizePolicyNaturalSize(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliLayouting_SetSizeExplictFollowedByResizePolicyNaturalSize");
+
+  Stage stage = Stage::GetCurrent();
+
+  AbsoluteLayout absoluteLayout = AbsoluteLayout::New();
+  Control container = Control::New();
+  container.SetName( "Container" );
+  DevelControl::SetLayout( container, absoluteLayout );
+  container.SetAnchorPoint( Dali::AnchorPoint::CENTER );
+  container.SetParentOrigin( Dali::ParentOrigin::CENTER );
+
+  TextLabel textLabel = CreateTextLabel( "W" );
+  tet_infoline("SetSize explicitly then set ResizePolicy::NaturalSize");
+  textLabel.SetSize( 300.0f, 200.0f );
+  textLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+  textLabel.SetName( "text-label" );
+  tet_infoline("Adding child to container");
+  container.Add( textLabel );
+
+  tet_infoline("Adding container stage");
+  stage.Add( container );
+
+  // Ensure layouting happens
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION ); // Not re-laid out
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 54.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  textLabel.SetProperty( TextLabel::Property::TEXT, "WWW" );
+
+  application.SendNotification();
+  application.Render();
+
+  // Add container to stage here
+  // Should call RequestLayout() to measure and layout
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::POSITION ), Vector3( 0.0f, 0.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( container.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 480.0f, 800.0f, 0.0f ), 0.0001f, TEST_LOCATION ); // Stage Size
+  DALI_TEST_EQUALS( textLabel.GetProperty<Vector3>( Actor::Property::SIZE ), Vector3( 162.0f, 64.0f, 0.0f ), 0.0001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
 int UtcDaliLayouting_StageAdd(void)
 {
   ToolkitTestApplication application;
@@ -3359,7 +3470,8 @@ int UtcDaliLayouting_StageAdd(void)
   child.SetAnchorPoint( Dali::AnchorPoint::TOP_LEFT );
   child.SetPosition( 0.0f, 0.0f );
   child.SetSize( 480.0f, 180.0f );
-  child.SetName( "Child Control" );
+  child.SetName( "ChildControl" );
+  tet_infoline("Adding child to container");
   container.Add( child );
 
   // Ensure layouting happens
@@ -3377,6 +3489,7 @@ int UtcDaliLayouting_StageAdd(void)
 
   // Add container to stage here
   // Should call RequestLayout() to measure and layout
+  tet_infoline("Adding container stage");
   stage.Add( container );
 
   application.SendNotification();
index 02dd0f7..e5af6bb 100755 (executable)
@@ -349,7 +349,7 @@ void LayoutGroup::MeasureChild( LayoutItemPtr child,
   // 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 );
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChild desiredWidth(%d) desiredHeight(%d)\n", desiredWidth, desiredHeight );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChild child WIDTH_SPEC(%d) child HEIGHT SPEC(%d)\n", desiredWidth, desiredHeight );
 
   auto padding = GetPadding(); // Padding of this layout's owner, not of the child being measured.
 
@@ -373,13 +373,13 @@ 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 );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChildWithMargins child WIDTH_SPEC(%d)\n",  desiredWidth );
 
   MeasureSpec childWidthMeasureSpec = GetChildMeasureSpec( parentWidthMeasureSpec,
                                                            LayoutLength( padding.start + padding.end ) +
                                                            widthUsed, desiredWidth );
 
-  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChildWithMargins desiredHeight(%d)\n",  desiredHeight );
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::MeasureChildWithMargins child HEIGHT_SPEC(%d)\n",  desiredHeight );
 
   MeasureSpec childHeightMeasureSpec = GetChildMeasureSpec( parentHeightMeasureSpec,
                                                             LayoutLength( padding.top + padding.bottom )+
@@ -397,12 +397,14 @@ MeasureSpec LayoutGroup::GetChildMeasureSpec(
   auto specMode = measureSpec.GetMode();
   LayoutLength specSize = measureSpec.GetSize();
 
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::GetChildMeasureSpec childDimension(%f)\n", childDimension.AsInteger() );
+
   LayoutLength size = std::max( LayoutLength(0), specSize - padding ); // reduce available size by the owners padding
 
   LayoutLength resultSize = 0;
   MeasureSpec::Mode resultMode = MeasureSpec::Mode::UNSPECIFIED;
 
-  switch( specMode )
+  switch( specMode ) // Parents specMode
   {
     // Parent has imposed an exact size on us
     case MeasureSpec::Mode::EXACTLY:
@@ -631,14 +633,21 @@ void LayoutGroup::ChildAddedToOwnerImpl( Actor child )
       Vector3 size = child.GetTargetSize();
       // If the size of the control is set explicitly make sure that the control size
       // stays the same after the layout except it is over written with match parent specs.
-      if ( size.x != 0 )
+
+      auto childControl = Toolkit::Control::DownCast(childLayout->GetOwner());
+
+      bool setWidthExplictly = ( childControl.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION ) > 0  );
+      if ( size.x != 0 || setWidthExplictly )
       {
-        childLayout->SetMinimumWidth( size.x );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::ChildAddedToOwner SetTargetWidth(%f)\n", size.x );
+        childLayout->SetTargetWidth( size.x );
       }
 
-      if ( size.y != 0 )
+      bool setHeightExplcitly = ( childControl.GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION ) > 0 );
+      if ( size.y != 0 || setHeightExplcitly )
       {
-        childLayout->SetMinimumHeight( size.y );
+        DALI_LOG_INFO( gLogFilter, Debug::Verbose, "LayoutGroup::ChildAddedToOwner SetTargetHeight(%f)\n", size.y);
+        childLayout->SetTargetHeight( size.y );
       }
       // Default layout data will be generated by Add().
     }
index 0b638de..67e0917 100644 (file)
@@ -353,7 +353,7 @@ LayoutLength LayoutItem::GetDefaultSize( LayoutLength size, MeasureSpec measureS
   auto specMode = measureSpec.GetMode();
   auto specSize = measureSpec.GetSize();
 
-  DALI_LOG_STREAM( gLayoutFilter, Debug::Verbose, "LayoutItem::GetDefaultSize MeasureSpec("<<measureSpec<< ") size:" << size << "\n" );
+  DALI_LOG_STREAM( gLayoutFilter, Debug::Verbose, "LayoutItem::GetDefaultSize size:" << size <<  "MeasureSpec(" << measureSpec << ") \n" );
 
   switch (specMode)
   {
@@ -366,10 +366,9 @@ LayoutLength LayoutItem::GetDefaultSize( LayoutLength size, MeasureSpec measureS
     {
       // Ensure the default size does not exceed the spec size unless the default size is 0.
       // Another container could provide a default size of 0.
-      LayoutLength tmp = specSize;
 
       // Do not set size to 0, use specSize in this case as could be a legacy container
-      if( size < tmp && size > LayoutLength( 0 ) )
+      if( ( size < specSize ) && ( size > LayoutLength( 0 ) )  )
       {
         result = size;
       }
@@ -394,8 +393,13 @@ void LayoutItem::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeas
   DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::OnMeasure\n");
 
   // GetDefaultSize will limit the MeasureSpec to the suggested minimumWidth and minimumHeight
-  SetMeasuredDimensions( GetDefaultSize( GetSuggestedMinimumWidth(), widthMeasureSpec ),
-                         GetDefaultSize( GetSuggestedMinimumHeight(), heightMeasureSpec ) );
+  auto minimumWidth = GetSuggestedMinimumWidth();
+  auto minimumHeight = GetSuggestedMinimumHeight();
+  DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::OnMeasure minimumWidth(%f) minimumHeight(%f)\n",
+                 minimumWidth.AsInteger(), minimumHeight.AsInteger() );
+
+  SetMeasuredDimensions( GetDefaultSize( minimumWidth, widthMeasureSpec ),
+                         GetDefaultSize( minimumHeight, heightMeasureSpec ) );
 }
 
 void LayoutItem::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
@@ -519,8 +523,21 @@ LayoutLength LayoutItem::GetSuggestedMinimumWidth() const
   auto owner = GetOwner();
   auto actor = Actor::DownCast(owner);
   auto naturalSize = actor ? actor.GetNaturalSize() : Vector3::ZERO;
+  LayoutLength layoutMinimumWidth = GetMinimumWidth();
+
+  // Set minimum size takes precedence over natural size.
+  LayoutLength result = std::max( layoutMinimumWidth, LayoutLength( naturalSize.width ) );
+
+  if( actor.GetChildCount() == 0 ) // If not a container
+  {
+    LayoutLength targetWidth = GetTargetWidth();
+    DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::GetSuggestedMinimumWidth targetWidth(%f)\n", targetWidth.AsInteger() );
+    result = (result > 0 && (targetWidth < 1 ) ) ? result : targetWidth;  // Use size set if no mininum width and control has no natural size.
+  }
 
-  return std::max( mImpl->mMinimumSize.GetWidth(), LayoutLength( naturalSize.width ) );
+  DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::GetSuggestedMinimumWidth control(%s) naturalWidth(%f) minimumSize.width(%f) targetWidth(%f) result(%f)\n",
+        actor.GetName().c_str(), LayoutLength( naturalSize.width ).AsInteger(), layoutMinimumWidth.AsInteger(), actor.GetTargetSize().width, result.AsInteger() );
+  return result;
 }
 
 LayoutLength LayoutItem::GetSuggestedMinimumHeight() const
@@ -528,8 +545,20 @@ LayoutLength LayoutItem::GetSuggestedMinimumHeight() const
   auto owner = GetOwner();
   auto actor = Actor::DownCast(owner);
   auto naturalSize = actor ? actor.GetNaturalSize() : Vector3::ZERO;
+  LayoutLength layoutMinimumHeight = GetMinimumHeight();
 
-  return std::max( mImpl->mMinimumSize.GetHeight(), LayoutLength( naturalSize.height ) );
+  // Set minimum size takes precedence over natural size.
+  LayoutLength result = std::max( layoutMinimumHeight, LayoutLength( naturalSize.height ) );
+
+  if( actor.GetChildCount() == 0 ) // If not a container
+  {
+    LayoutLength targetHeight = GetTargetHeight();
+    result = (result > 0 && (targetHeight < 1 ) )?result : targetHeight; // Use size set if no mininum width and control has no natural size.
+  }
+
+  DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::GetSuggestedMinimumHeight control(%s) naturalHeight(%f) minimumHeight(%f) targetHeight(%f) result(%f)\n",
+          actor.GetName().c_str(), naturalSize.height, layoutMinimumHeight.AsInteger(), actor.GetTargetSize().height, result.AsInteger() );
+  return result;
 }
 
 MeasuredSize LayoutItem::ResolveSizeAndState( LayoutLength size, MeasureSpec measureSpec, MeasuredSize::State childMeasuredState )
@@ -584,6 +613,9 @@ bool LayoutItem::SetFrame( LayoutLength left, LayoutLength top, LayoutLength rig
     mImpl->ClearPrivateFlag( Impl::PRIVATE_FLAG_FORCE_SET_FRAME );
   }
 
+  DALI_LOG_INFO( gLayoutFilter, Debug::Verbose, "LayoutItem::SetFrame %s changed size(%s)\n",
+        Actor::DownCast( GetOwner() ).GetName().c_str(), (changed)?"yes":"no" );
+
   LayoutLength oldWidth = mImpl->mRight - mImpl->mLeft;
   LayoutLength oldHeight = mImpl->mBottom - mImpl->mTop;
   LayoutLength newWidth = right - left;
@@ -660,6 +692,26 @@ bool LayoutItem::SetFrame( LayoutLength left, LayoutLength top, LayoutLength rig
   return changed;
 }
 
+LayoutLength LayoutItem::GetTargetWidth() const
+{
+  return mImpl->mTargetWidth;
+}
+
+LayoutLength LayoutItem::GetTargetHeight() const
+{
+  return mImpl->mTargetHeight;
+}
+
+void LayoutItem::SetTargetWidth( LayoutLength width )
+{
+  mImpl->mTargetWidth = width;
+}
+
+void LayoutItem::SetTargetHeight( LayoutLength height )
+{
+  mImpl->mTargetHeight = height;
+}
+
 void LayoutItem::OnLayoutAnimationFinished( Animation& animation )
 {
   auto owner = GetOwner();
index 47d65cc..9089eaf 100755 (executable)
@@ -359,6 +359,40 @@ public:
    */
   Extents GetMargin() const;
 
+  /**
+   * @brief Sets the target width of the layout item.
+   *
+   * The item may not actually be drawn as this size but the value is stored
+   * so if space allows it may take up this size at some point.
+   *
+   * @param[in] width The target width the layout will try to be, in pixels
+   */
+  void SetTargetWidth( LayoutLength width );
+
+  /**
+   * @brief Sets the target height of the layout item.
+   *
+   * The item may not actually be drawn as this size but the value is stored
+   * so if space allows it may take up this size at some point.
+   *
+   * @param[in] height The target width the layout will try to be, in pixels
+   */
+  void SetTargetHeight( LayoutLength height );
+
+  /**
+   * @brief Gets the target width of this layout item.
+   *
+   * @return height The target width set on this layout item
+   */
+  LayoutLength GetTargetWidth() const;
+
+  /**
+   * @brief Gets the target height of the layout item.
+   *
+   * @return height The target width set on this layout item
+   */
+  LayoutLength GetTargetHeight() const;
+
 protected:
   /**
    * @brief Allow directly deriving classes to remove layout children when unparented
index c97a8df..c254124 100644 (file)
@@ -37,6 +37,8 @@ LayoutItem::Impl::Impl()
   mMinimumSize(),
   mMeasuredWidth(0),
   mMeasuredHeight(0),
+  mTargetWidth(0),
+  mTargetHeight(0),
   mLeft( 0 ),
   mRight( 0 ),
   mTop( 0 ),
index 0b415ad..cff1577 100644 (file)
@@ -45,6 +45,9 @@ public:
   MeasuredSize mMeasuredWidth;
   MeasuredSize mMeasuredHeight;
 
+  LayoutLength mTargetWidth;  ///< Original fixed width that was set
+  LayoutLength mTargetHeight; ///< Original fixed height that was set
+
   LayoutLength mLeft;
   LayoutLength mRight;
   LayoutLength mTop;
index 1804809..a0788b0 100755 (executable)
@@ -707,6 +707,24 @@ void Control::OnRelayout( const Vector2& size, RelayoutContainer& container )
 
 void Control::OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
 {
+    DALI_LOG_INFO( gLogFilter, Debug::General, "Control::OnSetResizePolicy for %s %d\n", Self().GetName().c_str(), policy );
+
+    if( mImpl->GetLayout() )
+    {
+      const ResizePolicy::Type resizePolicy = Self().GetResizePolicy( dimension );
+
+      if( ResizePolicy::FIXED != resizePolicy && ( Self().GetProperty<int>( Toolkit::LayoutItem::ChildProperty::WIDTH_SPECIFICATION ) < 0 ) && ( dimension == Dimension::WIDTH || dimension == Dimension::ALL_DIMENSIONS ) )
+      {
+        DALI_LOG_INFO( gLogFilter, Debug::General, "Control::OnSetResizePolicy Reseting MinimumWidth\n" );
+        mImpl->GetLayout()->SetMinimumWidth( 0 );
+      }
+
+      if( ResizePolicy::FIXED != resizePolicy && ( Self().GetProperty<int>( Toolkit::LayoutItem::ChildProperty::HEIGHT_SPECIFICATION ) < 0 ) &&  ( dimension == Dimension::HEIGHT || dimension == Dimension::ALL_DIMENSIONS ) )
+      {
+        DALI_LOG_INFO( gLogFilter, Debug::General, "Control::OnSetResizePolicy Reseting MinimumHeight\n" );
+        mImpl->GetLayout()->SetMinimumHeight( 0 );
+      }
+    }
 }
 
 Vector3 Control::GetNaturalSize()