[AT-SPI] Fix role setting
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / flex-container / flex-container-impl.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 03d4583..5dc8719
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali/public-api/object/ref-object.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/public-api/object/type-registry-helper.h>
+#include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/scripting/scripting.h>
 #include <dali/public-api/size-negotiation/relayout-container.h>
 #include <dali/integration-api/debug.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/control/control-data-impl.h>
+
 using namespace Dali;
 
 namespace
@@ -37,19 +41,20 @@ namespace
 // currently not called from code so compiler will optimize these away, kept here for future debugging
 
 #define FLEX_CONTAINER_TAG "DALI Toolkit::FlexContainer "
-#define FC_LOG(fmt, args...) Debug::LogMessage(Debug::DebugInfo, FLEX_CONTAINER_TAG fmt, ## args)
-//#define FLEX_CONTAINER_DEBUG 1
+#define FC_LOG(fmt, args,...) Debug::LogMessage(Debug::DebugInfo, FLEX_CONTAINER_TAG fmt, ## args)
+// #define FLEX_CONTAINER_DEBUG 1
 
 #if defined(FLEX_CONTAINER_DEBUG)
-void PrintNode( Toolkit::Internal::FlexContainer::FlexItemNodeContainer itemNodes )
+void PrintNodes( Toolkit::Internal::FlexContainer::FlexItemNodeContainer itemNodes )
 {
   // Print the style property and layout of all the children
   for( unsigned int i = 0; i < itemNodes.size(); ++i )
   {
     FC_LOG( "Item %d style: \n", i );
-    print_css_node( itemNodes[i].node, (css_print_options_t)( CSS_PRINT_STYLE | CSS_PRINT_CHILDREN ) );
+    YGNodePrint( itemNodes[i].node, (YGPrintOptions)( YGPrintOptionsStyle | YGPrintOptionsChildren ) );
+    FC_LOG( "\n" );
     FC_LOG( "Item %d layout: \n", i );
-    print_css_node( itemNodes[i].node, (css_print_options_t)( CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN ) );
+    YGNodePrint( itemNodes[i].node, (YGPrintOptions)( YGPrintOptionsLayout | YGPrintOptionsChildren ) );
     FC_LOG( "\n" );
   }
 }
@@ -155,27 +160,6 @@ const Scripting::StringEnum ALIGN_CONTENT_STRING_TABLE[] =
 };
 const unsigned int ALIGN_CONTENT_STRING_TABLE_COUNT = sizeof( ALIGN_CONTENT_STRING_TABLE ) / sizeof( ALIGN_CONTENT_STRING_TABLE[0] );
 
-/**
- * The function used by the layout algorithm to be get the style properties
- * and layout information of the child at the given index.
- */
-css_node_t* GetChildNodeAtIndex( void *childrenNodes, int i )
-{
-  FlexContainer::FlexItemNodeContainer childrenNodeContainer = *( static_cast<FlexContainer::FlexItemNodeContainer*>( childrenNodes ) );
-  return childrenNodeContainer[i].node;
-}
-
-/**
- * The function used by the layout algorithm to check whether the node is dirty
- * for relayout.
- */
-bool IsNodeDirty( void *itemNodes )
-{
-  // We only calculate the layout when the child is added or removed, or when
-  // style properties are changed. So should always return true here.
-  return true;
-}
-
 } // Unnamed namespace
 
 Toolkit::FlexContainer FlexContainer::New()
@@ -195,22 +179,52 @@ Toolkit::FlexContainer FlexContainer::New()
 
 FlexContainer::~FlexContainer()
 {
-  free_css_node( mRootNode.node );
+  YGNodeFree( mRootNode.node );
 
   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
   {
-    free_css_node( mChildrenNodes[i].node );
+    YGNodeFree( mChildrenNodes[i].node );
   }
 
   mChildrenNodes.clear();
 }
 
