Refactored actor size negotiation 83/266583/3
authorDavid Steele <david.steele@samsung.com>
Mon, 15 Nov 2021 13:37:20 +0000 (13:37 +0000)
committerDavid Steele <david.steele@samsung.com>
Wed, 17 Nov 2021 13:18:35 +0000 (13:18 +0000)
Moved all size negotiation implementation to a new
ActorSizer class. This handles size negotiation and
target / animated size.

Moved static methods from ActorRelayouter into ActorSizer.

Change-Id: I5137bb333d0254c80ede361ee7d36899830de21f
Signed-off-by: David Steele <david.steele@samsung.com>
automated-tests/src/dali-internal/utc-Dali-Internal-ActorRelayout.cpp
automated-tests/src/dali/dali-test-suite-utils/test-custom-actor.cpp
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h
dali/internal/event/actors/actor-property-handler.cpp
dali/internal/event/actors/actor-relayouter.cpp
dali/internal/event/actors/actor-relayouter.h
dali/internal/event/actors/actor-sizer.cpp [new file with mode: 0644]
dali/internal/event/actors/actor-sizer.h [new file with mode: 0644]
dali/internal/event/size-negotiation/relayout-controller-impl.cpp
dali/internal/file.list

index 11babca..2e77750 100644 (file)
@@ -39,7 +39,7 @@ void utc_dali_internal_actor_relayouter_cleanup()
   test_return_value = TET_PASS;
 }
 
-int UtcDaliActorRelayouter_CalculateSize(void)
+int UtcDaliActorSizer_CalculateSize(void)
 {
   TestApplication application;
 
@@ -48,62 +48,78 @@ int UtcDaliActorRelayouter_CalculateSize(void)
   auto& testActorImpl = Test::Impl::GetImpl(actor);
   auto& actorImpl     = GetImplementation(actor);
 
-  scene.Add(actor);
-  actorImpl.SetSize(Vector2(100.0f, 100.0f));
-  actorImpl.SetPreferredSize(Vector2(200.0f, 350.0f));
-
-  Vector2 maxSize(400.0f, 500.0f);
+  DALI_TEST_EQUALS(testActorImpl.IsRelayoutEnabled(), false, TEST_LOCATION);
+  DALI_TEST_CHECK(true);
 
-  DALI_TEST_EQUALS(actorImpl.CalculateSize(Dimension::WIDTH, maxSize), 200.0f, 0.00001f, TEST_LOCATION);
-  DALI_TEST_EQUALS(actorImpl.CalculateSize(Dimension::HEIGHT, maxSize), 350.0f, 0.00001f, TEST_LOCATION);
+  actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+  actor[Dali::Actor::Property::SIZE] = Vector2(150.0f, 100.0f); // Should automatically set preferred size
+  scene.Add(actor);
 
-  actor.SetResizePolicy(ResizePolicy::USE_ASSIGNED_SIZE, Dimension::HEIGHT);
-  DALI_TEST_EQUALS(actorImpl.CalculateSize(Dimension::WIDTH, maxSize), 200.0f, 0.00001f, TEST_LOCATION);
-  DALI_TEST_EQUALS(actorImpl.CalculateSize(Dimension::HEIGHT, maxSize), maxSize.y, 0.00001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(actorImpl.IsRelayoutEnabled(), true, TEST_LOCATION);
 
   testActorImpl.SetNaturalSize(Vector3(150.0f, 180.0f, 150.0f));
   actor.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS);
-
-  DALI_TEST_EQUALS(actorImpl.CalculateSize(Dimension::WIDTH, maxSize), 150.0f, 0.00001f, TEST_LOCATION);
-  DALI_TEST_EQUALS(actorImpl.CalculateSize(Dimension::HEIGHT, maxSize), 180.0f, 0.00001f, TEST_LOCATION);
-
-  actor.SetResizePolicy(ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS);
-  auto child = Test::TestCustomActor::New();
-  child.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
-  child.SetProperty(Dali::Actor::Property::SIZE, Vector2(20.0f, 40.0f));
-  auto& childImpl = GetImplementation(child);
-  actor.Add(child);
-
   application.SendNotification();
   application.Render();
 
-  DALI_TEST_EQUALS(actorImpl.CalculateSize(Dimension::WIDTH, maxSize), 20.0f, 0.00001f, TEST_LOCATION);
-  DALI_TEST_EQUALS(actorImpl.CalculateSize(Dimension::HEIGHT, maxSize), 40.0f, 0.00001f, TEST_LOCATION);
+  Vector3 size = actor[Dali::Actor::Property::SIZE];
+  DALI_TEST_EQUALS(size.width, 150.0f, 0.00001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(size.height, 180.0f, 0.00001f, TEST_LOCATION);
 
   testActorImpl.SetWidthForHeightFactor(3.5f);
   testActorImpl.SetHeightForWidthFactor(1.7f);
   actor.SetResizePolicy(ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH);
-  DALI_TEST_EQUALS(actorImpl.CalculateSize(Dimension::WIDTH, maxSize), 140.0f, 0.00001f, TEST_LOCATION);
+  application.SendNotification();
+  application.Render();
+
+  size = Vector3(actor[Dali::Actor::Property::SIZE]);
+  DALI_TEST_EQUALS(size.width, 3.5f * 180.0f, 0.00001f, TEST_LOCATION);
 
   actor.SetResizePolicy(ResizePolicy::USE_NATURAL_SIZE, Dimension::WIDTH);
   actor.SetResizePolicy(ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT);
   application.SendNotification();
   application.Render();
-  DALI_TEST_EQUALS(actorImpl.CalculateSize(Dimension::HEIGHT, maxSize), 255.0f, 0.00001f, TEST_LOCATION);
+  size = Vector3(actor[Dali::Actor::Property::SIZE]);
+  DALI_TEST_EQUALS(size.height, 1.7f * 150.0f, 0.00001f, TEST_LOCATION);
+
+  auto child = Test::TestCustomActor::New();
+  child.SetResizePolicy(ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS);
+  child.SetProperty(Dali::Actor::Property::SIZE, Vector2(20.0f, 40.0f));
+  auto& childImpl = GetImplementation(child);
+  actor.Add(child);
+  actor.TestRelayoutRequest();
+
+  tet_infoline("Test actor takes child size");
+  actor.SetResizePolicy(ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS);
+  application.SendNotification();
+  application.Render();
+  Vector3 parentSize = actor[Dali::Actor::Property::SIZE];
+  DALI_TEST_EQUALS(parentSize.width, 20.0f, 0.00001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(parentSize.height, 40.0f, 0.00001f, TEST_LOCATION);
 
+  tet_infoline("Test child actor is the right factor of the parent");
+  actor[Dali::Actor::Property::SIZE] = Vector2(150.0f, 100.0f); // Should automatically set preferred size
   child.SetResizePolicy(ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS);
   child[Dali::Actor::Property::SIZE_MODE_FACTOR] = Vector3(0.5f, 1.0f, 1.0f);
+
+  childImpl.RelayoutRequest();
   application.SendNotification();
   application.Render();
-  DALI_TEST_EQUALS(childImpl.CalculateSize(Dimension::WIDTH, maxSize), 75.0f, 0.00001f, TEST_LOCATION);
-  DALI_TEST_EQUALS(childImpl.CalculateSize(Dimension::HEIGHT, maxSize), 255.0f, 0.00001f, TEST_LOCATION);
 
+  Vector3 childSize = child[Dali::Actor::Property::SIZE];
+  DALI_TEST_EQUALS(childSize.width, 75.0f, 0.00001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(childSize.height, 100.0f, 0.00001f, TEST_LOCATION);
+
+  tet_infoline("Test child actor is the right delta of the parent");
   child.SetResizePolicy(ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::ALL_DIMENSIONS);
   child[Dali::Actor::Property::SIZE_MODE_FACTOR] = Vector3(-40.0f, -20.0f, 1.0f);
+  child.TestRelayoutRequest();
   application.SendNotification();
   application.Render();
-  DALI_TEST_EQUALS(childImpl.CalculateSize(Dimension::WIDTH, maxSize), 110.0f, 0.00001f, TEST_LOCATION);
-  DALI_TEST_EQUALS(childImpl.CalculateSize(Dimension::HEIGHT, maxSize), 235.0f, 0.00001f, TEST_LOCATION);
+
+  Vector3 size2 = child[Dali::Actor::Property::SIZE];
+  DALI_TEST_EQUALS(size2.width, 110.0f, 0.00001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(size2.height, 80.0f, 0.00001f, TEST_LOCATION);
 
   END_TEST;
 }
index 6c7b1d6..8fff834 100644 (file)
@@ -397,7 +397,7 @@ void TestCustomActor::OnLayoutNegotiated(float size, Dimension::Type dimension)
 
 bool TestCustomActor::RelayoutDependentOnChildren(Dimension::Type dimension)
 {
-  return false;
+  return CustomActorImpl::RelayoutDependentOnChildrenBase(dimension);
 }
 
 void TestCustomActor::SetTransparent(bool transparent)
index b201786..174f5e3 100644 (file)
@@ -20,7 +20,6 @@
 
 // EXTERNAL INCLUDES
 #include <algorithm>
-#include <cfloat>
 #include <cmath>
 
 // INTERNAL INCLUDES
@@ -39,7 +38,6 @@
 #include <dali/internal/event/actors/actor-coords.h>
 #include <dali/internal/event/actors/actor-parent.h>
 #include <dali/internal/event/actors/actor-property-handler.h>
-#include <dali/internal/event/actors/actor-relayouter.h>
 #include <dali/internal/event/actors/camera-actor-impl.h>
 #include <dali/internal/event/common/event-thread-services.h>
 #include <dali/internal/event/common/property-helper.h>
@@ -51,9 +49,9 @@
 #include <dali/internal/event/render-tasks/render-task-impl.h>
 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
 #include <dali/internal/event/rendering/renderer-impl.h>
-#include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
 #include <dali/internal/update/manager/update-manager.h>
 #include <dali/internal/update/nodes/node-messages.h>
+#include <dali/public-api/size-negotiation/relayout-container.h>
 
 using Dali::Internal::SceneGraph::AnimatableProperty;
 using Dali::Internal::SceneGraph::Node;
@@ -766,14 +764,12 @@ void Actor::SetInheritOrientation(bool inherit)
 
 void Actor::SetSizeModeFactor(const Vector3& factor)
 {
-  EnsureRelayouter();
-
-  mRelayoutData->sizeModeFactor = factor;
+  mSizer.SetSizeModeFactor(factor);
 }
 
 const Vector3& Actor::GetSizeModeFactor() const
 {
-  return mRelayoutData ? mRelayoutData->sizeModeFactor : Relayouter::DEFAULT_SIZE_MODE_FACTOR;
+  return mSizer.GetSizeModeFactor();
 }
 
 void Actor::SetColorMode(ColorMode colorMode)
@@ -799,154 +795,31 @@ void Actor::SetSize(const Vector2& size)
   SetSize(Vector3(size.width, size.height, 0.f));
 }
 
-void Actor::SetSizeInternal(const Vector2& size)
-{
-  SetSizeInternal(Vector3(size.width, size.height, 0.f));
-}
-
 void Actor::SetSize(const Vector3& size)
 {
-  if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
-  {
-    // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
-    SetPreferredSize(size.GetVectorXY());
-  }
-  else
-  {
-    SetSizeInternal(size);
-  }
-}
-
-void Actor::SetSizeInternal(const Vector3& size)
-{
-  // dont allow recursive loop
-  DALI_ASSERT_ALWAYS(!mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet");
-  // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
-  Vector3 currentSize = GetCurrentSize();
-
-  if((fabsf(mTargetSize.width - size.width) > Math::MACHINE_EPSILON_1) ||
-     (fabsf(mTargetSize.height - size.height) > Math::MACHINE_EPSILON_1) ||
-     (fabsf(mTargetSize.depth - size.depth) > Math::MACHINE_EPSILON_1) ||
-     (fabsf(mTargetSize.width - currentSize.width) > Math::MACHINE_EPSILON_1) ||
-     (fabsf(mTargetSize.height - currentSize.height) > Math::MACHINE_EPSILON_1) ||
-     (fabsf(mTargetSize.depth - currentSize.depth) > Math::MACHINE_EPSILON_1))
-  {
-    mTargetSize = size;
-
-    // Update the preferred size after relayoutting
-    // It should be used in the next relayoutting
-    if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH && mRelayoutData)
-    {
-      mRelayoutData->preferredSize.width = mAnimatedSize.width;
-    }
-
-    if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT && mRelayoutData)
-    {
-      mRelayoutData->preferredSize.height = mAnimatedSize.height;
-    }
-
-    // node is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize);
-
-    // Notification for derived classes
-    mInsideOnSizeSet = true;
-    OnSizeSet(mTargetSize);
-    mInsideOnSizeSet = false;
-
-    // Raise a relayout request if the flag is not locked
-    if(mRelayoutData && !mRelayoutData->insideRelayout)
-    {
-      RelayoutRequest();
-    }
-  }
+  mSizer.SetSize(size);
 }
 
 void Actor::SetWidth(float width)
 {
-  if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
-  {
-    SetResizePolicy(ResizePolicy::FIXED, Dimension::WIDTH);
-    mRelayoutData->preferredSize.width = width;
-  }
-  else
-  {
-    mTargetSize.width = width;
-
-    // node is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width);
-  }
-
-  mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
-
-  RelayoutRequest();
+  mSizer.SetWidth(width);
 }
 
 void Actor::SetHeight(float height)
 {
-  if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
-  {
-    SetResizePolicy(ResizePolicy::FIXED, Dimension::HEIGHT);
-    mRelayoutData->preferredSize.height = height;
-  }
-  else
-  {
-    mTargetSize.height = height;
-
-    // node is being used in a separate thread; queue a message to set the value & base value
-    SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height);
-  }
-
-  mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
-
-  RelayoutRequest();
+  mSizer.SetHeight(height);
 }
 
 void Actor::SetDepth(float depth)
 {
-  mTargetSize.depth = depth;
-
-  mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
-
+  mSizer.SetDepth(depth);
   // node is being used in a separate thread; queue a message to set the value & base value
   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth);
 }
 
 Vector3 Actor::GetTargetSize() const
 {
-  Vector3 size = mTargetSize;
-
-  if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH)
-  {
-    // Should return animated size if size is animated
-    size.width = mAnimatedSize.width;
-  }
-  else
-  {
-    // Should return preferred size if size is fixed as set by SetSize
-    if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::FIXED)
-    {
-      size.width = GetPreferredSize().width;
-    }
-  }
-
-  if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT)
-  {
-    size.height = mAnimatedSize.height;
-  }
-  else
-  {
-    if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::FIXED)
-    {
-      size.height = GetPreferredSize().height;
-    }
-  }
-
-  if(mUseAnimatedSize & AnimatedSizeFlag::DEPTH)
-  {
-    size.depth = mAnimatedSize.depth;
-  }
-
-  return size;
+  return mSizer.GetTargetSize();
 }
 
 const Vector3& Actor::GetCurrentSize() const
