[AT-SPI] Fix role setting
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / table-view / table-view-impl.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 2250801..4f27bba
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 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 <sstream>
 #include <dali/public-api/object/ref-object.h>
 #include <dali/public-api/object/type-registry.h>
-#include <dali/devel-api/object/type-registry-helper.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
 {
-/*
- * Custom properties for where to put the actor.
- *
- * When an actor is add to the tableView through Actor::Add() instead of TableView::AddChild,
- * the following custom properties of the actor are checked to decide the actor position inside the table
- *
- * These non-animatable properties should be registered to the child which would be added to the table
- */
-const char * const CELL_INDEX_PROPERTY_NAME("cell-index");
-const char * const ROW_SPAN_PROPERTY_NAME("row-span");
-const char * const COLUMN_SPAN_PROPERTY_NAME("column-span");
-const char * const CELL_HORIZONTAL_ALIGNMENT_PROPERTY_NAME("cell-horizontal-alignment");
-const char * const CELL_VERTICAL_ALIGNMENT_PROPERTY_NAME("cell-vertical-alignment");
-
 /**
  * @brief Should the tableview fit around the given actor
  *
@@ -61,7 +51,7 @@ bool FitToChild( Actor actor, Dimension::Type dimension )
 // currently not called from code so compiler will optimize these away, kept here for future debugging
 
 #define TABLEVIEW_TAG "DALI Toolkit::TableView "
-#define TV_LOG(fmt, args...) Debug::LogMessage(Debug::DebugInfo, TABLEVIEW_TAG fmt, ## args)
+#define TV_LOG(fmt, args,...) Debug::LogMessage(Debug::DebugInfo, TABLEVIEW_TAG fmt, ## args)
 //#define TABLEVIEW_DEBUG 1
 
 #if defined(TABLEVIEW_DEBUG)
@@ -79,7 +69,7 @@ void PrintArray( Array2d<Dali::Toolkit::Internal::TableView::CellData>& array )
       if( data.actor )
       {
         actor = 'A';
-        actorName = data.actor.GetName();
+        actorName = data.actor.GetProperty< std::string >( Dali::Actor::Property::NAME );
       }
       TV_LOG("Array[%d,%d]=%c %s %d,%d,%d,%d  ", i, j, actor, actorName.c_str(),
           data.position.rowIndex, data.position.columnIndex,
@@ -142,11 +132,16 @@ BaseHandle Create()
 // Setup properties, signals and actions using the type-registry.
 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TableView, Toolkit::Control, Create );
 
-DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "rows",           UNSIGNED_INTEGER, ROWS           )
-DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "columns",        UNSIGNED_INTEGER, COLUMNS        )
-DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "cell-padding",   VECTOR2,          CELL_PADDING   )
-DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-rows",    MAP,              LAYOUT_ROWS    )
-DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-columns", MAP,              LAYOUT_COLUMNS )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "rows",           INTEGER, ROWS           )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "columns",        INTEGER, COLUMNS        )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "cellPadding",    VECTOR2, CELL_PADDING   )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layoutRows",     MAP,     LAYOUT_ROWS    )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layoutColumns",  MAP,     LAYOUT_COLUMNS )
+DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "cellIndex",                VECTOR2, CELL_INDEX                )
+DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "rowSpan",                  INTEGER, ROW_SPAN                  )
+DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "columnSpan",               INTEGER, COLUMN_SPAN               )
+DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "cellHorizontalAlignment",  STRING,  CELL_HORIZONTAL_ALIGNMENT )
+DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "cellVerticalAlignment",    STRING,  CELL_VERTICAL_ALIGNMENT   )
 
 DALI_TYPE_REGISTRATION_END()
 
@@ -254,6 +249,15 @@ bool TableView::AddChild( Actor& child, const Toolkit::TableView::CellPosition&
   }
 
   // Relayout the whole table
+  if( mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT && position.rowSpan == 1 )
+  {
+    mRowDirty = true;
+  }
+  if( mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT && position.columnSpan == 1 )
+  {
+    mColumnDirty = true;
+  }
+
   RelayoutRequest();
 
   return true;    // Addition successful
@@ -278,12 +282,20 @@ Actor TableView::RemoveChildAt( const Toolkit::TableView::CellPosition& position
   if( child )
   {
     RelayoutingLock lock( *this );
-    // Remove the child, this will trigger a call to OnControlChildRemove
+    // Remove the child, this will trigger a call to OnChildRemove
     Self().Remove( child );
 
     // relayout the table only if instances were found
     if( RemoveAllInstances( child ) )
     {
+      if( mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT )
+      {
+        mRowDirty = true;
+      }
+      if( mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT )
+      {
+        mColumnDirty = true;
+      }
       RelayoutRequest();
     }
   }
@@ -354,7 +366,7 @@ void TableView::InsertRow( unsigned int rowIndex )
   mRowData.Insert( mRowData.Begin() + rowIndex, RowColumnData() );
 
   // Sizes may have changed, so relayout
-  mRowColumnDirty = true;
+  mRowDirty = true;
   RelayoutRequest();
 }
 
@@ -395,7 +407,7 @@ void TableView::DeleteRow( unsigned int rowIndex, std::vector<Actor>& removed )
       else if( row >= rowIndex )    // If below of or at the inserted row, decrease row index
       {
         // Decrement index
-        if( position.rowIndex > 1 )
+        if( position.rowIndex > 0 )
         {
           position.rowIndex--;
         }
@@ -410,7 +422,10 @@ void TableView::DeleteRow( unsigned int rowIndex, std::vector<Actor>& removed )
   mRowData.Erase( mRowData.Begin() + rowIndex );
 
   // Sizes may have changed, so relayout
-  mRowColumnDirty = true;
+  mRowDirty = true;
+  // it is possible that the deletion of row leads to remove of child which might further lead to the change of FIT column
+  mColumnDirty = true;
+
   RelayoutRequest();
 }
 
@@ -453,7 +468,7 @@ void TableView::InsertColumn( unsigned int columnIndex )
   mColumnData.Insert( mColumnData.Begin() + columnIndex, RowColumnData() );
 
   // Sizes may have changed so relayout
-  mRowColumnDirty = true;
+  mColumnDirty = true;
   RelayoutRequest();
 }
 
@@ -509,7 +524,10 @@ void TableView::DeleteColumn( unsigned int columnIndex, std::vector<Actor>& remo
   mColumnData.Erase( mColumnData.Begin() + columnIndex );
 
   // Size may have changed so relayout
-  mRowColumnDirty = true;
+  mColumnDirty = true;
+  // it is possible that the deletion of column leads to remove of child which might further lead to the change of FIT row
+  mRowDirty = true;
+
   RelayoutRequest();
 }
 
@@ -550,7 +568,8 @@ void TableView::Resize( unsigned int rows, unsigned int columns, std::vector<Act
   RemoveAndGetLostActors( lost, removed, rowsRemoved, columnsRemoved );
 
   // Sizes may have changed so request a relayout
-  mRowColumnDirty = true;
+  mRowDirty = true;
+  mColumnDirty = true;
   RelayoutRequest();
 }
 
@@ -578,7 +597,7 @@ void TableView::SetFitHeight( unsigned int rowIndex )
   {
     mRowData[ rowIndex ].sizePolicy = Toolkit::TableView::FIT;
 
-    mRowColumnDirty = true;
+    mRowDirty = true;
     RelayoutRequest();
   }
 }
@@ -598,7 +617,7 @@ void TableView::SetFitWidth( unsigned int columnIndex )
   {
     mColumnData[ columnIndex ].sizePolicy = Toolkit::TableView::FIT;
 
-    mRowColumnDirty = true;
+    mColumnDirty = true;
     RelayoutRequest();
   }
 }
@@ -618,7 +637,7 @@ void TableView::SetFixedHeight( unsigned int rowIndex, float height )
   data.size = height;
   data.sizePolicy = Toolkit::TableView::FIXED;
 
-  mRowColumnDirty = true;
+  mRowDirty = true;
   RelayoutRequest();
 }
 
@@ -637,7 +656,7 @@ void TableView::SetFixedWidth( unsigned int columnIndex, float width )
   data.size = width;
   data.sizePolicy = Toolkit::TableView::FIXED;
 
-  mRowColumnDirty = true;
+  mColumnDirty = true;
   RelayoutRequest();
 }
 
@@ -656,7 +675,7 @@ void TableView::SetRelativeHeight( unsigned int rowIndex, float heightPercentage
   data.fillRatio = heightPercentage;
   data.sizePolicy = Toolkit::TableView::RELATIVE;
 
-  mRowColumnDirty = true;
+  mRowDirty = true;
   RelayoutRequest();
 }
 
@@ -675,7 +694,7 @@ void TableView::SetRelativeWidth( unsigned int columnIndex, float widthPercentag
   data.fillRatio = widthPercentage;
   data.sizePolicy = Toolkit::TableView::RELATIVE;
 
-  mRowColumnDirty = true;
+  mColumnDirty = true;
   RelayoutRequest();
 }
 
@@ -686,41 +705,45 @@ float TableView::GetRelativeWidth( unsigned int columnIndex ) const
   return mColumnData[ columnIndex ].fillRatio;
 }
 
-void TableView::CalculateRowColumnData()
-{
-  // Calculate the relative sizes
-  if( mRowColumnDirty )
-  {
-    ComputeRelativeSizes( mRowData );
-    ComputeRelativeSizes( mColumnData );
-
-    mRowColumnDirty = false;
-  }
-}
-
 void TableView::OnCalculateRelayoutSize( Dimension::Type dimension )
 {
-  CalculateRowColumnData();
-
-  if( dimension & Dimension::WIDTH )
+  if( (dimension & Dimension::WIDTH) && mColumnDirty )
   {
-    CalculateFixedSizes( mColumnData, Dimension::WIDTH );
+    /*
+     * FIXED and FIT have size in pixel
+     * Nothing to do with FIXED, as its value is assigned by user and will not get changed
+     *
+     * Need to update the size for FIT column here
+     */
+    CalculateFitSizes( mColumnData, Dimension::WIDTH );
+
+    /* RELATIVE and FILL have size in ratio
+     * Their size in pixel is not available until we get the negotiated size for the whole table
+     * Nothing to do with RELATIVE, as its ratio is assigned by user and will not get changed
+     *
+     * Need to update the ratio for FILL column here
+     */
+    CalculateFillSizes( mColumnData );
+
     mFixedTotals.width = CalculateTotalFixedSize( mColumnData );
   }
 