-void FlexContainer::SetContentDirection( Toolkit::FlexContainer::ContentDirection contentDirection )
+void FlexContainer::SetContentDirection( Toolkit::FlexContainer::ContentDirection contentDirection)
 {
   if( mContentDirection != contentDirection )
   {
-    mContentDirection = contentDirection;
-    mRootNode.node->style.direction = static_cast<css_direction_t>( mContentDirection );
+    Dali::CustomActor ownerActor(GetOwner());
+
+    if( Toolkit::FlexContainer::INHERIT != contentDirection )
+    {
+      mContentDirection = contentDirection;
+
+      ownerActor.SetProperty( Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION, false );
+
+      if( Toolkit::FlexContainer::LTR == contentDirection )
+      {
+        ownerActor.SetProperty(Dali::Actor::Property::LAYOUT_DIRECTION, Dali::LayoutDirection::LEFT_TO_RIGHT);
+      }
+      else
+      {
+        ownerActor.SetProperty(Dali::Actor::Property::LAYOUT_DIRECTION, Dali::LayoutDirection::RIGHT_TO_LEFT);
+      }
+    }
+    else
+    {
+      ownerActor.SetProperty( Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION, true );
+
+      Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( ownerActor.GetParent().GetProperty( Dali::Actor::Property::LAYOUT_DIRECTION ).Get<int>() );
+
+      if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection )
+      {
+        mContentDirection = Toolkit::FlexContainer::RTL;
+      }
+      else
+      {
+        mContentDirection = Toolkit::FlexContainer::LTR;
+      }
+    }
 
     RelayoutRequest();
   }