@@ -963,83 +836,42 @@ Vector3 Actor::GetNaturalSize() const
 
 void Actor::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension)
 {
-  EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
-
-  OnSetResizePolicy(policy, dimension);
-
-  // Trigger relayout on this control
-  RelayoutRequest();
+  mSizer.SetResizePolicy(policy, dimension);
 }
 
 ResizePolicy::Type Actor::GetResizePolicy(Dimension::Type dimension) const
 {
-  return mRelayoutData ? mRelayoutData->GetResizePolicy(dimension) : ResizePolicy::DEFAULT;
-}
-
-void Actor::SetSizeScalePolicy(SizeScalePolicy::Type policy)
-{
-  EnsureRelayouter();
-
-  mRelayoutData->sizeSetPolicy = policy;
-
-  // Trigger relayout on this control
-  RelayoutRequest();
-}
-
-SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
-{
-  return mRelayoutData ? mRelayoutData->sizeSetPolicy : Relayouter::DEFAULT_SIZE_SCALE_POLICY;
-}
-
-void Actor::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
-{
-  EnsureRelayouter().SetDimensionDependency(dimension, dependency);
-}
-
-Dimension::Type Actor::GetDimensionDependency(Dimension::Type dimension) const
-{
-  return mRelayoutData ? mRelayoutData->GetDimensionDependency(dimension) : Dimension::ALL_DIMENSIONS;
+  return mSizer.GetResizePolicy(dimension);
 }
 
 void Actor::SetRelayoutEnabled(bool relayoutEnabled)
 {
-  // If relayout data has not been allocated yet and the client is requesting
-  // to disable it, do nothing
-  if(mRelayoutData || relayoutEnabled)
-  {
-    EnsureRelayouter();
-
-    DALI_ASSERT_DEBUG(mRelayoutData && "mRelayoutData not created");
-
-    mRelayoutData->relayoutEnabled = relayoutEnabled;
-  }
+  mSizer.SetRelayoutEnabled(relayoutEnabled);
 }
 
 bool Actor::IsRelayoutEnabled() const
 {
-  // Assume that if relayout data has not been allocated yet then
-  // relayout is disabled
-  return mRelayoutData && mRelayoutData->relayoutEnabled;
+  return mSizer.IsRelayoutEnabled();
 }
 
 void Actor::SetLayoutDirty(bool dirty, Dimension::Type dimension)
 {
-  EnsureRelayouter().SetLayoutDirty(dirty, dimension);
+  mSizer.SetLayoutDirty(dirty, dimension);
 }
 
 bool Actor::IsLayoutDirty(Dimension::Type dimension) const
 {
-  return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
+  return mSizer.IsLayoutDirty(dimension);
 }
 
 bool Actor::RelayoutPossible(Dimension::Type dimension) const
 {
-  return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty(dimension);
+  return mSizer.RelayoutPossible(dimension);
 }
 
 bool Actor::RelayoutRequired(Dimension::Type dimension) const
 {
-  return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty(dimension);
+  return mSizer.RelayoutRequired(dimension);
 }
 
 uint32_t Actor::AddRenderer(Renderer& renderer)
@@ -1200,12 +1032,12 @@ DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
 Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
 : Object(&node),
   mParentImpl(*this),
+  mSizer(*this),
   mParent(nullptr),
   mScene(nullptr),
   mRenderers(nullptr),
   mParentOrigin(nullptr),
   mAnchorPoint(nullptr),
-  mRelayoutData(nullptr),
   mGestureData(nullptr),
   mInterceptTouchedSignal(),
   mTouchedSignal(),
@@ -1218,15 +1050,12 @@ Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
   mLayoutDirectionChangedSignal(),
   mTargetOrientation(Quaternion::IDENTITY),
   mTargetColor(Color::WHITE),
-  mTargetSize(Vector3::ZERO),
   mTargetPosition(Vector3::ZERO),
   mTargetScale(Vector3::ONE),
-  mAnimatedSize(Vector3::ZERO),
   mTouchAreaOffset(0, 0, 0, 0),
   mName(),
   mSortedDepth(0u),
   mDepth(0u),
-  mUseAnimatedSize(AnimatedSizeFlag::CLEAR),
   mIsRoot(ROOT_LAYER == derivedType),
   mIsLayer(LAYER == derivedType || ROOT_LAYER == derivedType),
   mIsOnScene(false),
@@ -1236,7 +1065,6 @@ Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
   mKeyboardFocusableChildren(true),
   mTouchFocusable(false),
   mOnSceneSignalled(false),
-  mInsideOnSizeSet(false),
   mInheritPosition(true),
   mInheritOrientation(true),
   mInheritScale(true),
@@ -1286,9 +1114,6 @@ Actor::~Actor()
   // Cleanup optional parent origin and anchor
   delete mParentOrigin;
   delete mAnchorPoint;
-
-  // Delete optional relayout data
-  delete mRelayoutData;
 }
 
 void Actor::Add(Actor& child, bool notify)
@@ -1677,238 +1502,115 @@ bool Actor::GetCurrentPropertyValue(Property::Index index, Property::Value& valu
   return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
 }
 
-Actor::Relayouter& Actor::EnsureRelayouter()
-{
-  // Assign relayouter
-  if(!mRelayoutData)
-  {
-    mRelayoutData = new Relayouter();
-  }
-
-  return *mRelayoutData;
-}
-
 bool Actor::RelayoutDependentOnParent(Dimension::Type dimension)
 {
-  return mRelayoutData && mRelayoutData->GetRelayoutDependentOnParent(dimension);
+  return mSizer.RelayoutDependentOnParent(dimension);
 }
 
 bool Actor::RelayoutDependentOnChildren(Dimension::Type dimension)
 {
-  return mRelayoutData && mRelayoutData->GetRelayoutDependentOnChildren(dimension);
-}
-
-bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
-{
-  return Actor::RelayoutDependentOnChildren(dimension);
+  return mSizer.RelayoutDependentOnChildrenBase(dimension);
 }
 
 bool Actor::RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension)
 {
-  return mRelayoutData && mRelayoutData->GetRelayoutDependentOnDimension(dimension, dependentDimension);
-}
-
-void Actor::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
-{
-  if(mRelayoutData)
-  {
-    mRelayoutData->SetNegotiatedDimension(negotiatedDimension, dimension);
-  }
-}
-
-float Actor::GetNegotiatedDimension(Dimension::Type dimension) const
-{
-  return mRelayoutData ? mRelayoutData->GetNegotiatedDimension(dimension) : 0.0f;
+  return mSizer.RelayoutDependentOnDimension(dimension, dependentDimension);
 }
 
 void Actor::SetPadding(const Vector2& padding, Dimension::Type dimension)
 {
-  EnsureRelayouter().SetPadding(padding, dimension);
+  mSizer.SetPadding(padding, dimension);
 }
 
 Vector2 Actor::GetPadding(Dimension::Type dimension) const
 {
-  return mRelayoutData ? mRelayoutData->GetPadding(dimension) : Relayouter::DEFAULT_DIMENSION_PADDING;
+  return mSizer.GetPadding(dimension);
 }
 
 void Actor::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
 {
-  EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
+  mSizer.SetLayoutNegotiated(negotiated, dimension);
 }
 
 bool Actor::IsLayoutNegotiated(Dimension::Type dimension) const
 {
-  return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
+  return mSizer.IsLayoutNegotiated(dimension);
 }
 
 float Actor::GetHeightForWidthBase(float width)
 {
-  const Vector3 naturalSize = GetNaturalSize();
-  return naturalSize.width > 0.0f ? naturalSize.height * width / naturalSize.width : width;
+  // Can be overridden in derived class
+  return mSizer.GetHeightForWidthBase(width);
 }
 
 float Actor::GetWidthForHeightBase(float height)
 {
-  const Vector3 naturalSize = GetNaturalSize();
-  return naturalSize.height > 0.0f ? naturalSize.width * height / naturalSize.height : height;
+  // Can be overridden in derived class
+  return mSizer.GetWidthForHeightBase(height);
 }
 
 float Actor::CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension)
 {
-  return Actor::Relayouter::CalculateChildSize(*this, GetImplementation(child), dimension);
+  // Can be overridden in derived class
+  return mSizer.CalculateChildSizeBase(child, dimension);
+}
+
+bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
+{
+  return mSizer.RelayoutDependentOnChildrenBase(dimension);
 }
 
 float Actor::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
 {
   // Can be overridden in derived class
-  return CalculateChildSizeBase(child, dimension);
+  return mSizer.CalculateChildSizeBase(child, dimension);
 }
 
 float Actor::GetHeightForWidth(float width)
 {
   // Can be overridden in derived class
-  return GetHeightForWidthBase(width);
+  return mSizer.GetHeightForWidthBase(width);
 }
 
 float Actor::GetWidthForHeight(float height)
 {
   // Can be overridden in derived class
-  return GetWidthForHeightBase(height);
-}
-
-float Actor::GetLatestSize(Dimension::Type dimension) const
-{
-  return IsLayoutNegotiated(dimension) ? GetNegotiatedDimension(dimension) : GetSize(dimension);
+  return mSizer.GetWidthForHeightBase(height);
 }
 
 float Actor::GetRelayoutSize(Dimension::Type dimension) const
 {
-  Vector2 padding = GetPadding(dimension);
-
-  return GetLatestSize(dimension) + padding.x + padding.y;
-}
-
-float Actor::NegotiateFromParent(Dimension::Type dimension)
-{
-  return Relayouter::NegotiateDimensionFromParent(*this, dimension);
-}
-
-float Actor::NegotiateFromChildren(Dimension::Type dimension)
-{
-  return Relayouter::NegotiateDimensionFromChildren(*this, dimension);
-}
-
-float Actor::GetSize(Dimension::Type dimension) const
-{
-  return Relayouter::GetDimensionValue(mTargetSize, dimension);
-}
-
-float Actor::GetNaturalSize(Dimension::Type dimension) const
-{
-  return Relayouter::GetDimensionValue(GetNaturalSize(), dimension);
-}
-
-float Actor::CalculateSize(Dimension::Type dimension, const Vector2& maximumSize)
-{
-  return Relayouter::CalculateSize(*this, dimension, maximumSize);
-}
-
-Vector2 Actor::ApplySizeSetPolicy(const Vector2& size)
-{
-  return mRelayoutData->ApplySizeSetPolicy(*this, size);
-}
-
-void Actor::SetNegotiatedSize(RelayoutContainer& container)
-{
-  // Do the set actor size
-  Vector2 negotiatedSize(GetLatestSize(Dimension::WIDTH), GetLatestSize(Dimension::HEIGHT));
-
-  // Adjust for size set policy
-  negotiatedSize = ApplySizeSetPolicy(negotiatedSize);
-
-  // Lock the flag to stop recursive relayouts on set size
-  mRelayoutData->insideRelayout = true;
-  SetSize(negotiatedSize);
-  mRelayoutData->insideRelayout = false;
-
-  // Clear flags for all dimensions
-  SetLayoutDirty(false);
-
-  // Give deriving classes a chance to respond
-  OnRelayout(negotiatedSize, container);
-
-  if(!mOnRelayoutSignal.Empty())
-  {
-    Dali::Actor handle(this);
-    mOnRelayoutSignal.Emit(handle);
-  }
-
-  mRelayoutData->relayoutRequested = false;
+  return mSizer.GetRelayoutSize(dimension);
 }
 
 void Actor::NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container)
 {
-  Relayouter::NegotiateSize(*this, allocatedSize, container);
-}
-
-void Actor::SetUseAssignedSize(bool use, Dimension::Type dimension)
-{
-  if(mRelayoutData)
-  {
-    mRelayoutData->SetUseAssignedSize(use, dimension);
-  }
-}
-
-bool Actor::GetUseAssignedSize(Dimension::Type dimension) const
-{
-  return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
+  mSizer.NegotiateSize(allocatedSize, container);
 }
 
 void Actor::RelayoutRequest(Dimension::Type dimension)
 {
-  Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
-  if(relayoutController)
-  {
-    Dali::Actor self(this);
-    relayoutController->RequestRelayout(self, dimension);
-
-    if(mRelayoutData)
-    {
-      mRelayoutData->relayoutRequested = true;
-    }
-  }
-}
-
-void Actor::SetPreferredSize(const Vector2& size)
-{
-  EnsureRelayouter().SetPreferredSize(*this, size);
-}
-
-Vector2 Actor::GetPreferredSize() const
-{
-  return mRelayoutData ? Vector2(mRelayoutData->preferredSize) : Relayouter::DEFAULT_PREFERRED_SIZE;
+  mSizer.RelayoutRequest(dimension);
 }
 
 void Actor::SetMinimumSize(float size, Dimension::Type dimension)
 {
-  EnsureRelayouter().SetMinimumSize(size, dimension);
-  RelayoutRequest();
+  mSizer.SetMinimumSize(size, dimension);
 }
 
 float Actor::GetMinimumSize(Dimension::Type dimension) const
 {
-  return mRelayoutData ? mRelayoutData->GetMinimumSize(dimension) : 0.0f;
+  return mSizer.GetMinimumSize(dimension);
 }
 
 void Actor::SetMaximumSize(float size, Dimension::Type dimension)
 {
-  EnsureRelayouter().SetMaximumSize(size, dimension);
-  RelayoutRequest();
+  mSizer.SetMaximumSize(size, dimension);
 }
 
 float Actor::GetMaximumSize(Dimension::Type dimension) const
 {
-  return mRelayoutData ? mRelayoutData->GetMaximumSize(dimension) : FLT_MAX;
+  return mSizer.GetMaximumSize(dimension);
 }
 
 void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage)
index 73a98aa..8f72b23 100644 (file)
 #include <string>
 
 // INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/events/gesture.h>
+#include <dali/public-api/math/viewport.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/size-negotiation/relayout-container.h>
+
 #include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/rendering/renderer-devel.h>
+
 #include <dali/internal/common/const-string.h>
 #include <dali/internal/common/internal-constants.h>
 #include <dali/internal/common/memory-pool-object-allocator.h>
 #include <dali/internal/event/actors/actor-parent-impl.h>
 #include <dali/internal/event/actors/actor-parent.h>
 #include <dali/internal/event/actors/actor-renderer-container.h>
+#include <dali/internal/event/actors/actor-sizer.h>
 #include <dali/internal/event/common/object-impl.h>
 #include <dali/internal/event/common/stage-def.h>
 #include <dali/internal/update/nodes/node-declarations.h>