-  if( dimension & Dimension::HEIGHT )
+  if( (dimension & Dimension::HEIGHT) && mRowDirty )
   {
-    CalculateFixedSizes( mRowData, Dimension::HEIGHT );
+    // refer to the comment above
+    CalculateFitSizes( mRowData, Dimension::HEIGHT );
+
+    // refer to the comment above
+    CalculateFillSizes( mRowData );
+
     mFixedTotals.height = CalculateTotalFixedSize( mRowData );
   }
 }
 
 void TableView::OnLayoutNegotiated( float size, Dimension::Type dimension )
 {
-  CalculateRowColumnData();
-
-  // Calculate the value of all relative sized rows and columns
-  if( dimension & Dimension::WIDTH )
+  // Update the column sizes
+  if( (dimension & Dimension::WIDTH) && mColumnDirty )
   {
     float remainingSize = size - mFixedTotals.width;
     if( remainingSize < 0.0f )
@@ -728,10 +751,24 @@ void TableView::OnLayoutNegotiated( float size, Dimension::Type dimension )
       remainingSize = 0.0f;
     }
 
-    CalculateRelativeSizes( mColumnData, remainingSize );
+    // update every column position in ColumnData array
+    float cumulatedWidth = 0.0f;
+    for( auto&& element : mColumnData )
+    {
+      if( element.sizePolicy == Toolkit::TableView::FILL || element.sizePolicy == Toolkit::TableView::RELATIVE )
+      {
+        element.size = element.fillRatio * remainingSize;
+      }
+
+      cumulatedWidth += element.size;
+      element.position = cumulatedWidth;
+    }
+
+    mColumnDirty = false;
   }
 