@@ -226,7 +240,7 @@ void FlexContainer::SetFlexDirection( Toolkit::FlexContainer::FlexDirection flex
   if( mFlexDirection != flexDirection )
   {
     mFlexDirection = flexDirection;
-    mRootNode.node->style.flex_direction = static_cast<css_flex_direction_t>( mFlexDirection );
+    YGNodeStyleSetFlexDirection( mRootNode.node, static_cast<YGFlexDirection>( flexDirection ) );
 
     RelayoutRequest();
   }
@@ -242,7 +256,7 @@ void FlexContainer::SetFlexWrap( Toolkit::FlexContainer::WrapType flexWrap )
   if( mFlexWrap != flexWrap )
   {
     mFlexWrap = flexWrap;
-    mRootNode.node->style.flex_wrap = static_cast<css_wrap_type_t>( mFlexWrap );
+    YGNodeStyleSetFlexWrap( mRootNode.node, static_cast<YGWrap>( flexWrap ) );
 
     RelayoutRequest();
   }
@@ -258,7 +272,7 @@ void FlexContainer::SetJustifyContent( Toolkit::FlexContainer::Justification jus
   if( mJustifyContent != justifyContent )
   {
     mJustifyContent = justifyContent;
-    mRootNode.node->style.justify_content = static_cast<css_justify_t>( mJustifyContent );
+    YGNodeStyleSetJustifyContent( mRootNode.node, static_cast<YGJustify>( justifyContent ) );
 
     RelayoutRequest();
   }
@@ -274,7 +288,7 @@ void FlexContainer::SetAlignItems( Toolkit::FlexContainer::Alignment alignItems
   if( mAlignItems != alignItems )
   {
     mAlignItems = alignItems;
-    mRootNode.node->style.align_items = static_cast<css_align_t>( mAlignItems );
+    YGNodeStyleSetAlignItems( mRootNode.node, static_cast<YGAlign>( alignItems ) );
 
     RelayoutRequest();
   }
@@ -290,7 +304,7 @@ void FlexContainer::SetAlignContent( Toolkit::FlexContainer::Alignment alignCont
   if( mAlignContent != alignContent )
   {
     mAlignContent = alignContent;
-    mRootNode.node->style.align_content = static_cast<css_align_t>( mAlignContent );
+    YGNodeStyleSetAlignContent( mRootNode.node, static_cast<YGAlign>( alignContent ) );
 
     RelayoutRequest();
   }
@@ -465,17 +479,13 @@ Property::Value FlexContainer::GetProperty( BaseObject* object, Property::Index
 
 void FlexContainer::OnChildAdd( Actor& child )
 {
-  // Anchor actor to top left of the container
-  child.SetAnchorPoint( AnchorPoint::TOP_LEFT );
-  child.SetParentOrigin( ParentOrigin::TOP_LEFT );
-
   // Create a new node for the child.
   FlexItemNode childNode;
   childNode.actor = child;
-  childNode.node = new_css_node();
-  childNode.node->get_child = GetChildNodeAtIndex;
-  childNode.node->is_dirty = IsNodeDirty;
-  mChildrenNodes.push_back(childNode);
+  childNode.node = YGNodeNew();
+
+  mChildrenNodes.push_back( childNode );
+  YGNodeInsertChild( mRootNode.node, childNode.node, mChildrenNodes.size() - 1 );
 
   Control::OnChildAdd( child );
 }
@@ -486,7 +496,9 @@ void FlexContainer::OnChildRemove( Actor& child )
   {
     if( mChildrenNodes[i].actor.GetHandle() == child )
     {
-      free_css_node( mChildrenNodes[i].node );
+      YGNodeRemoveChild( mRootNode.node, mChildrenNodes[i].node );
+      YGNodeFree( mChildrenNodes[i].node );
+
       mChildrenNodes.erase( mChildrenNodes.begin() + i );
 
       // Relayout the container only if instances were found
@@ -505,22 +517,32 @@ void FlexContainer::OnRelayout( const Vector2& size, RelayoutContainer& containe
     Actor child = mChildrenNodes[i].actor.GetHandle();
     if( child )
     {
+      // Anchor actor to top left of the container
+      if( child.GetProperty( Actor::Property::POSITION_USES_ANCHOR_POINT ).Get< bool >() )
+      {
+        child.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+      }
+      child.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+
       float negotiatedWidth = child.GetRelayoutSize(Dimension::WIDTH);
       float negotiatedHeight = child.GetRelayoutSize(Dimension::HEIGHT);
 
       if( negotiatedWidth > 0 )
       {
-        mChildrenNodes[i].node->style.dimensions[CSS_WIDTH] = negotiatedWidth;
+        YGNodeStyleSetWidth( mChildrenNodes[i].node, negotiatedWidth );
       }
       if( negotiatedHeight > 0 )
       {
-        mChildrenNodes[i].node->style.dimensions[CSS_HEIGHT] = negotiatedHeight;
+        YGNodeStyleSetHeight( mChildrenNodes[i].node, negotiatedHeight );
       }
     }
   }
 
   // Relayout the container
   RelayoutChildren();
+#if defined(FLEX_CONTAINER_DEBUG)
+  PrintNodes( mChildrenNodes );
+#endif
 
   for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
   {
@@ -540,8 +562,7 @@ void FlexContainer::OnRelayout( const Vector2& size, RelayoutContainer& containe
           child.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::HEIGHT );
         }
       }
-
-      container.Add( child, Vector2(mChildrenNodes[i].node->layout.dimensions[CSS_WIDTH], mChildrenNodes[i].node->layout.dimensions[CSS_HEIGHT] ) );
+      container.Add( child, Vector2(YGNodeLayoutGetWidth(mChildrenNodes[i].node), YGNodeLayoutGetHeight(mChildrenNodes[i].node) ) );
     }
   }
 }
@@ -556,9 +577,8 @@ void FlexContainer::OnSizeSet( const Vector3& size )
   if( mRootNode.node )
   {
     Actor self = Self();
-
-    mRootNode.node->style.dimensions[CSS_WIDTH] = size.x;
-    mRootNode.node->style.dimensions[CSS_HEIGHT] = size.y;
+    YGNodeStyleSetWidth( mRootNode.node, size.x );
+    YGNodeStyleSetHeight( mRootNode.node, size.y );
 
     RelayoutRequest();
   }
@@ -566,37 +586,45 @@ void FlexContainer::OnSizeSet( const Vector3& size )
   Control::OnSizeSet( size );
 }
 
-void FlexContainer::ComputeLayout()
+void FlexContainer::OnLayoutDirectionChanged( Dali::Actor actor, Dali::LayoutDirection::Type type )
 {
-  if( mRootNode.node )
+  Toolkit::FlexContainer flexContainer = Toolkit::FlexContainer::DownCast(actor);
+  Toolkit::FlexContainer::ContentDirection direction;
+
+  if( type == Dali::LayoutDirection::RIGHT_TO_LEFT )
   {
-    mRootNode.node->children_count = mChildrenNodes.size();
+    direction = Toolkit::FlexContainer::RTL;
+  }
+  else
+  {
+    direction = Toolkit::FlexContainer::LTR;
+  }
 
-    // Intialize the layout.
-    mRootNode.node->layout.position[CSS_LEFT] = 0;
-    mRootNode.node->layout.position[CSS_TOP] = 0;
-    mRootNode.node->layout.position[CSS_BOTTOM] = 0;
-    mRootNode.node->layout.position[CSS_RIGHT] = 0;
-    mRootNode.node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
-    mRootNode.node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
+  Toolkit::Internal::FlexContainer &flexContainerImpl = GetImpl( flexContainer );
+
+  if( flexContainerImpl.mContentDirection != direction )
+  {
+    Dali::CustomActor ownerActor(flexContainerImpl.GetOwner());
+    flexContainerImpl.mContentDirection = direction;
 
+    flexContainerImpl.RelayoutRequest();
+  }
+}
+
+void FlexContainer::ComputeLayout()
+{
+  if( mRootNode.node )
+  {
     for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
     {
-      css_node_t* childNode = mChildrenNodes[i].node;
+      YGNodeRef childNode = mChildrenNodes[i].node;
       Actor childActor = mChildrenNodes[i].actor.GetHandle();
 
-      childNode->layout.position[CSS_LEFT] = 0;
-      childNode->layout.position[CSS_TOP] = 0;
-      childNode->layout.position[CSS_BOTTOM] = 0;
-      childNode->layout.position[CSS_RIGHT] = 0;
-      childNode->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
-      childNode->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
-
       // Intialize the style of the child.
-      childNode->style.minDimensions[CSS_WIDTH] = childActor.GetMinimumSize().x;
-      childNode->style.minDimensions[CSS_HEIGHT] = childActor.GetMinimumSize().y;
-      childNode->style.maxDimensions[CSS_WIDTH] = childActor.GetMaximumSize().x;
-      childNode->style.maxDimensions[CSS_HEIGHT] = childActor.GetMaximumSize().y;
+      YGNodeStyleSetMinWidth( childNode, childActor.GetProperty< Vector2 >( Actor::Property::MINIMUM_SIZE ).x );
+      YGNodeStyleSetMinHeight( childNode, childActor.GetProperty< Vector2 >( Actor::Property::MINIMUM_SIZE ).y );
+      YGNodeStyleSetMaxWidth( childNode, childActor.GetProperty< Vector2 >( Actor::Property::MAXIMUM_SIZE ).x );
+      YGNodeStyleSetMaxHeight( childNode, childActor.GetProperty< Vector2 >( Actor::Property::MAXIMUM_SIZE ).y );
 
       // Check child properties on the child for how to layout it.
       // These properties should be dynamically registered to the child which
@@ -604,11 +632,11 @@ void FlexContainer::ComputeLayout()
 
       if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX ) != Property::NONE )
       {
-        childNode->style.flex = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX ).Get<float>();
+        YGNodeStyleSetFlex( childNode, childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX ).Get<float>() );
       }
 
       Toolkit::FlexContainer::Alignment alignSelf( Toolkit::FlexContainer::ALIGN_AUTO );
-      if( childActor.GetPropertyType( Toolkit::FlexContainer::FlexContainer::ChildProperty::ALIGN_SELF ) != Property::NONE )
+      if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::ALIGN_SELF ) != Property::NONE )
       {
         Property::Value alignSelfPropertyValue = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::ALIGN_SELF );
         if( alignSelfPropertyValue.GetType() == Property::INTEGER )
