2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-relayouter.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/actors/actor.h>
24 #include <dali/public-api/math/vector2.h>
25 #include <dali/public-api/math/vector3.h>
27 #include <dali/internal/event/actors/actor-impl.h>
28 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
30 #if defined(DEBUG_ENABLED)
31 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER");
38 ActorSizer::Relayouter::Relayouter()
39 : sizeModeFactor(DEFAULT_SIZE_MODE_FACTOR),
40 preferredSize(DEFAULT_PREFERRED_SIZE),
41 sizeSetPolicy(DEFAULT_SIZE_SCALE_POLICY),
42 relayoutEnabled(false),
43 insideRelayout(false),
44 relayoutRequested(false)
46 // Set size negotiation defaults
47 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
49 resizePolicies[i] = ResizePolicy::DEFAULT;
50 useAssignedSize[i] = false;
51 negotiatedDimensions[i] = 0.0f;
52 dimensionNegotiated[i] = false;
53 dimensionDirty[i] = false;
54 dimensionDependencies[i] = Dimension::ALL_DIMENSIONS;
55 dimensionPadding[i] = DEFAULT_DIMENSION_PADDING;
56 minimumSize[i] = 0.0f;
57 maximumSize[i] = FLT_MAX;
61 ResizePolicy::Type ActorSizer::Relayouter::GetResizePolicy(Dimension::Type dimension) const
63 // If more than one dimension is requested, just return the first one found
64 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
66 if((dimension & (1 << i)))
68 if(useAssignedSize[i])
70 return ResizePolicy::USE_ASSIGNED_SIZE;
74 return resizePolicies[i];
79 return ResizePolicy::DEFAULT;
82 Vector2 ActorSizer::Relayouter::ApplySizeSetPolicy(Internal::Actor& actor, const Vector2& size)
86 case SizeScalePolicy::USE_SIZE_SET:
91 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
93 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
94 const Vector3 naturalSize = actor.GetNaturalSize();
95 if(naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f)
97 const float sizeRatio = size.width / size.height;
98 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
100 if(naturalSizeRatio < sizeRatio)
102 return Vector2(naturalSizeRatio * size.height, size.height);
104 else if(naturalSizeRatio > sizeRatio)
106 return Vector2(size.width, size.width / naturalSizeRatio);
117 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
119 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
120 const Vector3 naturalSize = actor.GetNaturalSize();
121 if(naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f)
123 const float sizeRatio = size.width / size.height;
124 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
126 if(naturalSizeRatio < sizeRatio)
128 return Vector2(size.width, size.width / naturalSizeRatio);
130 else if(naturalSizeRatio > sizeRatio)
132 return Vector2(naturalSizeRatio * size.height, size.height);
151 void ActorSizer::Relayouter::SetUseAssignedSize(bool use, Dimension::Type dimension)
153 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
155 if(dimension & (1 << i))
157 useAssignedSize[i] = use;
162 bool ActorSizer::Relayouter::GetUseAssignedSize(Dimension::Type dimension) const
164 // If more than one dimension is requested, just return the first one found
165 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
167 if(dimension & (1 << i))
169 return useAssignedSize[i];
176 void ActorSizer::Relayouter::SetMinimumSize(float size, Dimension::Type dimension)
178 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
180 if(dimension & (1 << i))
182 minimumSize[i] = size;
187 float ActorSizer::Relayouter::GetMinimumSize(Dimension::Type dimension) const
189 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
191 if(dimension & (1 << i))
193 return minimumSize[i];
197 return 0.0f; // Default
200 void ActorSizer::Relayouter::SetMaximumSize(float size, Dimension::Type dimension)
202 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
204 if(dimension & (1 << i))
206 maximumSize[i] = size;
211 float ActorSizer::Relayouter::GetMaximumSize(Dimension::Type dimension) const
213 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
215 if(dimension & (1 << i))
217 return maximumSize[i];
221 return FLT_MAX; // Default
224 void ActorSizer::Relayouter::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension, Vector3& targetSize)
226 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
227 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
229 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
231 if(dimension & (1 << i))
233 if(policy == ResizePolicy::USE_ASSIGNED_SIZE)
235 useAssignedSize[i] = true;
239 resizePolicies[i] = policy;
240 useAssignedSize[i] = false;
245 if(policy == ResizePolicy::DIMENSION_DEPENDENCY)
247 if(dimension & Dimension::WIDTH)
249 SetDimensionDependency(Dimension::WIDTH, Dimension::HEIGHT);
252 if(dimension & Dimension::HEIGHT)
254 SetDimensionDependency(Dimension::HEIGHT, Dimension::WIDTH);
258 // If calling SetResizePolicy, assume we want relayout enabled
259 relayoutEnabled = true;
261 // If the resize policy is set to be FIXED, the preferred size
262 // should be overrided by the target size. Otherwise the target
263 // size should be overrided by the preferred size.
265 if(dimension & Dimension::WIDTH)
267 if(originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED)
269 preferredSize.width = targetSize.width;
271 else if(originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED)
273 targetSize.width = preferredSize.width;
277 if(dimension & Dimension::HEIGHT)
279 if(originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED)
281 preferredSize.height = targetSize.height;
283 else if(originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED)
285 targetSize.height = preferredSize.height;
290 bool ActorSizer::Relayouter::GetRelayoutDependentOnParent(Dimension::Type dimension)
292 // Check if actor is dependent on parent
293 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
295 if((dimension & (1 << i)))
297 const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
298 if(resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT)
307 bool ActorSizer::Relayouter::GetRelayoutDependentOnChildren(Dimension::Type dimension)
309 // Check if actor is dependent on children
310 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
312 if((dimension & (1 << i)))
314 const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
315 if(resizePolicy == ResizePolicy::FIT_TO_CHILDREN || resizePolicy == ResizePolicy::USE_NATURAL_SIZE)
326 bool ActorSizer::Relayouter::GetRelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependency)
328 // Check each possible dimension and see if it is dependent on the input one
329 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
331 if(dimension & (1 << i))
333 return resizePolicies[i] == ResizePolicy::DIMENSION_DEPENDENCY && dimensionDependencies[i] == dependency;
340 void ActorSizer::Relayouter::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
342 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
344 if(dimension & (1 << i))
346 dimensionDependencies[i] = dependency;
351 Dimension::Type ActorSizer::Relayouter::GetDimensionDependency(Dimension::Type dimension) const
353 // If more than one dimension is requested, just return the first one found
354 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
356 if((dimension & (1 << i)))
358 return dimensionDependencies[i];
362 return Dimension::ALL_DIMENSIONS; // Default
365 void ActorSizer::Relayouter::SetLayoutDirty(bool dirty, Dimension::Type dimension)
367 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
369 if(dimension & (1 << i))
371 dimensionDirty[i] = dirty;
376 bool ActorSizer::Relayouter::IsLayoutDirty(Dimension::Type dimension) const
378 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
380 if((dimension & (1 << i)) && dimensionDirty[i])
389 void ActorSizer::Relayouter::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
391 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
393 if(dimension & (1 << i))
395 negotiatedDimensions[i] = negotiatedDimension;
400 float ActorSizer::Relayouter::GetNegotiatedDimension(Dimension::Type dimension)
402 // If more than one dimension is requested, just return the first one found
403 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
405 if((dimension & (1 << i)))
407 return negotiatedDimensions[i];
411 return 0.0f; // Default
414 void ActorSizer::Relayouter::SetPadding(const Vector2& padding, Dimension::Type dimension)
416 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
418 if(dimension & (1 << i))
420 dimensionPadding[i] = padding;
425 Vector2 ActorSizer::Relayouter::GetPadding(Dimension::Type dimension)
427 // If more than one dimension is requested, just return the first one found
428 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
430 if((dimension & (1 << i)))
432 return dimensionPadding[i];
436 return DEFAULT_DIMENSION_PADDING;
439 void ActorSizer::Relayouter::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
441 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
443 if(dimension & (1 << i))
445 dimensionNegotiated[i] = negotiated;
450 bool ActorSizer::Relayouter::IsLayoutNegotiated(Dimension::Type dimension) const
452 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
454 if((dimension & (1 << i)) && dimensionNegotiated[i])
462 } // namespace Internal