Merge "Change size for new visual using initialized transformMap when mVisual is...
[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 };
140 const unsigned int JUSTIFY_CONTENT_STRING_TABLE_COUNT = sizeof( JUSTIFY_CONTENT_STRING_TABLE ) / sizeof( JUSTIFY_CONTENT_STRING_TABLE[0] );
141
142 const Scripting::StringEnum ALIGN_ITEMS_STRING_TABLE[] =
143 {
144   { "flexStart",   Toolkit::FlexContainer::ALIGN_FLEX_START  },
145   { "center",      Toolkit::FlexContainer::ALIGN_CENTER      },
146   { "flexEnd",     Toolkit::FlexContainer::ALIGN_FLEX_END    },
147   { "stretch",     Toolkit::FlexContainer::ALIGN_STRETCH     }
148 };
149 const unsigned int ALIGN_ITEMS_STRING_TABLE_COUNT = sizeof( ALIGN_ITEMS_STRING_TABLE ) / sizeof( ALIGN_ITEMS_STRING_TABLE[0] );
150
151 const Scripting::StringEnum ALIGN_CONTENT_STRING_TABLE[] =
152 {
153   { "flexStart",   Toolkit::FlexContainer::ALIGN_FLEX_START  },
154   { "center",      Toolkit::FlexContainer::ALIGN_CENTER      },
155   { "flexEnd",     Toolkit::FlexContainer::ALIGN_FLEX_END    },
156   { "stretch",     Toolkit::FlexContainer::ALIGN_STRETCH     }
157 };
158 const unsigned int ALIGN_CONTENT_STRING_TABLE_COUNT = sizeof( ALIGN_CONTENT_STRING_TABLE ) / sizeof( ALIGN_CONTENT_STRING_TABLE[0] );
159
160 } // Unnamed namespace
161
162 Toolkit::FlexContainer FlexContainer::New()
163 {
164   // Create the implementation, temporarily owned by this handle on stack
165   IntrusivePtr< FlexContainer > impl = new FlexContainer();
166
167   // Pass ownership to CustomActor handle
168   Toolkit::FlexContainer handle( *impl );
169
170   // Second-phase init of the implementation
171   // This can only be done after the CustomActor connection has been made...
172   impl->Initialize();
173
174   return handle;
175 }
176
177 FlexContainer::~FlexContainer()
178 {
179   YGNodeFree( mRootNode.node );
180
181   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
182   {
183     YGNodeFree( mChildrenNodes[i].node );
184   }
185
186   mChildrenNodes.clear();
187 }
188
189 void FlexContainer::SetContentDirection( Toolkit::FlexContainer::ContentDirection contentDirection)
190 {
191   if( mContentDirection != contentDirection )
192   {
193     Dali::CustomActor ownerActor(GetOwner());
194
195     if( Toolkit::FlexContainer::INHERIT != contentDirection )
196     {
197       mContentDirection = contentDirection;
198
199       ownerActor.SetProperty( Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION, false );
200
201       if( Toolkit::FlexContainer::LTR == contentDirection )
202       {
203         ownerActor.SetProperty(Dali::Actor::Property::LAYOUT_DIRECTION, Dali::LayoutDirection::LEFT_TO_RIGHT);
204       }
205       else
206       {
207         ownerActor.SetProperty(Dali::Actor::Property::LAYOUT_DIRECTION, Dali::LayoutDirection::RIGHT_TO_LEFT);
208       }
209     }
210     else
211     {
212       ownerActor.SetProperty( Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION, true );
213
214       Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( ownerActor.GetParent().GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get<int>() );
215
216       if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection )
217       {
218         mContentDirection = Toolkit::FlexContainer::RTL;
219       }
220       else
221       {
222         mContentDirection = Toolkit::FlexContainer::LTR;
223       }
224     }
225
226     RelayoutRequest();
227   }
228 }
229
230 Toolkit::FlexContainer::ContentDirection FlexContainer::GetContentDirection()
231 {
232   return mContentDirection;
233 }
234
235 void FlexContainer::SetFlexDirection( Toolkit::FlexContainer::FlexDirection flexDirection )
236 {
237   if( mFlexDirection != flexDirection )
238   {
239     mFlexDirection = flexDirection;
240     YGNodeStyleSetFlexDirection( mRootNode.node, static_cast<YGFlexDirection>( flexDirection ) );
241
242     RelayoutRequest();
243   }
244 }
245
246 Toolkit::FlexContainer::FlexDirection FlexContainer::GetFlexDirection()
247 {
248   return mFlexDirection;
249 }
250
251 void FlexContainer::SetFlexWrap( Toolkit::FlexContainer::WrapType flexWrap )
252 {
253   if( mFlexWrap != flexWrap )
254   {
255     mFlexWrap = flexWrap;
256     YGNodeStyleSetFlexWrap( mRootNode.node, static_cast<YGWrap>( flexWrap ) );
257
258     RelayoutRequest();
259   }
260 }
261
262 Toolkit::FlexContainer::WrapType FlexContainer::GetFlexWrap()
263 {
264   return mFlexWrap;
265 }
266
267 void FlexContainer::SetJustifyContent( Toolkit::FlexContainer::Justification justifyContent )
268 {
269   if( mJustifyContent != justifyContent )
270   {
271     mJustifyContent = justifyContent;
272     YGNodeStyleSetJustifyContent( mRootNode.node, static_cast<YGJustify>( justifyContent ) );
273
274     RelayoutRequest();
275   }
276 }
277
278 Toolkit::FlexContainer::Justification FlexContainer::GetJustifyContent()
279 {
280   return mJustifyContent;
281 }
282
283 void FlexContainer::SetAlignItems( Toolkit::FlexContainer::Alignment alignItems )
284 {
285   if( mAlignItems != alignItems )
286   {
287     mAlignItems = alignItems;
288     YGNodeStyleSetAlignItems( mRootNode.node, static_cast<YGAlign>( alignItems ) );
289
290     RelayoutRequest();
291   }
292 }
293
294 Toolkit::FlexContainer::Alignment FlexContainer::GetAlignItems()
295 {
296   return mAlignItems;
297 }
298
299 void FlexContainer::SetAlignContent( Toolkit::FlexContainer::Alignment alignContent )
300 {
301   if( mAlignContent != alignContent )
302   {
303     mAlignContent = alignContent;
304     YGNodeStyleSetAlignContent( mRootNode.node, static_cast<YGAlign>( alignContent ) );
305
306     RelayoutRequest();
307   }
308 }
309
310 Toolkit::FlexContainer::Alignment FlexContainer::GetAlignContent()
311 {
312   return mAlignContent;
313 }
314
315 void FlexContainer::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
316 {
317   Toolkit::FlexContainer flexContainer = Toolkit::FlexContainer::DownCast( Dali::BaseHandle( object ) );
318
319   if( flexContainer )
320   {
321     FlexContainer& flexContainerImpl( GetImpl( flexContainer ) );
322     switch( index )
323     {
324       case Toolkit::FlexContainer::Property::CONTENT_DIRECTION:
325       {
326         Toolkit::FlexContainer::ContentDirection contentDirection( Toolkit::FlexContainer::INHERIT );
327
328         if( value.GetType() == Property::INTEGER )
329         {
330           flexContainerImpl.SetContentDirection( static_cast<Toolkit::FlexContainer::ContentDirection>( value.Get< int >() ) );
331         }
332         else if( Scripting::GetEnumeration< Toolkit::FlexContainer::ContentDirection >( value.Get< std::string >().c_str(),
333                                                                                    CONTENT_DIRECTION_STRING_TABLE,
334                                                                                    CONTENT_DIRECTION_STRING_TABLE_COUNT,
335                                                                                    contentDirection ) )
336         {
337           flexContainerImpl.SetContentDirection(contentDirection);
338         }
339         break;
340       }
341       case Toolkit::FlexContainer::Property::FLEX_DIRECTION:
342       {
343         Toolkit::FlexContainer::FlexDirection flexDirection( Toolkit::FlexContainer::COLUMN );
344
345         if( value.GetType() == Property::INTEGER )
346         {
347           flexContainerImpl.SetFlexDirection( static_cast<Toolkit::FlexContainer::FlexDirection>( value.Get< int >() ) );
348         }
349         else if( Scripting::GetEnumeration< Toolkit::FlexContainer::FlexDirection >( value.Get< std::string >().c_str(),
350                                                                                 FLEX_DIRECTION_STRING_TABLE,
351                                                                                 FLEX_DIRECTION_STRING_TABLE_COUNT,
352                                                                                 flexDirection ) )
353         {
354           flexContainerImpl.SetFlexDirection(flexDirection);
355         }
356         break;
357       }
358       case Toolkit::FlexContainer::Property::FLEX_WRAP:
359       {
360         Toolkit::FlexContainer::WrapType flexWrap( Toolkit::FlexContainer::NO_WRAP );
361
362         if( value.GetType() == Property::INTEGER )
363         {
364           flexContainerImpl.SetFlexWrap( static_cast<Toolkit::FlexContainer::WrapType>( value.Get< int >() ) );
365         }
366         else if( Scripting::GetEnumeration< Toolkit::FlexContainer::WrapType >( value.Get< std::string >().c_str(),
367                                                                            FLEX_WRAP_STRING_TABLE,
368                                                                            FLEX_WRAP_STRING_TABLE_COUNT,
369                                                                            flexWrap ) )
370         {
371           flexContainerImpl.SetFlexWrap(flexWrap);
372         }
373         break;
374       }
375       case Toolkit::FlexContainer::Property::JUSTIFY_CONTENT:
376       {
377         Toolkit::FlexContainer::Justification justifyContent( Toolkit::FlexContainer::JUSTIFY_FLEX_START );
378
379         if( value.GetType() == Property::INTEGER )
380         {
381           flexContainerImpl.SetJustifyContent( static_cast<Toolkit::FlexContainer::Justification>( value.Get< int >() ) );
382         }
383         else if( Scripting::GetEnumeration< Toolkit::FlexContainer::Justification >( value.Get< std::string >().c_str(),
384                                                                                 JUSTIFY_CONTENT_STRING_TABLE,
385                                                                                 JUSTIFY_CONTENT_STRING_TABLE_COUNT,
386                                                                                 justifyContent ) )
387         {
388           flexContainerImpl.SetJustifyContent(justifyContent);
389         }
390         break;
391       }
392       case Toolkit::FlexContainer::Property::ALIGN_ITEMS:
393       {
394         Toolkit::FlexContainer::Alignment alignItems( Toolkit::FlexContainer::ALIGN_STRETCH );
395
396         if( value.GetType() == Property::INTEGER )
397         {
398           flexContainerImpl.SetAlignItems( static_cast<Toolkit::FlexContainer::Alignment>( value.Get< int >() ) );
399         }
400         else if( Scripting::GetEnumeration< Toolkit::FlexContainer::Alignment >( value.Get< std::string >().c_str(),
401                                                                             ALIGN_ITEMS_STRING_TABLE,
402                                                                             ALIGN_ITEMS_STRING_TABLE_COUNT,
403                                                                             alignItems ) )
404         {
405           flexContainerImpl.SetAlignItems(alignItems);
406         }
407         break;
408       }
409       case Toolkit::FlexContainer::Property::ALIGN_CONTENT:
410       {
411         Toolkit::FlexContainer::Alignment alignContent( Toolkit::FlexContainer::ALIGN_FLEX_START );
412
413         if( value.GetType() == Property::INTEGER )
414         {
415           flexContainerImpl.SetAlignContent( static_cast<Toolkit::FlexContainer::Alignment>( value.Get< int >() ) );
416         }
417         else if( Scripting::GetEnumeration< Toolkit::FlexContainer::Alignment >( value.Get< std::string >().c_str(),
418                                                                             ALIGN_CONTENT_STRING_TABLE,
419                                                                             ALIGN_CONTENT_STRING_TABLE_COUNT,
420                                                                             alignContent ) )
421         {
422           flexContainerImpl.SetAlignContent(alignContent);
423         }
424         break;
425       }
426     }
427   }
428 }
429
430 Property::Value FlexContainer::GetProperty( BaseObject* object, Property::Index index )
431 {
432   Property::Value value;
433
434   Toolkit::FlexContainer flexContainer = Toolkit::FlexContainer::DownCast( Dali::BaseHandle( object ) );
435
436   if( flexContainer )
437   {
438     FlexContainer& flexContainerImpl( GetImpl( flexContainer ) );
439     switch( index )
440     {
441       case Toolkit::FlexContainer::Property::CONTENT_DIRECTION:
442       {
443         value = flexContainerImpl.GetContentDirection();
444         break;
445       }
446       case Toolkit::FlexContainer::Property::FLEX_DIRECTION:
447       {
448         value = flexContainerImpl.GetFlexDirection();
449         break;
450       }
451       case Toolkit::FlexContainer::Property::FLEX_WRAP:
452       {
453         value = flexContainerImpl.GetFlexWrap();
454         break;
455       }
456       case Toolkit::FlexContainer::Property::JUSTIFY_CONTENT:
457       {
458         value = flexContainerImpl.GetJustifyContent();
459         break;
460       }
461       case Toolkit::FlexContainer::Property::ALIGN_ITEMS:
462       {
463         value = flexContainerImpl.GetAlignItems();
464         break;
465       }
466       case Toolkit::FlexContainer::Property::ALIGN_CONTENT:
467       {
468         value = flexContainerImpl.GetAlignContent();
469         break;
470       }
471     }
472   }
473
474   return value;
475 }
476
477 void FlexContainer::OnChildAdd( Actor& child )
478 {
479   // Create a new node for the child.
480   FlexItemNode childNode;
481   childNode.actor = child;
482   childNode.node = YGNodeNew();
483
484   mChildrenNodes.push_back( childNode );
485   YGNodeInsertChild( mRootNode.node, childNode.node, mChildrenNodes.size() - 1 );
486
487   Control::OnChildAdd( child );
488 }
489
490 void FlexContainer::OnChildRemove( Actor& child )
491 {
492   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
493   {
494     if( mChildrenNodes[i].actor.GetHandle() == child )
495     {
496       YGNodeRemoveChild( mRootNode.node, mChildrenNodes[i].node );
497       YGNodeFree( mChildrenNodes[i].node );
498
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       // Anchor actor to top left of the container
518       if( child.GetProperty( Actor::Property::POSITION_USES_ANCHOR_POINT ).Get< bool >() )
519       {
520         child.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
521       }
522       child.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
523
524       float negotiatedWidth = child.GetRelayoutSize(Dimension::WIDTH);
525       float negotiatedHeight = child.GetRelayoutSize(Dimension::HEIGHT);
526
527       if( negotiatedWidth > 0 )
528       {
529         YGNodeStyleSetWidth( mChildrenNodes[i].node, negotiatedWidth );
530       }
531       if( negotiatedHeight > 0 )
532       {
533         YGNodeStyleSetHeight( mChildrenNodes[i].node, negotiatedHeight );
534       }
535     }
536   }
537
538   // Relayout the container
539   RelayoutChildren();
540 #if defined(FLEX_CONTAINER_DEBUG)
541   PrintNodes( mChildrenNodes );
542 #endif
543
544   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
545   {
546     Actor child = mChildrenNodes[i].actor.GetHandle();
547     if( child )
548     {
549       if( child.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX ) != Property::NONE )
550       {
551         // Only Set to USE_ASSIGNED_SIZE if the child actor is flexible.
552
553         if( child.GetResizePolicy( Dimension::WIDTH ) != ResizePolicy::USE_ASSIGNED_SIZE )
554         {
555           child.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::WIDTH );
556         }
557         if( child.GetResizePolicy( Dimension::HEIGHT ) != ResizePolicy::USE_ASSIGNED_SIZE )
558         {
559           child.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::HEIGHT );
560         }
561       }
562       container.Add( child, Vector2(YGNodeLayoutGetWidth(mChildrenNodes[i].node), YGNodeLayoutGetHeight(mChildrenNodes[i].node) ) );
563     }
564   }
565 }
566
567 bool FlexContainer::RelayoutDependentOnChildren( Dimension::Type dimension )
568 {
569   return true;
570 }
571
572 void FlexContainer::OnSizeSet( const Vector3& size )
573 {
574   if( mRootNode.node )
575   {
576     Actor self = Self();
577     YGNodeStyleSetWidth( mRootNode.node, size.x );
578     YGNodeStyleSetHeight( mRootNode.node, size.y );
579
580     RelayoutRequest();
581   }
582
583   Control::OnSizeSet( size );
584 }
585
586 void FlexContainer::OnLayoutDirectionChanged( Dali::Actor actor, Dali::LayoutDirection::Type type )
587 {
588   Toolkit::FlexContainer flexContainer = Toolkit::FlexContainer::DownCast(actor);
589   Toolkit::FlexContainer::ContentDirection direction;
590
591   if( type == Dali::LayoutDirection::RIGHT_TO_LEFT )
592   {
593     direction = Toolkit::FlexContainer::RTL;
594   }
595   else
596   {
597     direction = Toolkit::FlexContainer::LTR;
598   }
599
600   Toolkit::Internal::FlexContainer &flexContainerImpl = GetImpl( flexContainer );
601
602   if( flexContainerImpl.mContentDirection != direction )
603   {
604     Dali::CustomActor ownerActor(flexContainerImpl.GetOwner());
605     flexContainerImpl.mContentDirection = direction;
606
607     flexContainerImpl.RelayoutRequest();
608   }
609 }
610
611 void FlexContainer::ComputeLayout()
612 {
613   if( mRootNode.node )
614   {
615     for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
616     {
617       YGNodeRef childNode = mChildrenNodes[i].node;
618       Actor childActor = mChildrenNodes[i].actor.GetHandle();
619
620       // Intialize the style of the child.
621       YGNodeStyleSetMinWidth( childNode, childActor.GetProperty< Vector2 >( Actor::Property::MINIMUM_SIZE ).x );
622       YGNodeStyleSetMinHeight( childNode, childActor.GetProperty< Vector2 >( Actor::Property::MINIMUM_SIZE ).y );
623       YGNodeStyleSetMaxWidth( childNode, childActor.GetProperty< Vector2 >( Actor::Property::MAXIMUM_SIZE ).x );
624       YGNodeStyleSetMaxHeight( childNode, childActor.GetProperty< Vector2 >( Actor::Property::MAXIMUM_SIZE ).y );
625
626       // Check child properties on the child for how to layout it.
627       // These properties should be dynamically registered to the child which
628       // would be added to FlexContainer.
629
630       if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX ) != Property::NONE )
631       {
632         YGNodeStyleSetFlex( childNode, childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX ).Get<float>() );
633       }
634
635       Toolkit::FlexContainer::Alignment alignSelf( Toolkit::FlexContainer::ALIGN_AUTO );
636       if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::ALIGN_SELF ) != Property::NONE )
637       {
638         Property::Value alignSelfPropertyValue = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::ALIGN_SELF );
639         if( alignSelfPropertyValue.GetType() == Property::INTEGER )
640         {
641           alignSelf = static_cast<Toolkit::FlexContainer::Alignment>( alignSelfPropertyValue.Get< int >() );
642         }
643         else if( alignSelfPropertyValue.GetType() == Property::STRING )
644         {
645           std::string value = alignSelfPropertyValue.Get<std::string>();
646           Scripting::GetEnumeration< Toolkit::FlexContainer::Alignment >( value.c_str(),
647                                                                           ALIGN_SELF_STRING_TABLE,
648                                                                           ALIGN_SELF_STRING_TABLE_COUNT,
649                                                                           alignSelf );
650         }
651         YGNodeStyleSetAlignSelf( childNode, static_cast<YGAlign>(alignSelf) );
652       }
653
654       if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN ) != Property::NONE )
655       {
656         Vector4 flexMargin = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN ).Get<Vector4>();
657         YGNodeStyleSetMargin( childNode, YGEdgeLeft, flexMargin.x );
658         YGNodeStyleSetMargin( childNode, YGEdgeTop, flexMargin.y );
659         YGNodeStyleSetMargin( childNode, YGEdgeRight, flexMargin.z );
660         YGNodeStyleSetMargin( childNode, YGEdgeBottom, flexMargin.w );
661       }
662     }
663
664     // Calculate the layout
665     YGDirection nodeLayoutDirection = YGDirectionInherit;
666     switch( mContentDirection )
667     {
668     case Dali::Toolkit::FlexContainer::LTR:
669     {
670       nodeLayoutDirection = YGDirectionLTR;
671       break;
672     }
673
674     case Dali::Toolkit::FlexContainer::RTL:
675     {
676       nodeLayoutDirection = YGDirectionRTL;
677       break;
678     }
679
680     case Dali::Toolkit::FlexContainer::INHERIT:
681     {
682       nodeLayoutDirection = YGDirectionInherit;
683       break;
684     }
685     }
686
687 #if defined(FLEX_CONTAINER_DEBUG)
688     YGNodePrint( mRootNode.node, (YGPrintOptions)( YGPrintOptionsLayout | YGPrintOptionsStyle | YGPrintOptionsChildren ) );
689 #endif
690     YGNodeCalculateLayout( mRootNode.node, Self().GetProperty< Vector2 >( Actor::Property::MAXIMUM_SIZE ).x, Self().GetProperty< Vector2 >( Actor::Property::MAXIMUM_SIZE ).y, nodeLayoutDirection );
691 #if defined(FLEX_CONTAINER_DEBUG)
692     YGNodePrint( mRootNode.node, (YGPrintOptions)( YGPrintOptionsLayout | YGPrintOptionsStyle | YGPrintOptionsChildren ) );
693 #endif
694   }
695 }
696
697 void FlexContainer::RelayoutChildren()
698 {
699   ComputeLayout();
700
701   // Set size and position of children according to the layout calculation
702   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
703   {
704     Dali::Actor child = mChildrenNodes[i].actor.GetHandle();
705     if( child )
706     {
707       child.SetProperty( Actor::Property::POSITION_X,  YGNodeLayoutGetLeft( mChildrenNodes[i].node ) );
708       child.SetProperty( Actor::Property::POSITION_Y,  YGNodeLayoutGetTop( mChildrenNodes[i].node ) );
709     }
710   }
711 }
712
713 Actor FlexContainer::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
714 {
715   Actor nextFocusableActor;
716
717   // First check whether there is any items in the container
718   if( mChildrenNodes.size() > 0 )
719   {
720     if ( !currentFocusedActor || currentFocusedActor == Self() )
721     {
722       // Nothing is currently focused, so the first child in the container should be focused.
723       nextFocusableActor = mChildrenNodes[0].actor.GetHandle();
724     }
725     else
726     {
727       // Check whether the current focused actor is within flex container
728       int currentFocusedActorIndex = -1;
729       for( unsigned int index = 0; index < mChildrenNodes.size(); index++ )
730       {
731         if( currentFocusedActor == mChildrenNodes[index].actor.GetHandle() )
732         {
733           currentFocusedActorIndex = index;
734           break;
735         }
736       }
737
738       if( currentFocusedActorIndex > -1 )
739       {
740         int previousCheckedActorIndex = -1;
741         int nextFocusedActorIndex = currentFocusedActorIndex;
742         switch ( direction )
743         {
744           case Toolkit::Control::KeyboardFocus::LEFT:
745           case Toolkit::Control::KeyboardFocus::UP:
746           {
747             // Search the next focusable actor in the backward direction
748             do
749             {
750               nextFocusedActorIndex--;
751               if( nextFocusedActorIndex < 0 )
752               {
753                 nextFocusedActorIndex = loopEnabled ? mChildrenNodes.size() - 1 : 0;
754               }
755               if( nextFocusedActorIndex != previousCheckedActorIndex && nextFocusedActorIndex != currentFocusedActorIndex )
756               {
757                 previousCheckedActorIndex = nextFocusedActorIndex;
758               }
759               else
760               {
761                 break;
762               }
763             } while ( !mChildrenNodes[nextFocusedActorIndex].actor.GetHandle().GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) );
764             break;
765           }
766           case Toolkit::Control::KeyboardFocus::RIGHT:
767           case Toolkit::Control::KeyboardFocus::DOWN:
768           {
769             // Search the next focusable actor in the forward direction
770             do
771             {
772               nextFocusedActorIndex++;
773               if( nextFocusedActorIndex > static_cast<int>(mChildrenNodes.size() - 1) )
774               {
775                 nextFocusedActorIndex = loopEnabled ? 0 : mChildrenNodes.size() - 1;
776               }
777               if( nextFocusedActorIndex != previousCheckedActorIndex && nextFocusedActorIndex != currentFocusedActorIndex )
778               {
779                 previousCheckedActorIndex = nextFocusedActorIndex;
780               }
781               else
782               {
783                 break;
784               }
785             } while ( !mChildrenNodes[nextFocusedActorIndex].actor.GetHandle().GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) );
786             break;
787           }
788           default:
789           {
790             break;
791           }
792         }
793
794         if( nextFocusedActorIndex != currentFocusedActorIndex )
795         {
796           nextFocusableActor = mChildrenNodes[nextFocusedActorIndex].actor.GetHandle();
797         }
798         else
799         {
800           // No focusble child in the container
801           nextFocusableActor = Actor();
802         }
803       }
804       else
805       {
806         // The current focused actor is not within flex container, so the first child in the container should be focused.
807         nextFocusableActor = mChildrenNodes[0].actor.GetHandle();
808       }
809     }
810   }
811
812   return nextFocusableActor;
813 }
814
815 FlexContainer::FlexContainer()
816 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
817   mContentDirection( Toolkit::FlexContainer::INHERIT ),
818   mFlexDirection( Toolkit::FlexContainer::COLUMN ),
819   mFlexWrap( Toolkit::FlexContainer::NO_WRAP ),
820   mJustifyContent( Toolkit::FlexContainer::JUSTIFY_FLEX_START ),
821   mAlignItems( Toolkit::FlexContainer::ALIGN_STRETCH ),
822   mAlignContent( Toolkit::FlexContainer::ALIGN_FLEX_START )
823 {
824   SetKeyboardNavigationSupport( true );
825 }
826
827 void FlexContainer::OnInitialize()
828 {
829   // Initialize the node for the flex container itself
830   Dali::Actor self = Self();
831   self.LayoutDirectionChangedSignal().Connect( this, &FlexContainer::OnLayoutDirectionChanged );
832
833   mRootNode.actor = self;
834   mRootNode.node = YGNodeNew();
835   YGNodeSetContext( mRootNode.node, &mChildrenNodes );
836
837   // Set default style
838   YGNodeStyleSetFlexDirection( mRootNode.node, static_cast<YGFlexDirection>( mFlexDirection ) );
839   YGNodeStyleSetFlexWrap( mRootNode.node, static_cast<YGWrap>( mFlexWrap ) );
840   YGNodeStyleSetJustifyContent( mRootNode.node, static_cast<YGJustify>( mJustifyContent ) );
841   YGNodeStyleSetAlignItems( mRootNode.node, static_cast<YGAlign>( mAlignItems ) );
842   YGNodeStyleSetAlignContent( mRootNode.node, static_cast<YGAlign>( mAlignContent ) );
843
844   // Make self as keyboard focusable and focus group
845   self.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE, true );
846   SetAsKeyboardFocusGroup( true );
847 }
848
849 } // namespace Internal
850
851 } // namespace Toolkit
852
853 } // namespace Dali