-  if( dimension & Dimension::HEIGHT )
+  // Update the row sizes
+  if( (dimension & Dimension::HEIGHT) && mRowDirty )
   {
     float remainingSize = size - mFixedTotals.height;
     if( remainingSize < 0.0f )
@@ -739,36 +776,51 @@ void TableView::OnLayoutNegotiated( float size, Dimension::Type dimension )
       remainingSize = 0.0f;
     }
 
-    CalculateRelativeSizes( mRowData, remainingSize );
+    // update every row position in RowData array
+    float cumulatedHeight = 0.0f;
+    for( unsigned int row = 0, rowCount = mCellData.GetRows(); row < rowCount; ++row )
+    {
+      if( mRowData[ row ].sizePolicy == Toolkit::TableView::FILL ||  mRowData[ row ].sizePolicy == Toolkit::TableView::RELATIVE)
+      {
+        mRowData[ row ].size = mRowData[ row ].fillRatio * remainingSize;
+      }
+
+      cumulatedHeight += mRowData[ row ].size;
+      mRowData[row].position = cumulatedHeight;
+    }
+
+    mRowDirty = false;
   }
 }
 
+void TableView::OnSizeSet( const Vector3& size )
+{
+  // If this table view is size negotiated by another actor or control, then the
+  // rows and columns must be recalculated or the new size will not take effect.
+  mRowDirty = mColumnDirty = true;
+  RelayoutRequest();
+
+  Control::OnSizeSet( size );
+}
+
 void TableView::OnRelayout( const Vector2& size, RelayoutContainer& container )
 {
-  CalculateRowColumnData();
+  // Go through the layout data
+  float totalWidth = 0.0;
 
-  // update every column position in ColumnData array
-  float cumulatedWidth = 0.0f;
-  const unsigned int columnCount = mCellData.GetColumns();
-  for( unsigned int column = 0; column < columnCount; ++column )
-  {
-    mColumnData[column].position = cumulatedWidth;
-    cumulatedWidth += mColumnData[ column ].size;
-  }
+  Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>() );
 
-  // update every row position in RowData array
-  float cumulatedHeight = 0.0f;
-  const unsigned int rowCount = mCellData.GetRows();
-  for( unsigned int row = 0; row < rowCount; ++row )
+  if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection )
   {
-    mRowData[row].position = cumulatedHeight;
-    cumulatedHeight += mRowData[ row ].size;
+    for (auto&& element : mColumnData)
+    {
+      totalWidth += element.size;
+    }
   }
 