-#include <dali/public-api/actors/actor.h>
-#include <dali/public-api/common/dali-common.h>
-#include <dali/public-api/common/vector-wrapper.h>
-#include <dali/public-api/events/gesture.h>
-#include <dali/public-api/math/viewport.h>
-#include <dali/public-api/object/ref-object.h>
-#include <dali/public-api/size-negotiation/relayout-container.h>
 
 namespace Dali
 {
@@ -75,41 +78,6 @@ class Actor : public Object, public ActorParent
 {
 public:
   /**
-   * @brief Struct to hold an actor and a dimension
-   */
-  struct ActorDimensionPair
-  {
-    /**
-     * @brief Constructor
-     *
-     * @param[in] newActor The actor to assign
-     * @param[in] newDimension The dimension to assign
-     */
-    ActorDimensionPair(Actor* newActor, Dimension::Type newDimension)
-    : actor(newActor),
-      dimension(newDimension)
-    {
-    }
-
-    /**
-     * @brief Equality operator
-     *
-     * @param[in] lhs The left hand side argument
-     * @param[in] rhs The right hand side argument
-     */
-    bool operator==(const ActorDimensionPair& rhs)
-    {
-      return (actor == rhs.actor) && (dimension == rhs.dimension);
-    }
-
-    Actor*          actor;     ///< The actor to hold
-    Dimension::Type dimension; ///< The dimension to hold
-  };
-
-  using ActorDimensionStack = std::vector<ActorDimensionPair>;
-
-public:
-  /**
    * Create a new actor.
    * @return A smart-pointer to the newly allocated Actor.
    */
@@ -297,13 +265,6 @@ public:
   void SetSize(const Vector2& size);
 
   /**
-   * Sets the update size for an actor.
-   *
-   * @param[in] size The size to set.
-   */
-  void SetSizeInternal(const Vector2& size);
-
-  /**
    * Sets the size of an actor.
    * This does not interfere with the actors scale factor.
    * @param [in] size The new size.
@@ -311,13 +272,6 @@ public:
   void SetSize(const Vector3& size);
 
   /**
-   * Sets the update size for an actor.
-   *
-   * @param[in] size The size to set.
-   */
-  void SetSizeInternal(const Vector3& size);
-
-  /**
    * Set the width component of the Actor's size.
    * @param [in] width The new width component.
    */
@@ -857,16 +811,6 @@ public:
   virtual bool RelayoutDependentOnChildren(Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
 
   /**
-   * @brief Determine if this actor is dependent on it's children for relayout.
-   *
-   * Called from deriving classes
-   *
-   * @param dimension The dimension(s) to check for
-   * @return Return if the actor is dependent on it's children
-   */
-  virtual bool RelayoutDependentOnChildrenBase(Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
-
-  /**
    * @brief Calculate the size for a child
    *
    * @param[in] child The child actor to calculate the size for
@@ -913,24 +857,6 @@ public:
   void NegotiateSize(const Vector2& size, RelayoutContainer& container);
 
   /**
-   * @brief Set whether size negotiation should use the assigned size of the actor
-   * during relayout for the given dimension(s)
-   *
-   * @param[in] use Whether the assigned size of the actor should be used
-   * @param[in] dimension The dimension(s) to set. Can be a bitfield of multiple dimensions
-   */
-  void SetUseAssignedSize(bool use, Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
-
-  /**
-   * @brief Returns whether size negotiation should use the assigned size of the actor
-   * during relayout for a single dimension
-   *
-   * @param[in] dimension The dimension to get
-   * @return Return whether the assigned size of the actor should be used. If more than one dimension is requested, just return the first one found
-   */
-  bool GetUseAssignedSize(Dimension::Type dimension) const;
-
-  /**
    * @copydoc Dali::Actor::SetResizePolicy()
    */
   void SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
@@ -941,26 +867,6 @@ public:
   ResizePolicy::Type GetResizePolicy(Dimension::Type dimension) const;
 
   /**
-   * @copydoc Dali::Actor::SetSizeScalePolicy()
-   */
-  void SetSizeScalePolicy(SizeScalePolicy::Type policy);
-
-  /**
-   * @copydoc Dali::Actor::GetSizeScalePolicy()
-   */
-  SizeScalePolicy::Type GetSizeScalePolicy() const;
-
-  /**
-   * @copydoc Dali::Actor::SetDimensionDependency()
-   */
-  void SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency);
-
-  /**
-   * @copydoc Dali::Actor::GetDimensionDependency()
-   */
-  Dimension::Type GetDimensionDependency(Dimension::Type dimension) const;
-
-  /**
    * @brief Set the size negotiation relayout enabled on this actor
    *
    * @param[in] relayoutEnabled Boolean to enable or disable relayout
@@ -976,6 +882,7 @@ public:
 
   /**
    * @brief Mark an actor as having it's layout dirty
+   * @note Only called from RelayoutController
    *
    * @param dirty Whether to mark actor as dirty or not
    * @param dimension The dimension(s) to mark as dirty
@@ -984,6 +891,7 @@ public:
 
   /**
    * @brief Return if any of an actor's dimensions are marked as dirty
+   * @note Only called from RelayoutController
    *
    * @param dimension The dimension(s) to check
    * @return Return if any of the requested dimensions are dirty
@@ -992,6 +900,7 @@ public:
 
   /**
    * @brief Returns if relayout is enabled and the actor is not dirty
+   * @note Only called from RelayoutController
    *
    * @return Return if it is possible to relayout the actor
    */
@@ -999,6 +908,7 @@ public:
 
   /**
    * @brief Returns if relayout is enabled and the actor is dirty
+   * @note Only called from RelayoutController
    *
    * @return Return if it is required to relayout the actor
    */
@@ -1021,6 +931,7 @@ public:
 
   /**
    * @brief Determine if this actor is dependent on it's parent for relayout
+   * @note Only called from RelayoutController
    *
    * @param dimension The dimension(s) to check for
    * @return Return if the actor is dependent on it's parent
@@ -1029,6 +940,7 @@ public:
 
   /**
    * @brief Determine if this actor has another dimension depedent on the specified one
+   * @note Only called from RelayoutController
    *
    * @param dimension The dimension to check for
    * @param dependentDimension The dimension to check for dependency with
@@ -1037,47 +949,6 @@ public:
   bool RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension);
 
   /**
-   * @brief Calculate the size of a dimension
-   *
-   * @param[in] dimension The dimension to calculate the size for
-   * @param[in] maximumSize The upper bounds on the size
-   * @return Return the calculated size for the dimension
-   */
-  float CalculateSize(Dimension::Type dimension, const Vector2& maximumSize);
-
-  /**
-   * Negotiate a dimension based on the size of the parent
-   *
-   * @param[in] dimension The dimension to negotiate on
-   * @return Return the negotiated size
-   */
-  float NegotiateFromParent(Dimension::Type dimension);
-
-  /**
-   * @brief Negotiate a dimension based on the size of the children
-   *
-   * @param[in] dimension The dimension to negotiate on
-   * @return Return the negotiated size
-   */
-  float NegotiateFromChildren(Dimension::Type dimension);
-
-  /**
-   * Set the negotiated dimension value for the given dimension(s)
-   *
-   * @param negotiatedDimension The value to set
-   * @param dimension The dimension(s) to set the value for
-   */
-  void SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
-
-  /**
-   * Return the value of negotiated dimension for the given dimension
-   *
-   * @param dimension The dimension to retrieve
-   * @return Return the value of the negotiated dimension
-   */
-  float GetNegotiatedDimension(Dimension::Type dimension) const;
-
-  /**
    * @brief Set the padding for a dimension
    *
    * @param[in] padding Padding for the dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
@@ -1094,22 +965,6 @@ public:
   Vector2 GetPadding(Dimension::Type dimension) const;
 
   /**
-   * Return the actor size for a given dimension
-   *
-   * @param[in] dimension The dimension to retrieve the size for
-   * @return Return the size for the given dimension
-   */
-  float GetSize(Dimension::Type dimension) const;
-
-  /**
-   * Return the natural size of the actor for a given dimension
-   *
-   * @param[in] dimension The dimension to retrieve the size for
-   * @return Return the natural size for the given dimension
-   */
-  float GetNaturalSize(Dimension::Type dimension) const;
-
-  /**
    * @brief Return the amount of size allocated for relayout
    *
    * May include padding
@@ -1120,21 +975,6 @@ public:
   float GetRelayoutSize(Dimension::Type dimension) const;
 
   /**
-   * @brief If the size has been negotiated return that else return normal size
-   *
-   * @param[in] dimension The dimension to retrieve
-   * @return Return the size
-   */
-  float GetLatestSize(Dimension::Type dimension) const;
-
-  /**
-   * Apply the negotiated size to the actor
-   *
-   * @param[in] container The container to fill with actors that require further relayout
-   */
-  void SetNegotiatedSize(RelayoutContainer& container);
-
-  /**
    * @brief Flag the actor as having it's layout dimension negotiated.
    *
    * @param[in] negotiated The status of the flag to set.
@@ -1165,7 +1005,7 @@ public:
   float GetWidthForHeightBase(float height);
 
   /**
-   * @brief Calculate the size for a child
+   * @brief provides the Actor implementation of CalculateChildSize
    *
    * @param[in] child The child actor to calculate the size for
    * @param[in] dimension The dimension to calculate the size for. E.g. width or height.
@@ -1174,18 +1014,12 @@ public:
   float CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension);
 
   /**
-   * @brief Set the preferred size for size negotiation
-   *
-   * @param[in] size The preferred size to set
-   */
-  void SetPreferredSize(const Vector2& size);
-
-  /**
-   * @brief Return the preferred size used for size negotiation
+   * @brief Determine if this actor is dependent on it's children for relayout.
    *
-   * @return Return the preferred size
+   * @param dimension The dimension(s) to check for
+   * @return Return if the actor is dependent on it's children
    */
-  Vector2 GetPreferredSize() const;
+  bool RelayoutDependentOnChildrenBase(Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
 
   /**
    * @copydoc Dali::Actor::SetMinimumSize
@@ -1799,19 +1633,6 @@ private:
     };
   };
 
-  struct AnimatedSizeFlag
-  {
-    enum Type
-    {
-      CLEAR  = 0,
-      WIDTH  = 1,
-      HEIGHT = 2,
-      DEPTH  = 4
-    };
-  };
-
-  struct Relayouter;
-
   // Remove default constructor and copy constructor
   Actor()             = delete;
   Actor(const Actor&) = delete;
@@ -1906,19 +1727,6 @@ private:
   bool GetCurrentPropertyValue(Property::Index index, Property::Value& value) const;
 
   /**
-   * @brief Ensure the relayouter is allocated
-   */
-  Relayouter& EnsureRelayouter();
-
-  /**
-   * @brief Apply the size set policy to the input size
-   *
-   * @param[in] size The size to apply the policy to
-   * @return Return the adjusted size
-   */
-  Vector2 ApplySizeSetPolicy(const Vector2& size);
-
-  /**
    * Retrieve the parent object of an Actor.
    * @return The parent object, or NULL if the Actor does not have a parent.
    */
@@ -2004,12 +1812,12 @@ private:
 
 protected:
   ActorParentImpl    mParentImpl;   ///< Implementation of ActorParent;
+  ActorSizer         mSizer;        ///< Implementation for managing actor size
   ActorParent*       mParent;       ///< Each actor (except the root) can have one parent
   Scene*             mScene;        ///< The scene the actor is added to
   RendererContainer* mRenderers;    ///< Renderer container
   Vector3*           mParentOrigin; ///< NULL means ParentOrigin::DEFAULT. ParentOrigin is non-animatable
   Vector3*           mAnchorPoint;  ///< NULL means AnchorPoint::DEFAULT. AnchorPoint is non-animatable
-  Relayouter*        mRelayoutData; ///< Struct to hold optional collection of relayout variables
   ActorGestureData*  mGestureData;  ///< Optional Gesture data. Only created when actor requires gestures
 
   // Signals
@@ -2025,16 +1833,13 @@ protected:
 
   Quaternion mTargetOrientation; ///< Event-side storage for orientation
   Vector4    mTargetColor;       ///< Event-side storage for color
-  Vector3    mTargetSize;        ///< Event-side storage for size (not a pointer as most actors will have a size)
   Vector3    mTargetPosition;    ///< Event-side storage for position (not a pointer as most actors will have a position)
   Vector3    mTargetScale;       ///< Event-side storage for scale
-  Vector3    mAnimatedSize;      ///< Event-side storage for size animation
   Rect<int>  mTouchAreaOffset;   ///< touch area offset (left, right, bottom, top)
 
-  ConstString mName;            ///< Name of the actor
-  uint32_t    mSortedDepth;     ///< The sorted depth index. A combination of tree traversal and sibling order.
-  int16_t     mDepth;           ///< The depth in the hierarchy of the actor. Only 32,767 levels of depth are supported
-  uint16_t    mUseAnimatedSize; ///< Whether the size is animated.
+  ConstString mName;        ///< Name of the actor
+  uint32_t    mSortedDepth; ///< The sorted depth index. A combination of tree traversal and sibling order.
+  int16_t     mDepth;       ///< The depth in the hierarchy of the actor. Only 32,767 levels of depth are supported
 
   const bool               mIsRoot : 1;                    ///< Flag to identify the root actor
   const bool               mIsLayer : 1;                   ///< Flag to identify that this is a layer
@@ -2068,6 +1873,7 @@ private:
   struct SiblingHandler;
 
   friend class ActorParentImpl; // Allow impl to call private methods on actor
+  friend class ActorSizer;      // Allow sizer to call private methods on actor
 };
 
 } // namespace Internal
index cce13c8..2012ed1 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <dali/internal/event/actors/actor-impl.h>
 #include <dali/internal/event/actors/actor-relayouter.h>
+#include <dali/internal/event/actors/actor-sizer.h>
 #include <dali/internal/event/common/property-helper.h>
 #include <dali/internal/update/nodes/node-declarations.h>
 #include <dali/internal/update/nodes/node-messages.h>
@@ -423,30 +424,30 @@ void Actor::PropertyHandler::SetDefaultProperty(Internal::Actor& actor, Property
 
     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
     {
-      ResizePolicy::Type type = actor.GetResizePolicy(Dimension::WIDTH);
+      ResizePolicy::Type type = actor.mSizer.GetResizePolicy(Dimension::WIDTH);
       if(Scripting::GetEnumerationProperty<ResizePolicy::Type>(property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type))
       {
-        actor.SetResizePolicy(type, Dimension::WIDTH);
+        actor.mSizer.SetResizePolicy(type, Dimension::WIDTH);
       }
       break;
     }
 
     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
     {
-      ResizePolicy::Type type = actor.GetResizePolicy(Dimension::HEIGHT);
+      ResizePolicy::Type type = actor.mSizer.GetResizePolicy(Dimension::HEIGHT);
       if(Scripting::GetEnumerationProperty<ResizePolicy::Type>(property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type))
       {
-        actor.SetResizePolicy(type, Dimension::HEIGHT);
+        actor.mSizer.SetResizePolicy(type, Dimension::HEIGHT);
       }
       break;
     }
 
     case Dali::Actor::Property::SIZE_SCALE_POLICY:
     {
-      SizeScalePolicy::Type type = actor.GetSizeScalePolicy();
+      SizeScalePolicy::Type type = actor.mSizer.GetSizeScalePolicy();
       if(Scripting::GetEnumerationProperty<SizeScalePolicy::Type>(property, SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type))
       {
-        actor.SetSizeScalePolicy(type);
+        actor.mSizer.SetSizeScalePolicy(type);
       }
       break;
     }
@@ -455,7 +456,7 @@ void Actor::PropertyHandler::SetDefaultProperty(Internal::Actor& actor, Property
     {
       if(property.Get<bool>())
       {
-        actor.SetResizePolicy(ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH);
+        actor.mSizer.SetResizePolicy(ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH);
       }
       break;
     }
@@ -464,7 +465,7 @@ void Actor::PropertyHandler::SetDefaultProperty(Internal::Actor& actor, Property
     {
       if(property.Get<bool>())
       {
-        actor.SetResizePolicy(ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT);
+        actor.mSizer.SetResizePolicy(ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT);
       }
       break;
     }
@@ -797,68 +798,40 @@ void Actor::PropertyHandler::OnNotifyDefaultPropertyAnimation(Internal::Actor& a
       {
         case Dali::Actor::Property::SIZE:
         {
-          if(value.Get(actor.mTargetSize))
+          Vector3 targetSize;
+          if(value.Get(targetSize))
           {
-            actor.mAnimatedSize    = actor.mTargetSize;
-            actor.mUseAnimatedSize = AnimatedSizeFlag::WIDTH | AnimatedSizeFlag::HEIGHT | AnimatedSizeFlag::DEPTH;
-
-            if(actor.mRelayoutData && !actor.mRelayoutData->relayoutRequested)
-            {
-              actor.mRelayoutData->preferredSize.width  = actor.mAnimatedSize.width;
-              actor.mRelayoutData->preferredSize.height = actor.mAnimatedSize.height;
-            }
-
-            // Notify deriving classes
-            actor.OnSizeAnimation(animation, actor.mTargetSize);
+            actor.mSizer.OnAnimateSize(animation, targetSize, false);
           }
           break;
         }
 
         case Dali::Actor::Property::SIZE_WIDTH:
         {
-          if(value.Get(actor.mTargetSize.width))
+          float width;
+          if(value.Get(width))
           {
-            actor.mAnimatedSize.width = actor.mTargetSize.width;
-            actor.mUseAnimatedSize |= AnimatedSizeFlag::WIDTH;
-
-            if(actor.mRelayoutData && !actor.mRelayoutData->relayoutRequested)
-            {
-              actor.mRelayoutData->preferredSize.width = actor.mAnimatedSize.width;
-            }
-
-            // Notify deriving classes
-            actor.OnSizeAnimation(animation, actor.mTargetSize);
+            actor.mSizer.OnAnimateWidth(animation, width, false);
           }
           break;
         }
 
         case Dali::Actor::Property::SIZE_HEIGHT:
         {
-          if(value.Get(actor.mTargetSize.height))
+          float height;
+          if(value.Get(height))
           {
-            actor.mAnimatedSize.height = actor.mTargetSize.height;
-            actor.mUseAnimatedSize |= AnimatedSizeFlag::HEIGHT;
-
-            if(actor.mRelayoutData && !actor.mRelayoutData->relayoutRequested)
-            {
-              actor.mRelayoutData->preferredSize.height = actor.mAnimatedSize.height;
-            }
-
-            // Notify deriving classes
-            actor.OnSizeAnimation(animation, actor.mTargetSize);
+            actor.mSizer.OnAnimateHeight(animation, height, false);
           }
           break;
         }
 
         case Dali::Actor::Property::SIZE_DEPTH:
         {
-          if(value.Get(actor.mTargetSize.depth))
+          float depth;
+          if(value.Get(depth))
           {
-            actor.mAnimatedSize.depth = actor.mTargetSize.depth;
-            actor.mUseAnimatedSize |= AnimatedSizeFlag::DEPTH;
-
-            // Notify deriving classes
-            actor.OnSizeAnimation(animation, actor.mTargetSize);
+            actor.mSizer.OnAnimateDepth(animation, depth, false);
           }
           break;
         }
@@ -969,68 +942,40 @@ void Actor::PropertyHandler::OnNotifyDefaultPropertyAnimation(Internal::Actor& a
       {
         case Dali::Actor::Property::SIZE:
         {
-          if(AdjustValue<Vector3>(actor.mTargetSize, value))
+          Vector3 targetSize;
+          if(value.Get(targetSize))
           {
-            actor.mAnimatedSize    = actor.mTargetSize;
-            actor.mUseAnimatedSize = AnimatedSizeFlag::WIDTH | AnimatedSizeFlag::HEIGHT | AnimatedSizeFlag::DEPTH;
-
-            if(actor.mRelayoutData && !actor.mRelayoutData->relayoutRequested)
-            {
-              actor.mRelayoutData->preferredSize.width  = actor.mAnimatedSize.width;
-              actor.mRelayoutData->preferredSize.height = actor.mAnimatedSize.height;
-            }
-
-            // Notify deriving classes
-            actor.OnSizeAnimation(animation, actor.mTargetSize);
+            actor.mSizer.OnAnimateSize(animation, targetSize, true);
           }
           break;
         }
 
         case Dali::Actor::Property::SIZE_WIDTH:
         {
-          if(AdjustValue<float>(actor.mTargetSize.width, value))
+          float width;
+          if(value.Get(width))
           {
-            actor.mAnimatedSize.width = actor.mTargetSize.width;
-            actor.mUseAnimatedSize |= AnimatedSizeFlag::WIDTH;
-
-            if(actor.mRelayoutData && !actor.mRelayoutData->relayoutRequested)
-            {
-              actor.mRelayoutData->preferredSize.width = actor.mAnimatedSize.width;
-            }
-
-            // Notify deriving classes
-            actor.OnSizeAnimation(animation, actor.mTargetSize);
+            actor.mSizer.OnAnimateWidth(animation, width, true);
           }
           break;
         }
 
         case Dali::Actor::Property::SIZE_HEIGHT:
         {
-          if(AdjustValue<float>(actor.mTargetSize.height, value))
+          float height;
+          if(value.Get(height))
           {
-            actor.mAnimatedSize.height = actor.mTargetSize.height;
-            actor.mUseAnimatedSize |= AnimatedSizeFlag::HEIGHT;
-
-            if(actor.mRelayoutData && !actor.mRelayoutData->relayoutRequested)
-            {
-              actor.mRelayoutData->preferredSize.height = actor.mAnimatedSize.height;
-            }
-
-            // Notify deriving classes
-            actor.OnSizeAnimation(animation, actor.mTargetSize);
+            actor.mSizer.OnAnimateHeight(animation, height, true);
           }
           break;
         }
 
         case Dali::Actor::Property::SIZE_DEPTH:
         {
-          if(AdjustValue<float>(actor.mTargetSize.depth, value))
+          float depth;
+          if(value.Get(depth))
           {
-            actor.mAnimatedSize.depth = actor.mTargetSize.depth;
-            actor.mUseAnimatedSize |= AnimatedSizeFlag::DEPTH;
-
-            // Notify deriving classes
-            actor.OnSizeAnimation(animation, actor.mTargetSize);
+            actor.mSizer.OnAnimateDepth(animation, depth, true);
           }
           break;
         }
@@ -1553,31 +1498,31 @@ bool Actor::PropertyHandler::GetCachedPropertyValue(const Internal::Actor& actor
 
     case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
     {
-      value = Scripting::GetLinearEnumerationName<ResizePolicy::Type>(actor.GetResizePolicy(Dimension::WIDTH), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT);
+      value = Scripting::GetLinearEnumerationName<ResizePolicy::Type>(actor.mSizer.GetResizePolicy(Dimension::WIDTH), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT);
       break;
     }
 
     case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
     {
-      value = Scripting::GetLinearEnumerationName<ResizePolicy::Type>(actor.GetResizePolicy(Dimension::HEIGHT), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT);
+      value = Scripting::GetLinearEnumerationName<ResizePolicy::Type>(actor.mSizer.GetResizePolicy(Dimension::HEIGHT), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT);
       break;
     }
 
     case Dali::Actor::Property::SIZE_SCALE_POLICY:
     {
-      value = actor.GetSizeScalePolicy();
+      value = actor.mSizer.GetSizeScalePolicy();
       break;
     }
 
     case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
     {
-      value = (actor.GetResizePolicy(Dimension::WIDTH) == ResizePolicy::DIMENSION_DEPENDENCY) && (actor.GetDimensionDependency(Dimension::WIDTH) == Dimension::HEIGHT);
+      value = (actor.mSizer.GetResizePolicy(Dimension::WIDTH) == ResizePolicy::DIMENSION_DEPENDENCY) && (actor.mSizer.GetDimensionDependency(Dimension::WIDTH) == Dimension::HEIGHT);
       break;
     }
 
     case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
     {
-      value = (actor.GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::DIMENSION_DEPENDENCY) && (actor.GetDimensionDependency(Dimension::HEIGHT) == Dimension::WIDTH);
+      value = (actor.mSizer.GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::DIMENSION_DEPENDENCY) && (actor.mSizer.GetDimensionDependency(Dimension::HEIGHT) == Dimension::WIDTH);
       break;
     }
 
index f8e57d1..cfebf86 100644 (file)
 #include <dali/public-api/math/vector2.h>
 #include <dali/public-api/math/vector3.h>
 
+#include <dali/internal/event/actors/actor-impl.h>
 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
 
-namespace
-{
 #if defined(DEBUG_ENABLED)
 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER");
 #endif
 
-/**
- * @brief Extract a given dimension from a Vector2
- *
- * @param[in] values The values to extract from
- * @param[in] dimension The dimension to extract
- * @return Return the value for the dimension
- */
-constexpr float GetDimensionValue(const Dali::Vector2& values, const Dali::Dimension::Type dimension)
-{
-  switch(dimension)
-  {
-    case Dali::Dimension::WIDTH:
-    {
-      return values.width;
-    }
-    case Dali::Dimension::HEIGHT:
-    {
-      return values.height;
-    }
-    default:
-    {
-      break;
-    }
-  }
-  return 0.0f;
-}
-
-} // unnamed namespace
-
 namespace Dali
 {
 namespace Internal
 {
-Actor::Relayouter::Relayouter()
+ActorSizer::Relayouter::Relayouter()
 : sizeModeFactor(DEFAULT_SIZE_MODE_FACTOR),
   preferredSize(DEFAULT_PREFERRED_SIZE),
   sizeSetPolicy(DEFAULT_SIZE_SCALE_POLICY),
@@ -88,7 +58,7 @@ Actor::Relayouter::Relayouter()
   }
 }
 
-ResizePolicy::Type Actor::Relayouter::GetResizePolicy(Dimension::Type dimension) const
+ResizePolicy::Type ActorSizer::Relayouter::GetResizePolicy(Dimension::Type dimension) const
 {
   // If more than one dimension is requested, just return the first one found
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
@@ -109,55 +79,7 @@ ResizePolicy::Type Actor::Relayouter::GetResizePolicy(Dimension::Type dimension)
   return ResizePolicy::DEFAULT;
 }
 
-void Actor::Relayouter::SetPadding(const Vector2& padding, Dimension::Type dimension)
-{
-  for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
-  {
-    if(dimension & (1 << i))
-    {
-      dimensionPadding[i] = padding;
-    }
-  }
-}
-
-Vector2 Actor::Relayouter::GetPadding(Dimension::Type dimension)
-{
-  // If more than one dimension is requested, just return the first one found
-  for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
-  {
-    if((dimension & (1 << i)))
-    {
-      return dimensionPadding[i];
-    }
-  }
-
-  return DEFAULT_DIMENSION_PADDING;
-}
-
-void Actor::Relayouter::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
-{
-  for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
-  {
-    if(dimension & (1 << i))
-    {
-      dimensionNegotiated[i] = negotiated;
-    }
-  }
-}
-
-bool Actor::Relayouter::IsLayoutNegotiated(Dimension::Type dimension) const
-{
-  for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
-  {
-    if((dimension & (1 << i)) && dimensionNegotiated[i])
-    {
-      return true;
-    }
-  }
-  return false;
-}
-
-Vector2 Actor::Relayouter::ApplySizeSetPolicy(Internal::Actor& actor, const Vector2& size)
+Vector2 ActorSizer::Relayouter::ApplySizeSetPolicy(Internal::Actor& actor, const Vector2& size)
 {
   switch(sizeSetPolicy)
   {
@@ -226,7 +148,7 @@ Vector2 Actor::Relayouter::ApplySizeSetPolicy(Internal::Actor& actor, const Vect
   return size;
 }
 
-void Actor::Relayouter::SetUseAssignedSize(bool use, Dimension::Type dimension)
+void ActorSizer::Relayouter::SetUseAssignedSize(bool use, Dimension::Type dimension)
 {
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
@@ -237,7 +159,7 @@ void Actor::Relayouter::SetUseAssignedSize(bool use, Dimension::Type dimension)
   }
 }
 
-bool Actor::Relayouter::GetUseAssignedSize(Dimension::Type dimension) const
+bool ActorSizer::Relayouter::GetUseAssignedSize(Dimension::Type dimension) const
 {
   // If more than one dimension is requested, just return the first one found
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
@@ -251,7 +173,7 @@ bool Actor::Relayouter::GetUseAssignedSize(Dimension::Type dimension) const
   return false;
 }
 
-void Actor::Relayouter::SetMinimumSize(float size, Dimension::Type dimension)
+void ActorSizer::Relayouter::SetMinimumSize(float size, Dimension::Type dimension)
 {
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
@@ -262,7 +184,7 @@ void Actor::Relayouter::SetMinimumSize(float size, Dimension::Type dimension)
   }
 }
 
-float Actor::Relayouter::GetMinimumSize(Dimension::Type dimension) const
+float ActorSizer::Relayouter::GetMinimumSize(Dimension::Type dimension) const
 {
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
@@ -275,7 +197,7 @@ float Actor::Relayouter::GetMinimumSize(Dimension::Type dimension) const
   return 0.0f; // Default
 }
 
-void Actor::Relayouter::SetMaximumSize(float size, Dimension::Type dimension)
+void ActorSizer::Relayouter::SetMaximumSize(float size, Dimension::Type dimension)
 {
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
@@ -286,7 +208,7 @@ void Actor::Relayouter::SetMaximumSize(float size, Dimension::Type dimension)
   }
 }
 
-float Actor::Relayouter::GetMaximumSize(Dimension::Type dimension) const
+float ActorSizer::Relayouter::GetMaximumSize(Dimension::Type dimension) const
 {
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
@@ -299,7 +221,7 @@ float Actor::Relayouter::GetMaximumSize(Dimension::Type dimension) const
   return FLT_MAX; // Default
 }
 
-void Actor::Relayouter::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension, Vector3& targetSize)
+void ActorSizer::Relayouter::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension, Vector3& targetSize)
 {
   ResizePolicy::Type originalWidthPolicy  = GetResizePolicy(Dimension::WIDTH);
   ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
@@ -365,7 +287,7 @@ void Actor::Relayouter::SetResizePolicy(ResizePolicy::Type policy, Dimension::Ty
   }
 }
 
-bool Actor::Relayouter::GetRelayoutDependentOnParent(Dimension::Type dimension)
+bool ActorSizer::Relayouter::GetRelayoutDependentOnParent(Dimension::Type dimension)
 {
   // Check if actor is dependent on parent
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
@@ -382,7 +304,7 @@ bool Actor::Relayouter::GetRelayoutDependentOnParent(Dimension::Type dimension)
   return false;
 }
 
-bool Actor::Relayouter::GetRelayoutDependentOnChildren(Dimension::Type dimension)
+bool ActorSizer::Relayouter::GetRelayoutDependentOnChildren(Dimension::Type dimension)
 {
   // Check if actor is dependent on children
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
@@ -401,7 +323,7 @@ bool Actor::Relayouter::GetRelayoutDependentOnChildren(Dimension::Type dimension
   return false;
 }
 
-bool Actor::Relayouter::GetRelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependency)
+bool ActorSizer::Relayouter::GetRelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependency)
 {
   // Check each possible dimension and see if it is dependent on the input one
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
@@ -415,7 +337,7 @@ bool Actor::Relayouter::GetRelayoutDependentOnDimension(Dimension::Type dimensio
   return false;
 }
 
-void Actor::Relayouter::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
+void ActorSizer::Relayouter::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
 {
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
@@ -426,7 +348,7 @@ void Actor::Relayouter::SetDimensionDependency(Dimension::Type dimension, Dimens
   }
 }
 
-Dimension::Type Actor::Relayouter::GetDimensionDependency(Dimension::Type dimension) const
+Dimension::Type ActorSizer::Relayouter::GetDimensionDependency(Dimension::Type dimension) const
 {
   // If more than one dimension is requested, just return the first one found
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
@@ -440,7 +362,7 @@ Dimension::Type Actor::Relayouter::GetDimensionDependency(Dimension::Type dimens
   return Dimension::ALL_DIMENSIONS; // Default
 }
 
-void Actor::Relayouter::SetLayoutDirty(bool dirty, Dimension::Type dimension)
+void ActorSizer::Relayouter::SetLayoutDirty(bool dirty, Dimension::Type dimension)
 {
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
@@ -451,7 +373,7 @@ void Actor::Relayouter::SetLayoutDirty(bool dirty, Dimension::Type dimension)
   }
 }
 
-bool Actor::Relayouter::IsLayoutDirty(Dimension::Type dimension) const
+bool ActorSizer::Relayouter::IsLayoutDirty(Dimension::Type dimension) const
 {
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
@@ -464,38 +386,7 @@ bool Actor::Relayouter::IsLayoutDirty(Dimension::Type dimension) const
   return false;
 }
 
-void Actor::Relayouter::SetPreferredSize(Actor& actor, const Vector2& size)
-{
-  // If valid width or height, then set the resize policy to FIXED
-  // A 0 width or height may also be required so if the resize policy has not been changed, i.e. is still set to DEFAULT,
-  // then change to FIXED as well
-
-  if(size.width > 0.0f || GetResizePolicy(Dimension::WIDTH) == ResizePolicy::DEFAULT)
-  {
-    actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::WIDTH);
-  }
-
-  if(size.height > 0.0f || GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::DEFAULT)
-  {
-    actor.SetResizePolicy(ResizePolicy::FIXED, Dimension::HEIGHT);
-  }
-
-  actor.mRelayoutData->preferredSize = size;
-
-  actor.mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
-
-  actor.RelayoutRequest();
-}
-
-float Actor::Relayouter::ClampDimension(const Internal::Actor& actor, float size, Dimension::Type dimension)
-{
-  const float minSize = actor.GetMinimumSize(dimension);
-  const float maxSize = actor.GetMaximumSize(dimension);
-
-  return std::max(minSize, std::min(size, maxSize));
-}
-
-void Actor::Relayouter::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
+void ActorSizer::Relayouter::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
 {
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
@@ -506,7 +397,7 @@ void Actor::Relayouter::SetNegotiatedDimension(float negotiatedDimension, Dimens
   }
 }
 
-float Actor::Relayouter::GetNegotiatedDimension(Dimension::Type dimension)
+float ActorSizer::Relayouter::GetNegotiatedDimension(Dimension::Type dimension)
 {
   // If more than one dimension is requested, just return the first one found
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
@@ -520,286 +411,52 @@ float Actor::Relayouter::GetNegotiatedDimension(Dimension::Type dimension)
   return 0.0f; // Default
 }
 
-float Actor::Relayouter::NegotiateDimensionFromParent(Actor& actor, Dimension::Type dimension)
+void ActorSizer::Relayouter::SetPadding(const Vector2& padding, Dimension::Type dimension)
 {
-  Actor* parent = actor.GetParent();
-  if(parent)
-  {
-    Vector2 padding(actor.GetPadding(dimension));
-    Vector2 parentPadding(parent->GetPadding(dimension));
-
-    // Need to use actor API here to allow deriving actors to layout their children
-    return parent->CalculateChildSize(Dali::Actor(&actor), dimension) - parentPadding.x - parentPadding.y - padding.x - padding.y;
-  }
-
-  return 0.0f;
-}
-
-float Actor::Relayouter::NegotiateDimensionFromChildren(Actor& actor, Dimension::Type dimension)
-{
-  float maxDimensionPoint = 0.0f;
-
-  for(uint32_t i = 0, count = actor.GetChildCount(); i < count; ++i)
-  {
-    ActorPtr child = actor.GetChildAt(i);
-
-    if(!child->RelayoutDependentOnParent(dimension))
-    {
-      // Calculate the min and max points that the children range across
-      float childPosition = GetDimensionValue(child->GetTargetPosition(), dimension);
-      float dimensionSize = child->GetRelayoutSize(dimension);
-      maxDimensionPoint   = std::max(maxDimensionPoint, childPosition + dimensionSize);
-    }
-  }
-
-  return maxDimensionPoint;
-}
-
-void Actor::Relayouter::NegotiateDimension(Actor& actor, Dimension::Type dimension, const Vector2& allocatedSize, Actor::ActorDimensionStack& recursionStack)
-{
-  // Check if it needs to be negotiated
-  if(actor.IsLayoutDirty(dimension) && !actor.IsLayoutNegotiated(dimension))
+  for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
-    // Check that we havn't gotten into an infinite loop
-    Actor::ActorDimensionPair searchActor    = Actor::ActorDimensionPair(&actor, dimension);
-    bool                      recursionFound = false;
-    for(auto& element : recursionStack)
-    {
-      if(element == searchActor)
-      {
-        recursionFound = true;
-        break;
-      }
-    }
-
-    if(!recursionFound)
-    {
-      // Record the path that we have taken
-      recursionStack.push_back(Actor::ActorDimensionPair(&actor, dimension));
-
-      // Dimension dependency check
-      for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
-      {
-        Dimension::Type dimensionToCheck = static_cast<Dimension::Type>(1 << i);
-
-        if(actor.RelayoutDependentOnDimension(dimension, dimensionToCheck))
-        {
-          NegotiateDimension(actor, dimensionToCheck, allocatedSize, recursionStack);
-        }
-      }
-
-      // Parent dependency check
-      Actor* parent = actor.GetParent();
-      if(parent && actor.RelayoutDependentOnParent(dimension))
-      {
-        NegotiateDimension(*parent, dimension, allocatedSize, recursionStack);
-      }
-
-      // Children dependency check
-      if(actor.RelayoutDependentOnChildren(dimension))
-      {
-        for(uint32_t i = 0, count = actor.GetChildCount(); i < count; ++i)
-        {
-          ActorPtr child = actor.GetChildAt(i);
-
-          // Only relayout child first if it is not dependent on this actor
-          if(!child->RelayoutDependentOnParent(dimension))
-          {
-            NegotiateDimension(*child, dimension, allocatedSize, recursionStack);
-          }
-        }
-      }
-
-      // For deriving classes
-      actor.OnCalculateRelayoutSize(dimension);
-
-      // All dependencies checked, calculate the size and set negotiated flag
-      const float newSize = ClampDimension(actor, actor.CalculateSize(dimension, allocatedSize), dimension);
-
-      actor.SetNegotiatedDimension(newSize, dimension);
-      actor.SetLayoutNegotiated(true, dimension);
-
-      // For deriving classes
-      actor.OnLayoutNegotiated(newSize, dimension);
-
-      // This actor has been successfully processed, pop it off the recursion stack
-      recursionStack.pop_back();
-    }
-    else
+    if(dimension & (1 << i))
     {
-      // TODO: Break infinite loop
-      actor.SetLayoutNegotiated(true, dimension);
+      dimensionPadding[i] = padding;
     }
   }
 }
 
-void Actor::Relayouter::NegotiateDimensions(Actor& actor, const Vector2& allocatedSize)
+Vector2 ActorSizer::Relayouter::GetPadding(Dimension::Type dimension)
 {
-  // Negotiate all dimensions that require it
-  ActorDimensionStack recursionStack;
-
+  // If more than one dimension is requested, just return the first one found
   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
-    const Dimension::Type dimension = static_cast<Dimension::Type>(1 << i);
-
-    // Negotiate
-    NegotiateDimension(actor, dimension, allocatedSize, recursionStack);
-  }
-}
-
-void Actor::Relayouter::NegotiateSize(Actor& actor, const Vector2& allocatedSize, RelayoutContainer& container)
-{
-  // Force a size negotiation for actors that has assigned size during relayout
-  // This is required as otherwise the flags that force a relayout will not
-  // necessarilly be set. This will occur if the actor has already been laid out.
-  // The dirty flags are then cleared. Then if the actor is added back into the
-  // relayout container afterwards, the dirty flags would still be clear...
-  // causing a relayout to be skipped. Here we force any actors added to the
-  // container to be relayed out.
-  DALI_LOG_TIMER_START(NegSizeTimer1);
-
-  if(actor.GetUseAssignedSize(Dimension::WIDTH))
-  {
-    actor.SetLayoutNegotiated(false, Dimension::WIDTH);
-  }
-  if(actor.GetUseAssignedSize(Dimension::HEIGHT))
-  {
-    actor.SetLayoutNegotiated(false, Dimension::HEIGHT);
-  }
-
-  // Do the negotiation
-  NegotiateDimensions(actor, allocatedSize);
-
-  // Set the actor size
-  actor.SetNegotiatedSize(container);
-
-  // Negotiate down to children
-  for(uint32_t i = 0, count = actor.GetChildCount(); i < count; ++i)
-  {
-    ActorPtr child = actor.GetChildAt(i);
-
-    // Forces children that have already been laid out to be relayed out
-    // if they have assigned size during relayout.
-    if(child->GetUseAssignedSize(Dimension::WIDTH))
-    {
-      child->SetLayoutNegotiated(false, Dimension::WIDTH);
-      child->SetLayoutDirty(true, Dimension::WIDTH);
-    }
-
-    if(child->GetUseAssignedSize(Dimension::HEIGHT))
-    {
-      child->SetLayoutNegotiated(false, Dimension::HEIGHT);
-      child->SetLayoutDirty(true, Dimension::HEIGHT);
-    }
-
-    // Only relayout if required
-    if(child->RelayoutRequired())
+    if((dimension & (1 << i)))
     {
-      container.Add(Dali::Actor(child.Get()), actor.mTargetSize.GetVectorXY());
+      return dimensionPadding[i];
     }
   }
-  DALI_LOG_TIMER_END(NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
-}
 
-/**
- * @brief Extract a given dimension from a Vector3
- *
- * @param[in] values The values to extract from
- * @param[in] dimension The dimension to extract
- * @return Return the value for the dimension
- */
-float Actor::Relayouter::GetDimensionValue(const Vector3& values, const Dimension::Type dimension)
-{
-  return ::GetDimensionValue(values.GetVectorXY(), dimension);
+  return DEFAULT_DIMENSION_PADDING;
 }
 
-float Actor::Relayouter::CalculateSize(Actor& actor, Dimension::Type dimension, const Vector2& maximumSize)
+void ActorSizer::Relayouter::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
 {
-  switch(actor.GetResizePolicy(dimension))
+  for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
-    case ResizePolicy::USE_NATURAL_SIZE:
-    {
-      return actor.GetNaturalSize(dimension);
-    }
-
-    case ResizePolicy::FIXED:
-    {
-      return ::GetDimensionValue(actor.GetPreferredSize(), dimension);
-    }
-
-    case ResizePolicy::USE_ASSIGNED_SIZE:
-    {
-      return ::GetDimensionValue(maximumSize, dimension);
-    }
-
-    case ResizePolicy::FILL_TO_PARENT:
-    case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
-    case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
-    {
-      return NegotiateDimensionFromParent(actor, dimension);
-    }
-
-    case ResizePolicy::FIT_TO_CHILDREN:
-    {
-      return NegotiateDimensionFromChildren(actor, dimension);
-    }
-
-    case ResizePolicy::DIMENSION_DEPENDENCY:
-    {
-      const Dimension::Type dimensionDependency = actor.GetDimensionDependency(dimension);
-
-      // Custom rules
-      if(dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT)
-      {
-        return actor.GetWidthForHeight(actor.GetNegotiatedDimension(Dimension::HEIGHT));
-      }
-
-      if(dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH)
-      {
-        return actor.GetHeightForWidth(actor.GetNegotiatedDimension(Dimension::WIDTH));
-      }
-
-      break;
-    }
-
-    default:
+    if(dimension & (1 << i))
     {
-      break;
+      dimensionNegotiated[i] = negotiated;
     }
   }
-
-  return 0.0f; // Default
 }
 
-float Actor::Relayouter::CalculateChildSize(Actor& actor, const Actor& child, Dimension::Type dimension)
+bool ActorSizer::Relayouter::IsLayoutNegotiated(Dimension::Type dimension) const
 {
-  // Fill to parent, taking size mode factor into account
-  switch(child.GetResizePolicy(dimension))
+  for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
   {
-    case ResizePolicy::FILL_TO_PARENT:
-    {
-      return actor.GetLatestSize(dimension);
-    }
-
-    case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
-    {
-      Property::Value value               = child.GetProperty(Dali::Actor::Property::SIZE_MODE_FACTOR);
-      Vector3         childSizeModeFactor = value.Get<Vector3>();
-      return actor.GetLatestSize(dimension) * GetDimensionValue(childSizeModeFactor, dimension);
-    }
-
-    case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
-    {
-      Property::Value value               = child.GetProperty(Dali::Actor::Property::SIZE_MODE_FACTOR);
-      Vector3         childSizeModeFactor = value.Get<Vector3>();
-      return actor.GetLatestSize(dimension) + GetDimensionValue(childSizeModeFactor, dimension);
-    }
-
-    default:
+    if((dimension & (1 << i)) && dimensionNegotiated[i])
     {
-      return actor.GetLatestSize(dimension);
+      return true;
     }
   }
+  return false;
 }
 
 } // namespace Internal
index 40c4911..f1ade33 100644 (file)
@@ -20,6 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali/internal/event/actors/actor-impl.h>
+
 #include <dali/public-api/math/vector2.h>
 #include <dali/public-api/math/vector3.h>
 
@@ -30,7 +31,7 @@ namespace Internal
 /**
  * Struct to do some actor specific relayouting and store related variables
  */
-struct Actor::Relayouter
+struct ActorSizer::Relayouter
 {
   // Defaults
   static constexpr Vector3               DEFAULT_SIZE_MODE_FACTOR{1.0f, 1.0f, 1.0f};
@@ -47,18 +48,6 @@ struct Actor::Relayouter
   /// @copydoc Actor::GetResizePolicy
   ResizePolicy::Type GetResizePolicy(Dimension::Type dimension) const;
 
-  /// @copydoc Actor::SetPadding
-  void SetPadding(const Vector2& padding, Dimension::Type dimension);
-
-  /// @copydoc Actor::GetPadding
-  Vector2 GetPadding(Dimension::Type dimension);
-
-  /// @copydoc Actor::SetLayoutNegotiated
-  void SetLayoutNegotiated(bool negotiated, Dimension::Type dimension);
-
-  /// @copydoc Actor::IsLayoutNegotiated
-  bool IsLayoutNegotiated(Dimension::Type dimension) const;
-
   /// @copydoc Actor::ApplySizeSetPolicy
   Vector2 ApplySizeSetPolicy(Internal::Actor& actor, const Vector2& size);
 
@@ -104,95 +93,23 @@ struct Actor::Relayouter
   /// @copydoc Actor::IsLayoutDirty
   bool IsLayoutDirty(Dimension::Type dimension) const;
 
-  /// @copydoc Actor::SetPreferredSize
-  /// @actor[in] actor The Actor whose preferred size we wish to set
-  void SetPreferredSize(Actor& actor, const Vector2& size);
-
-  /**
-   * @brief Clamp a dimension given the relayout constraints on given actor
-   *
-   * @param[in] actor The actor to clamp
-   * @param[in] size The size to constrain
-   * @param[in] dimension The dimension the size exists in
-   * @return Return the clamped size
-   */
-  static float ClampDimension(const Internal::Actor& actor, float size, Dimension::Type dimension);
-
   /// @copydoc Actor::SetNegotiatedDimension
   void SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension);
 
   /// @copydoc Actor::GetNegotiatedDimension
   float GetNegotiatedDimension(Dimension::Type dimension);
 
-  /**
-   * Negotiate a dimension based on the size of the parent
-   *
-   * @param[in] dimension The dimension to negotiate on
-   * @return Return the negotiated size
-   */
-  static float NegotiateDimensionFromParent(Actor& actor, Dimension::Type dimension);
-
-  /**
-   * @brief Negotiate a dimension based on the size of the children
-   *
-   * @param[in] dimension The dimension to negotiate on
-   * @return Return the negotiated size
-   */
-  static float NegotiateDimensionFromChildren(Actor& actor, Dimension::Type dimension);
-
-  /**
-   * Negotiate size for a specific dimension
-   *
-   * The algorithm adopts a recursive dependency checking approach. Meaning, that wherever dependencies
-   * are found, e.g. an actor dependent on its parent, the dependency will be calculated first with NegotiatedDimension and
-   * LayoutDimensionNegotiated flags being filled in on the actor.
-   *
-   * @post All actors that exist in the dependency chain connected to the given actor will have had their NegotiatedDimensions
-   * calculated and set as well as the LayoutDimensionNegotiated flags.
-   *
-   * @param[in] actor The actor whose dimension we are negotiating
-   * @param[in] dimension The dimension to negotiate on
-   * @param[in] allocatedSize The size constraint that the actor must respect
-   */
-  static void NegotiateDimension(Actor& actor, Dimension::Type dimension, const Vector2& allocatedSize, Actor::ActorDimensionStack& recursionStack);
-
-  /**
-   * Negotiate sizes for a control in all dimensions
-   *
-   * @param[in] actor The actor whose dimensions we are negotiating
-   * @param[in] allocatedSize The size constraint that the control must respect
-   */
-  static void NegotiateDimensions(Actor& actor, const Vector2& allocatedSize);
-
-  /**
-   * @brief Called by the RelayoutController to negotiate the size of an actor.
-   *
-   * The size allocated by the the algorithm is passed in which the
-   * actor must adhere to.  A container is passed in as well which
-   * the actor should populate with actors it has not / or does not
-   * need to handle in its size negotiation.
-   *
-   * @param[in] actor The actor whose size we are negotiating
-   * @param[in]      size       The allocated size.
-   * @param[in,out]  container  The container that holds actors that are fed back into the
-   *                            RelayoutController algorithm.
-   */
-  static void NegotiateSize(Actor& actor, const Vector2& allocatedSize, RelayoutContainer& container);
-
-  /**
-   * Get the value for the given dimension
-   *
-   * @param[in] values The vector to get values from
-   * @param[in] dimension The dimension to fetch
-   * @return the value of the given dimension
-   */
-  static float GetDimensionValue(const Vector3& values, const Dimension::Type dimension);
-
-  /// @copydoc Actor::CalculateSize
-  static float CalculateSize(Actor& actor, Dimension::Type dimension, const Vector2& maximumSize);
-
-  /// @copydoc Actor::CalculateChildSizeBase
-  static float CalculateChildSize(Actor& actor, const Actor& child, Dimension::Type dimension);
+  /// @copydoc Actor::SetPadding
+  void SetPadding(const Vector2& padding, Dimension::Type dimension);
+
+  /// @copydoc Actor::GetPadding
+  Vector2 GetPadding(Dimension::Type dimension);
+
+  /// @copydoc Actor::SetLayoutNegotiated
+  void SetLayoutNegotiated(bool negotiated, Dimension::Type dimension);
+
+  /// @copydoc Actor::IsLayoutNegotiated
+  bool IsLayoutNegotiated(Dimension::Type dimension) const;
 
 public:
   ResizePolicy::Type resizePolicies[Dimension::DIMENSION_COUNT];  ///< Resize policies
diff --git a/dali/internal/event/actors/actor-sizer.cpp b/dali/internal/event/actors/actor-sizer.cpp
new file mode 100644 (file)
index 0000000..d5c00ea
--- /dev/null
@@ -0,0 +1,868 @@
+/*
+ * Copyright (c) 2021 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/internal/event/actors/actor-sizer.h>
+
+// EXTERNAL INCLUDES
+#include <cfloat>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/actor-relayouter.h>
+#include <dali/internal/event/animation/animation-impl.h>
+#include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/update/nodes/node-declarations.h>
+#include <dali/internal/update/nodes/node-messages.h>
+#include <dali/internal/update/nodes/node.h>
+
+#if defined(DEBUG_ENABLED)
+extern Debug::Filter* gLogRelayoutFilter;
+#endif
+
+namespace
+{
+/**
+ * @brief Extract a given dimension from a Vector2
+ *
+ * @param[in] values The values to extract from
+ * @param[in] dimension The dimension to extract
+ * @return Return the value for the dimension
+ */
+constexpr float GetDimensionValue(const Dali::Vector2& values, const Dali::Dimension::Type dimension)
+{
+  switch(dimension)
+  {
+    case Dali::Dimension::WIDTH:
+    {
+      return values.width;
+    }
+    case Dali::Dimension::HEIGHT:
+    {
+      return values.height;
+    }
+    default:
+    {
+      break;
+    }
+  }
+  return 0.0f;
+}
+} // namespace
+
+namespace Dali::Internal
+{
+ActorSizer::ActorSizer(Internal::Actor& owner)
+: mOwner(owner),
+  mRelayoutData(nullptr),
+  mTargetSize(Vector3::ZERO),
+  mAnimatedSize(Vector3::ZERO),
+  mUseAnimatedSize(AnimatedSizeFlag::CLEAR),
+  mInsideOnSizeSet(false)
+{
+}
+
+ActorSizer::~ActorSizer()
+{
+  // Delete optional relayout data
+  delete mRelayoutData;
+}
+
+void ActorSizer::SetSizeModeFactor(const Vector3& factor)
+{
+  EnsureRelayouter();
+
+  mRelayoutData->sizeModeFactor = factor;
+}
+const Vector3& ActorSizer::GetSizeModeFactor() const
+{
+  return mRelayoutData ? mRelayoutData->sizeModeFactor : Relayouter::DEFAULT_SIZE_MODE_FACTOR;
+}
+
+void ActorSizer::SetSize(const Vector3& size)
+{
+  if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
+  {
+    // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
+    SetPreferredSize(size.GetVectorXY());
+  }
+  else
+  {
+    SetSizeInternal(size);
+  }
+}
+
+void ActorSizer::SetSizeInternal(const Vector3& size)
+{
+  // dont allow recursive loop
+  DALI_ASSERT_ALWAYS(!mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet");
+  // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
+  Vector3 currentSize = mOwner.GetCurrentSize();
+
+  if((fabsf(mTargetSize.width - size.width) > Math::MACHINE_EPSILON_1) ||
+     (fabsf(mTargetSize.height - size.height) > Math::MACHINE_EPSILON_1) ||
+     (fabsf(mTargetSize.depth - size.depth) > Math::MACHINE_EPSILON_1) ||
+     (fabsf(mTargetSize.width - currentSize.width) > Math::MACHINE_EPSILON_1) ||
+     (fabsf(mTargetSize.height - currentSize.height) > Math::MACHINE_EPSILON_1) ||
+     (fabsf(mTargetSize.depth - currentSize.depth) > Math::MACHINE_EPSILON_1))
+  {
+    mTargetSize = size;
+
+    // Update the preferred size after relayoutting
+    // It should be used in the next relayoutting
+    if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH && mRelayoutData)
+    {
+      mRelayoutData->preferredSize.width = mAnimatedSize.width;
+    }
+
+    if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT && mRelayoutData)
+    {
+      mRelayoutData->preferredSize.height = mAnimatedSize.height;
+    }
+
+    // node is being used in a separate thread; queue a message to set the value & base value
+    auto& node = mOwner.GetNode();
+    SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(mOwner.GetEventThreadServices(), &node, &node.mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize);
+
+    // Notification for derived classes
+    mInsideOnSizeSet = true;
+    mOwner.OnSizeSet(mTargetSize);
+    mInsideOnSizeSet = false;
+
+    // Raise a relayout request if the flag is not locked
+    if(mRelayoutData && !mRelayoutData->insideRelayout)
+    {
+      RelayoutRequest();
+    }
+  }
+}
+
+void ActorSizer::SetWidth(float width)
+{
+  if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
+  {
+    SetResizePolicy(ResizePolicy::FIXED, Dimension::WIDTH);
+    mRelayoutData->preferredSize.width = width;
+  }
+  else
+  {
+    mTargetSize.width = width;
+
+    // node is being used in a separate thread; queue a message to set the value & base value
+    auto& node = mOwner.GetNode();
+    SceneGraph::NodeTransformComponentMessage<Vector3>::Send(mOwner.GetEventThreadServices(), &node, &node.mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width);
+  }
+
+  mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
+  RelayoutRequest();
+}
+
+void ActorSizer::SetHeight(float height)
+{
+  if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
+  {
+    SetResizePolicy(ResizePolicy::FIXED, Dimension::HEIGHT);
+    mRelayoutData->preferredSize.height = height;
+  }
+  else
+  {
+    mTargetSize.height = height;
+
+    // node is being used in a separate thread; queue a message to set the value & base value
+    auto& node = mOwner.GetNode();
+    SceneGraph::NodeTransformComponentMessage<Vector3>::Send(mOwner.GetEventThreadServices(), &node, &node.mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height);
+  }
+
+  mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
+  RelayoutRequest();
+}
+
+void ActorSizer::SetDepth(float depth)
+{
+  mTargetSize.depth = depth;
+
+  mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
+
+  // node is being used in a separate thread; queue a message to set the value & base value
+  auto& node = mOwner.GetNode();
+  SceneGraph::NodeTransformComponentMessage<Vector3>::Send(mOwner.GetEventThreadServices(), &node, &node.mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth);
+}
+
+Vector3 ActorSizer::GetTargetSize() const
+{
+  Vector3 size = mTargetSize;
+
+  if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH)
+  {
+    // Should return animated size if size is animated
+    size.width = mAnimatedSize.width;
+  }
+  else
+  {
+    // Should return preferred size if size is fixed as set by SetSize
+    if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::FIXED)
+    {
+      size.width = GetPreferredSize().width;
+    }
+  }
+
+  if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT)
+  {
+    size.height = mAnimatedSize.height;
+  }
+  else
+  {
+    if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::FIXED)
+    {
+      size.height = GetPreferredSize().height;
+    }
+  }
+
+  if(mUseAnimatedSize & AnimatedSizeFlag::DEPTH)
+  {
+    size.depth = mAnimatedSize.depth;
+  }
+
+  return size;
+}
+
+void ActorSizer::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension)
+{
+  EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
+  mOwner.OnSetResizePolicy(policy, dimension);
+  RelayoutRequest();
+}
+
+ResizePolicy::Type ActorSizer::GetResizePolicy(Dimension::Type dimension) const
+{
+  return mRelayoutData ? mRelayoutData->GetResizePolicy(dimension) : ResizePolicy::DEFAULT;
+}
+
+void ActorSizer::SetSizeScalePolicy(SizeScalePolicy::Type policy)
+{
+  EnsureRelayouter();
+  mRelayoutData->sizeSetPolicy = policy;
+  RelayoutRequest();
+}
+
+SizeScalePolicy::Type ActorSizer::GetSizeScalePolicy() const
+{
+  return mRelayoutData ? mRelayoutData->sizeSetPolicy : Relayouter::DEFAULT_SIZE_SCALE_POLICY;
+}
+
+Dimension::Type ActorSizer::GetDimensionDependency(Dimension::Type dimension) const
+{
+  return mRelayoutData ? mRelayoutData->GetDimensionDependency(dimension) : Dimension::ALL_DIMENSIONS;
+}
+
+void ActorSizer::SetRelayoutEnabled(bool relayoutEnabled)
+{
+  // If relayout data has not been allocated yet and the client is requesting
+  // to disable it, do nothing
+  if(mRelayoutData || relayoutEnabled)
+  {
+    EnsureRelayouter();
+
+    DALI_ASSERT_DEBUG(mRelayoutData && "mRelayoutData not created");
+
+    mRelayoutData->relayoutEnabled = relayoutEnabled;
+  }
+}
+
+bool ActorSizer::IsRelayoutEnabled() const
+{
+  // Assume that if relayout data has not been allocated yet then relayout is disabled
+  return mRelayoutData && mRelayoutData->relayoutEnabled;
+}
+
+void ActorSizer::SetLayoutDirty(bool dirty, Dimension::Type dimension)
+{
+  EnsureRelayouter().SetLayoutDirty(dirty, dimension);
+}
+
+bool ActorSizer::IsLayoutDirty(Dimension::Type dimension) const
+{
+  return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
+}
+
+bool ActorSizer::RelayoutPossible(Dimension::Type dimension) const
+{
+  return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty(dimension);
+}
+
+bool ActorSizer::RelayoutRequired(Dimension::Type dimension) const
+{
+  return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty(dimension);
+}
+
+ActorSizer::Relayouter& ActorSizer::EnsureRelayouter()
+{
+  // Assign relayouter
+  if(!mRelayoutData)
+  {
+    mRelayoutData = new Relayouter();
+  }
+
+  return *mRelayoutData;
+}
+
+bool ActorSizer::RelayoutDependentOnParent(Dimension::Type dimension)
+{
+  return mRelayoutData && mRelayoutData->GetRelayoutDependentOnParent(dimension);
+}
+
+bool ActorSizer::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
+{
+  return mRelayoutData && mRelayoutData->GetRelayoutDependentOnChildren(dimension);
+}
+
+bool ActorSizer::RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension)
+{
+  return mRelayoutData && mRelayoutData->GetRelayoutDependentOnDimension(dimension, dependentDimension);
+}
+
+void ActorSizer::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
+{
+  if(mRelayoutData)
+  {
+    mRelayoutData->SetNegotiatedDimension(negotiatedDimension, dimension);
+  }
+}
+
+float ActorSizer::GetNegotiatedDimension(Dimension::Type dimension) const
+{
+  return mRelayoutData ? mRelayoutData->GetNegotiatedDimension(dimension) : 0.0f;
+}
+
+void ActorSizer::SetPadding(const Vector2& padding, Dimension::Type dimension)
+{
+  EnsureRelayouter().SetPadding(padding, dimension);
+}
+
+Vector2 ActorSizer::GetPadding(Dimension::Type dimension) const
+{
+  return mRelayoutData ? mRelayoutData->GetPadding(dimension) : Relayouter::DEFAULT_DIMENSION_PADDING;
+}
+
+void ActorSizer::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
+{
+  EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
+}
+
+bool ActorSizer::IsLayoutNegotiated(Dimension::Type dimension) const
+{
+  return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
+}
+
+float ActorSizer::GetHeightForWidthBase(float width)
+{
+  const Vector3 naturalSize = mOwner.GetNaturalSize();
+  return naturalSize.width > 0.0f ? naturalSize.height * width / naturalSize.width : width;
+}
+
+float ActorSizer::GetWidthForHeightBase(float height)
+{
+  const Vector3 naturalSize = mOwner.GetNaturalSize();
+  return naturalSize.height > 0.0f ? naturalSize.width * height / naturalSize.height : height;
+}
+
+float ActorSizer::CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension)
+{
+  // Fill to parent, taking size mode factor into account
+  switch(child.GetResizePolicy(dimension))
+  {
+    case ResizePolicy::FILL_TO_PARENT:
+    {
+      return GetLatestSize(dimension);
+    }
+
+    case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
+    {
+      Property::Value value               = child.GetProperty(Dali::Actor::Property::SIZE_MODE_FACTOR);
+      Vector3         childSizeModeFactor = value.Get<Vector3>();
+      return GetLatestSize(dimension) * GetDimensionValue(childSizeModeFactor, dimension);
+    }
+
+    case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
+    {
+      Property::Value value               = child.GetProperty(Dali::Actor::Property::SIZE_MODE_FACTOR);
+      Vector3         childSizeModeFactor = value.Get<Vector3>();
+      return GetLatestSize(dimension) + GetDimensionValue(childSizeModeFactor, dimension);
+    }
+
+    default:
+    {
+      return GetLatestSize(dimension);
+    }
+  }
+}
+
+float ActorSizer::GetLatestSize(Dimension::Type dimension) const
+{
+  return IsLayoutNegotiated(dimension) ? GetNegotiatedDimension(dimension) : GetSize(dimension);
+}
+
+float ActorSizer::GetRelayoutSize(Dimension::Type dimension) const
+{
+  Vector2 padding = GetPadding(dimension);
+
+  return GetLatestSize(dimension) + padding.x + padding.y;
+}
+
+float ActorSizer::NegotiateFromParent(Dimension::Type dimension)
+{
+  Actor* parent = mOwner.GetParent();
+  if(parent)
+  {
+    Vector2 padding(GetPadding(dimension));
+    Vector2 parentPadding(parent->mSizer.GetPadding(dimension));
+
+    // Need to use actor API here to allow deriving actors to layout their children
+    return parent->CalculateChildSize(Dali::Actor(&mOwner), dimension) - parentPadding.x - parentPadding.y - padding.x - padding.y;
+  }
+
+  return 0.0f;
+}
+
+float ActorSizer::NegotiateFromChildren(Dimension::Type dimension)
+{
+  float maxDimensionPoint = 0.0f;
+
+  for(uint32_t i = 0, count = mOwner.GetChildCount(); i < count; ++i)
+  {
+    ActorPtr child = mOwner.GetChildAt(i);
+
+    if(!child->RelayoutDependentOnParent(dimension))
+    {
+      // Calculate the min and max points that the children range across
+      float childPosition = GetDimensionValue(child->GetTargetPosition(), dimension);
+      float dimensionSize = child->mSizer.GetRelayoutSize(dimension);
+      maxDimensionPoint   = std::max(maxDimensionPoint, childPosition + dimensionSize);
+    }
+  }
+
+  return maxDimensionPoint;
+}
+
+float ActorSizer::GetSize(Dimension::Type dimension) const
+{
+  return GetDimensionValue(mTargetSize, dimension);
+}
+
+float ActorSizer::GetNaturalSize(Dimension::Type dimension) const
+{
+  return GetDimensionValue(mOwner.GetNaturalSize(), dimension);
+}
+
+Vector2 ActorSizer::ApplySizeSetPolicy(const Vector2& size)
+{
+  return mRelayoutData->ApplySizeSetPolicy(mOwner, size);
+}
+
+void ActorSizer::SetNegotiatedSize(RelayoutContainer& container)
+{
+  // Do the set actor size
+  Vector2 negotiatedSize(GetLatestSize(Dimension::WIDTH), GetLatestSize(Dimension::HEIGHT));
+
+  // Adjust for size set policy
+  negotiatedSize = ApplySizeSetPolicy(negotiatedSize);
+
+  // Lock the flag to stop recursive relayouts on set size
+  mRelayoutData->insideRelayout = true;
+  SetSize(Vector3(negotiatedSize.width, negotiatedSize.height, 0.0f));
+  mRelayoutData->insideRelayout = false;
+
+  // Clear flags for all dimensions
+  SetLayoutDirty(false);
+
+  // Give deriving classes a chance to respond
+  mOwner.OnRelayout(negotiatedSize, container);
+
+  if(!mOwner.mOnRelayoutSignal.Empty())
+  {
+    Dali::Actor handle(&mOwner);
+    mOwner.mOnRelayoutSignal.Emit(handle);
+  }
+
+  mRelayoutData->relayoutRequested = false;
+}
+
+void ActorSizer::NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container)
+{
+  // Force a size negotiation for actors that has assigned size during relayout
+  // This is required as otherwise the flags that force a relayout will not
+  // necessarilly be set. This will occur if the actor has already been laid out.
+  // The dirty flags are then cleared. Then if the actor is added back into the
+  // relayout container afterwards, the dirty flags would still be clear...
+  // causing a relayout to be skipped. Here we force any actors added to the
+  // container to be relayed out.
+  DALI_LOG_TIMER_START(NegSizeTimer1);
+
+  if(GetUseAssignedSize(Dimension::WIDTH))
+  {
+    SetLayoutNegotiated(false, Dimension::WIDTH);
+  }
+  if(GetUseAssignedSize(Dimension::HEIGHT))
+  {
+    SetLayoutNegotiated(false, Dimension::HEIGHT);
+  }
+
+  // Do the negotiation
+  NegotiateDimensions(allocatedSize);
+
+  // Set the actor size
+  SetNegotiatedSize(container);
+
+  // Negotiate down to children
+  for(uint32_t i = 0, count = mOwner.GetChildCount(); i < count; ++i)
+  {
+    ActorPtr    child      = mOwner.GetChildAt(i);
+    ActorSizer& childSizer = child->mSizer;
+
+    // Forces children that have already been laid out to be relayed out
+    // if they have assigned size during relayout.
+    if(childSizer.GetUseAssignedSize(Dimension::WIDTH))
+    {
+      childSizer.SetLayoutNegotiated(false, Dimension::WIDTH);
+      childSizer.SetLayoutDirty(true, Dimension::WIDTH);
+    }
+
+    if(childSizer.GetUseAssignedSize(Dimension::HEIGHT))
+    {
+      childSizer.SetLayoutNegotiated(false, Dimension::HEIGHT);
+      childSizer.SetLayoutDirty(true, Dimension::HEIGHT);
+    }
+
+    // Only relayout if required
+    if(childSizer.RelayoutRequired())
+    {
+      container.Add(Dali::Actor(child.Get()), mTargetSize.GetVectorXY());
+    }
+  }
+
+  // Reset the flag so that size negotiation will respect the actor's original resize policy
+  SetUseAssignedSize(false);
+  DALI_LOG_TIMER_END(NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
+}
+
+void ActorSizer::SetUseAssignedSize(bool use, Dimension::Type dimension)
+{
+  if(mRelayoutData)
+  {
+    mRelayoutData->SetUseAssignedSize(use, dimension);
+  }
+}
+
+bool ActorSizer::GetUseAssignedSize(Dimension::Type dimension) const
+{
+  return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
+}
+
+void ActorSizer::RelayoutRequest(Dimension::Type dimension)
+{
+  Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
+  if(relayoutController)
+  {
+    Dali::Actor owner(&mOwner);
+    relayoutController->RequestRelayout(owner, dimension);
+
+    if(mRelayoutData)
+    {
+      mRelayoutData->relayoutRequested = true;
+    }
+  }
+}
+
+void ActorSizer::SetPreferredSize(const Vector2& size)
+{
+  EnsureRelayouter();
+
+  // If valid width or height, then set the resize policy to FIXED
+  // A 0 width or height may also be required so if the resize policy has not been changed, i.e. is still set to DEFAULT,
+  // then change to FIXED as well
+
+  if(size.width > 0.0f || GetResizePolicy(Dimension::WIDTH) == ResizePolicy::DEFAULT)
+  {
+    SetResizePolicy(ResizePolicy::FIXED, Dimension::WIDTH);
+  }
+
+  if(size.height > 0.0f || GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::DEFAULT)
+  {
+    SetResizePolicy(ResizePolicy::FIXED, Dimension::HEIGHT);
+  }
+
+  mRelayoutData->preferredSize = size;
+  mUseAnimatedSize             = AnimatedSizeFlag::CLEAR;
+  RelayoutRequest();
+}
+
+Vector2 ActorSizer::GetPreferredSize() const
+{
+  return mRelayoutData ? Vector2(mRelayoutData->preferredSize) : Relayouter::DEFAULT_PREFERRED_SIZE;
+}
+
+void ActorSizer::SetMinimumSize(float size, Dimension::Type dimension)
+{
+  EnsureRelayouter().SetMinimumSize(size, dimension);
+  RelayoutRequest();
+}
+
+float ActorSizer::GetMinimumSize(Dimension::Type dimension) const
+{
+  return mRelayoutData ? mRelayoutData->GetMinimumSize(dimension) : 0.0f;
+}
+
+void ActorSizer::SetMaximumSize(float size, Dimension::Type dimension)
+{
+  EnsureRelayouter().SetMaximumSize(size, dimension);
+  RelayoutRequest();
+}
+
+float ActorSizer::GetMaximumSize(Dimension::Type dimension) const
+{
+  return mRelayoutData ? mRelayoutData->GetMaximumSize(dimension) : FLT_MAX;
+}
+
+void ActorSizer::OnAnimateSize(Animation& animation, Vector3 targetSize, bool relative)
+{
+  mTargetSize      = targetSize + mTargetSize * float(relative);
+  mAnimatedSize    = mTargetSize;
+  mUseAnimatedSize = AnimatedSizeFlag::WIDTH | AnimatedSizeFlag::HEIGHT | AnimatedSizeFlag::DEPTH;
+
+  if(mRelayoutData && !mRelayoutData->relayoutRequested)
+  {
+    mRelayoutData->preferredSize.width  = mAnimatedSize.width;
+    mRelayoutData->preferredSize.height = mAnimatedSize.height;
+  }
+
+  // Notify deriving classes
+  mOwner.OnSizeAnimation(animation, mTargetSize);
+}
+
+void ActorSizer::OnAnimateWidth(Animation& animation, float width, bool relative)
+{
+  mTargetSize.width   = width + float(relative) * mTargetSize.width;
+  mAnimatedSize.width = mTargetSize.width;
+  mUseAnimatedSize |= AnimatedSizeFlag::WIDTH;
+
+  if(mRelayoutData && !mRelayoutData->relayoutRequested)
+  {
+    mRelayoutData->preferredSize.width = mAnimatedSize.width;
+  }
+
+  // Notify deriving classes
+  mOwner.OnSizeAnimation(animation, mTargetSize);
+}
+
+void ActorSizer::OnAnimateHeight(Animation& animation, float height, bool relative)
+{
+  mTargetSize.height   = height + float(relative) * mTargetSize.height;
+  mAnimatedSize.height = mTargetSize.height;
+  mUseAnimatedSize |= AnimatedSizeFlag::HEIGHT;
+
+  if(mRelayoutData && !mRelayoutData->relayoutRequested)
+  {
+    mRelayoutData->preferredSize.height = mAnimatedSize.height;
+  }
+
+  // Notify deriving classes
+  mOwner.OnSizeAnimation(animation, mTargetSize);
+}
+
+void ActorSizer::OnAnimateDepth(Animation& animation, float depth, bool relative)
+{
+  mTargetSize.depth   = depth + float(relative) * mTargetSize.depth;
+  mAnimatedSize.depth = mTargetSize.depth;
+  mUseAnimatedSize |= AnimatedSizeFlag::DEPTH;
+
+  // Notify deriving classes
+  mOwner.OnSizeAnimation(animation, mTargetSize);
+}
+
+/**
+ * @brief Extract a given dimension from a Vector3
+ *
+ * @param[in] values The values to extract from
+ * @param[in] dimension The dimension to extract
+ * @return Return the value for the dimension
+ */
+float ActorSizer::GetDimensionValue(const Vector3& values, const Dimension::Type dimension) const
+{
+  return ::GetDimensionValue(values.GetVectorXY(), dimension);
+}
+
+float ActorSizer::ClampDimension(float size, Dimension::Type dimension) const
+{
+  const float minSize = GetMinimumSize(dimension);
+  const float maxSize = GetMaximumSize(dimension);
+
+  return std::max(minSize, std::min(size, maxSize));
+}
+
+void ActorSizer::NegotiateDimension(Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack)
+{
+  // Check if it needs to be negotiated
+  if(IsLayoutDirty(dimension) && !IsLayoutNegotiated(dimension))
+  {
+    // Check that we havn't gotten into an infinite loop
+    ActorDimensionPair searchActor    = ActorDimensionPair(&mOwner, dimension);
+    bool               recursionFound = false;
+    for(auto& element : recursionStack)
+    {
+      if(element == searchActor)
+      {
+        recursionFound = true;
+        break;
+      }
+    }
+
+    if(!recursionFound)
+    {
+      // Record the path that we have taken
+      recursionStack.push_back(ActorDimensionPair(&mOwner, dimension));
+
+      // Dimension dependency check
+      for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
+      {
+        Dimension::Type dimensionToCheck = static_cast<Dimension::Type>(1 << i);
+
+        if(RelayoutDependentOnDimension(dimension, dimensionToCheck))
+        {
+          NegotiateDimension(dimensionToCheck, allocatedSize, recursionStack);
+        }
+      }
+
+      // Parent dependency check
+      Actor* parent = mOwner.GetParent();
+      if(parent && RelayoutDependentOnParent(dimension))
+      {
+        parent->mSizer.NegotiateDimension(dimension, allocatedSize, recursionStack);
+      }
+
+      // Children dependency check
+      if(mOwner.RelayoutDependentOnChildren(dimension))
+      {
+        for(uint32_t i = 0, count = mOwner.GetChildCount(); i < count; ++i)
+        {
+          ActorPtr child = mOwner.GetChildAt(i);
+
+          // Only relayout child first if it is not dependent on this actor
+          if(!child->RelayoutDependentOnParent(dimension))
+          {
+            child->mSizer.NegotiateDimension(dimension, allocatedSize, recursionStack);
+          }
+        }
+      }
+
+      // For deriving classes
+      mOwner.OnCalculateRelayoutSize(dimension);
+
+      // All dependencies checked, calculate the size and set negotiated flag
+      const float newSize = ClampDimension(CalculateSize(dimension, allocatedSize), dimension);
+
+      SetNegotiatedDimension(newSize, dimension);
+      SetLayoutNegotiated(true, dimension);
+
+      // For deriving classes
+      mOwner.OnLayoutNegotiated(newSize, dimension);
+
+      // This actor has been successfully processed, pop it off the recursion stack
+      recursionStack.pop_back();
+    }
+    else
+    {
+      // TODO: Break infinite loop
+      SetLayoutNegotiated(true, dimension);
+    }
+  }
+}
+
+void ActorSizer::NegotiateDimensions(const Vector2& allocatedSize)
+{
+  // Negotiate all dimensions that require it
+  ActorDimensionStack recursionStack;
+
+  for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
+  {
+    const Dimension::Type dimension = static_cast<Dimension::Type>(1 << i);
+
+    // Negotiate
+    NegotiateDimension(dimension, allocatedSize, recursionStack);
+  }
+}
+
+float ActorSizer::CalculateSize(Dimension::Type dimension, const Vector2& maximumSize)
+{
+  switch(GetResizePolicy(dimension))
+  {
+    case ResizePolicy::USE_NATURAL_SIZE:
+    {
+      return GetNaturalSize(dimension);
+    }
+
+    case ResizePolicy::FIXED:
+    {
+      return ::GetDimensionValue(GetPreferredSize(), dimension);
+    }
+
+    case ResizePolicy::USE_ASSIGNED_SIZE:
+    {
+      return ::GetDimensionValue(maximumSize, dimension);
+    }
+
+    case ResizePolicy::FILL_TO_PARENT:
+    case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
+    case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
+    {
+      return NegotiateFromParent(dimension);
+    }
+
+    case ResizePolicy::FIT_TO_CHILDREN:
+    {
+      return NegotiateFromChildren(dimension);
+    }
+
+    case ResizePolicy::DIMENSION_DEPENDENCY:
+    {
+      const Dimension::Type dimensionDependency = GetDimensionDependency(dimension);
+
+      // Custom rules
+      if(dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT)
+      {
+        // Use actor API to allow deriving actors to layout their content
+        return mOwner.GetWidthForHeight(GetNegotiatedDimension(Dimension::HEIGHT));
+      }
+
+      if(dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH)
+      {
+        // Use actor API to allow deriving actors to layout their content
+        return mOwner.GetHeightForWidth(GetNegotiatedDimension(Dimension::WIDTH));
+      }
+
+      break;
+    }
+
+    default:
+    {
+      break;
+    }
+  }
+
+  return 0.0f; // Default
+}
+
+} // namespace Dali::Internal
diff --git a/dali/internal/event/actors/actor-sizer.h b/dali/internal/event/actors/actor-sizer.h
new file mode 100644 (file)
index 0000000..2149694
--- /dev/null
@@ -0,0 +1,368 @@
+#ifndef DALI_INTERNAL_ACTOR_SIZER_H
+#define DALI_INTERNAL_ACTOR_SIZER_H
+
+/*
+ * Copyright (c) 2021 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/internal/event/actors/actor-declarations.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/size-negotiation/relayout-container.h>
+
+namespace Dali::Internal
+{
+class Actor;
+class Animation;
+
+/**
+ * Class to handle sizing of actor. Uses size negotiation and animation.
+ */
+class ActorSizer
+{
+public:
+  struct AnimatedSizeFlag
+  {
+    enum Type
+    {
+      CLEAR  = 0,
+      WIDTH  = 1,
+      HEIGHT = 2,
+      DEPTH  = 4
+    };
+  };
+
+  /**
+   * @brief Struct to hold an actor and a dimension
+   */
+  struct ActorDimensionPair
+  {
+    /**
+     * @brief Constructor
+     *
+     * @param[in] newActor The actor to assign
+     * @param[in] newDimension The dimension to assign
+     */
+    ActorDimensionPair(Actor* newActor, Dimension::Type newDimension)
+    : actor(newActor),
+      dimension(newDimension)
+    {
+    }
+
+    /**
+     * @brief Equality operator
+     *
+     * @param[in] lhs The left hand side argument
+     * @param[in] rhs The right hand side argument
+     */
+    bool operator==(const ActorDimensionPair& rhs)
+    {
+      return (actor == rhs.actor) && (dimension == rhs.dimension);
+    }
+
+    Actor*          actor;     ///< The actor to hold
+    Dimension::Type dimension; ///< The dimension to hold
+  };
+
+  using ActorDimensionStack = std::vector<ActorDimensionPair>;
+
+public:
+  /// Constructor
+  ActorSizer(Internal::Actor& owner);
+
+  /// Destructor
+  ~ActorSizer();
+
+  // Remove default constructor, copy constructor and assignment operator
+  ActorSizer()                  = delete;
+  ActorSizer(const ActorSizer&) = delete;
+  ActorSizer& operator=(const ActorSizer) = delete;
+
+  ///@copydoc Actor::SetSizerModeFactor
+  void SetSizeModeFactor(const Vector3& factor);
+
+  ///@copydoc Actor::
+  const Vector3& GetSizeModeFactor() const;
+
+  ///@copydoc Actor::SetSize
+  void SetSize(const Vector3& size);
+
+  ///@ Set the target size / preferred size
+  void SetSizeInternal(const Vector3& size);
+
+  ///@copydoc Actor::SetWidth
+  void SetWidth(float width);
+
+  ///@copydoc Actor::SetHeight
+  void SetHeight(float height);
+
+  ///@copydoc Actor::SetDepth
+  void SetDepth(float depth);
+
+  ///@copydoc Actor::GetTargetSize
+  Vector3 GetTargetSize() const;
+
+  ///@copydoc Actor::SetResizePolicy
+  void SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
+
+  ///@copydoc Actor:::Type
+  ResizePolicy::Type GetResizePolicy(Dimension::Type dimension) const;
+
+  ///@copydoc Actor::SetSizeScalePolicy
+  void SetSizeScalePolicy(SizeScalePolicy::Type policy);
+
+  ///@copydoc Actor:::GetSizeScalePolicy
+  SizeScalePolicy::Type GetSizeScalePolicy() const;
+
+  ///@copydoc Actor::SetDimensionDependency
+  void SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency);
+
+  ///@copydoc Actor::GetDimensionDependency
+  Dimension::Type GetDimensionDependency(Dimension::Type dimension) const;
+
+  ///@copydoc Actor::SetRelayoutEnabled
+  void SetRelayoutEnabled(bool relayoutEnabled);
+
+  ///@copydoc Actor::IsRelayoutEnabled
+  bool IsRelayoutEnabled() const;
+
+  ///@copydoc Actor::SetLayoutDirty
+  void SetLayoutDirty(bool dirty, Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
+
+  ///@copydoc Actor::IsLayoutDirty
+  bool IsLayoutDirty(Dimension::Type dimension = Dimension::ALL_DIMENSIONS) const;
+
+  ///@copydoc Actor::RelayoutPossible
+  bool RelayoutPossible(Dimension::Type dimension = Dimension::ALL_DIMENSIONS) const;
+
+  ///@copydoc Actor::RelayoutRequired
+  bool RelayoutRequired(Dimension::Type dimension = Dimension::ALL_DIMENSIONS) const;
+
+  ///@copydoc Actor::RelayoutDependentOnParent
+  bool RelayoutDependentOnParent(Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
+
+  ///@copydoc Actor::RelayoutDependentOnChildren
+  bool RelayoutDependentOnChildrenBase(Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
+
+  ///@copydoc Actor::RelayoutDependentOnDimension
+  bool RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension);
+
+  ///@copydoc Actor::SetNegotiatedDimension
+  void SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
+
+  ///@copydoc Actor::GetNegotiatedDimension
+  float GetNegotiatedDimension(Dimension::Type dimension) const;
+
+  ///@copydoc Actor::SetPadding
+  void SetPadding(const Vector2& padding, Dimension::Type dimension);
+
+  ///@copydoc Actor::GetPadding
+  Vector2 GetPadding(Dimension::Type dimension) const;
+
+  ///@copydoc Actor::SetLayoutNegotiated
+  void SetLayoutNegotiated(bool negotiated, Dimension::Type dimension);
+
+  ///@copydoc Actor::IsLayoutNegotiated
+  bool IsLayoutNegotiated(Dimension::Type dimension) const;
+
+  ///@copydoc Actor::GetHeightForWidth
+  float GetHeightForWidthBase(float width);
+
+  ///@copydoc Actor::GetWidthForHeight
+  float GetWidthForHeightBase(float height);
+
+  ///@copydoc Actor::CalculateChildSize
+  float CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension);
+
+  ///@copydoc Actor::GetLatestSize
+  float GetLatestSize(Dimension::Type dimension) const;
+
+  ///@copydoc Actor::GetRelayoutSize
+  float GetRelayoutSize(Dimension::Type dimension) const;
+
+  ///@copydoc Actor::GetSize
+  float GetSize(Dimension::Type dimension) const;
+
+  ///@copydoc Actor::GetNaturalSize
+  float GetNaturalSize(Dimension::Type dimension) const;
+
+  ///@copydoc Actor::ApplySizeSetPolicy
+  Vector2 ApplySizeSetPolicy(const Vector2& size);
+
+  ///@copydoc Actor::SetNegotiatedSize
+  void SetNegotiatedSize(RelayoutContainer& container);
+
+  ///@copydoc Actor::NegotiateSize
+  void NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container);
+
+  ///@copydoc Actor::RelayoutRequest
+  void RelayoutRequest(Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
+
+  ///@copydoc Actor::SetMinimumSize
+  void SetMinimumSize(float size, Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
+
+  ///@copydoc Actor::GetMinimumSize
+  float GetMinimumSize(Dimension::Type dimension) const;
+
+  ///@copydoc Actor::SetMaximumSize
+  void SetMaximumSize(float size, Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
+
+  ///@copydoc Actor::GetMaximumSize
+  float GetMaximumSize(Dimension::Type dimension) const;
+
+  /**
+   * Update target / preferred / animated size when size animation starts
+   * @param[in] animation The animation modifying the size
+   * @param[in] targetSize The new target size
+   */
+  void OnAnimateSize(Animation& animation, Vector3 targetSize, bool relative);
+
+  /**
+   * Update target / preferred / animated width when size animation starts
+   * @param[in] animation The animation modifying the width
+   * @param[in] targetWidth The new target width
+   */
+  void OnAnimateWidth(Animation& animation, float targetWidth, bool relative);
+
+  /**
+   * Update target / preferred / animated height when size animation starts
+   * @param[in] animation The animation modifying the height
+   * @param[in] targetHeight The new target height
+   */
+  void OnAnimateHeight(Animation& animation, float targetHeight, bool relative);
+
+  /**
+   * Update target / preferred / animated depth when size animation starts
+   * @param[in] animation The animation modifying the depth
+   * @param[in] targetDepth The new target depth
+   */
+  void OnAnimateDepth(Animation& animation, float targetDepth, bool relative);
+
+private:
+  struct Relayouter;
+
+  /**
+   * @brief Ensure the relayouter is allocated
+   */
+  Relayouter& EnsureRelayouter();
+
+  /**
+  * @brief Extract a given dimension from a Vector3
+  *
+  * @param[in] values The values to extract from
+  * @param[in] dimension The dimension to extract
+  * @return Return the value for the dimension
+  */
+  float GetDimensionValue(const Vector3& values, const Dimension::Type dimension) const;
+
+  /**
+   * @brief Clamp a dimension given the relayout constraints on given actor
+   *
+   * @param[in] size The size to constrain
+   * @param[in] dimension The dimension the size exists in
+   * @return Return the clamped size
+   */
+  float ClampDimension(float size, Dimension::Type dimension) const;
+
+  /**
+   * Negotiate a dimension based on the size of the parent
+   *
+   * @param[in] dimension The dimension to negotiate on
+   * @return Return the negotiated size
+   */
+  float NegotiateFromParent(Dimension::Type dimension);
+
+  /**
+   * @brief Negotiate a dimension based on the size of the children
+   *
+   * @param[in] dimension The dimension to negotiate on
+   * @return Return the negotiated size
+   */
+  float NegotiateFromChildren(Dimension::Type dimension);
+
+  /**
+   * Negotiate size for a specific dimension
+   *
+   * The algorithm adopts a recursive dependency checking approach. Meaning, that wherever dependencies
+   * are found, e.g. an actor dependent on its parent, the dependency will be calculated first with NegotiatedDimension and
+   * LayoutDimensionNegotiated flags being filled in on the actor.
+   *
+   * @post All actors that exist in the dependency chain connected to the given actor will have had their NegotiatedDimensions
+   * calculated and set as well as the LayoutDimensionNegotiated flags.
+   *
+   * @param[in] dimension The dimension to negotiate on
+   * @param[in] allocatedSize The size constraint that the actor must respect
+   */
+  void NegotiateDimension(Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack);
+
+  /**
+   * Negotiate sizes for a control in all dimensions
+   *
+   * @param[in] allocatedSize The size constraint that the control must respect
+   */
+  void NegotiateDimensions(const Vector2& allocatedSize);
+
+  /**
+   * @brief Set whether size negotiation should use the assigned size of the actor
+   * during relayout for the given dimension(s)
+   *
+   * @param[in] use Whether the assigned size of the actor should be used
+   * @param[in] dimension The dimension(s) to set. Can be a bitfield of multiple dimensions
+   */
+  void SetUseAssignedSize(bool use, Dimension::Type dimension = Dimension::ALL_DIMENSIONS);
+
+  /**
+   * @brief Returns whether size negotiation should use the assigned size of the actor
+   * during relayout for a single dimension
+   *
+   * @param[in] dimension The dimension to get
+   * @return Return whether the assigned size of the actor should be used. If more than one dimension is requested, just return the first one found
+   */
+  bool GetUseAssignedSize(Dimension::Type dimension) const;
+
+  /**
+   * @brief Calculate the size of a dimension
+   *
+   * @param[in] dimension The dimension to calculate the size for
+   * @param[in] maximumSize The upper bounds on the size
+   * @return Return the calculated size for the dimension
+   */
+  float CalculateSize(Dimension::Type dimension, const Vector2& maximumSize);
+
+  /**
+   * @brief Set the preferred size for size negotiation
+   *
+   * @param[in] size The preferred size to set
+   */
+  void SetPreferredSize(const Vector2& size);
+
+  /**
+   * @brief Get the preferred size for size negotiation
+   *
+   * @return size The preferred size to set
+   */
+  Vector2 GetPreferredSize() const;
+
+private:
+  Internal::Actor& mOwner;           // Owner of this actor sizer
+  Relayouter*      mRelayoutData;    ///< Struct to hold optional collection of relayout variables
+  Dali::Vector3    mTargetSize;      ///< Event-side storage for size (not a pointer as most actors will have a size)
+  Dali::Vector3    mAnimatedSize;    ///< Event-side storage for size animation
+  uint16_t         mUseAnimatedSize; ///< Whether the size is animated.
+  bool             mInsideOnSizeSet : 1;
+};
+
+} // namespace Dali::Internal
+
+#endif //DALI_INTERNAL_ACTOR_SIZER_H
index 653b20a..622db16 100644 (file)
@@ -444,11 +444,7 @@ void RelayoutController::Relayout()
 
           // 3. Negotiate the size with the current actor. Pass it an empty container which the actor
           //    has to fill with all the actors it has not done any size negotiation for.
-
           actorImpl.NegotiateSize(size, *mRelayoutStack);
-
-          // Reset the flag so that size negotiation will respect the actor's original resize policy
-          actorImpl.SetUseAssignedSize(false);
         }
       }
 
index 9f4ad89..bd014f7 100644 (file)
@@ -18,6 +18,7 @@ SET( internal_src_files
   ${internal_src_dir}/event/actors/actor-renderer-container.cpp
   ${internal_src_dir}/event/actors/actor-relayouter.cpp
   ${internal_src_dir}/event/actors/actor-parent-impl.cpp
+  ${internal_src_dir}/event/actors/actor-sizer.cpp
   ${internal_src_dir}/event/actors/custom-actor-internal.cpp
   ${internal_src_dir}/event/actors/layer-impl.cpp
   ${internal_src_dir}/event/actors/layer-list.cpp