2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/controls/flex-container/flex-container-impl.h>
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/scripting/scripting.h>
27 #include <dali/public-api/size-negotiation/relayout-container.h>
28 #include <dali/integration-api/debug.h>
35 #if defined(DEBUG_ENABLED)
36 // debugging support, very useful when new features are added or bugs are hunted down
37 // currently not called from code so compiler will optimize these away, kept here for future debugging
39 #define FLEX_CONTAINER_TAG "DALI Toolkit::FlexContainer "
40 #define FC_LOG(fmt, args...) Debug::LogMessage(Debug::DebugInfo, FLEX_CONTAINER_TAG fmt, ## args)
41 //#define FLEX_CONTAINER_DEBUG 1
43 #if defined(FLEX_CONTAINER_DEBUG)
44 void PrintNode( Toolkit::Internal::FlexContainer::FlexItemNodeContainer itemNodes )
46 // Print the style property and layout of all the children
47 for( unsigned int i = 0; i < itemNodes.size(); ++i )
49 FC_LOG( "Item %d style: \n", i );
50 print_css_node( itemNodes[i].node, (css_print_options_t)( CSS_PRINT_STYLE | CSS_PRINT_CHILDREN ) );
51 FC_LOG( "Item %d layout: \n", i );
52 print_css_node( itemNodes[i].node, (css_print_options_t)( CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN ) );
57 #endif // defined(FLEX_CONTAINER_DEBUG)
58 #endif // defined(DEBUG_ENABLED)
78 return Toolkit::FlexContainer::New();
81 // Setup properties, signals and actions using the type-registry.
82 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::FlexContainer, Toolkit::Control, Create );
84 DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "contentDirection", INTEGER, CONTENT_DIRECTION )
85 DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "flexDirection", INTEGER, FLEX_DIRECTION )
86 DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "flexWrap", INTEGER, FLEX_WRAP )
87 DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "justifyContent", INTEGER, JUSTIFY_CONTENT )
88 DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "alignItems", INTEGER, ALIGN_ITEMS )
89 DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "alignContent", INTEGER, ALIGN_CONTENT )
90 DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "flex", FLOAT, FLEX )
91 DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "alignSelf", INTEGER, ALIGN_SELF )
92 DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "flexMargin", VECTOR4, FLEX_MARGIN )
94 DALI_TYPE_REGISTRATION_END()
96 const Scripting::StringEnum ALIGN_SELF_STRING_TABLE[] =
98 { "auto", Toolkit::FlexContainer::ALIGN_AUTO },
99 { "flexStart", Toolkit::FlexContainer::ALIGN_FLEX_START },
100 { "center", Toolkit::FlexContainer::ALIGN_CENTER },
101 { "flexEnd", Toolkit::FlexContainer::ALIGN_FLEX_END },
102 { "stretch", Toolkit::FlexContainer::ALIGN_STRETCH }
104 const unsigned int ALIGN_SELF_STRING_TABLE_COUNT = sizeof( ALIGN_SELF_STRING_TABLE ) / sizeof( ALIGN_SELF_STRING_TABLE[0] );
106 const Scripting::StringEnum CONTENT_DIRECTION_STRING_TABLE[] =
108 { "inherit", Toolkit::FlexContainer::INHERIT },
109 { "LTR", Toolkit::FlexContainer::LTR },
110 { "RTL", Toolkit::FlexContainer::RTL }
112 const unsigned int CONTENT_DIRECTION_STRING_TABLE_COUNT = sizeof( CONTENT_DIRECTION_STRING_TABLE ) / sizeof( CONTENT_DIRECTION_STRING_TABLE[0] );
114 const Scripting::StringEnum FLEX_DIRECTION_STRING_TABLE[] =
116 { "column", Toolkit::FlexContainer::COLUMN },
117 { "columnReverse", Toolkit::FlexContainer::COLUMN_REVERSE },
118 { "row", Toolkit::FlexContainer::ROW },
119 { "rowReverse", Toolkit::FlexContainer::ROW_REVERSE }
121 const unsigned int FLEX_DIRECTION_STRING_TABLE_COUNT = sizeof( FLEX_DIRECTION_STRING_TABLE ) / sizeof( FLEX_DIRECTION_STRING_TABLE[0] );
123 const Scripting::StringEnum FLEX_WRAP_STRING_TABLE[] =
125 { "noWrap", Toolkit::FlexContainer::NO_WRAP },
126 { "wrap", Toolkit::FlexContainer::WRAP }
128 const unsigned int FLEX_WRAP_STRING_TABLE_COUNT = sizeof( FLEX_WRAP_STRING_TABLE ) / sizeof( FLEX_WRAP_STRING_TABLE[0] );
130 const Scripting::StringEnum JUSTIFY_CONTENT_STRING_TABLE[] =
132 { "flexStart", Toolkit::FlexContainer::JUSTIFY_FLEX_START },
133 { "center", Toolkit::FlexContainer::JUSTIFY_CENTER },
134 { "flexEnd", Toolkit::FlexContainer::JUSTIFY_FLEX_END },
135 { "spaceBetween", Toolkit::FlexContainer::JUSTIFY_SPACE_BETWEEN },
136 { "spaceAround", Toolkit::FlexContainer::JUSTIFY_SPACE_AROUND }
138 const unsigned int JUSTIFY_CONTENT_STRING_TABLE_COUNT = sizeof( JUSTIFY_CONTENT_STRING_TABLE ) / sizeof( JUSTIFY_CONTENT_STRING_TABLE[0] );
140 const Scripting::StringEnum ALIGN_ITEMS_STRING_TABLE[] =
142 { "flexStart", Toolkit::FlexContainer::ALIGN_FLEX_START },
143 { "center", Toolkit::FlexContainer::ALIGN_CENTER },
144 { "flexEnd", Toolkit::FlexContainer::ALIGN_FLEX_END },
145 { "stretch", Toolkit::FlexContainer::ALIGN_STRETCH }
147 const unsigned int ALIGN_ITEMS_STRING_TABLE_COUNT = sizeof( ALIGN_ITEMS_STRING_TABLE ) / sizeof( ALIGN_ITEMS_STRING_TABLE[0] );
149 const Scripting::StringEnum ALIGN_CONTENT_STRING_TABLE[] =
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 }
156 const unsigned int ALIGN_CONTENT_STRING_TABLE_COUNT = sizeof( ALIGN_CONTENT_STRING_TABLE ) / sizeof( ALIGN_CONTENT_STRING_TABLE[0] );
159 * The function used by the layout algorithm to be get the style properties
160 * and layout information of the child at the given index.
162 css_node_t* GetChildNodeAtIndex( void *childrenNodes, int i )
164 FlexContainer::FlexItemNodeContainer childrenNodeContainer = *( static_cast<FlexContainer::FlexItemNodeContainer*>( childrenNodes ) );
165 return childrenNodeContainer[i].node;
169 * The function used by the layout algorithm to check whether the node is dirty
172 bool IsNodeDirty( void *itemNodes )
174 // We only calculate the layout when the child is added or removed, or when
175 // style properties are changed. So should always return true here.
179 } // Unnamed namespace
181 Toolkit::FlexContainer FlexContainer::New()
183 // Create the implementation, temporarily owned by this handle on stack
184 IntrusivePtr< FlexContainer > impl = new FlexContainer();
186 // Pass ownership to CustomActor handle
187 Toolkit::FlexContainer handle( *impl );
189 // Second-phase init of the implementation
190 // This can only be done after the CustomActor connection has been made...
196 FlexContainer::~FlexContainer()
198 free_css_node( mRootNode.node );
200 for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
202 free_css_node( mChildrenNodes[i].node );
205 mChildrenNodes.clear();
208 void FlexContainer::SetContentDirection( Toolkit::FlexContainer::ContentDirection contentDirection )
210 if( mContentDirection != contentDirection )
212 mContentDirection = contentDirection;
213 mRootNode.node->style.direction = static_cast<css_direction_t>( mContentDirection );
219 Toolkit::FlexContainer::ContentDirection FlexContainer::GetContentDirection()
221 return mContentDirection;
224 void FlexContainer::SetFlexDirection( Toolkit::FlexContainer::FlexDirection flexDirection )
226 if( mFlexDirection != flexDirection )
228 mFlexDirection = flexDirection;
229 mRootNode.node->style.flex_direction = static_cast<css_flex_direction_t>( mFlexDirection );
235 Toolkit::FlexContainer::FlexDirection FlexContainer::GetFlexDirection()
237 return mFlexDirection;
240 void FlexContainer::SetFlexWrap( Toolkit::FlexContainer::WrapType flexWrap )
242 if( mFlexWrap != flexWrap )
244 mFlexWrap = flexWrap;
245 mRootNode.node->style.flex_wrap = static_cast<css_wrap_type_t>( mFlexWrap );
251 Toolkit::FlexContainer::WrapType FlexContainer::GetFlexWrap()
256 void FlexContainer::SetJustifyContent( Toolkit::FlexContainer::Justification justifyContent )
258 if( mJustifyContent != justifyContent )
260 mJustifyContent = justifyContent;
261 mRootNode.node->style.justify_content = static_cast<css_justify_t>( mJustifyContent );
267 Toolkit::FlexContainer::Justification FlexContainer::GetJustifyContent()
269 return mJustifyContent;
272 void FlexContainer::SetAlignItems( Toolkit::FlexContainer::Alignment alignItems )
274 if( mAlignItems != alignItems )
276 mAlignItems = alignItems;
277 mRootNode.node->style.align_items = static_cast<css_align_t>( mAlignItems );
283 Toolkit::FlexContainer::Alignment FlexContainer::GetAlignItems()
288 void FlexContainer::SetAlignContent( Toolkit::FlexContainer::Alignment alignContent )
290 if( mAlignContent != alignContent )
292 mAlignContent = alignContent;
293 mRootNode.node->style.align_content = static_cast<css_align_t>( mAlignContent );
299 Toolkit::FlexContainer::Alignment FlexContainer::GetAlignContent()
301 return mAlignContent;
304 void FlexContainer::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
306 Toolkit::FlexContainer flexContainer = Toolkit::FlexContainer::DownCast( Dali::BaseHandle( object ) );
310 FlexContainer& flexContainerImpl( GetImpl( flexContainer ) );
313 case Toolkit::FlexContainer::Property::CONTENT_DIRECTION:
315 Toolkit::FlexContainer::ContentDirection contentDirection( Toolkit::FlexContainer::INHERIT );
317 if( value.GetType() == Property::INTEGER )
319 flexContainerImpl.SetContentDirection( static_cast<Toolkit::FlexContainer::ContentDirection>( value.Get< int >() ) );
321 else if( Scripting::GetEnumeration< Toolkit::FlexContainer::ContentDirection >( value.Get< std::string >().c_str(),
322 CONTENT_DIRECTION_STRING_TABLE,
323 CONTENT_DIRECTION_STRING_TABLE_COUNT,
326 flexContainerImpl.SetContentDirection(contentDirection);
330 case Toolkit::FlexContainer::Property::FLEX_DIRECTION:
332 Toolkit::FlexContainer::FlexDirection flexDirection( Toolkit::FlexContainer::COLUMN );
334 if( value.GetType() == Property::INTEGER )
336 flexContainerImpl.SetFlexDirection( static_cast<Toolkit::FlexContainer::FlexDirection>( value.Get< int >() ) );
338 else if( Scripting::GetEnumeration< Toolkit::FlexContainer::FlexDirection >( value.Get< std::string >().c_str(),
339 FLEX_DIRECTION_STRING_TABLE,
340 FLEX_DIRECTION_STRING_TABLE_COUNT,
343 flexContainerImpl.SetFlexDirection(flexDirection);
347 case Toolkit::FlexContainer::Property::FLEX_WRAP:
349 Toolkit::FlexContainer::WrapType flexWrap( Toolkit::FlexContainer::NO_WRAP );
351 if( value.GetType() == Property::INTEGER )
353 flexContainerImpl.SetFlexWrap( static_cast<Toolkit::FlexContainer::WrapType>( value.Get< int >() ) );
355 else if( Scripting::GetEnumeration< Toolkit::FlexContainer::WrapType >( value.Get< std::string >().c_str(),
356 FLEX_WRAP_STRING_TABLE,
357 FLEX_WRAP_STRING_TABLE_COUNT,
360 flexContainerImpl.SetFlexWrap(flexWrap);
364 case Toolkit::FlexContainer::Property::JUSTIFY_CONTENT:
366 Toolkit::FlexContainer::Justification justifyContent( Toolkit::FlexContainer::JUSTIFY_FLEX_START );
368 if( value.GetType() == Property::INTEGER )
370 flexContainerImpl.SetJustifyContent( static_cast<Toolkit::FlexContainer::Justification>( value.Get< int >() ) );
372 else if( Scripting::GetEnumeration< Toolkit::FlexContainer::Justification >( value.Get< std::string >().c_str(),
373 JUSTIFY_CONTENT_STRING_TABLE,
374 JUSTIFY_CONTENT_STRING_TABLE_COUNT,
377 flexContainerImpl.SetJustifyContent(justifyContent);
381 case Toolkit::FlexContainer::Property::ALIGN_ITEMS:
383 Toolkit::FlexContainer::Alignment alignItems( Toolkit::FlexContainer::ALIGN_STRETCH );
385 if( value.GetType() == Property::INTEGER )
387 flexContainerImpl.SetAlignItems( static_cast<Toolkit::FlexContainer::Alignment>( value.Get< int >() ) );
389 else if( Scripting::GetEnumeration< Toolkit::FlexContainer::Alignment >( value.Get< std::string >().c_str(),
390 ALIGN_ITEMS_STRING_TABLE,
391 ALIGN_ITEMS_STRING_TABLE_COUNT,
394 flexContainerImpl.SetAlignItems(alignItems);
398 case Toolkit::FlexContainer::Property::ALIGN_CONTENT:
400 Toolkit::FlexContainer::Alignment alignContent( Toolkit::FlexContainer::ALIGN_FLEX_START );
402 if( value.GetType() == Property::INTEGER )
404 flexContainerImpl.SetAlignContent( static_cast<Toolkit::FlexContainer::Alignment>( value.Get< int >() ) );
406 else if( Scripting::GetEnumeration< Toolkit::FlexContainer::Alignment >( value.Get< std::string >().c_str(),
407 ALIGN_CONTENT_STRING_TABLE,
408 ALIGN_CONTENT_STRING_TABLE_COUNT,
411 flexContainerImpl.SetAlignContent(alignContent);
419 Property::Value FlexContainer::GetProperty( BaseObject* object, Property::Index index )
421 Property::Value value;
423 Toolkit::FlexContainer flexContainer = Toolkit::FlexContainer::DownCast( Dali::BaseHandle( object ) );
427 FlexContainer& flexContainerImpl( GetImpl( flexContainer ) );
430 case Toolkit::FlexContainer::Property::CONTENT_DIRECTION:
432 value = flexContainerImpl.GetContentDirection();
435 case Toolkit::FlexContainer::Property::FLEX_DIRECTION:
437 value = flexContainerImpl.GetFlexDirection();
440 case Toolkit::FlexContainer::Property::FLEX_WRAP:
442 value = flexContainerImpl.GetFlexWrap();
445 case Toolkit::FlexContainer::Property::JUSTIFY_CONTENT:
447 value = flexContainerImpl.GetJustifyContent();
450 case Toolkit::FlexContainer::Property::ALIGN_ITEMS:
452 value = flexContainerImpl.GetAlignItems();
455 case Toolkit::FlexContainer::Property::ALIGN_CONTENT:
457 value = flexContainerImpl.GetAlignContent();
466 void FlexContainer::OnChildAdd( Actor& child )
468 Control::OnChildAdd( child );
470 // Anchor actor to top left of the container
471 child.SetAnchorPoint( AnchorPoint::TOP_LEFT );
472 child.SetParentOrigin( ParentOrigin::TOP_LEFT );
474 // Create a new node for the child.
475 FlexItemNode childNode;
476 childNode.actor = child;
477 childNode.node = new_css_node();
478 childNode.node->get_child = GetChildNodeAtIndex;
479 childNode.node->is_dirty = IsNodeDirty;
480 mChildrenNodes.push_back(childNode);
483 void FlexContainer::OnChildRemove( Actor& child )
485 for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
487 if( mChildrenNodes[i].actor.GetHandle() == child )
489 free_css_node( mChildrenNodes[i].node );
490 mChildrenNodes.erase( mChildrenNodes.begin() + i );
492 // Relayout the container only if instances were found
498 Control::OnChildRemove( child );
501 void FlexContainer::OnRelayout( const Vector2& size, RelayoutContainer& container )
503 for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
505 Actor child = mChildrenNodes[i].actor.GetHandle();
508 float negotiatedWidth = child.GetRelayoutSize(Dimension::WIDTH);
509 float negotiatedHeight = child.GetRelayoutSize(Dimension::HEIGHT);
511 if( negotiatedWidth > 0 )
513 mChildrenNodes[i].node->style.dimensions[CSS_WIDTH] = negotiatedWidth;
515 if( negotiatedHeight > 0 )
517 mChildrenNodes[i].node->style.dimensions[CSS_HEIGHT] = negotiatedHeight;
522 // Relayout the container
525 for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
527 Actor child = mChildrenNodes[i].actor.GetHandle();
530 if( child.GetResizePolicy( Dimension::WIDTH ) != ResizePolicy::USE_ASSIGNED_SIZE )
532 child.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::WIDTH );
534 if( child.GetResizePolicy( Dimension::HEIGHT ) != ResizePolicy::USE_ASSIGNED_SIZE )
536 child.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::HEIGHT );
539 container.Add( child, Vector2(mChildrenNodes[i].node->layout.dimensions[CSS_WIDTH], mChildrenNodes[i].node->layout.dimensions[CSS_HEIGHT] ) );
544 bool FlexContainer::RelayoutDependentOnChildren( Dimension::Type dimension )
549 void FlexContainer::OnSizeSet( const Vector3& size )
555 mRootNode.node->style.dimensions[CSS_WIDTH] = size.x;
556 mRootNode.node->style.dimensions[CSS_HEIGHT] = size.y;
562 void FlexContainer::OnSizeAnimation( Animation& animation, const Vector3& targetSize )
564 // @todo Animate the children to their target size and position
567 void FlexContainer::ComputeLayout()
571 mRootNode.node->children_count = mChildrenNodes.size();
573 // Intialize the layout.
574 mRootNode.node->layout.position[CSS_LEFT] = 0;
575 mRootNode.node->layout.position[CSS_TOP] = 0;
576 mRootNode.node->layout.position[CSS_BOTTOM] = 0;
577 mRootNode.node->layout.position[CSS_RIGHT] = 0;
578 mRootNode.node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
579 mRootNode.node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
581 for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
583 css_node_t* childNode = mChildrenNodes[i].node;
584 Actor childActor = mChildrenNodes[i].actor.GetHandle();
586 childNode->layout.position[CSS_LEFT] = 0;
587 childNode->layout.position[CSS_TOP] = 0;
588 childNode->layout.position[CSS_BOTTOM] = 0;
589 childNode->layout.position[CSS_RIGHT] = 0;
590 childNode->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
591 childNode->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
593 // Intialize the style of the child.
594 childNode->style.minDimensions[CSS_WIDTH] = childActor.GetMinimumSize().x;
595 childNode->style.minDimensions[CSS_HEIGHT] = childActor.GetMinimumSize().y;
596 childNode->style.maxDimensions[CSS_WIDTH] = childActor.GetMaximumSize().x;
597 childNode->style.maxDimensions[CSS_HEIGHT] = childActor.GetMaximumSize().y;
599 // Check child properties on the child for how to layout it.
600 // These properties should be dynamically registered to the child which
601 // would be added to FlexContainer.
603 if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX ) != Property::NONE )
605 childNode->style.flex = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX ).Get<float>();
608 Toolkit::FlexContainer::Alignment alignSelf( Toolkit::FlexContainer::ALIGN_AUTO );
609 if( childActor.GetPropertyType( Toolkit::FlexContainer::FlexContainer::ChildProperty::ALIGN_SELF ) != Property::NONE )
611 Property::Value alignSelfPropertyValue = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::ALIGN_SELF );
612 if( alignSelfPropertyValue.GetType() == Property::INTEGER )
614 alignSelf = static_cast<Toolkit::FlexContainer::Alignment>( alignSelfPropertyValue.Get< int >() );
616 else if( alignSelfPropertyValue.GetType() == Property::STRING )
618 std::string value = alignSelfPropertyValue.Get<std::string>();
619 Scripting::GetEnumeration< Toolkit::FlexContainer::Alignment >( value.c_str(),
620 ALIGN_SELF_STRING_TABLE,
621 ALIGN_SELF_STRING_TABLE_COUNT,
625 childNode->style.align_self = static_cast<css_align_t>(alignSelf);
627 if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN ) != Property::NONE )
629 Vector4 flexMargin = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN ).Get<Vector4>();
630 childNode->style.margin[CSS_LEFT] = flexMargin.x;
631 childNode->style.margin[CSS_TOP] = flexMargin.y;
632 childNode->style.margin[CSS_RIGHT] = flexMargin.z;
633 childNode->style.margin[CSS_BOTTOM] = flexMargin.w;
637 // Calculate the layout
638 layoutNode( mRootNode.node, Self().GetMaximumSize().x, Self().GetMaximumSize().y, mRootNode.node->style.direction );
642 void FlexContainer::RelayoutChildren()
646 // Set size and position of children according to the layout calculation
647 for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
649 Dali::Actor child = mChildrenNodes[i].actor.GetHandle();
652 child.SetX( mChildrenNodes[i].node->layout.position[CSS_LEFT] );
653 child.SetY( mChildrenNodes[i].node->layout.position[CSS_TOP] );
658 Actor FlexContainer::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
660 Actor nextFocusableActor;
662 // First check whether there is any items in the container
663 if( mChildrenNodes.size() > 0 )
665 if ( !currentFocusedActor || currentFocusedActor == Self() )
667 // Nothing is currently focused, so the first child in the container should be focused.
668 nextFocusableActor = mChildrenNodes[0].actor.GetHandle();
672 // Check whether the current focused actor is within flex container
673 int currentFocusedActorIndex = -1;
674 for( unsigned int index = 0; index < mChildrenNodes.size(); index++ )
676 if( currentFocusedActor == mChildrenNodes[index].actor.GetHandle() )
678 currentFocusedActorIndex = index;
683 if( currentFocusedActorIndex > -1 )
685 int previousCheckedActorIndex = -1;
686 int nextFocusedActorIndex = currentFocusedActorIndex;
689 case Toolkit::Control::KeyboardFocus::LEFT:
690 case Toolkit::Control::KeyboardFocus::UP:
692 // Search the next focusable actor in the backward direction
695 nextFocusedActorIndex--;
696 if( nextFocusedActorIndex < 0 )
698 nextFocusedActorIndex = loopEnabled ? mChildrenNodes.size() - 1 : 0;
700 if( nextFocusedActorIndex != previousCheckedActorIndex && nextFocusedActorIndex != currentFocusedActorIndex )
702 previousCheckedActorIndex = nextFocusedActorIndex;
708 } while ( !mChildrenNodes[nextFocusedActorIndex].actor.GetHandle().IsKeyboardFocusable() );
711 case Toolkit::Control::KeyboardFocus::RIGHT:
712 case Toolkit::Control::KeyboardFocus::DOWN:
714 // Search the next focusable actor in the forward direction
717 nextFocusedActorIndex++;
718 if( nextFocusedActorIndex > static_cast<int>(mChildrenNodes.size() - 1) )
720 nextFocusedActorIndex = loopEnabled ? 0 : mChildrenNodes.size() - 1;
722 if( nextFocusedActorIndex != previousCheckedActorIndex && nextFocusedActorIndex != currentFocusedActorIndex )
724 previousCheckedActorIndex = nextFocusedActorIndex;
730 } while ( !mChildrenNodes[nextFocusedActorIndex].actor.GetHandle().IsKeyboardFocusable() );
735 if( nextFocusedActorIndex != currentFocusedActorIndex )
737 nextFocusableActor = mChildrenNodes[nextFocusedActorIndex].actor.GetHandle();
741 // No focusble child in the container
742 nextFocusableActor = Actor();
747 // The current focused actor is not within flex container, so the first child in the container should be focused.
748 nextFocusableActor = mChildrenNodes[0].actor.GetHandle();
753 return nextFocusableActor;
756 FlexContainer::FlexContainer()
757 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
758 mContentDirection( Toolkit::FlexContainer::INHERIT ),
759 mFlexDirection( Toolkit::FlexContainer::COLUMN ),
760 mFlexWrap( Toolkit::FlexContainer::NO_WRAP ),
761 mJustifyContent( Toolkit::FlexContainer::JUSTIFY_FLEX_START ),
762 mAlignItems( Toolkit::FlexContainer::ALIGN_STRETCH ),
763 mAlignContent( Toolkit::FlexContainer::ALIGN_FLEX_START )
765 SetKeyboardNavigationSupport( true );
768 void FlexContainer::OnInitialize()
770 // Initialize the node for the flex container itself
771 Dali::Actor self = Self();
772 mRootNode.actor = self;
773 mRootNode.node = new_css_node();
774 mRootNode.node->context = &mChildrenNodes;
777 mRootNode.node->style.direction = static_cast<css_direction_t>( mContentDirection );
778 mRootNode.node->style.flex_direction = static_cast<css_flex_direction_t>( mFlexDirection );
779 mRootNode.node->style.flex_wrap = static_cast<css_wrap_type_t>( mFlexWrap );
780 mRootNode.node->style.justify_content = static_cast<css_justify_t>( mJustifyContent );
781 mRootNode.node->style.align_items = static_cast<css_align_t>( mAlignItems );
782 mRootNode.node->style.align_content = static_cast<css_align_t>( mAlignContent );
785 mRootNode.node->get_child = GetChildNodeAtIndex;
786 mRootNode.node->is_dirty = IsNodeDirty;
788 // Make self as keyboard focusable and focus group
789 self.SetKeyboardFocusable( true );
790 SetAsKeyboardFocusGroup( true );
793 } // namespace Internal
795 } // namespace Toolkit