Add SpaceEvenly to flex justification
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / flex-container / flex-container-impl.cpp
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
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
18 // CLASS HEADER
19 #include <dali-toolkit/internal/controls/flex-container/flex-container-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <sstream>
23 #include <dali/public-api/object/ref-object.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/public-api/object/type-registry-helper.h>
26 #include <dali/devel-api/actors/actor-devel.h>
27 #include <dali/devel-api/scripting/scripting.h>
28 #include <dali/public-api/size-negotiation/relayout-container.h>
29 #include <dali/integration-api/debug.h>
30
31 using namespace Dali;
32
33 namespace
34 {
35
36 #if defined(DEBUG_ENABLED)
37 // debugging support, very useful when new features are added or bugs are hunted down
38 // currently not called from code so compiler will optimize these away, kept here for future debugging
39
40 #define FLEX_CONTAINER_TAG "DALI Toolkit::FlexContainer "
41 #define FC_LOG(fmt, args,...) Debug::LogMessage(Debug::DebugInfo, FLEX_CONTAINER_TAG fmt, ## args)
42 // #define FLEX_CONTAINER_DEBUG 1
43
44 #if defined(FLEX_CONTAINER_DEBUG)
45 void PrintNodes( Toolkit::Internal::FlexContainer::FlexItemNodeContainer itemNodes )
46 {
47   // Print the style property and layout of all the children
48   for( unsigned int i = 0; i < itemNodes.size(); ++i )
49   {
50     FC_LOG( "Item %d style: \n", i );
51     YGNodePrint( itemNodes[i].node, (YGPrintOptions)( YGPrintOptionsStyle | YGPrintOptionsChildren ) );
52     FC_LOG( "\n" );
53     FC_LOG( "Item %d layout: \n", i );
54     YGNodePrint( itemNodes[i].node, (YGPrintOptions)( YGPrintOptionsLayout | YGPrintOptionsChildren ) );
55     FC_LOG( "\n" );
56   }
57 }
58
59 #endif // defined(FLEX_CONTAINER_DEBUG)
60 #endif // defined(DEBUG_ENABLED)
61
62
63 } // namespace
64
65 namespace Dali
66 {
67
68 namespace Toolkit
69 {
70
71 namespace Internal
72 {
73
74 namespace
75 {
76
77 // Type registration
78 BaseHandle Create()
79 {
80   return Toolkit::FlexContainer::New();
81 }
82
83 // Setup properties, signals and actions using the type-registry.
84 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::FlexContainer, Toolkit::Control, Create );
85
86 DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer,        "contentDirection",  INTEGER,  CONTENT_DIRECTION )
87 DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer,        "flexDirection",     INTEGER,  FLEX_DIRECTION    )
88 DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer,        "flexWrap",          INTEGER,  FLEX_WRAP         )
89 DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer,        "justifyContent",    INTEGER,  JUSTIFY_CONTENT   )
90 DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer,        "alignItems",        INTEGER,  ALIGN_ITEMS       )
91 DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer,        "alignContent",      INTEGER,  ALIGN_CONTENT     )
92 DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, FlexContainer,  "flex",              FLOAT,    FLEX              )
93 DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, FlexContainer,  "alignSelf",         INTEGER,  ALIGN_SELF        )
94 DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, FlexContainer,  "flexMargin",        VECTOR4,  FLEX_MARGIN       )
95
96 DALI_TYPE_REGISTRATION_END()
97
98 const Scripting::StringEnum ALIGN_SELF_STRING_TABLE[] =
99 {
100   { "auto",        Toolkit::FlexContainer::ALIGN_AUTO        },
101   { "flexStart",   Toolkit::FlexContainer::ALIGN_FLEX_START  },
102   { "center",      Toolkit::FlexContainer::ALIGN_CENTER      },
103   { "flexEnd",     Toolkit::FlexContainer::ALIGN_FLEX_END    },
104   { "stretch",     Toolkit::FlexContainer::ALIGN_STRETCH     }
105 };
106 const unsigned int ALIGN_SELF_STRING_TABLE_COUNT = sizeof( ALIGN_SELF_STRING_TABLE ) / sizeof( ALIGN_SELF_STRING_TABLE[0] );
107
108 const Scripting::StringEnum CONTENT_DIRECTION_STRING_TABLE[] =
109 {
110   { "inherit",     Toolkit::FlexContainer::INHERIT           },
111   { "LTR",         Toolkit::FlexContainer::LTR               },
112   { "RTL",         Toolkit::FlexContainer::RTL               }
113 };
114 const unsigned int CONTENT_DIRECTION_STRING_TABLE_COUNT = sizeof( CONTENT_DIRECTION_STRING_TABLE ) / sizeof( CONTENT_DIRECTION_STRING_TABLE[0] );
115
116 const Scripting::StringEnum FLEX_DIRECTION_STRING_TABLE[] =
117 {
118   { "column",          Toolkit::FlexContainer::COLUMN          },
119   { "columnReverse",   Toolkit::FlexContainer::COLUMN_REVERSE  },
120   { "row",             Toolkit::FlexContainer::ROW             },
121   { "rowReverse",      Toolkit::FlexContainer::ROW_REVERSE     }
122 };
123 const unsigned int FLEX_DIRECTION_STRING_TABLE_COUNT = sizeof( FLEX_DIRECTION_STRING_TABLE ) / sizeof( FLEX_DIRECTION_STRING_TABLE[0] );
124
125 const Scripting::StringEnum FLEX_WRAP_STRING_TABLE[] =
126 {
127   { "noWrap",          Toolkit::FlexContainer::NO_WRAP         },
128   { "wrap",            Toolkit::FlexContainer::WRAP            }
129 };
130 const unsigned int FLEX_WRAP_STRING_TABLE_COUNT = sizeof( FLEX_WRAP_STRING_TABLE ) / sizeof( FLEX_WRAP_STRING_TABLE[0] );
131
132 const Scripting::StringEnum JUSTIFY_CONTENT_STRING_TABLE[] =
133 {
134   { "flexStart",       Toolkit::FlexContainer::JUSTIFY_FLEX_START     },
135   { "center",          Toolkit::FlexContainer::JUSTIFY_CENTER         },
136   { "flexEnd",         Toolkit::FlexContainer::JUSTIFY_FLEX_END       },
137   { "spaceBetween",    Toolkit::FlexContainer::JUSTIFY_SPACE_BETWEEN  },
138   { "spaceAround",     Toolkit::FlexContainer::JUSTIFY_SPACE_AROUND   },
139   { "spaceEvenly",     Toolkit::FlexContainer::JUSTIFY_SPACE_EVENLY   }
140 };
141 const unsigned int JUSTIFY_CONTENT_STRING_TABLE_COUNT = sizeof( JUSTIFY_CONTENT_STRING_TABLE ) / sizeof( JUSTIFY_CONTENT_STRING_TABLE[0] );
142
143 const Scripting::StringEnum ALIGN_ITEMS_STRING_TABLE[] =
144 {
145   { "flexStart",   Toolkit::FlexContainer::ALIGN_FLEX_START  },
146   { "center",      Toolkit::FlexContainer::ALIGN_CENTER      },
147   { "flexEnd",     Toolkit::FlexContainer::ALIGN_FLEX_END    },
148   { "stretch",     Toolkit::FlexContainer::ALIGN_STRETCH     }
149 };
150 const unsigned int ALIGN_ITEMS_STRING_TABLE_COUNT = sizeof( ALIGN_ITEMS_STRING_TABLE ) / sizeof( ALIGN_ITEMS_STRING_TABLE[0] );
151
152 const Scripting::StringEnum ALIGN_CONTENT_STRING_TABLE[] =
153 {
154   { "flexStart",   Toolkit::FlexContainer::ALIGN_FLEX_START  },
155   { "center",      Toolkit::FlexContainer::ALIGN_CENTER      },
156   { "flexEnd",     Toolkit::FlexContainer::ALIGN_FLEX_END    },
157   { "stretch",     Toolkit::FlexContainer::ALIGN_STRETCH     }
158 };
159 const unsigned int ALIGN_CONTENT_STRING_TABLE_COUNT = sizeof( ALIGN_CONTENT_STRING_TABLE ) / sizeof( ALIGN_CONTENT_STRING_TABLE[0] );
160
161 } // Unnamed namespace
162
163 Toolkit::FlexContainer FlexContainer::New()
164 {
165   // Create the implementation, temporarily owned by this handle on stack
166   IntrusivePtr< FlexContainer > impl = new FlexContainer();
167
168   // Pass ownership to CustomActor handle
169   Toolkit::FlexContainer handle( *impl );
170
171   // Second-phase init of the implementation
172   // This can only be done after the CustomActor connection has been made...
173   impl->Initialize();
174
175   return handle;
176 }
177
178 FlexContainer::~FlexContainer()
179 {
180   YGNodeFree( mRootNode.node );
181
182   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
183   {
184     YGNodeFree( mChildrenNodes[i].node );
185   }
186
187   mChildrenNodes.clear();
188 }
189
190 void FlexContainer::SetContentDirection( Toolkit::FlexContainer::ContentDirection contentDirection)
191 {
192   if( mContentDirection != contentDirection )
193   {
194     Dali::CustomActor ownerActor(GetOwner());
195
196     if( Toolkit::FlexContainer::INHERIT != contentDirection )
197     {
198       mContentDirection = contentDirection;
199
200       ownerActor.SetProperty( Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION, false );
201
202       if( Toolkit::FlexContainer::LTR == contentDirection )
203       {
204         ownerActor.SetProperty(Dali::Actor::Property::LAYOUT_DIRECTION, Dali::LayoutDirection::LEFT_TO_RIGHT);
205       }
206       else
207       {
208         ownerActor.SetProperty(Dali::Actor::Property::LAYOUT_DIRECTION, Dali::LayoutDirection::RIGHT_TO_LEFT);
209       }
210     }
211     else
212     {
213       ownerActor.SetProperty( Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION, true );
214
215       Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( ownerActor.GetParent().GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get<int>() );
216
217       if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection )
218       {
219         mContentDirection = Toolkit::FlexContainer::RTL;
220       }
221       else
222       {
223         mContentDirection = Toolkit::FlexContainer::LTR;
224       }
225     }
226
227     RelayoutRequest();
228   }
229 }
230
231 Toolkit::FlexContainer::ContentDirection FlexContainer::GetContentDirection()
232 {
233   return mContentDirection;
234 }
235
236 void FlexContainer::SetFlexDirection( Toolkit::FlexContainer::FlexDirection flexDirection )
237 {
238   if( mFlexDirection != flexDirection )
239   {
240     mFlexDirection = flexDirection;
241     YGNodeStyleSetFlexDirection( mRootNode.node, static_cast<YGFlexDirection>( flexDirection ) );
242
243     RelayoutRequest();
244   }
245 }
246
247 Toolkit::FlexContainer::FlexDirection FlexContainer::GetFlexDirection()
248 {
249   return mFlexDirection;
250 }
251
252 void FlexContainer::SetFlexWrap( Toolkit::FlexContainer::WrapType flexWrap )
253 {
254   if( mFlexWrap != flexWrap )
255   {
256     mFlexWrap = flexWrap;
257     YGNodeStyleSetFlexWrap( mRootNode.node, static_cast<YGWrap>( flexWrap ) );
258
259     RelayoutRequest();
260   }
261 }
262
263 Toolkit::FlexContainer::WrapType FlexContainer::GetFlexWrap()
264 {
265   return mFlexWrap;
266 }
267
268 void FlexContainer::SetJustifyContent( Toolkit::FlexContainer::Justification justifyContent )
269 {
270   if( mJustifyContent != justifyContent )
271   {
272     mJustifyContent = justifyContent;
273     YGNodeStyleSetJustifyContent( mRootNode.node, static_cast<YGJustify>( justifyContent ) );
274
275     RelayoutRequest();
276   }
277 }
278
279 Toolkit::FlexContainer::Justification FlexContainer::GetJustifyContent()
280 {
281   return mJustifyContent;
282 }
283
284 void FlexContainer::SetAlignItems( Toolkit::FlexContainer::Alignment alignItems )
285 {
286   if( mAlignItems != alignItems )
287   {
288     mAlignItems = alignItems;
289     YGNodeStyleSetAlignItems( mRootNode.node, static_cast<YGAlign>( alignItems ) );
290
291     RelayoutRequest();
292   }
293 }
294
295 Toolkit::FlexContainer::Alignment FlexContainer::GetAlignItems()
296 {
297   return mAlignItems;
298 }
299
300 void FlexContainer::SetAlignContent( Toolkit::FlexContainer::Alignment alignContent )
301 {
302   if( mAlignContent != alignContent )
303   {
304     mAlignContent = alignContent;
305     YGNodeStyleSetAlignContent( mRootNode.node, static_cast<YGAlign>( alignContent ) );
306
307     RelayoutRequest();
308   }
309 }
310
311 Toolkit::FlexContainer::Alignment FlexContainer::GetAlignContent()
312 {
313   return mAlignContent;
314 }
315
316 void FlexContainer::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
317 {
318   Toolkit::FlexContainer flexContainer = Toolkit::FlexContainer::DownCast( Dali::BaseHandle( object ) );
319
320   if( flexContainer )
321   {
322     FlexContainer& flexContainerImpl( GetImpl( flexContainer ) );
323     switch( index )
324     {
325       case Toolkit::FlexContainer::Property::CONTENT_DIRECTION:
326       {
327         Toolkit::FlexContainer::ContentDirection contentDirection( Toolkit::FlexContainer::INHERIT );
328
329         if( value.GetType() == Property::INTEGER )
330         {
331           flexContainerImpl.SetContentDirection( static_cast<Toolkit::FlexContainer::ContentDirection>( value.Get< int >() ) );
332         }
333         else if( Scripting::GetEnumeration< Toolkit::FlexContainer::ContentDirection >( value.Get< std::string >().c_str(),
334                                                                                    CONTENT_DIRECTION_STRING_TABLE,
335                                                                                    CONTENT_DIRECTION_STRING_TABLE_COUNT,
336                                                                                    contentDirection ) )
337         {
338           flexContainerImpl.SetContentDirection(contentDirection);
339         }
340         break;
341       }
342       case Toolkit::FlexContainer::Property::FLEX_DIRECTION:
343       {
344         Toolkit::FlexContainer::FlexDirection flexDirection( Toolkit::FlexContainer::COLUMN );
345
346         if( value.GetType() == Property::INTEGER )
347         {
348           flexContainerImpl.SetFlexDirection( static_cast<Toolkit::FlexContainer::FlexDirection>( value.Get< int >() ) );
349         }
350         else if( Scripting::GetEnumeration< Toolkit::FlexContainer::FlexDirection >( value.Get< std::string >().c_str(),
351                                                                                 FLEX_DIRECTION_STRING_TABLE,
352                                                                                 FLEX_DIRECTION_STRING_TABLE_COUNT,
353                                                                                 flexDirection ) )
354         {
355           flexContainerImpl.SetFlexDirection(flexDirection);
356         }
357         break;
358       }
359       case Toolkit::FlexContainer::Property::FLEX_WRAP:
360       {
361         Toolkit::FlexContainer::WrapType flexWrap( Toolkit::FlexContainer::NO_WRAP );
362
363         if( value.GetType() == Property::INTEGER )
364         {
365           flexContainerImpl.SetFlexWrap( static_cast<Toolkit::FlexContainer::WrapType>( value.Get< int >() ) );
366         }
367         else if( Scripting::GetEnumeration< Toolkit::FlexContainer::WrapType >( value.Get< std::string >().c_str(),
368                                                                            FLEX_WRAP_STRING_TABLE,
369                                                                            FLEX_WRAP_STRING_TABLE_COUNT,
370                                                                            flexWrap ) )
371         {
372           flexContainerImpl.SetFlexWrap(flexWrap);
373         }
374         break;
375       }
376       case Toolkit::FlexContainer::Property::JUSTIFY_CONTENT:
377       {
378         Toolkit::FlexContainer::Justification justifyContent( Toolkit::FlexContainer::JUSTIFY_FLEX_START );
379
380         if( value.GetType() == Property::INTEGER )
381         {
382           flexContainerImpl.SetJustifyContent( static_cast<Toolkit::FlexContainer::Justification>( value.Get< int >() ) );
383         }
384         else if( Scripting::GetEnumeration< Toolkit::FlexContainer::Justification >( value.Get< std::string >().c_str(),
385                                                                                 JUSTIFY_CONTENT_STRING_TABLE,
386                                                                                 JUSTIFY_CONTENT_STRING_TABLE_COUNT,
387                                                                                 justifyContent ) )
388         {
389           flexContainerImpl.SetJustifyContent(justifyContent);
390         }
391         break;
392       }
393       case Toolkit::FlexContainer::Property::ALIGN_ITEMS:
394       {
395         Toolkit::FlexContainer::Alignment alignItems( Toolkit::FlexContainer::ALIGN_STRETCH );
396
397         if( value.GetType() == Property::INTEGER )
398         {
399           flexContainerImpl.SetAlignItems( static_cast<Toolkit::FlexContainer::Alignment>( value.Get< int >() ) );
400         }
401         else if( Scripting::GetEnumeration< Toolkit::FlexContainer::Alignment >( value.Get< std::string >().c_str(),
402                                                                             ALIGN_ITEMS_STRING_TABLE,
403                                                                             ALIGN_ITEMS_STRING_TABLE_COUNT,
404                                                                             alignItems ) )
405         {
406           flexContainerImpl.SetAlignItems(alignItems);
407         }
408         break;
409       }
410       case Toolkit::FlexContainer::Property::ALIGN_CONTENT:
411       {
412         Toolkit::FlexContainer::Alignment alignContent( Toolkit::FlexContainer::ALIGN_FLEX_START );
413
414         if( value.GetType() == Property::INTEGER )
415         {
416           flexContainerImpl.SetAlignContent( static_cast<Toolkit::FlexContainer::Alignment>( value.Get< int >() ) );
417         }
418         else if( Scripting::GetEnumeration< Toolkit::FlexContainer::Alignment >( value.Get< std::string >().c_str(),
419                                                                             ALIGN_CONTENT_STRING_TABLE,
420                                                                             ALIGN_CONTENT_STRING_TABLE_COUNT,
421                                                                             alignContent ) )
422         {
423           flexContainerImpl.SetAlignContent(alignContent);
424         }
425         break;
426       }
427     }
428   }
429 }
430
431 Property::Value FlexContainer::GetProperty( BaseObject* object, Property::Index index )
432 {
433   Property::Value value;
434
435   Toolkit::FlexContainer flexContainer = Toolkit::FlexContainer::DownCast( Dali::BaseHandle( object ) );
436
437   if( flexContainer )
438   {
439     FlexContainer& flexContainerImpl( GetImpl( flexContainer ) );
440     switch( index )
441     {
442       case Toolkit::FlexContainer::Property::CONTENT_DIRECTION:
443       {
444         value = flexContainerImpl.GetContentDirection();
445         break;
446       }
447       case Toolkit::FlexContainer::Property::FLEX_DIRECTION:
448       {
449         value = flexContainerImpl.GetFlexDirection();
450         break;
451       }
452       case Toolkit::FlexContainer::Property::FLEX_WRAP:
453       {
454         value = flexContainerImpl.GetFlexWrap();
455         break;
456       }
457       case Toolkit::FlexContainer::Property::JUSTIFY_CONTENT:
458       {
459         value = flexContainerImpl.GetJustifyContent();
460         break;
461       }
462       case Toolkit::FlexContainer::Property::ALIGN_ITEMS:
463       {
464         value = flexContainerImpl.GetAlignItems();
465         break;
466       }
467       case Toolkit::FlexContainer::Property::ALIGN_CONTENT:
468       {
469         value = flexContainerImpl.GetAlignContent();
470         break;
471       }
472     }
473   }
474
475   return value;
476 }
477
478 void FlexContainer::OnChildAdd( Actor& child )
479 {
480   // Create a new node for the child.
481   FlexItemNode childNode;
482   childNode.actor = child;
483   childNode.node = YGNodeNew();
484
485   mChildrenNodes.push_back( childNode );
486   YGNodeInsertChild( mRootNode.node, childNode.node, mChildrenNodes.size() - 1 );
487
488   Control::OnChildAdd( child );
489 }
490
491 void FlexContainer::OnChildRemove( Actor& child )
492 {
493   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
494   {
495     if( mChildrenNodes[i].actor.GetHandle() == child )
496     {
497       YGNodeRemoveChild( mRootNode.node, mChildrenNodes[i].node );
498       YGNodeFree( mChildrenNodes[i].node );
499
500       mChildrenNodes.erase( mChildrenNodes.begin() + i );
501
502       // Relayout the container only if instances were found
503       RelayoutRequest();
504       break;
505     }
506   }
507
508   Control::OnChildRemove( child );
509 }
510
511 void FlexContainer::OnRelayout( const Vector2& size, RelayoutContainer& container )
512 {
513   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
514   {
515     Actor child = mChildrenNodes[i].actor.GetHandle();
516     if( child )
517     {
518       // Anchor actor to top left of the container
519       if( child.GetProperty( Actor::Property::POSITION_USES_ANCHOR_POINT ).Get< bool >() )
520       {
521         child.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
522       }
523       child.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
524
525       float negotiatedWidth = child.GetRelayoutSize(Dimension::WIDTH);
526       float negotiatedHeight = child.GetRelayoutSize(Dimension::HEIGHT);
527
528       if( negotiatedWidth > 0 )
529       {
530         YGNodeStyleSetWidth( mChildrenNodes[i].node, negotiatedWidth );
531       }
532       if( negotiatedHeight > 0 )
533       {
534         YGNodeStyleSetHeight( mChildrenNodes[i].node, negotiatedHeight );
535       }
536     }
537   }
538
539   // Relayout the container
540   RelayoutChildren();
541 #if defined(FLEX_CONTAINER_DEBUG)
542   PrintNodes( mChildrenNodes );
543 #endif
544
545   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
546   {
547     Actor child = mChildrenNodes[i].actor.GetHandle();
548     if( child )
549     {
550       if( child.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX ) != Property::NONE )
551       {
552         // Only Set to USE_ASSIGNED_SIZE if the child actor is flexible.
553
554         if( child.GetResizePolicy( Dimension::WIDTH ) != ResizePolicy::USE_ASSIGNED_SIZE )
555         {
556           child.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::WIDTH );
557         }
558         if( child.GetResizePolicy( Dimension::HEIGHT ) != ResizePolicy::USE_ASSIGNED_SIZE )
559         {
560           child.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::HEIGHT );
561         }
562       }
563       container.Add( child, Vector2(YGNodeLayoutGetWidth(mChildrenNodes[i].node), YGNodeLayoutGetHeight(mChildrenNodes[i].node) ) );
564     }
565   }
566 }
567
568 bool FlexContainer::RelayoutDependentOnChildren( Dimension::Type dimension )
569 {
570   return true;
571 }
572
573 void FlexContainer::OnSizeSet( const Vector3& size )
574 {
575   if( mRootNode.node )
576   {
577     Actor self = Self();
578     YGNodeStyleSetWidth( mRootNode.node, size.x );
579     YGNodeStyleSetHeight( mRootNode.node, size.y );
580
581     RelayoutRequest();
582   }
583
584   Control::OnSizeSet( size );
585 }
586
587 void FlexContainer::OnLayoutDirectionChanged( Dali::Actor actor, Dali::LayoutDirection::Type type )
588 {
589   Toolkit::FlexContainer flexContainer = Toolkit::FlexContainer::DownCast(actor);
590   Toolkit::FlexContainer::ContentDirection direction;
591
592   if( type == Dali::LayoutDirection::RIGHT_TO_LEFT )
593   {
594     direction = Toolkit::FlexContainer::RTL;
595   }
596   else
597   {
598     direction = Toolkit::FlexContainer::LTR;
599   }
600
601   Toolkit::Internal::FlexContainer &flexContainerImpl = GetImpl( flexContainer );
602
603   if( flexContainerImpl.mContentDirection != direction )
604   {
605     Dali::CustomActor ownerActor(flexContainerImpl.GetOwner());
606     flexContainerImpl.mContentDirection = direction;
607
608     flexContainerImpl.RelayoutRequest();
609   }
610 }
611
612 void FlexContainer::ComputeLayout()
613 {
614   if( mRootNode.node )
615   {
616     for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
617     {
618       YGNodeRef childNode = mChildrenNodes[i].node;
619       Actor childActor = mChildrenNodes[i].actor.GetHandle();
620
621       // Intialize the style of the child.
622       YGNodeStyleSetMinWidth( childNode, childActor.GetProperty< Vector2 >( Actor::Property::MINIMUM_SIZE ).x );
623       YGNodeStyleSetMinHeight( childNode, childActor.GetProperty< Vector2 >( Actor::Property::MINIMUM_SIZE ).y );
624       YGNodeStyleSetMaxWidth( childNode, childActor.GetProperty< Vector2 >( Actor::Property::MAXIMUM_SIZE ).x );
625       YGNodeStyleSetMaxHeight( childNode, childActor.GetProperty< Vector2 >( Actor::Property::MAXIMUM_SIZE ).y );
626
627       // Check child properties on the child for how to layout it.
628       // These properties should be dynamically registered to the child which
629       // would be added to FlexContainer.
630
631       if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX ) != Property::NONE )
632       {
633         YGNodeStyleSetFlex( childNode, childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX ).Get<float>() );
634       }
635
636       Toolkit::FlexContainer::Alignment alignSelf( Toolkit::FlexContainer::ALIGN_AUTO );
637       if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::ALIGN_SELF ) != Property::NONE )
638       {
639         Property::Value alignSelfPropertyValue = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::ALIGN_SELF );
640         if( alignSelfPropertyValue.GetType() == Property::INTEGER )
641         {
642           alignSelf = static_cast<Toolkit::FlexContainer::Alignment>( alignSelfPropertyValue.Get< int >() );
643         }
644         else if( alignSelfPropertyValue.GetType() == Property::STRING )
645         {
646           std::string value = alignSelfPropertyValue.Get<std::string>();
647           Scripting::GetEnumeration< Toolkit::FlexContainer::Alignment >( value.c_str(),
648                                                                           ALIGN_SELF_STRING_TABLE,
649                                                                           ALIGN_SELF_STRING_TABLE_COUNT,
650                                                                           alignSelf );
651         }
652         YGNodeStyleSetAlignSelf( childNode, static_cast<YGAlign>(alignSelf) );
653       }
654
655       if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN ) != Property::NONE )
656       {
657         Vector4 flexMargin = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN ).Get<Vector4>();
658         YGNodeStyleSetMargin( childNode, YGEdgeLeft, flexMargin.x );
659         YGNodeStyleSetMargin( childNode, YGEdgeTop, flexMargin.y );
660         YGNodeStyleSetMargin( childNode, YGEdgeRight, flexMargin.z );
661         YGNodeStyleSetMargin( childNode, YGEdgeBottom, flexMargin.w );
662       }
663     }
664
665     // Calculate the layout
666     YGDirection nodeLayoutDirection = YGDirectionInherit;
667     switch( mContentDirection )
668     {
669     case Dali::Toolkit::FlexContainer::LTR:
670     {
671       nodeLayoutDirection = YGDirectionLTR;
672       break;
673     }
674
675     case Dali::Toolkit::FlexContainer::RTL:
676     {
677       nodeLayoutDirection = YGDirectionRTL;
678       break;
679     }
680
681     case Dali::Toolkit::FlexContainer::INHERIT:
682     {
683       nodeLayoutDirection = YGDirectionInherit;
684       break;
685     }
686     }
687
688 #if defined(FLEX_CONTAINER_DEBUG)
689     YGNodePrint( mRootNode.node, (YGPrintOptions)( YGPrintOptionsLayout | YGPrintOptionsStyle | YGPrintOptionsChildren ) );
690 #endif
691     YGNodeCalculateLayout( mRootNode.node, Self().GetProperty< Vector2 >( Actor::Property::MAXIMUM_SIZE ).x, Self().GetProperty< Vector2 >( Actor::Property::MAXIMUM_SIZE ).y, nodeLayoutDirection );
692 #if defined(FLEX_CONTAINER_DEBUG)
693     YGNodePrint( mRootNode.node, (YGPrintOptions)( YGPrintOptionsLayout | YGPrintOptionsStyle | YGPrintOptionsChildren ) );
694 #endif
695   }
696 }
697
698 void FlexContainer::RelayoutChildren()
699 {
700   ComputeLayout();
701
702   // Set size and position of children according to the layout calculation
703   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
704   {
705     Dali::Actor child = mChildrenNodes[i].actor.GetHandle();
706     if( child )
707     {
708       child.SetProperty( Actor::Property::POSITION_X,  YGNodeLayoutGetLeft( mChildrenNodes[i].node ) );
709       child.SetProperty( Actor::Property::POSITION_Y,  YGNodeLayoutGetTop( mChildrenNodes[i].node ) );
710     }
711   }
712 }
713
714 Actor FlexContainer::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
715 {
716   Actor nextFocusableActor;
717
718   // First check whether there is any items in the container
719   if( mChildrenNodes.size() > 0 )
720   {
721     if ( !currentFocusedActor || currentFocusedActor == Self() )
722     {
723       // Nothing is currently focused, so the first child in the container should be focused.
724       nextFocusableActor = mChildrenNodes[0].actor.GetHandle();
725     }
726     else
727     {
728       // Check whether the current focused actor is within flex container
729       int currentFocusedActorIndex = -1;
730       for( unsigned int index = 0; index < mChildrenNodes.size(); index++ )
731       {
732         if( currentFocusedActor == mChildrenNodes[index].actor.GetHandle() )
733         {
734           currentFocusedActorIndex = index;
735           break;
736         }
737       }
738
739       if( currentFocusedActorIndex > -1 )
740       {
741         int previousCheckedActorIndex = -1;
742         int nextFocusedActorIndex = currentFocusedActorIndex;
743         switch ( direction )
744         {
745           case Toolkit::Control::KeyboardFocus::LEFT:
746           case Toolkit::Control::KeyboardFocus::UP:
747           {
748             // Search the next focusable actor in the backward direction
749             do
750             {
751               nextFocusedActorIndex--;
752               if( nextFocusedActorIndex < 0 )
753               {
754                 nextFocusedActorIndex = loopEnabled ? mChildrenNodes.size() - 1 : 0;
755               }
756               if( nextFocusedActorIndex != previousCheckedActorIndex && nextFocusedActorIndex != currentFocusedActorIndex )
757               {
758                 previousCheckedActorIndex = nextFocusedActorIndex;
759               }
760               else
761               {
762                 break;
763               }
764             } while ( !mChildrenNodes[nextFocusedActorIndex].actor.GetHandle().GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) );
765             break;
766           }
767           case Toolkit::Control::KeyboardFocus::RIGHT:
768           case Toolkit::Control::KeyboardFocus::DOWN:
769           {
770             // Search the next focusable actor in the forward direction
771             do
772             {
773               nextFocusedActorIndex++;
774               if( nextFocusedActorIndex > static_cast<int>(mChildrenNodes.size() - 1) )
775               {
776                 nextFocusedActorIndex = loopEnabled ? 0 : mChildrenNodes.size() - 1;
777               }
778               if( nextFocusedActorIndex != previousCheckedActorIndex && nextFocusedActorIndex != currentFocusedActorIndex )
779               {
780                 previousCheckedActorIndex = nextFocusedActorIndex;
781               }
782               else
783               {
784                 break;
785               }
786             } while ( !mChildrenNodes[nextFocusedActorIndex].actor.GetHandle().GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) );
787             break;
788           }
789           default:
790           {
791             break;
792           }
793         }
794
795         if( nextFocusedActorIndex != currentFocusedActorIndex )
796         {
797           nextFocusableActor = mChildrenNodes[nextFocusedActorIndex].actor.GetHandle();
798         }
799         else
800         {
801           // No focusble child in the container
802           nextFocusableActor = Actor();
803         }
804       }
805       else
806       {
807         // The current focused actor is not within flex container, so the first child in the container should be focused.
808         nextFocusableActor = mChildrenNodes[0].actor.GetHandle();
809       }
810     }
811   }
812
813   return nextFocusableActor;
814 }
815
816 FlexContainer::FlexContainer()
817 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
818   mContentDirection( Toolkit::FlexContainer::INHERIT ),
819   mFlexDirection( Toolkit::FlexContainer::COLUMN ),
820   mFlexWrap( Toolkit::FlexContainer::NO_WRAP ),
821   mJustifyContent( Toolkit::FlexContainer::JUSTIFY_FLEX_START ),
822   mAlignItems( Toolkit::FlexContainer::ALIGN_STRETCH ),
823   mAlignContent( Toolkit::FlexContainer::ALIGN_FLEX_START )
824 {
825   SetKeyboardNavigationSupport( true );
826 }
827
828 void FlexContainer::OnInitialize()
829 {
830   // Initialize the node for the flex container itself
831   Dali::Actor self = Self();
832   self.LayoutDirectionChangedSignal().Connect( this, &FlexContainer::OnLayoutDirectionChanged );
833
834   mRootNode.actor = self;
835   mRootNode.node = YGNodeNew();
836   YGNodeSetContext( mRootNode.node, &mChildrenNodes );
837
838   // Set default style
839   YGNodeStyleSetFlexDirection( mRootNode.node, static_cast<YGFlexDirection>( mFlexDirection ) );
840   YGNodeStyleSetFlexWrap( mRootNode.node, static_cast<YGWrap>( mFlexWrap ) );
841   YGNodeStyleSetJustifyContent( mRootNode.node, static_cast<YGJustify>( mJustifyContent ) );
842   YGNodeStyleSetAlignItems( mRootNode.node, static_cast<YGAlign>( mAlignItems ) );
843   YGNodeStyleSetAlignContent( mRootNode.node, static_cast<YGAlign>( mAlignContent ) );
844
845   // Make self as keyboard focusable and focus group
846   self.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE, true );
847   SetAsKeyboardFocusGroup( true );
848 }
849
850 } // namespace Internal
851
852 } // namespace Toolkit
853
854 } // namespace Dali