-  // Go through the layout data
-  for( unsigned int row = 0; row < rowCount; ++row )
+  for( unsigned int row = 0, rowCount = mCellData.GetRows(); row < rowCount; ++row )
   {
-    for( unsigned int column = 0; column < columnCount; ++column )
+    for( unsigned int column = 0, columnCount = mCellData.GetColumns(); column < columnCount; ++column )
     {
       CellData& cellData= mCellData[ row ][ column ];
       Actor& actor = cellData.actor;
@@ -780,53 +832,54 @@ void TableView::OnRelayout( const Vector2& size, RelayoutContainer& container )
       if( actor &&  position.rowIndex == row && position.columnIndex == column )
       {
         // Anchor actor to top left of the cell
-        actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
-        actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+        if( actor.GetProperty( Actor::Property::POSITION_USES_ANCHOR_POINT ).Get< bool >() )
+        {
+          actor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+        }
+        actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
 
-        Vector2( actor.GetRelayoutSize( Dimension::WIDTH ), actor.GetRelayoutSize( Dimension::HEIGHT ) );
+        Padding padding = actor.GetProperty<Vector4>( Actor::Property::PADDING );
 
-        Padding padding;
-        actor.GetPadding( padding );
+        float left = (column > 0) ? mColumnData[column - 1].position : 0.f;
+        float right;
 
-        if( cellData.horizontalAlignment == HorizontalAlignment::LEFT )
+        if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection )
         {
-          actor.SetX( mColumnData[column].position + mPadding.width + padding.left );
+          right = totalWidth - left;
+          left = right - mColumnData[column].size;
         }
         else
         {
-          float cellRightPosition = column+position.columnSpan < columnCount ? mColumnData[column+position.columnSpan].position : cumulatedWidth;
+          right = left + mColumnData[column].size;
+        }
 
-          if( cellData.horizontalAlignment ==  HorizontalAlignment::RIGHT )
-          {
-            actor.SetX( cellRightPosition - mPadding.width - padding.right - actor.GetRelayoutSize( Dimension::WIDTH ) );
-          }
-          else //if( cellData.horizontalAlignment ==  HorizontalAlignment::CENTER )
-          {
-            actor.SetX( (mColumnData[column].position + cellRightPosition
-                       + padding.left - padding.right
-                       - actor.GetRelayoutSize( Dimension::WIDTH )) * 0.5f );
-          }
+        float top = row > 0 ? mRowData[row-1].position : 0.f;
+        float bottom = mRowData[row+position.rowSpan-1].position;
+
+        if( cellData.horizontalAlignment == HorizontalAlignment::LEFT )
+        {
+          actor.SetProperty( Actor::Property::POSITION_X,  left + mPadding.width + padding.left );
+        }
+        else if( cellData.horizontalAlignment ==  HorizontalAlignment::RIGHT )
+        {
+          actor.SetProperty( Actor::Property::POSITION_X,  right - mPadding.width - padding.right - actor.GetRelayoutSize( Dimension::WIDTH ) );
+        }
+        else //if( cellData.horizontalAlignment ==  HorizontalAlignment::CENTER )
+        {
+          actor.SetProperty( Actor::Property::POSITION_X,  (left + right + padding.left - padding.right - actor.GetRelayoutSize( Dimension::WIDTH )) * 0.5f );
         }
 
         if( cellData.verticalAlignment == VerticalAlignment::TOP )
         {
-          actor.SetY( mRowData[row].position + mPadding.height + padding.top );
+          actor.SetProperty( Actor::Property::POSITION_Y,  top + mPadding.height + padding.top );
         }
-        else
+        else if( cellData.verticalAlignment == VerticalAlignment::BOTTOM )
         {
-          float cellBottomPosition = row+position.rowSpan < rowCount ? mRowData[row+position.rowSpan].position : cumulatedHeight;
-
-          if( cellData.verticalAlignment == VerticalAlignment::BOTTOM )
-
-          {
-            actor.SetY( cellBottomPosition - mPadding.height - padding.bottom -  actor.GetRelayoutSize( Dimension::HEIGHT ) );
-          }
-          else //if( cellData.verticalAlignment = VerticalAlignment::CENTER )
-          {
-            actor.SetY( (mRowData[row].position + cellBottomPosition
-                       + padding.top - padding.bottom
-                       - actor.GetRelayoutSize( Dimension::HEIGHT )) * 0.5f );
-          }
+          actor.SetProperty( Actor::Property::POSITION_Y,  bottom - mPadding.height - padding.bottom -  actor.GetRelayoutSize( Dimension::HEIGHT ) );
+        }
+        else //if( cellData.verticalAlignment = VerticalAlignment::CENTER )
+        {
+          actor.SetProperty( Actor::Property::POSITION_Y,  (top + bottom + padding.top - padding.bottom - actor.GetRelayoutSize( Dimension::HEIGHT )) * 0.5f );
         }
       }
     }
