test_return_value = TET_PASS;
}
-int UtcDaliActorRelayouter_CalculateSize(void)
+int UtcDaliActorSizer_CalculateSize(void)
{
TestApplication application;
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;
}
bool TestCustomActor::RelayoutDependentOnChildren(Dimension::Type dimension)
{
- return false;
+ return CustomActorImpl::RelayoutDependentOnChildrenBase(dimension);
}
void TestCustomActor::SetTransparent(bool transparent)
// EXTERNAL INCLUDES
#include <algorithm>
-#include <cfloat>
#include <cmath>
// INTERNAL INCLUDES
#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>
#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;
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)
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
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)
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(),
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),
mKeyboardFocusableChildren(true),
mTouchFocusable(false),
mOnSceneSignalled(false),
- mInsideOnSizeSet(false),
mInheritPosition(true),
mInheritOrientation(true),
mInheritScale(true),
// Cleanup optional parent origin and anchor
delete mParentOrigin;
delete mAnchorPoint;
-
- // Delete optional relayout data
- delete mRelayoutData;
}
void Actor::Add(Actor& child, bool notify)
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)
#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
{
{
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.
*/
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.
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.
*/
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
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);
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
/**
* @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
/**
* @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
/**
* @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
*/
/**
* @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
*/
/**
* @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
/**
* @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
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)
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
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.
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.
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
};
};
- 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;
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.
*/
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
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
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
#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>
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;
}
{
if(property.Get<bool>())
{
- actor.SetResizePolicy(ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH);
+ actor.mSizer.SetResizePolicy(ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH);
}
break;
}
{
if(property.Get<bool>())
{
- actor.SetResizePolicy(ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT);
+ actor.mSizer.SetResizePolicy(ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT);
}
break;
}
{
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;
}
{
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;
}
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;
}
#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),
}
}
-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)
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)
{
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)
{
}
}
-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)
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)
{
}
}
-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)
{
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)
{
}
}
-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)
{
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);
}
}
-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)
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)
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)
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)
{
}
}
-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)
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)
{
}
}
-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)
{
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)
{
}
}
-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)
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
// INTERNAL INCLUDES
#include <dali/internal/event/actors/actor-impl.h>
+
#include <dali/public-api/math/vector2.h>
#include <dali/public-api/math/vector3.h>
/**
* 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};
/// @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);
/// @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
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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
// 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);
}
}
${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