2 * Copyright (c) 2014 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.
20 #include "alignment-impl.h"
23 #include <dali/public-api/object/type-registry.h>
42 return Toolkit::Alignment::New();
45 TypeRegistration mType( typeid(Toolkit::Alignment), typeid(Toolkit::Control), Create );
47 struct ScaleToFillConstraint
50 * @param padding to be added.
52 ScaleToFillConstraint( const Toolkit::Alignment::Padding& padding )
57 * CopyConstructor. Used by Boost.
58 * @param rhs Copying from.
60 ScaleToFillConstraint( const ScaleToFillConstraint& rhs )
61 : mPadding( rhs.mPadding )
65 * Called by render thread
67 Vector3 operator()( const Vector3& currentSize,
68 const PropertyInput& parentSizeProperty )
70 const Vector3& parentSize( parentSizeProperty.GetVector3() );
71 return GetSize( currentSize, parentSize );
74 inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
76 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
77 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
79 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
80 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 ) )
82 // no point trying to squeeze actors into this small size
85 return Vector3( parentSizeWidth, parentSizeHeight, parentSize.depth );
88 const Toolkit::Alignment::Padding mPadding;
91 struct ScaleToFitKeepAspectConstraint
94 * @param padding to be added.
96 ScaleToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
97 : mPadding( padding ),
103 * CopyConstructor. Used by Boost.
104 * @param rhs Copying from.
106 ScaleToFitKeepAspectConstraint( const ScaleToFitKeepAspectConstraint& rhs )
107 : mPadding( rhs.mPadding ),
108 mSizeStored( rhs.mSizeStored ),
109 mOriginalSize( rhs.mOriginalSize )
113 * Called by render thread
115 Vector3 operator()( const Vector3& currentSize,
116 const PropertyInput& parentSizeProperty )
118 const Vector3& parentSize( parentSizeProperty.GetVector3() );
119 return GetSize( currentSize, parentSize );
122 inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
124 if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
126 mOriginalSize = currentSize;
130 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
131 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
133 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
134 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
135 ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
137 // no point trying to squeeze actors into this small size
138 return Vector3::ZERO;
141 return mOriginalSize * std::min( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
144 const Toolkit::Alignment::Padding mPadding;
146 Vector3 mOriginalSize;
149 struct ScaleToFillKeepAspectConstraint
152 * @param padding to be added.
154 ScaleToFillKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
155 : mPadding( padding ),
156 mSizeStored( false ),
161 * CopyConstructor. Used by Boost.
162 * @param rhs Copying from.
164 ScaleToFillKeepAspectConstraint( const ScaleToFillKeepAspectConstraint& rhs )
165 : mPadding( rhs.mPadding ),
166 mSizeStored( rhs.mSizeStored ),
167 mOriginalSize( rhs.mOriginalSize )
171 * Called by render thread
173 Vector3 operator()( const Vector3& currentSize,
174 const PropertyInput& parentSizeProperty )
176 const Vector3& parentSize( parentSizeProperty.GetVector3() );
177 return GetSize( currentSize, parentSize );
180 Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
182 if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
184 mOriginalSize = currentSize;
188 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
189 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
191 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
192 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
193 ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
195 // no point trying to squeeze actors into this small size
196 return Vector3::ZERO;
199 return mOriginalSize * std::max( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
202 const Toolkit::Alignment::Padding mPadding;
204 Vector3 mOriginalSize;
207 struct ShrinkToFitConstraint
210 * @param padding to be added.
212 ShrinkToFitConstraint( const Toolkit::Alignment::Padding& padding )
213 : mPadding( padding ),
214 mSizeStored( false ),
219 * CopyConstructor. Used by Boost.
220 * @param rhs Copying from.
222 ShrinkToFitConstraint( const ShrinkToFitConstraint& rhs )
223 : mPadding( rhs.mPadding ),
224 mSizeStored( rhs.mSizeStored ),
225 mOriginalSize( rhs.mOriginalSize )
229 * Called by render thread
231 Vector3 operator()( const Vector3& currentSize,
232 const PropertyInput& parentSizeProperty )
234 const Vector3& parentSize( parentSizeProperty.GetVector3() );
235 return GetSize( currentSize, parentSize );
238 Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
240 if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
242 mOriginalSize = currentSize;
246 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
247 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
249 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
250 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
251 ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
253 // no point trying to squeeze actors into this small size
254 return Vector3::ZERO;
257 return Vector3( std::min( parentSizeWidth, mOriginalSize.width ), std::min( parentSizeHeight, mOriginalSize.height ), std::min( parentSize.depth, mOriginalSize.depth ) );
260 const Toolkit::Alignment::Padding mPadding;
262 Vector3 mOriginalSize;
266 * Constraint that uses naturalSize if it fits inside parent and parent size if not. It also adds some padding pixels
268 struct ShrinkToFitKeepAspectConstraint
271 * @param padding to be added.
273 ShrinkToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
274 : mPadding( padding ),
275 mSizeStored( false ),
280 * CopyConstructor. Used by Boost.
281 * @param rhs Copying from.
283 ShrinkToFitKeepAspectConstraint( const ShrinkToFitKeepAspectConstraint& rhs )
284 : mPadding( rhs.mPadding ),
285 mSizeStored( rhs.mSizeStored ),
286 mOriginalSize( rhs.mOriginalSize )
290 * Called by render thread
292 Vector3 operator()( const Vector3& currentSize,
293 const PropertyInput& parentSizeProperty )
295 const Vector3& parentSize( parentSizeProperty.GetVector3() );
296 return GetSize( currentSize, parentSize );
299 inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
301 if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
303 mOriginalSize = currentSize;
307 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
308 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
310 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
311 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
312 ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
314 // no point trying to squeeze actors into this small size
315 return Vector3::ZERO;
318 return Vector3( ShrinkInside( Vector2( parentSizeWidth, parentSizeHeight ), Vector2( mOriginalSize ) ) );
321 const Toolkit::Alignment::Padding mPadding;
323 Vector3 mOriginalSize;
327 * Constraint that modifies the contained actor taking into account the padding value.
329 struct PositionConstraint
332 * @param padding The padding value
333 * @param horizontalAlignment The horizontal alignment.
334 * @param verticalAlignment The vertical alignment.
336 PositionConstraint( const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment )
337 : mPadding( padding ),
338 mHorizontalAlignment( horizontalAlignment ),
339 mVerticalAlignment( verticalAlignment )
343 * CopyConstructor. Used by Boost.
344 * @param rhs Copying from.
346 PositionConstraint( const PositionConstraint& rhs )
347 : mPadding( rhs.mPadding ),
348 mHorizontalAlignment( rhs.mHorizontalAlignment ),
349 mVerticalAlignment( rhs.mVerticalAlignment )
353 * Called by render thread.
355 Vector3 operator()( const Vector3& currentPosition,
356 const PropertyInput& currentSizeProperty,
357 const PropertyInput& parentSizeProperty )
359 const Vector3& currentSize( currentSizeProperty.GetVector3() );
360 const Vector3& parentSize( parentSizeProperty.GetVector3() );
362 Vector3 position( 0.f, 0.f, 0.f );
364 switch( mHorizontalAlignment )
366 case Dali::Toolkit::Alignment::HorizontalLeft:
368 position.x += mPadding.left;
371 case Dali::Toolkit::Alignment::HorizontalCenter:
373 if( currentSize.width + mPadding.left + mPadding.right >= parentSize.width )
375 position.x += 0.5f * ( mPadding.left - mPadding.right );
379 case Dali::Toolkit::Alignment::HorizontalRight:
381 position.x -= mPadding.right;
386 DALI_ASSERT_ALWAYS( !"Wrong horizontal alignment value" );
391 switch( mVerticalAlignment )
393 case Dali::Toolkit::Alignment::VerticalTop:
395 position.y += mPadding.top;
398 case Dali::Toolkit::Alignment::VerticalCenter:
400 if( currentSize.height + mPadding.top + mPadding.bottom >= parentSize.height )
402 position.y += 0.5f * ( mPadding.top - mPadding.bottom );
406 case Dali::Toolkit::Alignment::VerticalBottom:
408 position.y -= mPadding.bottom;
413 DALI_ASSERT_ALWAYS( !"Wrong vertical alignment value" );
421 const Toolkit::Alignment::Padding mPadding;
422 const Toolkit::Alignment::Type mHorizontalAlignment;
423 const Toolkit::Alignment::Type mVerticalAlignment;
426 void SetPositionConstraint( Actor actor, const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
428 Constraint constraint = Constraint::New<Vector3>( Actor::POSITION,
429 LocalSource( Actor::SIZE ),
430 ParentSource( Actor::SIZE ),
431 PositionConstraint( padding, horizontal, vertical ) );
432 actor.ApplyConstraint( constraint );
436 Toolkit::Alignment Alignment::New( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
438 // Create the implementation, temporarily owned on stack
439 IntrusivePtr< Alignment > internalAlignment = new Alignment( horizontal, vertical );
441 // Pass ownership to Toolkit::View
442 Toolkit::Alignment alignment( *internalAlignment );
444 // Second-phase init of the implementation
445 // This can only be done after the CustomActor connection has been made...
446 internalAlignment->Initialize();
451 void Alignment::SetAlignmentType( Toolkit::Alignment::Type type )
453 // Horizontal Alignment
454 bool horizontalSet(false);
456 if( type & Toolkit::Alignment::HorizontalLeft )
458 mHorizontal = Toolkit::Alignment::HorizontalLeft;
459 horizontalSet = true;
461 if( type & Toolkit::Alignment::HorizontalCenter )
463 DALI_ASSERT_ALWAYS(!horizontalSet);
464 mHorizontal = Toolkit::Alignment::HorizontalCenter;
465 horizontalSet = true;
467 if( type & Toolkit::Alignment::HorizontalRight )
469 DALI_ASSERT_ALWAYS(!horizontalSet);
470 mHorizontal = Toolkit::Alignment::HorizontalRight;
473 // Vertical Alignment
474 bool verticalSet(false);
476 if( type & Toolkit::Alignment::VerticalTop )
478 mVertical = Toolkit::Alignment::VerticalTop;
481 if( type & Toolkit::Alignment::VerticalCenter )
483 DALI_ASSERT_ALWAYS(!verticalSet);
484 mVertical = Toolkit::Alignment::VerticalCenter;
487 if( type & Toolkit::Alignment::VerticalBottom )
489 DALI_ASSERT_ALWAYS(!verticalSet);
490 mVertical = Toolkit::Alignment::VerticalBottom;
496 Toolkit::Alignment::Type Alignment::GetAlignmentType() const
498 return Toolkit::Alignment::Type( mHorizontal | mVertical );
501 void Alignment::SetScaling( Toolkit::Alignment::Scaling scaling )
508 Toolkit::Alignment::Scaling Alignment::GetScaling() const
513 void Alignment::SetPadding( const Toolkit::Alignment::Padding& padding )
515 DALI_ASSERT_ALWAYS( ( padding.left >= 0.f ) && ( padding.top >= 0.f ) && ( padding.right >= 0.f ) && ( padding.bottom >= 0.f ) );
522 const Toolkit::Alignment::Padding& Alignment::GetPadding() const
527 void Alignment::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
529 // lay out the actors
530 Vector3 anchorPointAndParentOrigin = Vector3::ZERO;
531 anchorPointAndParentOrigin.z = 0.5f;
532 // anchorPoint.x is initialized to 0.0, which is HorizontalLeft
533 if( Toolkit::Alignment::HorizontalCenter == mHorizontal )
535 anchorPointAndParentOrigin.x = 0.5f;
537 else if( Toolkit::Alignment::HorizontalRight == mHorizontal )
539 anchorPointAndParentOrigin.x = 1.0f;
541 // anchorPoint.y is initialized to 0.0, which is VerticalTop
542 if( Toolkit::Alignment::VerticalCenter == mVertical )
544 anchorPointAndParentOrigin.y = 0.5f;
546 else if( Toolkit::Alignment::VerticalBottom == mVertical )
548 anchorPointAndParentOrigin.y = 1.0f;
551 unsigned int childCount = Self().GetChildCount();
552 for( unsigned int i=0; i<childCount; ++i )
554 Actor actor = Self().GetChildAt(i);
556 actor.SetAnchorPoint( anchorPointAndParentOrigin );
557 actor.SetParentOrigin( anchorPointAndParentOrigin );
559 if( Toolkit::Alignment::ScaleNone != mScaling )
561 actor.RemoveConstraints();
564 Vector3 actorSize ( actor.GetCurrentSize() );
565 Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
566 if ( actorSize == Vector3::ZERO && control )
568 actorSize = control.GetNaturalSize();
575 case Toolkit::Alignment::ScaleNone:
577 // Nothing to do but needed just to not to jump to the default.
581 case Toolkit::Alignment::ScaleToFill:
583 ScaleToFillConstraint constraint( mPadding );
584 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
585 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
588 case Toolkit::Alignment::ScaleToFitKeepAspect:
590 ScaleToFitKeepAspectConstraint constraint( mPadding );
591 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
592 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
595 case Toolkit::Alignment::ScaleToFillKeepAspect:
597 ScaleToFillKeepAspectConstraint constraint( mPadding );
598 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
599 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
602 case Toolkit::Alignment::ShrinkToFit:
604 ShrinkToFitConstraint constraint( mPadding );
605 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
606 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
609 case Toolkit::Alignment::ShrinkToFitKeepAspect:
611 ShrinkToFitKeepAspectConstraint constraint( mPadding );
612 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
613 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
618 DALI_ASSERT_ALWAYS( !"Invalid Alignment::mGeometryScaling value" );
623 Relayout( actor, childSize, container );
627 Alignment::Alignment( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
628 : Control( CONTROL_BEHAVIOUR_NONE ),
629 mHorizontal( horizontal ),
630 mVertical( vertical ),
631 mScaling( Toolkit::Alignment::ScaleNone ),
632 mPadding( 0.f, 0.f, 0.f, 0.f )
636 Alignment::~Alignment()
640 } // namespace Internal
642 } // namespace Toolkit