@@ -854,17 +907,25 @@ void TableView::SetProperty( BaseObject* object, Property::Index index, const Pr
     {
       case Toolkit::TableView::Property::ROWS:
       {
-        if( value.Get<unsigned int>() != tableViewImpl.GetRows() )
+        int rows = 0;
+        if( value.Get( rows ) && rows >= 0 )
         {
-          tableViewImpl.Resize( value.Get<unsigned int>(), tableViewImpl.GetColumns() );
+          if( static_cast<unsigned int>(rows) != tableViewImpl.GetRows() )
+          {
+            tableViewImpl.Resize( rows, tableViewImpl.GetColumns() );
+          }
         }
         break;
       }
       case Toolkit::TableView::Property::COLUMNS:
       {
-        if( value.Get<unsigned int>() != tableViewImpl.GetColumns() )
+        int columns = 0;
+        if( value.Get( columns ) && columns >= 0 )
         {
-          tableViewImpl.Resize( tableViewImpl.GetRows(), value.Get<unsigned int>() );
+          if( static_cast<unsigned int>( columns ) != tableViewImpl.GetColumns() )
+          {
+            tableViewImpl.Resize( tableViewImpl.GetRows(), value.Get<int>() );
+          }
         }
         break;
       }
@@ -900,12 +961,12 @@ Property::Value TableView::GetProperty( BaseObject* object, Property::Index inde
     {
       case Toolkit::TableView::Property::ROWS:
       {
-        value = tableViewImpl.GetRows();
+        value = static_cast<int>( tableViewImpl.GetRows() );
         break;
       }
       case Toolkit::TableView::Property::COLUMNS:
       {
-        value = tableViewImpl.GetColumns();
+        value = static_cast<int>( tableViewImpl.GetColumns() );
         break;
       }
       case Toolkit::TableView::Property::CELL_PADDING:
@@ -929,101 +990,106 @@ Property::Value TableView::GetProperty( BaseObject* object, Property::Index inde
   return value;
 }
 
-void TableView::OnControlChildAdd( Actor& child )
+void TableView::OnChildAdd( Actor& child )
 {
-  if( mLayoutingChild )
-  {
-    // we're in the middle of laying out children so no point doing anything here
-    return;
-  }
-
-  // Test properties on actor
-  HorizontalAlignment::Type horizontalAlignment = HorizontalAlignment::LEFT;
-  VerticalAlignment::Type verticalAlignment = VerticalAlignment::TOP;
-  if( child.GetPropertyIndex( CELL_HORIZONTAL_ALIGNMENT_PROPERTY_NAME ) != Property::INVALID_INDEX )
-  {
-    std::string value = child.GetProperty( child.GetPropertyIndex(CELL_HORIZONTAL_ALIGNMENT_PROPERTY_NAME) ).Get<std::string >();
-    Scripting::GetEnumeration< HorizontalAlignment::Type >( value.c_str(),
-                                                            HORIZONTAL_ALIGNMENT_STRING_TABLE,
-                                                            HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
-                                                            horizontalAlignment );
-  }
-  if( child.GetPropertyIndex( CELL_VERTICAL_ALIGNMENT_PROPERTY_NAME ) != Property::INVALID_INDEX )
+  if( ! mLayoutingChild )
   {
-    std::string value = child.GetProperty( child.GetPropertyIndex(CELL_VERTICAL_ALIGNMENT_PROPERTY_NAME) ).Get<std::string >();
-    Scripting::GetEnumeration< VerticalAlignment::Type >( value.c_str(),
-                                                          VERTICAL_ALIGNMENT_STRING_TABLE,
-                                                          VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
-                                                          verticalAlignment );
-  }
+    // Ensure we're not in the middle of laying out children
 
+    // Check child properties on actor to decide its position inside the table
+    HorizontalAlignment::Type horizontalAlignment = HorizontalAlignment::LEFT;
+    VerticalAlignment::Type verticalAlignment = VerticalAlignment::TOP;
 
-  Toolkit::TableView::CellPosition cellPosition;
-  if( child.GetPropertyIndex(ROW_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
-  {
-    cellPosition.rowSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(ROW_SPAN_PROPERTY_NAME) ).Get<float>() );
-  }
+    if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_HORIZONTAL_ALIGNMENT ) != Property::NONE )
+    {
+      std::string value = child.GetProperty( Toolkit::TableView::ChildProperty::CELL_HORIZONTAL_ALIGNMENT ).Get<std::string >();
+      Scripting::GetEnumeration< HorizontalAlignment::Type >( value.c_str(),
+                                                              HORIZONTAL_ALIGNMENT_STRING_TABLE,
+                                                              HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
+                                                              horizontalAlignment );
+    }
 
-  if( child.GetPropertyIndex(COLUMN_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
-  {
-    cellPosition.columnSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(COLUMN_SPAN_PROPERTY_NAME) ).Get<float>() );
-  }
+    if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_VERTICAL_ALIGNMENT ) != Property::NONE )
+    {
+      std::string value = child.GetProperty( Toolkit::TableView::ChildProperty::CELL_VERTICAL_ALIGNMENT ).Get<std::string >();
+      Scripting::GetEnumeration< VerticalAlignment::Type >( value.c_str(),
+                                                            VERTICAL_ALIGNMENT_STRING_TABLE,
+                                                            VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
+                                                            verticalAlignment );
+    }
 
-  if( child.GetPropertyIndex(CELL_INDEX_PROPERTY_NAME) != Property::INVALID_INDEX )
-  {
-    Vector2 indices = child.GetProperty( child.GetPropertyIndex(CELL_INDEX_PROPERTY_NAME) ).Get<Vector2 >();
-    cellPosition.rowIndex = static_cast<unsigned int>( indices.x );
-    cellPosition.columnIndex = static_cast<unsigned int>( indices.y );
+    Toolkit::TableView::CellPosition cellPosition;
+    if( child.GetPropertyType( Toolkit::TableView::ChildProperty::ROW_SPAN ) != Property::NONE )
+    {
+      cellPosition.rowSpan = child.GetProperty( Toolkit::TableView::ChildProperty::ROW_SPAN ).Get< int >();
+    }
 
-    AddChild( child, cellPosition );
-    SetCellAlignment(cellPosition, horizontalAlignment, verticalAlignment);
+    if( child.GetPropertyType( Toolkit::TableView::ChildProperty::COLUMN_SPAN ) != Property::NONE )
+    {
+      cellPosition.columnSpan = child.GetProperty( Toolkit::TableView::ChildProperty::COLUMN_SPAN ).Get< int >();
+    }
 
-    // Do not continue
-    RelayoutRequest();
-    return;
-  }
+    if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_INDEX ) != Property::NONE )
+    {
+      Vector2 indices = child.GetProperty( Toolkit::TableView::ChildProperty::CELL_INDEX ).Get<Vector2 >();
+      cellPosition.rowIndex = static_cast<unsigned int>( indices.x );
+      cellPosition.columnIndex = static_cast<unsigned int>( indices.y );
 
-  // Find the first available cell to store the actor in
-  const unsigned int rowCount = mCellData.GetRows();
-  const unsigned int columnCount = mCellData.GetColumns();
-  for( unsigned int row = 0; row < rowCount; ++row )
-  {
-    for( unsigned int column = 0; column < columnCount; ++column )
+      AddChild( child, cellPosition );
+      SetCellAlignment(cellPosition, horizontalAlignment, verticalAlignment);
+    }
+    else
     {
-      if( !(mCellData[ row ][ column ].actor) )
+      bool availableCellFound = false;
+
+      // Find the first available cell to store the actor in
+      const unsigned int rowCount = mCellData.GetRows();
+      const unsigned int columnCount = mCellData.GetColumns();
+      for( unsigned int row = 0; row < rowCount && !availableCellFound; ++row )
+      {
+        for( unsigned int column = 0; column < columnCount && !availableCellFound; ++column )
+        {
+          if( !(mCellData[ row ][ column ].actor) )
+          {
+            // Put the actor in the cell
+            CellData data;
+            data.actor = child;
+            data.position.columnIndex = column;
+            data.position.rowIndex = row;
+            data.horizontalAlignment = horizontalAlignment;
+            data.verticalAlignment = verticalAlignment;
+            mCellData[ row ][ column ] = data;
+
+            availableCellFound = true;
+            break;
+          }
+        }
+      }
+
+      if( ! availableCellFound )
       {
-        // Put the actor in the cell
+        // No empty cells, so increase size of the table
+        unsigned int newColumnCount = ( columnCount > 0 ) ? columnCount : 1;
+        ResizeContainers( rowCount + 1, newColumnCount );
+
+        // Put the actor in the first cell of the new row
         CellData data;
         data.actor = child;
-        data.position.columnIndex = column;
-        data.position.rowIndex = row;
+        data.position.rowIndex = rowCount;
+        data.position.columnIndex = 0;
         data.horizontalAlignment = horizontalAlignment;
         data.verticalAlignment = verticalAlignment;
-        mCellData[ row ][ column ] = data;
-
-        // Don't continue
-        RelayoutRequest();
-        return;
+        mCellData[ rowCount ][ 0 ] = data;
       }
+
+      RelayoutRequest();
     }
   }
 
