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"
41 return Toolkit::Alignment::New();
44 TypeRegistration mType( typeid(Toolkit::Alignment), typeid(Toolkit::Control), Create );
46 struct ScaleToFillConstraint
49 * @param padding to be added.
51 ScaleToFillConstraint( const Toolkit::Alignment::Padding& padding )
56 * CopyConstructor. Used by Boost.
57 * @param rhs Copying from.
59 ScaleToFillConstraint( const ScaleToFillConstraint& rhs )
60 : mPadding( rhs.mPadding )
64 * Called by render thread
66 Vector3 operator()( const Vector3& currentSize,
67 const PropertyInput& parentSizeProperty )
69 const Vector3& parentSize( parentSizeProperty.GetVector3() );
70 return GetSize( currentSize, parentSize );
73 inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
75 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
76 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
78 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
79 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 ) )
81 // no point trying to squeeze actors into this small size
84 return Vector3( parentSizeWidth, parentSizeHeight, parentSize.depth );
87 const Toolkit::Alignment::Padding mPadding;
90 struct ScaleToFitKeepAspectConstraint
93 * @param padding to be added.
95 ScaleToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
96 : mPadding( padding ),
102 * CopyConstructor. Used by Boost.
103 * @param rhs Copying from.
105 ScaleToFitKeepAspectConstraint( const ScaleToFitKeepAspectConstraint& rhs )
106 : mPadding( rhs.mPadding ),
107 mSizeStored( rhs.mSizeStored ),
108 mOriginalSize( rhs.mOriginalSize )
112 * Called by render thread
114 Vector3 operator()( const Vector3& currentSize,
115 const PropertyInput& parentSizeProperty )
117 const Vector3& parentSize( parentSizeProperty.GetVector3() );
118 return GetSize( currentSize, parentSize );
121 inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
123 if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
125 mOriginalSize = currentSize;
129 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
130 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
132 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
133 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
134 ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
136 // no point trying to squeeze actors into this small size
137 return Vector3::ZERO;
140 return mOriginalSize * std::min( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
143 const Toolkit::Alignment::Padding mPadding;
145 Vector3 mOriginalSize;
148 struct ScaleToFillKeepAspectConstraint
151 * @param padding to be added.
153 ScaleToFillKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
154 : mPadding( padding ),
155 mSizeStored( false ),
160 * CopyConstructor. Used by Boost.
161 * @param rhs Copying from.
163 ScaleToFillKeepAspectConstraint( const ScaleToFillKeepAspectConstraint& rhs )
164 : mPadding( rhs.mPadding ),
165 mSizeStored( rhs.mSizeStored ),
166 mOriginalSize( rhs.mOriginalSize )
170 * Called by render thread
172 Vector3 operator()( const Vector3& currentSize,
173 const PropertyInput& parentSizeProperty )
175 const Vector3& parentSize( parentSizeProperty.GetVector3() );
176 return GetSize( currentSize, parentSize );
179 Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
181 if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
183 mOriginalSize = currentSize;
187 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
188 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
190 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
191 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
192 ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
194 // no point trying to squeeze actors into this small size
195 return Vector3::ZERO;
198 return mOriginalSize * std::max( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
201 const Toolkit::Alignment::Padding mPadding;
203 Vector3 mOriginalSize;
206 struct ShrinkToFitConstraint
209 * @param padding to be added.
211 ShrinkToFitConstraint( const Toolkit::Alignment::Padding& padding )
212 : mPadding( padding ),
213 mSizeStored( false ),
218 * CopyConstructor. Used by Boost.
219 * @param rhs Copying from.
221 ShrinkToFitConstraint( const ShrinkToFitConstraint& rhs )
222 : mPadding( rhs.mPadding ),
223 mSizeStored( rhs.mSizeStored ),
224 mOriginalSize( rhs.mOriginalSize )
228 * Called by render thread
230 Vector3 operator()( const Vector3& currentSize,
231 const PropertyInput& parentSizeProperty )
233 const Vector3& parentSize( parentSizeProperty.GetVector3() );
234 return GetSize( currentSize, parentSize );
237 Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
239 if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
241 mOriginalSize = currentSize;
245 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
246 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
248 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
249 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
250 ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
252 // no point trying to squeeze actors into this small size
253 return Vector3::ZERO;
256 return Vector3( std::min( parentSizeWidth, mOriginalSize.width ), std::min( parentSizeHeight, mOriginalSize.height ), std::min( parentSize.depth, mOriginalSize.depth ) );
259 const Toolkit::Alignment::Padding mPadding;
261 Vector3 mOriginalSize;
265 * Constraint that uses naturalSize if it fits inside parent and parent size if not. It also adds some padding pixels
267 struct ShrinkToFitKeepAspectConstraint
270 * @param padding to be added.
272 ShrinkToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
273 : mPadding( padding ),
274 mSizeStored( false ),
279 * CopyConstructor. Used by Boost.
280 * @param rhs Copying from.
282 ShrinkToFitKeepAspectConstraint( const ShrinkToFitKeepAspectConstraint& rhs )
283 : mPadding( rhs.mPadding ),
284 mSizeStored( rhs.mSizeStored ),
285 mOriginalSize( rhs.mOriginalSize )
289 * Called by render thread
291 Vector3 operator()( const Vector3& currentSize,
292 const PropertyInput& parentSizeProperty )
294 const Vector3& parentSize( parentSizeProperty.GetVector3() );
295 return GetSize( currentSize, parentSize );
298 inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
300 if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
302 mOriginalSize = currentSize;
306 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
307 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
309 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
310 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
311 ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
313 // no point trying to squeeze actors into this small size
314 return Vector3::ZERO;
317 return Vector3( ShrinkInside( Vector2( parentSizeWidth, parentSizeHeight ), Vector2( mOriginalSize ) ) );
320 const Toolkit::Alignment::Padding mPadding;
322 Vector3 mOriginalSize;
326 * Constraint that modifies the contained actor taking into account the padding value.
328 struct PositionConstraint
331 * @param padding The padding value
332 * @param horizontalAlignment The horizontal alignment.
333 * @param verticalAlignment The vertical alignment.
335 PositionConstraint( const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment )
336 : mPadding( padding ),
337 mHorizontalAlignment( horizontalAlignment ),
338 mVerticalAlignment( verticalAlignment )
342 * CopyConstructor. Used by Boost.
343 * @param rhs Copying from.
345 PositionConstraint( const PositionConstraint& rhs )
346 : mPadding( rhs.mPadding ),
347 mHorizontalAlignment( rhs.mHorizontalAlignment ),
348 mVerticalAlignment( rhs.mVerticalAlignment )
352 * Called by render thread.
354 Vector3 operator()( const Vector3& currentPosition,
355 const PropertyInput& currentSizeProperty,
356 const PropertyInput& parentSizeProperty )
358 const Vector3& currentSize( currentSizeProperty.GetVector3() );
359 const Vector3& parentSize( parentSizeProperty.GetVector3() );
361 Vector3 position( 0.f, 0.f, 0.f );
363 switch( mHorizontalAlignment )
365 case Dali::Toolkit::Alignment::HorizontalLeft:
367 position.x += mPadding.left;
370 case Dali::Toolkit::Alignment::HorizontalCenter:
372 if( currentSize.width + mPadding.left + mPadding.right >= parentSize.width )
374 position.x += 0.5f * ( mPadding.left - mPadding.right );
378 case Dali::Toolkit::Alignment::HorizontalRight:
380 position.x -= mPadding.right;
385 DALI_ASSERT_ALWAYS( !"Wrong horizontal alignment value" );
390 switch( mVerticalAlignment )
392 case Dali::Toolkit::Alignment::VerticalTop:
394 position.y += mPadding.top;
397 case Dali::Toolkit::Alignment::VerticalCenter:
399 if( currentSize.height + mPadding.top + mPadding.bottom >= parentSize.height )
401 position.y += 0.5f * ( mPadding.top - mPadding.bottom );
405 case Dali::Toolkit::Alignment::VerticalBottom:
407 position.y -= mPadding.bottom;
412 DALI_ASSERT_ALWAYS( !"Wrong vertical alignment value" );
420 const Toolkit::Alignment::Padding mPadding;
421 const Toolkit::Alignment::Type mHorizontalAlignment;
422 const Toolkit::Alignment::Type mVerticalAlignment;
425 void SetPositionConstraint( Actor actor, const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
427 Constraint constraint = Constraint::New<Vector3>( Actor::POSITION,
428 LocalSource( Actor::SIZE ),
429 ParentSource( Actor::SIZE ),
430 PositionConstraint( padding, horizontal, vertical ) );
431 actor.ApplyConstraint( constraint );
435 Toolkit::Alignment Alignment::New( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
437 // Create the implementation, temporarily owned on stack
438 IntrusivePtr< Alignment > internalAlignment = new Alignment( horizontal, vertical );
440 // Pass ownership to Toolkit::View
441 Toolkit::Alignment alignment( *internalAlignment );
443 // Second-phase init of the implementation
444 // This can only be done after the CustomActor connection has been made...
445 internalAlignment->Initialize();
450 void Alignment::SetAlignmentType( Toolkit::Alignment::Type type )
452 // Horizontal Alignment
453 bool horizontalSet(false);
455 if( type & Toolkit::Alignment::HorizontalLeft )
457 mHorizontal = Toolkit::Alignment::HorizontalLeft;
458 horizontalSet = true;
460 if( type & Toolkit::Alignment::HorizontalCenter )
462 DALI_ASSERT_ALWAYS(!horizontalSet);
463 mHorizontal = Toolkit::Alignment::HorizontalCenter;
464 horizontalSet = true;
466 if( type & Toolkit::Alignment::HorizontalRight )
468 DALI_ASSERT_ALWAYS(!horizontalSet);
469 mHorizontal = Toolkit::Alignment::HorizontalRight;
472 // Vertical Alignment
473 bool verticalSet(false);
475 if( type & Toolkit::Alignment::VerticalTop )
477 mVertical = Toolkit::Alignment::VerticalTop;
480 if( type & Toolkit::Alignment::VerticalCenter )
482 DALI_ASSERT_ALWAYS(!verticalSet);
483 mVertical = Toolkit::Alignment::VerticalCenter;
486 if( type & Toolkit::Alignment::VerticalBottom )
488 DALI_ASSERT_ALWAYS(!verticalSet);
489 mVertical = Toolkit::Alignment::VerticalBottom;
495 Toolkit::Alignment::Type Alignment::GetAlignmentType() const
497 return Toolkit::Alignment::Type( mHorizontal | mVertical );
500 void Alignment::SetScaling( Toolkit::Alignment::Scaling scaling )
507 Toolkit::Alignment::Scaling Alignment::GetScaling() const
512 void Alignment::SetPadding( const Toolkit::Alignment::Padding& padding )
514 DALI_ASSERT_ALWAYS( ( padding.left >= 0.f ) && ( padding.top >= 0.f ) && ( padding.right >= 0.f ) && ( padding.bottom >= 0.f ) );
521 const Toolkit::Alignment::Padding& Alignment::GetPadding() const
526 void Alignment::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
528 // lay out the actors
529 Vector3 anchorPointAndParentOrigin = Vector3::ZERO;
530 anchorPointAndParentOrigin.z = 0.5f;
531 // anchorPoint.x is initialized to 0.0, which is HorizontalLeft
532 if( Toolkit::Alignment::HorizontalCenter == mHorizontal )
534 anchorPointAndParentOrigin.x = 0.5f;
536 else if( Toolkit::Alignment::HorizontalRight == mHorizontal )
538 anchorPointAndParentOrigin.x = 1.0f;
540 // anchorPoint.y is initialized to 0.0, which is VerticalTop
541 if( Toolkit::Alignment::VerticalCenter == mVertical )
543 anchorPointAndParentOrigin.y = 0.5f;
545 else if( Toolkit::Alignment::VerticalBottom == mVertical )
547 anchorPointAndParentOrigin.y = 1.0f;
550 unsigned int childCount = Self().GetChildCount();
551 for( unsigned int i=0; i<childCount; ++i )
553 Actor actor = Self().GetChildAt(i);
555 actor.SetAnchorPoint( anchorPointAndParentOrigin );
556 actor.SetParentOrigin( anchorPointAndParentOrigin );
558 if( Toolkit::Alignment::ScaleNone != mScaling )
560 actor.RemoveConstraints();
563 Vector3 actorSize ( actor.GetCurrentSize() );
564 Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
565 if ( actorSize == Vector3::ZERO && control )
567 actorSize = control.GetNaturalSize();
574 case Toolkit::Alignment::ScaleNone:
576 // Nothing to do but needed just to not to jump to the default.
580 case Toolkit::Alignment::ScaleToFill:
582 ScaleToFillConstraint constraint( mPadding );
583 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
584 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
587 case Toolkit::Alignment::ScaleToFitKeepAspect:
589 ScaleToFitKeepAspectConstraint constraint( mPadding );
590 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
591 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
594 case Toolkit::Alignment::ScaleToFillKeepAspect:
596 ScaleToFillKeepAspectConstraint constraint( mPadding );
597 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
598 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
601 case Toolkit::Alignment::ShrinkToFit:
603 ShrinkToFitConstraint constraint( mPadding );
604 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
605 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
608 case Toolkit::Alignment::ShrinkToFitKeepAspect:
610 ShrinkToFitKeepAspectConstraint constraint( mPadding );
611 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
612 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
617 DALI_ASSERT_ALWAYS( !"Invalid Alignment::mGeometryScaling value" );
622 Relayout( actor, childSize, container );
626 Alignment::Alignment( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
627 : Control( CONTROL_BEHAVIOUR_NONE ),
628 mHorizontal( horizontal ),
629 mVertical( vertical ),
630 mScaling( Toolkit::Alignment::ScaleNone ),
631 mPadding( 0.f, 0.f, 0.f, 0.f )
635 Alignment::~Alignment()
639 } // namespace Internal
641 } // namespace Toolkit