@@ -623,21 +651,49 @@ void FlexContainer::ComputeLayout()
                                                                           ALIGN_SELF_STRING_TABLE_COUNT,
                                                                           alignSelf );
         }
+        YGNodeStyleSetAlignSelf( childNode, static_cast<YGAlign>(alignSelf) );
       }
-      childNode->style.align_self = static_cast<css_align_t>(alignSelf);
 
       if( childActor.GetPropertyType( Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN ) != Property::NONE )
       {
         Vector4 flexMargin = childActor.GetProperty( Toolkit::FlexContainer::ChildProperty::FLEX_MARGIN ).Get<Vector4>();
-        childNode->style.margin[CSS_LEFT] = flexMargin.x;
-        childNode->style.margin[CSS_TOP] = flexMargin.y;
-        childNode->style.margin[CSS_RIGHT] = flexMargin.z;
-        childNode->style.margin[CSS_BOTTOM] = flexMargin.w;
+        YGNodeStyleSetMargin( childNode, YGEdgeLeft, flexMargin.x );
+        YGNodeStyleSetMargin( childNode, YGEdgeTop, flexMargin.y );
+        YGNodeStyleSetMargin( childNode, YGEdgeRight, flexMargin.z );
+        YGNodeStyleSetMargin( childNode, YGEdgeBottom, flexMargin.w );
       }
     }
 
     // Calculate the layout
-    layoutNode( mRootNode.node, Self().GetMaximumSize().x, Self().GetMaximumSize().y, mRootNode.node->style.direction );
+    YGDirection nodeLayoutDirection = YGDirectionInherit;
+    switch( mContentDirection )
+    {
+    case Dali::Toolkit::FlexContainer::LTR:
+    {
+      nodeLayoutDirection = YGDirectionLTR;
+      break;
+    }
+
+    case Dali::Toolkit::FlexContainer::RTL:
+    {
+      nodeLayoutDirection = YGDirectionRTL;
+      break;
+    }
+
+    case Dali::Toolkit::FlexContainer::INHERIT:
+    {
+      nodeLayoutDirection = YGDirectionInherit;
+      break;
+    }
+    }
+
+#if defined(FLEX_CONTAINER_DEBUG)
+    YGNodePrint( mRootNode.node, (YGPrintOptions)( YGPrintOptionsLayout | YGPrintOptionsStyle | YGPrintOptionsChildren ) );
+#endif
+    YGNodeCalculateLayout( mRootNode.node, Self().GetProperty< Vector2 >( Actor::Property::MAXIMUM_SIZE ).x, Self().GetProperty< Vector2 >( Actor::Property::MAXIMUM_SIZE ).y, nodeLayoutDirection );
+#if defined(FLEX_CONTAINER_DEBUG)
+    YGNodePrint( mRootNode.node, (YGPrintOptions)( YGPrintOptionsLayout | YGPrintOptionsStyle | YGPrintOptionsChildren ) );
+#endif
   }
 }
 