-  // No empty cells, so increase size of the table
-  unsigned int newColumnCount = ( columnCount > 0 ) ? columnCount : 1;
-  ResizeContainers( rowCount + 1, newColumnCount );
-
-  // Put the actor in the first cell of the new row
-  CellData data;
-  data.actor = child;
-  data.position.rowIndex = rowCount;
-  data.position.columnIndex = 0;
-  data.horizontalAlignment = horizontalAlignment;
-  data.verticalAlignment = verticalAlignment;
-  mCellData[ rowCount ][ 0 ] = data;
-  RelayoutRequest();
+  Control::OnChildAdd( child );
 }
 
-void TableView::OnControlChildRemove( Actor& child )
+void TableView::OnChildRemove( Actor& child )
 {
   // dont process if we're in the middle of bigger operation like delete row, column or resize
   if( !mLayoutingChild )
@@ -1034,13 +1100,17 @@ void TableView::OnControlChildRemove( Actor& child )
       RelayoutRequest();
     }
   }
+
+  Control::OnChildRemove( child );
 }
 
 TableView::TableView( unsigned int initialRows, unsigned int initialColumns )
-: Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
+: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
   mCellData( initialRows, initialColumns ),
+  mPreviousFocusedActor(),
   mLayoutingChild( false ),
-  mRowColumnDirty( true )     // Force recalculation first time
+  mRowDirty( true ),     // Force recalculation first time
+  mColumnDirty( true )
 {
   SetKeyboardNavigationSupport( true );
   ResizeContainers( initialRows, initialColumns );
@@ -1050,8 +1120,13 @@ void TableView::OnInitialize()
 {
   // Make self as keyboard focusable and focus group
   Actor self = Self();
-  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::TABLE ) );
+  } );
 }
 
 void TableView::ResizeContainers( unsigned int rows, unsigned int columns )
