Revert "[SRUK] (StyleManager) Create a style manager"
[platform/core/uifw/dali-toolkit.git] / base / dali-toolkit / internal / controls / alignment / alignment-impl.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 //     http://floralicense.org/license/
9 //
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.
15 //
16
17 // CLASS HEADER
18
19 #include "alignment-impl.h"
20
21 // INTERNAL INCLUDES
22
23 // EXTERNAL INCLUDES
24
25 namespace Dali
26 {
27
28 namespace Toolkit
29 {
30
31 namespace Internal
32 {
33
34 namespace
35 {
36
37 //Type Registration
38 BaseHandle Create()
39 {
40   return Toolkit::Alignment::New();
41 }
42
43 TypeRegistration mType( typeid(Toolkit::Alignment), typeid(Toolkit::Control), Create );
44
45 struct ScaleToFillConstraint
46 {
47   /**
48    * @param padding to be added.
49    */
50   ScaleToFillConstraint( const Toolkit::Alignment::Padding& padding )
51   : mPadding( padding )
52   {}
53
54   /**
55    * CopyConstructor. Used by Boost.
56    * @param rhs Copying from.
57    */
58   ScaleToFillConstraint( const ScaleToFillConstraint& rhs )
59   : mPadding( rhs.mPadding )
60   {}
61
62   /**
63    * Called by render thread
64    */
65   Vector3 operator()( const Vector3& currentSize,
66                       const PropertyInput& parentSizeProperty )
67   {
68     const Vector3& parentSize( parentSizeProperty.GetVector3() );
69     return GetSize( currentSize, parentSize );
70   }
71
72   inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
73   {
74     const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
75     const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
76
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 ) )
79     {
80       // no point trying to squeeze actors into this small size
81       return Vector3::ZERO;
82     }
83     return  Vector3( parentSizeWidth, parentSizeHeight, parentSize.depth );
84   }
85
86   const Toolkit::Alignment::Padding mPadding;
87 };
88
89 struct ScaleToFitKeepAspectConstraint
90 {
91   /**
92    * @param padding to be added.
93    */
94   ScaleToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
95   : mPadding( padding ),
96     mSizeStored( false ),
97     mOriginalSize()
98   {}
99
100   /**
101    * CopyConstructor. Used by Boost.
102    * @param rhs Copying from.
103    */
104   ScaleToFitKeepAspectConstraint( const ScaleToFitKeepAspectConstraint& rhs )
105   : mPadding( rhs.mPadding ),
106     mSizeStored( rhs.mSizeStored ),
107     mOriginalSize( rhs.mOriginalSize )
108   {}
109
110   /**
111    * Called by render thread
112    */
113   Vector3 operator()( const Vector3& currentSize,
114                       const PropertyInput& parentSizeProperty )
115   {
116     const Vector3& parentSize( parentSizeProperty.GetVector3() );
117     return GetSize( currentSize, parentSize );
118   }
119
120   inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
121   {
122     if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
123     {
124       mOriginalSize = currentSize;
125       mSizeStored = true;
126     }
127
128     const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
129     const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
130
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 ) )
134     {
135       // no point trying to squeeze actors into this small size
136       return Vector3::ZERO;
137     }
138
139     return mOriginalSize * std::min( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
140   }
141
142   const Toolkit::Alignment::Padding mPadding;
143         bool                        mSizeStored;
144         Vector3                     mOriginalSize;
145 };
146
147 struct ScaleToFillKeepAspectConstraint
148 {
149   /**
150    * @param padding to be added.
151    */
152   ScaleToFillKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
153   : mPadding( padding ),
154     mSizeStored( false ),
155     mOriginalSize()
156   { }
157
158   /**
159    * CopyConstructor. Used by Boost.
160    * @param rhs Copying from.
161    */
162   ScaleToFillKeepAspectConstraint( const ScaleToFillKeepAspectConstraint& rhs )
163   : mPadding( rhs.mPadding ),
164     mSizeStored( rhs.mSizeStored ),
165     mOriginalSize( rhs.mOriginalSize )
166   {}
167
168   /**
169    * Called by render thread
170    */
171   Vector3 operator()( const Vector3& currentSize,
172                       const PropertyInput& parentSizeProperty )
173   {
174     const Vector3& parentSize( parentSizeProperty.GetVector3() );
175     return GetSize( currentSize, parentSize );
176   }
177
178   Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
179   {
180     if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
181     {
182       mOriginalSize = currentSize;
183       mSizeStored = true;
184     }
185
186     const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
187     const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
188
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 ) )
192     {
193       // no point trying to squeeze actors into this small size
194       return Vector3::ZERO;
195     }
196
197     return mOriginalSize * std::max( ( parentSizeWidth / mOriginalSize.width ), ( parentSizeHeight / mOriginalSize.height ) );
198   }
199
200   const Toolkit::Alignment::Padding mPadding;
201         bool                        mSizeStored;
202         Vector3                     mOriginalSize;
203 };
204
205 struct ShrinkToFitConstraint
206 {
207   /**
208    * @param padding to be added.
209    */
210   ShrinkToFitConstraint( const Toolkit::Alignment::Padding& padding )
211   : mPadding( padding ),
212     mSizeStored( false ),
213     mOriginalSize()
214   {}
215
216   /**
217    * CopyConstructor. Used by Boost.
218    * @param rhs Copying from.
219    */
220   ShrinkToFitConstraint( const ShrinkToFitConstraint& rhs )
221   : mPadding( rhs.mPadding ),
222     mSizeStored( rhs.mSizeStored ),
223     mOriginalSize( rhs.mOriginalSize )
224   { }
225
226   /**
227    * Called by render thread
228    */
229   Vector3 operator()( const Vector3& currentSize,
230                       const PropertyInput& parentSizeProperty )
231   {
232     const Vector3& parentSize( parentSizeProperty.GetVector3() );
233     return GetSize( currentSize, parentSize );
234   }
235
236   Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
237   {
238     if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
239     {
240       mOriginalSize = currentSize;
241       mSizeStored = true;
242     }
243
244     const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
245     const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
246
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 ) )
250     {
251       // no point trying to squeeze actors into this small size
252       return Vector3::ZERO;
253     }
254
255     return Vector3( std::min( parentSizeWidth, mOriginalSize.width ), std::min( parentSizeHeight, mOriginalSize.height ), std::min( parentSize.depth, mOriginalSize.depth ) );
256   }
257
258   const Toolkit::Alignment::Padding mPadding;
259         bool                        mSizeStored;
260         Vector3                     mOriginalSize;
261 };
262
263 /**
264  * Constraint that uses naturalSize if it fits inside parent and parent size if not. It also adds some padding pixels
265  */
266 struct ShrinkToFitKeepAspectConstraint
267 {
268   /**
269    * @param padding to be added.
270    */
271   ShrinkToFitKeepAspectConstraint( const Toolkit::Alignment::Padding& padding )
272   : mPadding( padding ),
273     mSizeStored( false ),
274     mOriginalSize()
275   {}
276
277   /**
278    * CopyConstructor. Used by Boost.
279    * @param rhs Copying from.
280    */
281   ShrinkToFitKeepAspectConstraint( const ShrinkToFitKeepAspectConstraint& rhs )
282   : mPadding( rhs.mPadding ),
283     mSizeStored( rhs.mSizeStored ),
284     mOriginalSize( rhs.mOriginalSize )
285   { }
286
287   /**
288    * Called by render thread
289    */
290   Vector3 operator()( const Vector3& currentSize,
291                       const PropertyInput& parentSizeProperty )
292   {
293     const Vector3& parentSize( parentSizeProperty.GetVector3() );
294     return GetSize( currentSize, parentSize );
295   }
296
297   inline Vector3 GetSize( const Vector3& currentSize, const Vector3& parentSize )
298   {
299     if( ( !mSizeStored ) && ( Vector3::ZERO != currentSize ) )
300     {
301       mOriginalSize = currentSize;
302       mSizeStored = true;
303     }
304
305     const float parentSizeWidth = parentSize.width - ( mPadding.left + mPadding.right );
306     const float parentSizeHeight = parentSize.height - ( mPadding.top + mPadding.bottom );
307
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 ) )
311     {
312       // no point trying to squeeze actors into this small size
313       return Vector3::ZERO;
314     }
315
316     return Vector3( ShrinkInside( Vector2( parentSizeWidth, parentSizeHeight ), Vector2( mOriginalSize ) ) );
317   }
318
319   const Toolkit::Alignment::Padding mPadding;
320         bool                        mSizeStored;
321         Vector3                     mOriginalSize;
322 };
323
324 /**
325  * Constraint that modifies the contained actor taking into account the padding value.
326  */
327 struct PositionConstraint
328 {
329   /**
330    * @param padding The padding value
331    * @param horizontalAlignment The horizontal alignment.
332    * @param verticalAlignment The vertical alignment.
333    */
334   PositionConstraint( const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontalAlignment, Toolkit::Alignment::Type verticalAlignment )
335   : mPadding( padding ),
336     mHorizontalAlignment( horizontalAlignment ),
337     mVerticalAlignment( verticalAlignment )
338   {}
339
340   /**
341    * CopyConstructor. Used by Boost.
342    * @param rhs Copying from.
343    */
344   PositionConstraint( const PositionConstraint& rhs )
345   : mPadding( rhs.mPadding ),
346     mHorizontalAlignment( rhs.mHorizontalAlignment ),
347     mVerticalAlignment( rhs.mVerticalAlignment )
348   {}
349
350   /**
351    * Called by render thread.
352    */
353   Vector3 operator()( const Vector3& currentPosition,
354                       const PropertyInput& currentSizeProperty,
355                       const PropertyInput& parentSizeProperty )
356   {
357     const Vector3& currentSize( currentSizeProperty.GetVector3() );
358     const Vector3& parentSize( parentSizeProperty.GetVector3() );
359
360     Vector3 position( 0.f, 0.f, 0.f );
361
362     switch( mHorizontalAlignment )
363     {
364       case Dali::Toolkit::Alignment::HorizontalLeft:
365       {
366         position.x += mPadding.left;
367         break;
368       }
369       case Dali::Toolkit::Alignment::HorizontalCenter:
370       {
371         if( currentSize.width + mPadding.left + mPadding.right >= parentSize.width )
372         {
373           position.x += 0.5f * ( mPadding.left - mPadding.right );
374         }
375         break;
376       }
377       case Dali::Toolkit::Alignment::HorizontalRight:
378       {
379         position.x -= mPadding.right;
380         break;
381       }
382       default:
383       {
384         DALI_ASSERT_ALWAYS( !"Wrong horizontal alignment value" );
385         break;
386       }
387     }
388
389     switch( mVerticalAlignment )
390     {
391       case Dali::Toolkit::Alignment::VerticalTop:
392       {
393         position.y += mPadding.top;
394         break;
395       }
396       case Dali::Toolkit::Alignment::VerticalCenter:
397       {
398         if( currentSize.height + mPadding.top + mPadding.bottom >= parentSize.height )
399         {
400           position.y += 0.5f * ( mPadding.top - mPadding.bottom );
401         }
402         break;
403       }
404       case Dali::Toolkit::Alignment::VerticalBottom:
405       {
406         position.y -= mPadding.bottom;
407         break;
408       }
409       default:
410       {
411         DALI_ASSERT_ALWAYS( !"Wrong vertical alignment value" );
412         break;
413       }
414     }
415
416     return position;
417   }
418
419   const Toolkit::Alignment::Padding mPadding;
420   const Toolkit::Alignment::Type mHorizontalAlignment;
421   const Toolkit::Alignment::Type mVerticalAlignment;
422 };
423
424 void SetPositionConstraint( Actor actor, const Toolkit::Alignment::Padding& padding, Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
425 {
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 );
431 }
432 } // namespace
433
434 Toolkit::Alignment Alignment::New( Toolkit::Alignment::Type horizontal, Toolkit::Alignment::Type vertical )
435 {
436   // Create the implementation, temporarily owned on stack
437   IntrusivePtr< Alignment > internalAlignment = new Alignment( horizontal, vertical );
438
439   // Pass ownership to Toolkit::View
440   Toolkit::Alignment alignment( *internalAlignment );
441
442   // Second-phase init of the implementation
443   // This can only be done after the CustomActor connection has been made...
444   internalAlignment->Initialize();
445
446   return alignment;
447 }
448
449 void Alignment::SetAlignmentType( Toolkit::Alignment::Type type )
450 {
451   // Horizontal Alignment
452   bool horizontalSet(false);
453
454   if( type & Toolkit::Alignment::HorizontalLeft )
455   {
456     mHorizontal = Toolkit::Alignment::HorizontalLeft;
457     horizontalSet = true;
458   }
459   if( type & Toolkit::Alignment::HorizontalCenter )
460   {
461     DALI_ASSERT_ALWAYS(!horizontalSet);
462     mHorizontal = Toolkit::Alignment::HorizontalCenter;
463     horizontalSet = true;
464   }
465   if( type & Toolkit::Alignment::HorizontalRight )
466   {
467     DALI_ASSERT_ALWAYS(!horizontalSet);
468     mHorizontal = Toolkit::Alignment::HorizontalRight;
469   }
470
471   // Vertical Alignment
472   bool verticalSet(false);
473
474   if( type & Toolkit::Alignment::VerticalTop )
475   {
476     mVertical = Toolkit::Alignment::VerticalTop;
477     verticalSet = true;
478   }
479   if( type & Toolkit::Alignment::VerticalCenter )
480   {
481     DALI_ASSERT_ALWAYS(!verticalSet);
482     mVertical = Toolkit::Alignment::VerticalCenter;
483     verticalSet = true;
484   }
485   if( type & Toolkit::Alignment::VerticalBottom )
486   {
487     DALI_ASSERT_ALWAYS(!verticalSet);
488     mVertical = Toolkit::Alignment::VerticalBottom;
489   }
490
491   RelayoutRequest();
492 }
493
494 Toolkit::Alignment::Type Alignment::GetAlignmentType() const
495 {
496   return Toolkit::Alignment::Type( mHorizontal | mVertical );
497 }
498
499 void Alignment::SetScaling( Toolkit::Alignment::Scaling scaling )
500 {
501   mScaling = scaling;
502
503   RelayoutRequest();
504 }
505
506 Toolkit::Alignment::Scaling Alignment::GetScaling() const
507 {
508   return mScaling;
509 }
510
511 void Alignment::SetPadding( const Toolkit::Alignment::Padding& padding )
512 {
513   DALI_ASSERT_ALWAYS( ( padding.left >= 0.f ) && ( padding.top >= 0.f ) && ( padding.right >= 0.f ) && ( padding.bottom >= 0.f ) );
514
515   mPadding = padding;
516
517   RelayoutRequest();
518 }
519
520 const Toolkit::Alignment::Padding& Alignment::GetPadding() const
521 {
522   return mPadding;
523 }
524
525 void Alignment::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
526 {
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 )
532   {
533     anchorPointAndParentOrigin.x = 0.5f;
534   }
535   else if( Toolkit::Alignment::HorizontalRight == mHorizontal )
536   {
537     anchorPointAndParentOrigin.x = 1.0f;
538   }
539   // anchorPoint.y is initialized to 0.0, which is VerticalTop
540   if( Toolkit::Alignment::VerticalCenter == mVertical )
541   {
542     anchorPointAndParentOrigin.y = 0.5f;
543   }
544   else if( Toolkit::Alignment::VerticalBottom == mVertical )
545   {
546     anchorPointAndParentOrigin.y = 1.0f;
547   }
548
549   unsigned int childCount = Self().GetChildCount();
550   for( unsigned int i=0; i<childCount; ++i )
551   {
552     Actor actor = Self().GetChildAt(i);
553
554     actor.SetAnchorPoint( anchorPointAndParentOrigin );
555     actor.SetParentOrigin( anchorPointAndParentOrigin );
556
557     if( Toolkit::Alignment::ScaleNone != mScaling )
558     {
559       actor.RemoveConstraints();
560     }
561
562     Vector3 actorSize ( actor.GetCurrentSize() );
563     Toolkit::Control control( Toolkit::Control::DownCast( actor ) );
564     if ( actorSize == Vector3::ZERO && control )
565     {
566       actorSize = control.GetNaturalSize();
567     }
568
569     Vector2 childSize;
570
571     switch( mScaling )
572     {
573       case Toolkit::Alignment::ScaleNone:
574       {
575         // Nothing to do but needed just to not to jump to the default.
576         childSize = size;
577         break;
578       }
579       case Toolkit::Alignment::ScaleToFill:
580       {
581         ScaleToFillConstraint constraint( mPadding );
582         childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
583         SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
584         break;
585       }
586       case Toolkit::Alignment::ScaleToFitKeepAspect:
587       {
588         ScaleToFitKeepAspectConstraint constraint( mPadding );
589         childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
590         SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
591         break;
592       }
593       case Toolkit::Alignment::ScaleToFillKeepAspect:
594       {
595         ScaleToFillKeepAspectConstraint constraint( mPadding );
596         childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
597         SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
598         break;
599       }
600       case Toolkit::Alignment::ShrinkToFit:
601       {
602         ShrinkToFitConstraint constraint( mPadding );
603         childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
604         SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
605         break;
606       }
607       case Toolkit::Alignment::ShrinkToFitKeepAspect:
608       {
609         ShrinkToFitKeepAspectConstraint constraint( mPadding );
610         childSize = Vector2( constraint.GetSize( actorSize, Vector3(size) ) );
611         SetPositionConstraint( actor, mPadding, mHorizontal, mVertical );
612         break;
613       }
614       default:
615       {
616         DALI_ASSERT_ALWAYS( !"Invalid Alignment::mGeometryScaling value" );
617         break;
618       }
619     }
620
621     Relayout( actor, childSize, container );
622   }
623 }
624
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 )
631 {
632 }
633
634 Alignment::~Alignment()
635 {
636 }
637
638 } // namespace Internal
639
640 } // namespace Toolkit
641
642 } // namespace Dali