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::GetRelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependency)
292 // Check each possible dimension and see if it is dependent on the input one
293 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
295 if(dimension & (1 << i))
297 return resizePolicies[i] == ResizePolicy::DIMENSION_DEPENDENCY && dimensionDependencies[i] == dependency;
304 void ActorSizer::Relayouter::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
306 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
308 if(dimension & (1 << i))
310 dimensionDependencies[i] = dependency;
315 Dimension::Type ActorSizer::Relayouter::GetDimensionDependency(Dimension::Type dimension) const
317 // If more than one dimension is requested, just return the first one found
318 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
320 if((dimension & (1 << i)))
322 return dimensionDependencies[i];
326 return Dimension::ALL_DIMENSIONS; // Default
329 void ActorSizer::Relayouter::SetLayoutDirty(bool dirty, Dimension::Type dimension)
331 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
333 if(dimension & (1 << i))
335 dimensionDirty[i] = dirty;
340 bool ActorSizer::Relayouter::IsLayoutDirty(Dimension::Type dimension) const
342 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
344 if((dimension & (1 << i)) && dimensionDirty[i])
353 void ActorSizer::Relayouter::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
355 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
357 if(dimension & (1 << i))
359 negotiatedDimensions[i] = negotiatedDimension;
364 float ActorSizer::Relayouter::GetNegotiatedDimension(Dimension::Type dimension)
366 // If more than one dimension is requested, just return the first one found
367 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
369 if((dimension & (1 << i)))
371 return negotiatedDimensions[i];
375 return 0.0f; // Default
378 void ActorSizer::Relayouter::SetPadding(const Vector2& padding, Dimension::Type dimension)
380 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
382 if(dimension & (1 << i))
384 dimensionPadding[i] = padding;
389 Vector2 ActorSizer::Relayouter::GetPadding(Dimension::Type dimension)
391 // If more than one dimension is requested, just return the first one found
392 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
394 if((dimension & (1 << i)))
396 return dimensionPadding[i];
400 return DEFAULT_DIMENSION_PADDING;
403 void ActorSizer::Relayouter::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
405 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
407 if(dimension & (1 << i))
409 dimensionNegotiated[i] = negotiated;
414 bool ActorSizer::Relayouter::IsLayoutNegotiated(Dimension::Type dimension) const
416 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
418 if((dimension & (1 << i)) && dimensionNegotiated[i])
426 } // namespace Internal