@@ -1145,7 +1220,7 @@ void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl,
                                          void(TableView::*funcFit)(unsigned int),
                                          const Property::Value& value )
 {
-  Property::Map* map = value.GetMap();
+  const Property::Map* map = value.GetMap();
   if( map )
   {
     unsigned int index(0);
@@ -1158,8 +1233,8 @@ void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl,
       if( childMap )
       {
         Property::Value* policy = childMap->Find( "policy" );
-        Property::Value* value = childMap->Find( "value" );
-        if( policy && value )
+        Property::Value* childMapValue = childMap->Find( "value" );
+        if( policy && childMapValue )
         {
           std::string policyValue;
           policy->Get( policyValue );
@@ -1171,11 +1246,11 @@ void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl,
           {
             if( policy == Toolkit::TableView::FIXED  )
             {
-              (tableViewImpl.*funcFixed)( index, value->Get<float>() );
+              (tableViewImpl.*funcFixed)( index, childMapValue->Get<float>() );
             }
             else if( policy == Toolkit::TableView::RELATIVE )
             {
-              (tableViewImpl.*funcRelative)( index, value->Get<float>() );
+              (tableViewImpl.*funcRelative)( index, childMapValue->Get<float>() );
             }
             else if( policy == Toolkit::TableView::FIT )
             {
@@ -1284,51 +1359,78 @@ Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolki
       int numberOfColumns = GetColumns();
       int numberOfRows = GetRows();
 
+      bool lastCell = false;
+      Actor nextValidActor;
+
       switch ( direction )
       {
         case Toolkit::Control::KeyboardFocus::LEFT:
         {
-          if(--currentColumn < 0)
+          do
           {
-            currentColumn = numberOfColumns - 1;
-            if(--currentRow < 0)
+            if(--currentColumn < 0)
             {
-              currentRow = loopEnabled ? numberOfRows - 1 : 0;
-              focusLost = (currentRow == 0);
+              currentColumn = numberOfColumns - 1;
+              if(--currentRow < 0)
+              {
+                lastCell = true;
+                currentRow = loopEnabled ? numberOfRows - 1 : 0;
+                focusLost = (currentRow == 0);
+              }
             }
-          }
+            nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
+          } while ( !nextValidActor && !lastCell );
           break;
         }
         case Toolkit::Control::KeyboardFocus::RIGHT:
         {
-          if(++currentColumn > numberOfColumns - 1)
+          do
           {
-            currentColumn = 0;
-            if(++currentRow > numberOfRows - 1)
+            if(++currentColumn > numberOfColumns - 1)
             {
-              currentRow = loopEnabled ? 0 : numberOfRows - 1;
-              focusLost = (currentRow == numberOfRows - 1);
+              currentColumn = 0;
+              if(++currentRow > numberOfRows - 1)
+              {
+                lastCell = true;
+                currentRow = loopEnabled ? 0 : numberOfRows - 1;
+                focusLost = (currentRow == numberOfRows - 1);
+              }
             }
-          }
+            nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
+          } while ( !nextValidActor && !lastCell );
           break;
         }
         case Toolkit::Control::KeyboardFocus::UP:
         {
-          if(--currentRow < 0)
+          do
           {
-            currentRow = loopEnabled ? numberOfRows - 1 : 0;
-            focusLost = (currentRow == 0);
-          }
+            if(--currentRow < 0)
+            {
+              lastCell = true;
+              currentRow = loopEnabled ? numberOfRows - 1 : 0;
+              focusLost = (currentRow == 0);
+            }
+            nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
+          } while ( !nextValidActor && !lastCell );
           break;
         }
         case Toolkit::Control::KeyboardFocus::DOWN:
 
         {
-          if(++currentRow > numberOfRows - 1)
+          do
           {
-            currentRow = loopEnabled ? 0 : numberOfRows - 1;
-            focusLost = (currentRow == numberOfRows - 1);
-          }
+            if(++currentRow > numberOfRows - 1)
+            {
+              lastCell = true;
+              currentRow = loopEnabled ? 0 : numberOfRows - 1;
+              focusLost = (currentRow == numberOfRows - 1);
+            }
+            nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
+          } while ( !nextValidActor && !lastCell );
+          break;
+        }
+        default:
+        {
           break;
         }
       }
@@ -1337,12 +1439,49 @@ Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolki
       if(!focusLost)
       {
         nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
+
+        // Save the focused actor in the TableView.
+        mPreviousFocusedActor = nextFocusableActor;
       }
     }
     else
     {
-      // The current focused actor is not within table view, so the child in the first cell should be focused.
-      nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
+      // The current focused actor is not within this TableView.
+
+      unsigned int numberOfColumns = GetColumns();
+      unsigned int numberOfRows = GetRows();
+
+      // Check whether the previous focused actor is a focus group (i.e. a layout container)
+      bool wasFocusedOnLayoutContainer = false;
+      Actor previousFocusedActor = mPreviousFocusedActor.GetHandle();
+      if( previousFocusedActor )
+      {
+        Toolkit::Control control = Toolkit::Control::DownCast( previousFocusedActor );
+        if( control )
+        {
+          Internal::Control& controlImpl = static_cast<Internal::Control&>(control.GetImplementation());
+          wasFocusedOnLayoutContainer = controlImpl.IsKeyboardFocusGroup();
+        }
+      }
+
+      // Check whether the previous focused actor is a layout container and also a child of this TableView
+      Toolkit::TableView::CellPosition position;
+      if( wasFocusedOnLayoutContainer && FindChildPosition( previousFocusedActor, position ) )
+      {
+        nextFocusableActor = GetNextKeyboardFocusableActor(previousFocusedActor, direction, loopEnabled);
+      }
+      else
+      {
+        // Otherwise, move the focus to either the first or the last cell according to the given direction.
+        if(direction == Toolkit::Control::KeyboardFocus::LEFT || direction == Toolkit::Control::KeyboardFocus::UP)
+        {
+          nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(numberOfRows - 1, numberOfColumns - 1));
+        }
+        else
+        {
+          nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
+        }
+      }
     }
   }
 
