2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 "alignment-impl.h"
40 return Toolkit::Alignment::New();
43 TypeRegistration mType( typeid(Toolkit::Alignment), typeid(Toolkit::Control), Create );
45 struct ScaleToFillConstraint
48 * @param padding to be added.
50 ScaleToFillConstraint( const Toolkit::Alignment::Padding& padding )
55 * CopyConstructor. Used by Boost.
56 * @param rhs Copying from.
58 ScaleToFillConstraint( const ScaleToFillConstraint& rhs )
59 : mPadding( rhs.mPadding )
63 * Called by render thread
65 Vector3 operator()( const Vector3& currentSize,
66 const PropertyInput& parentSizeProperty )
68 const Vector3& parentSize( parentSizeProperty.GetVector3() );
69 return GetSize( currentSize, parentSize );
72 inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
74 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
75 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
77 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
78 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 ) )
80 // no point trying to squeeze actors into this small size
83 return Vector3( parentSizeWidth, parentSizeHeight, parentSize.depth );
86 const Toolkit::Alignment::Padding mPadding;
89 struct ScaleToFitKeepAspectConstraint
92 * @param padding to be added.
94 ScaleToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
95 : mPadding( padding ),
101 * CopyConstructor. Used by Boost.
102 * @param rhs Copying from.
104 ScaleToFitKeepAspectConstraint( const ScaleToFitKeepAspectConstraint& rhs )
105 : mPadding( rhs.mPadding ),
106 mSizeStored( rhs.mSizeStored ),
107 mOriginalSize( rhs.mOriginalSize )
111 * Called by render thread
113 Vector3 operator()( const Vector3& currentSize,
114 const PropertyInput& parentSizeProperty )
116 const Vector3& parentSize( parentSizeProperty.GetVector3() );
117 return GetSize( currentSize, parentSize );
120 inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
122 if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
124 mOriginalSize = currentSize;
128 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
129 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
131 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
132 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
133 ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
135 // no point trying to squeeze actors into this small size
136 return Vector3::ZERO;
139 return mOriginalSize * std::min( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
142 const Toolkit::Alignment::Padding mPadding;
144 Vector3 mOriginalSize;
147 struct ScaleToFillKeepAspectConstraint
150 * @param padding to be added.
152 ScaleToFillKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
153 : mPadding( padding ),
154 mSizeStored( false ),
159 * CopyConstructor. Used by Boost.
160 * @param rhs Copying from.
162 ScaleToFillKeepAspectConstraint( const ScaleToFillKeepAspectConstraint& rhs )
163 : mPadding( rhs.mPadding ),
164 mSizeStored( rhs.mSizeStored ),
165 mOriginalSize( rhs.mOriginalSize )
169 * Called by render thread
171 Vector3 operator()( const Vector3& currentSize,
172 const PropertyInput& parentSizeProperty )
174 const Vector3& parentSize( parentSizeProperty.GetVector3() );
175 return GetSize( currentSize, parentSize );
178 Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
180 if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
182 mOriginalSize = currentSize;
186 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
187 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
189 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
190 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
191 ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
193 // no point trying to squeeze actors into this small size
194 return Vector3::ZERO;
197 return mOriginalSize * std::max( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
200 const Toolkit::Alignment::Padding mPadding;
202 Vector3 mOriginalSize;
205 struct ShrinkToFitConstraint
208 * @param padding to be added.
210 ShrinkToFitConstraint( const Toolkit::Alignment::Padding& padding )
211 : mPadding( padding ),
212 mSizeStored( false ),
217 * CopyConstructor. Used by Boost.
218 * @param rhs Copying from.
220 ShrinkToFitConstraint( const ShrinkToFitConstraint& rhs )
221 : mPadding( rhs.mPadding ),
222 mSizeStored( rhs.mSizeStored ),
223 mOriginalSize( rhs.mOriginalSize )
227 * Called by render thread
229 Vector3 operator()( const Vector3& currentSize,
230 const PropertyInput& parentSizeProperty )
232 const Vector3& parentSize( parentSizeProperty.GetVector3() );
233 return GetSize( currentSize, parentSize );
236 Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
238 if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
240 mOriginalSize = currentSize;
244 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
245 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
247 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
248 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
249 ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
251 // no point trying to squeeze actors into this small size
252 return Vector3::ZERO;
255 return Vector3( std::min( parentSizeWidth, mOriginalSize.width ), std::min( parentSizeHeight, mOriginalSize.height ), std::min( parentSize.depth, mOriginalSize.depth ) );
258 const Toolkit::Alignment::Padding mPadding;
260 Vector3 mOriginalSize;
264 * Constraint that uses naturalSize if it fits inside parent and parent size if not. It also adds some padding pixels
266 struct ShrinkToFitKeepAspectConstraint
269 * @param padding to be added.
271 ShrinkToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
272 : mPadding( padding ),
273 mSizeStored( false ),
278 * CopyConstructor. Used by Boost.
279 * @param rhs Copying from.
281 ShrinkToFitKeepAspectConstraint( const ShrinkToFitKeepAspectConstraint& rhs )
282 : mPadding( rhs.mPadding ),
283 mSizeStored( rhs.mSizeStored ),
284 mOriginalSize( rhs.mOriginalSize )
288 * Called by render thread
290 Vector3 operator()( const Vector3& currentSize,
291 const PropertyInput& parentSizeProperty )
293 const Vector3& parentSize( parentSizeProperty.GetVector3() );
294 return GetSize( currentSize, parentSize );
297 inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
299 if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
301 mOriginalSize = currentSize;
305 const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
306 const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
308 // prevent ridiculous sizes if parent is really small or if we don't have a proper size for the actor
309 if( ( parentSizeWidth < Math::MACHINE_EPSILON_1000 ) || ( parentSizeHeight < Math::MACHINE_EPSILON_1000 )||
310 ( mOriginalSize.width < Math::MACHINE_EPSILON_1000 ) || ( mOriginalSize.height < Math::MACHINE_EPSILON_1000 ) )
312 // no point trying to squeeze actors into this small size
313 return Vector3::ZERO;
316 return Vector3( ShrinkInside( Vector2( parentSizeWidth, parentSizeHeight ), Vector2( mOriginalSize ) ) );
319 const Toolkit::Alignment::Padding mPadding;
321 Vector3 mOriginalSize;
325 * Constraint that modifies the contained actor taking into account the padding value.
327 struct PositionConstraint
330 * @param padding The padding value
331 * @param horizontalAlignment The horizontal alignment.
332 * @param verticalAlignment The vertical alignment.
334 PositionConstraint( const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment )
335 : mPadding( padding ),
336 mHorizontalAlignment( horizontalAlignment ),
337 mVerticalAlignment( verticalAlignment )
341 * CopyConstructor. Used by Boost.
342 * @param rhs Copying from.
344 PositionConstraint( const PositionConstraint& rhs )
345 : mPadding( rhs.mPadding ),
346 mHorizontalAlignment( rhs.mHorizontalAlignment ),
347 mVerticalAlignment( rhs.mVerticalAlignment )
351 * Called by render thread.
353 Vector3 operator()( const Vector3& currentPosition,
354 const PropertyInput& currentSizeProperty,
355 const PropertyInput& parentSizeProperty )
357 const Vector3& currentSize( currentSizeProperty.GetVector3() );
358 const Vector3& parentSize( parentSizeProperty.GetVector3() );
360 Vector3 position( 0.f, 0.f, 0.f );
362 switch( mHorizontalAlignment )
364 case Dali::Toolkit::Alignment::HorizontalLeft:
366 position.x += mPadding.left;
369 case Dali::Toolkit::Alignment::HorizontalCenter:
371 if( currentSize.width + mPadding.left + mPadding.right >= parentSize.width )
373 position.x += 0.5f * ( mPadding.left - mPadding.right );
377 case Dali::Toolkit::Alignment::HorizontalRight:
379 position.x -= mPadding.right;
384 DALI_ASSERT_ALWAYS( !"Wrong horizontal alignment value" );
389 switch( mVerticalAlignment )
391 case Dali::Toolkit::Alignment::VerticalTop:
393 position.y += mPadding.top;
396 case Dali::Toolkit::Alignment::VerticalCenter:
398 if( currentSize.height + mPadding.top + mPadding.bottom >= parentSize.height )
400 position.y += 0.5f * ( mPadding.top - mPadding.bottom );
404 case Dali::Toolkit::Alignment::VerticalBottom:
406 position.y -= mPadding.bottom;
411 DALI_ASSERT_ALWAYS( !"Wrong vertical alignment value" );
419 const Toolkit::Alignment::Padding mPadding;
420 const Toolkit::Alignment::Type mHorizontalAlignment;
421 const Toolkit::Alignment::Type mVerticalAlignment;
424 void SetPositionConstraint( Actor actor, const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
426 Constraint constraint = Constraint::New<Vector3>( Actor::POSITION,
427 LocalSource( Actor::SIZE ),
428 ParentSource( Actor::SIZE ),
429 PositionConstraint( padding, horizontal, vertical ) );
430 actor.ApplyConstraint( constraint );
434 Toolkit::Alignment Alignment::New( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
436 // Create the implementation, temporarily owned on stack
437 IntrusivePtr< Alignment > internalAlignment = new Alignment( horizontal, vertical );
439 // Pass ownership to Toolkit::View
440 Toolkit::Alignment alignment( *internalAlignment );
442 // Second-phase init of the implementation
443 // This can only be done after the CustomActor connection has been made...
444 internalAlignment->Initialize();
449 void Alignment::SetAlignmentType( Toolkit::Alignment::Type type )
451 // Horizontal Alignment
452 bool horizontalSet(false);
454 if( type & Toolkit::Alignment::HorizontalLeft )
456 mHorizontal = Toolkit::Alignment::HorizontalLeft;
457 horizontalSet = true;
459 if( type & Toolkit::Alignment::HorizontalCenter )
461 DALI_ASSERT_ALWAYS(!horizontalSet);
462 mHorizontal = Toolkit::Alignment::HorizontalCenter;
463 horizontalSet = true;
465 if( type & Toolkit::Alignment::HorizontalRight )
467 DALI_ASSERT_ALWAYS(!horizontalSet);
468 mHorizontal = Toolkit::Alignment::HorizontalRight;
471 // Vertical Alignment
472 bool verticalSet(false);
474 if( type & Toolkit::Alignment::VerticalTop )
476 mVertical = Toolkit::Alignment::VerticalTop;
479 if( type & Toolkit::Alignment::VerticalCenter )
481 DALI_ASSERT_ALWAYS(!verticalSet);
482 mVertical = Toolkit::Alignment::VerticalCenter;
485 if( type & Toolkit::Alignment::VerticalBottom )
487 DALI_ASSERT_ALWAYS(!verticalSet);
488 mVertical = Toolkit::Alignment::VerticalBottom;
494 Toolkit::Alignment::Type Alignment::GetAlignmentType() const
496 return Toolkit::Alignment::Type( mHorizontal | mVertical );
499 void Alignment::SetScaling( Toolkit::Alignment::Scaling scaling )
506 Toolkit::Alignment::Scaling Alignment::GetScaling() const
511 void Alignment::SetPadding( const Toolkit::Alignment::Padding& padding )
513 DALI_ASSERT_ALWAYS( ( padding.left >= 0.f ) && ( padding.top >= 0.f ) && ( padding.right >= 0.f ) && ( padding.bottom >= 0.f ) );
520 const Toolkit::Alignment::Padding& Alignment::GetPadding() const
525 void Alignment::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
527 // lay out the actors
528 Vector3 anchorPointAndParentOrigin = Vector3::ZERO;
529 anchorPointAndParentOrigin.z = 0.5f;
530 // anchorPoint.x is initialized to 0.0, which is HorizontalLeft
531 if( Toolkit::Alignment::HorizontalCenter == mHorizontal )
533 anchorPointAndParentOrigin.x = 0.5f;
535 else if( Toolkit::Alignment::HorizontalRight == mHorizontal )
537 anchorPointAndParentOrigin.x = 1.0f;
539 // anchorPoint.y is initialized to 0.0, which is VerticalTop
540 if( Toolkit::Alignment::VerticalCenter == mVertical )
542 anchorPointAndParentOrigin.y = 0.5f;
544 else if( Toolkit::Alignment::VerticalBottom == mVertical )
546 anchorPointAndParentOrigin.y = 1.0f;
549 unsigned int childCount = Self().GetChildCount();
550 for( unsigned int i=0; i<childCount; ++i )
552 Actor actor = Self().GetChildAt(i);
554 actor.SetAnchorPoint( anchorPointAndParentOrigin );
555 actor.SetParentOrigin( anchorPointAndParentOrigin );
557 if( Toolkit::Alignment::ScaleNone != mScaling )
559 actor.RemoveConstraints();
562 Vector3 actorSize ( actor.GetCurrentSize() );
563 Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
564 if ( actorSize == Vector3::ZERO && control )
566 actorSize = control.GetNaturalSize();
573 case Toolkit::Alignment::ScaleNone:
575 // Nothing to do but needed just to not to jump to the default.
579 case Toolkit::Alignment::ScaleToFill:
581 ScaleToFillConstraint constraint( mPadding );
582 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
583 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
586 case Toolkit::Alignment::ScaleToFitKeepAspect:
588 ScaleToFitKeepAspectConstraint constraint( mPadding );
589 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
590 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
593 case Toolkit::Alignment::ScaleToFillKeepAspect:
595 ScaleToFillKeepAspectConstraint constraint( mPadding );
596 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
597 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
600 case Toolkit::Alignment::ShrinkToFit:
602 ShrinkToFitConstraint constraint( mPadding );
603 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
604 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
607 case Toolkit::Alignment::ShrinkToFitKeepAspect:
609 ShrinkToFitKeepAspectConstraint constraint( mPadding );
610 childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
611 SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
616 DALI_ASSERT_ALWAYS( !"Invalid Alignment::mGeometryScaling value" );
621 Relayout( actor, childSize, container );
625 Alignment::Alignment( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
626 : Control( false ), // doesn't require touch events
627 mHorizontal( horizontal ),
628 mVertical( vertical ),
629 mScaling( Toolkit::Alignment::ScaleNone ),
630 mPadding( 0.f, 0.f, 0.f, 0.f )
634 Alignment::~Alignment()
638 } // namespace Internal
640 } // namespace Toolkit