@@ -651,8 +707,8 @@ void FlexContainer::RelayoutChildren()
     Dali::Actor child = mChildrenNodes[i].actor.GetHandle();
     if( child )
     {
-      child.SetX( mChildrenNodes[i].node->layout.position[CSS_LEFT] );
-      child.SetY( mChildrenNodes[i].node->layout.position[CSS_TOP] );
+      child.SetProperty( Actor::Property::POSITION_X,  YGNodeLayoutGetLeft( mChildrenNodes[i].node ) );
+      child.SetProperty( Actor::Property::POSITION_Y,  YGNodeLayoutGetTop( mChildrenNodes[i].node ) );
     }
   }
 }
@@ -707,7 +763,7 @@ Actor FlexContainer::GetNextKeyboardFocusableActor(Actor currentFocusedActor, To
               {
                 break;
               }
-            } while ( !mChildrenNodes[nextFocusedActorIndex].actor.GetHandle().IsKeyboardFocusable() );
+            } while ( !mChildrenNodes[nextFocusedActorIndex].actor.GetHandle().GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) );
             break;
           }
           case Toolkit::Control::KeyboardFocus::RIGHT:
@@ -729,7 +785,7 @@ Actor FlexContainer::GetNextKeyboardFocusableActor(Actor currentFocusedActor, To
               {
                 break;
               }
-            } while ( !mChildrenNodes[nextFocusedActorIndex].actor.GetHandle().IsKeyboardFocusable() );
+            } while ( !mChildrenNodes[nextFocusedActorIndex].actor.GetHandle().GetProperty< bool >( Actor::Property::KEYBOARD_FOCUSABLE ) );
             break;
           }
           default:
@@ -775,25 +831,27 @@ void FlexContainer::OnInitialize()
 {
   // Initialize the node for the flex container itself
   Dali::Actor self = Self();
+  self.LayoutDirectionChangedSignal().Connect( this, &FlexContainer::OnLayoutDirectionChanged );
+
   mRootNode.actor = self;
-  mRootNode.node = new_css_node();
-  mRootNode.node->context = &mChildrenNodes;
+  mRootNode.node = YGNodeNew();
+  YGNodeSetContext( mRootNode.node, &mChildrenNodes );
 
   // Set default style
-  mRootNode.node->style.direction = static_cast<css_direction_t>( mContentDirection );
-  mRootNode.node->style.flex_direction = static_cast<css_flex_direction_t>( mFlexDirection );
-  mRootNode.node->style.flex_wrap = static_cast<css_wrap_type_t>( mFlexWrap );
-  mRootNode.node->style.justify_content = static_cast<css_justify_t>( mJustifyContent );
-  mRootNode.node->style.align_items = static_cast<css_align_t>( mAlignItems );
-  mRootNode.node->style.align_content = static_cast<css_align_t>( mAlignContent );
-
-  // Set callbacks.
-  mRootNode.node->get_child = GetChildNodeAtIndex;
-  mRootNode.node->is_dirty = IsNodeDirty;
+  YGNodeStyleSetFlexDirection( mRootNode.node, static_cast<YGFlexDirection>( mFlexDirection ) );
+  YGNodeStyleSetFlexWrap( mRootNode.node, static_cast<YGWrap>( mFlexWrap ) );
+  YGNodeStyleSetJustifyContent( mRootNode.node, static_cast<YGJustify>( mJustifyContent ) );
+  YGNodeStyleSetAlignItems( mRootNode.node, static_cast<YGAlign>( mAlignItems ) );
+  YGNodeStyleSetAlignContent( mRootNode.node, static_cast<YGAlign>( mAlignContent ) );
 
   // Make self as keyboard focusable and focus group
-  self.SetKeyboardFocusable( true );
+  self.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE, true );
   SetAsKeyboardFocusGroup( true );
+
+  DevelControl::SetAccessibilityConstructor( self, []( Dali::Actor actor ) {
+    return std::unique_ptr< Dali::Accessibility::Accessible >(
+      new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::FILLER ) );
+  } );
 }
 
 } // namespace Internal