@@ -1357,76 +1496,44 @@ Vector3 TableView::GetNaturalSize()
 
 float TableView::CalculateChildSize( const Actor& child, Dimension::Type dimension )
 {
-  CalculateRowColumnData();
-
-  const unsigned int rowCount = mCellData.GetRows();
-  const unsigned int columnCount = mCellData.GetColumns();
-
-  for( unsigned int row = 0; row < rowCount; ++row )
+  Toolkit::TableView::CellPosition position;
+  if( FindChildPosition( child, position) )
   {
-    for( unsigned int column = 0; column < columnCount; ++column )
+    switch( dimension )
     {
-      // check if this cell has an actor
-      Actor& actor = mCellData[ row ][ column ].actor;
-
-      if( actor && ( actor == child ) )
+      case Dimension::WIDTH:
       {
-        const Toolkit::TableView::CellPosition position = mCellData[ row ][ column ].position;
+        float cellSize = 0.0f;
+        cellSize = mColumnData[position.columnIndex+position.columnSpan-1].position
+                 - (position.columnIndex > 0 ? mColumnData[position.columnIndex-1].position : 0.f)
+                 - mPadding.width * 2.0f;
 
-        // If there is an actor and this is the main cell of the actor.
-        // An actor can be in multiple cells if its row or columnspan is more than 1.
-        if ( ( position.rowIndex == row ) && ( position.columnIndex == column ) )
+        if( cellSize < 0.0f )
         {
-          switch( dimension )
-          {
-            case Dimension::WIDTH:
-            {
-              float cellSize = 0.0f;
-
-              // Accumulate the width
-              for( unsigned int i = 0; i < position.columnSpan; ++i )
-              {
-                DALI_ASSERT_DEBUG( column + i < mColumnData.Size() );
-                cellSize += mColumnData[ column + i ].size;
-              }
-
-              // Apply padding
-              cellSize -= mPadding.width * 2.0f;
-              if( cellSize < 0.0f )
-              {
-                cellSize = 0.0f;
-              }
-
-              return cellSize;
-            }
-
-            case Dimension::HEIGHT:
-            {
-              float cellSize = 0.0f;
+          cellSize = 0.0f;
+        }
 
-              // Accumulate the height
-              for( unsigned int i = 0; i < position.rowSpan; ++i )
-              {
-                DALI_ASSERT_DEBUG( row + i < mRowData.Size() );
-                cellSize += mRowData[ row + i ].size;
-              }
+        return cellSize;
+      }
 
-              // Apply padding
-              cellSize -= mPadding.height * 2.0f;
-              if( cellSize < 0.0f )
-              {
-                cellSize = 0.0f;
-              }
+      case Dimension::HEIGHT:
+      {
+        float cellSize = 0.0f;
 
-              return cellSize;
-            }
+        cellSize = mRowData[position.rowIndex+position.rowSpan-1].position
+                 - (position.rowIndex > 0 ? mRowData[position.rowIndex-1].position : 0.f)
+                 - mPadding.height * 2.0f;
 
-            default:
-            {
-              return 0.0f;
-            }
-          }
+        if( cellSize < 0.0f )
+        {
+          cellSize = 0.0f;
         }
+
+        return cellSize;
+      }
+      default:
+      {
+        return 0.0f;
       }
     }
   }
@@ -1465,7 +1572,7 @@ void TableView::SetCellAlignment( Toolkit::TableView::CellPosition position, Hor
   data.verticalAlignment = vertical;
 }
 
-void TableView::ComputeRelativeSizes( RowColumnArray& data )
+void TableView::CalculateFillSizes( RowColumnArray& data )
 {
   // First pass: Count number of fill entries and calculate used relative space
   Dali::Vector< RowColumnData* > fillData;
@@ -1556,7 +1663,7 @@ Vector2 TableView::GetCellPadding( Dimension::Type dimension )
   return Vector2();
 }
 
-void TableView::CalculateFixedSizes( RowColumnArray& data, Dimension::Type dimension )
+void TableView::CalculateFitSizes( RowColumnArray& data, Dimension::Type dimension )
 {
   Vector2 cellPadding = GetCellPadding( dimension );
 
@@ -1596,21 +1703,6 @@ void TableView::CalculateFixedSizes( RowColumnArray& data, Dimension::Type dimen
   }
 }
 
-void TableView::CalculateRelativeSizes( RowColumnArray& data, float size )
-{
-  const unsigned int dataCount = data.Size();
-
-  for( unsigned int i = 0; i < dataCount; ++i )
-  {
-    RowColumnData& dataInstance = data[ i ];
-
-    if( dataInstance.sizePolicy == Toolkit::TableView::FILL ||  dataInstance.sizePolicy == Toolkit::TableView::RELATIVE)
-    {
-      dataInstance.size = dataInstance.fillRatio * size;
-    }
-  }
-}
-
 bool TableView::FindFit( const RowColumnArray& data )
 {
   for( unsigned int i = 0, count = data.Size(); i < count; ++i )