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