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