2 * Copyright (c) 2020 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/public-api/math/vector2.h>
23 #include <dali/public-api/math/vector3.h>
24 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
32 Actor::Relayouter::Relayouter()
33 : sizeModeFactor( DEFAULT_SIZE_MODE_FACTOR ),
34 preferredSize( DEFAULT_PREFERRED_SIZE ),
35 sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ),
36 relayoutEnabled( false ),
37 insideRelayout( false )
39 // Set size negotiation defaults
40 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
42 resizePolicies[ i ] = ResizePolicy::DEFAULT;
43 useAssignedSize[ i ] = false;
44 negotiatedDimensions[ i ] = 0.0f;
45 dimensionNegotiated[ i ] = false;
46 dimensionDirty[ i ] = false;
47 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
48 dimensionPadding[ i ] = DEFAULT_DIMENSION_PADDING;
49 minimumSize[ i ] = 0.0f;
50 maximumSize[ i ] = FLT_MAX;
54 ResizePolicy::Type Actor::Relayouter::GetResizePolicy( Dimension::Type dimension ) const
56 // If more than one dimension is requested, just return the first one found
57 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
59 if( ( dimension & ( 1 << i ) ) )
61 if( useAssignedSize[ i ] )
63 return ResizePolicy::USE_ASSIGNED_SIZE;
67 return resizePolicies[ i ];
72 return ResizePolicy::DEFAULT;
75 void Actor::Relayouter::SetPadding( const Vector2& padding, Dimension::Type dimension )
77 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
79 if( dimension & ( 1 << i ) )
81 dimensionPadding[ i ] = padding;
86 void Actor::Relayouter::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
88 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
90 if( dimension & ( 1 << i ) )
92 dimensionNegotiated[ i ] = negotiated;
97 bool Actor::Relayouter::IsLayoutNegotiated( Dimension::Type dimension ) const
99 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
101 if( ( dimension & ( 1 << i ) ) && dimensionNegotiated[ i ] )
109 Vector2 Actor::Relayouter::ApplySizeSetPolicy( Internal::Actor& actor, const Vector2& size )
111 switch( sizeSetPolicy )
113 case SizeScalePolicy::USE_SIZE_SET:
118 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
120 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
121 const Vector3 naturalSize = actor.GetNaturalSize();
122 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
124 const float sizeRatio = size.width / size.height;
125 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
127 if( naturalSizeRatio < sizeRatio )
129 return Vector2( naturalSizeRatio * size.height, size.height );
131 else if( naturalSizeRatio > sizeRatio )
133 return Vector2( size.width, size.width / naturalSizeRatio );
144 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
146 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
147 const Vector3 naturalSize = actor.GetNaturalSize();
148 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
150 const float sizeRatio = size.width / size.height;
151 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
153 if( naturalSizeRatio < sizeRatio )
155 return Vector2( size.width, size.width / naturalSizeRatio );
157 else if( naturalSizeRatio > sizeRatio )
159 return Vector2( naturalSizeRatio * size.height, size.height );
178 void Actor::Relayouter::SetUseAssignedSize( bool use, Dimension::Type dimension )
180 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
182 if( dimension & ( 1 << i ) )
184 useAssignedSize[ i ] = use;
189 bool Actor::Relayouter::GetUseAssignedSize( Dimension::Type dimension ) const
191 // If more than one dimension is requested, just return the first one found
192 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
194 if( dimension & ( 1 << i ) )
196 return useAssignedSize[ i ];
203 void Actor::Relayouter::SetMinimumSize( float size, Dimension::Type dimension )
205 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
207 if( dimension & ( 1 << i ) )
209 minimumSize[ i ] = size;
214 float Actor::Relayouter::GetMinimumSize( Dimension::Type dimension ) const
216 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
218 if( dimension & ( 1 << i ) )
220 return minimumSize[ i ];
224 return 0.0f; // Default
227 void Actor::Relayouter::SetMaximumSize( float size, Dimension::Type dimension )
229 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
231 if( dimension & ( 1 << i ) )
233 maximumSize[ i ] = size;
238 float Actor::Relayouter::GetMaximumSize( Dimension::Type dimension ) const
240 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
242 if( dimension & ( 1 << i ) )
244 return maximumSize[ i ];
248 return FLT_MAX; // Default
251 void Actor::Relayouter::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension, Vector3& targetSize )
253 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
254 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
256 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
258 if( dimension & ( 1 << i ) )
260 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
262 useAssignedSize[ i ] = true;
266 resizePolicies[ i ] = policy;
267 useAssignedSize[ i ] = false;
272 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
274 if( dimension & Dimension::WIDTH )
276 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
279 if( dimension & Dimension::HEIGHT )
281 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
285 // If calling SetResizePolicy, assume we want relayout enabled
286 relayoutEnabled = true;
288 // If the resize policy is set to be FIXED, the preferred size
289 // should be overrided by the target size. Otherwise the target
290 // size should be overrided by the preferred size.
292 if( dimension & Dimension::WIDTH )
294 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
296 preferredSize.width = targetSize.width;
298 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
300 targetSize.width = preferredSize.width;
304 if( dimension & Dimension::HEIGHT )
306 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
308 preferredSize.height = targetSize.height;
310 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
312 targetSize.height = preferredSize.height;
317 void Actor::Relayouter::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
319 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
321 if( dimension & ( 1 << i ) )
323 dimensionDependencies[ i ] = dependency;
328 Dimension::Type Actor::Relayouter::GetDimensionDependency( Dimension::Type dimension ) const
330 // If more than one dimension is requested, just return the first one found
331 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
333 if( ( dimension & ( 1 << i ) ) )
335 return dimensionDependencies[ i ];
339 return Dimension::ALL_DIMENSIONS; // Default
342 void Actor::Relayouter::SetLayoutDirty( bool dirty, Dimension::Type dimension )
344 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
346 if( dimension & ( 1 << i ) )
348 dimensionDirty[ i ] = dirty;
353 bool Actor::Relayouter::IsLayoutDirty( Dimension::Type dimension ) const
355 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
357 if( ( dimension & ( 1 << i ) ) && dimensionDirty[ i ] )
366 float Actor::Relayouter::ClampDimension( const Internal::Actor& actor, float size, Dimension::Type dimension )
368 const float minSize = actor.GetMinimumSize( dimension );
369 const float maxSize = actor.GetMaximumSize( dimension );
371 return std::max( minSize, std::min( size, maxSize ) );
374 } // namespace Internal