X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Ftable-view%2Ftable-view-impl.cpp;h=4f27bba831e202a4893eef9b49bc7fc1d3ddde4f;hp=f482fdda081fc2c5dcd00ea964db7837087b2fd2;hb=f546dd5d83a968e573f8f053a01ce43df32c71a0;hpb=91b8f5bbaa7d68f5ca8fc94287b8c181a10ba894 diff --git a/dali-toolkit/internal/controls/table-view/table-view-impl.cpp b/dali-toolkit/internal/controls/table-view/table-view-impl.cpp old mode 100644 new mode 100755 index f482fdd..4f27bba --- a/dali-toolkit/internal/controls/table-view/table-view-impl.cpp +++ b/dali-toolkit/internal/controls/table-view/table-view-impl.cpp @@ -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. @@ -22,29 +22,19 @@ #include #include #include -#include +#include +#include #include #include #include +// INTERNAL INCLUDES +#include + 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& 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, @@ -144,9 +134,14 @@ DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TableView, Toolkit::Control, Create ); DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "rows", INTEGER, ROWS ) DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "columns", 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, "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() @@ -287,7 +282,7 @@ 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 @@ -412,7 +407,7 @@ void TableView::DeleteRow( unsigned int rowIndex, std::vector& 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--; } @@ -758,15 +753,15 @@ void TableView::OnLayoutNegotiated( float size, Dimension::Type dimension ) // update every column position in ColumnData array float cumulatedWidth = 0.0f; - for( unsigned int column = 0, columnCount = mCellData.GetColumns(); column < columnCount; ++column ) + for( auto&& element : mColumnData ) { - if( mColumnData[ column ].sizePolicy == Toolkit::TableView::FILL || mColumnData[ column ].sizePolicy == Toolkit::TableView::RELATIVE) + if( element.sizePolicy == Toolkit::TableView::FILL || element.sizePolicy == Toolkit::TableView::RELATIVE ) { - mColumnData[ column ].size = mColumnData[ column ].fillRatio * remainingSize; + element.size = element.fillRatio * remainingSize; } - cumulatedWidth += mColumnData[ column ].size; - mColumnData[column].position = cumulatedWidth; + cumulatedWidth += element.size; + element.position = cumulatedWidth; } mColumnDirty = false; @@ -804,11 +799,25 @@ void TableView::OnSizeSet( const Vector3& size ) // 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 ) { // Go through the layout data + float totalWidth = 0.0; + + Dali::LayoutDirection::Type layoutDirection = static_cast( Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get() ); + + if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection ) + { + for (auto&& element : mColumnData) + { + totalWidth += element.size; + } + } + for( unsigned int row = 0, rowCount = mCellData.GetRows(); row < rowCount; ++row ) { for( unsigned int column = 0, columnCount = mCellData.GetColumns(); column < columnCount; ++column ) @@ -823,41 +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 ); + + Padding padding = actor.GetProperty( Actor::Property::PADDING ); - Padding padding; - actor.GetPadding( padding ); + float left = (column > 0) ? mColumnData[column - 1].position : 0.f; + float right; + + if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection ) + { + right = totalWidth - left; + left = right - mColumnData[column].size; + } + else + { + right = left + mColumnData[column].size; + } - float left = column > 0 ? mColumnData[column-1].position : 0.f; - float right = mColumnData[column+position.columnSpan-1].position; float top = row > 0 ? mRowData[row-1].position : 0.f; float bottom = mRowData[row+position.rowSpan-1].position; if( cellData.horizontalAlignment == HorizontalAlignment::LEFT ) { - actor.SetX( left + mPadding.width + padding.left ); + actor.SetProperty( Actor::Property::POSITION_X, left + mPadding.width + padding.left ); } else if( cellData.horizontalAlignment == HorizontalAlignment::RIGHT ) { - actor.SetX( right - mPadding.width - padding.right - actor.GetRelayoutSize( Dimension::WIDTH ) ); + actor.SetProperty( Actor::Property::POSITION_X, right - mPadding.width - padding.right - actor.GetRelayoutSize( Dimension::WIDTH ) ); } else //if( cellData.horizontalAlignment == HorizontalAlignment::CENTER ) { - actor.SetX( (left + right + padding.left - padding.right - actor.GetRelayoutSize( Dimension::WIDTH )) * 0.5f ); + 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( top + mPadding.height + padding.top ); + actor.SetProperty( Actor::Property::POSITION_Y, top + mPadding.height + padding.top ); } else if( cellData.verticalAlignment == VerticalAlignment::BOTTOM ) { - actor.SetY( bottom - mPadding.height - padding.bottom - actor.GetRelayoutSize( Dimension::HEIGHT ) ); + actor.SetProperty( Actor::Property::POSITION_Y, bottom - mPadding.height - padding.bottom - actor.GetRelayoutSize( Dimension::HEIGHT ) ); } else //if( cellData.verticalAlignment = VerticalAlignment::CENTER ) { - actor.SetY( (top + bottom + padding.top - padding.bottom - actor.GetRelayoutSize( Dimension::HEIGHT )) * 0.5f ); + actor.SetProperty( Actor::Property::POSITION_Y, (top + bottom + padding.top - padding.bottom - actor.GetRelayoutSize( Dimension::HEIGHT )) * 0.5f ); } } } @@ -968,100 +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(); - 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(); - 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( child.GetProperty( child.GetPropertyIndex(ROW_SPAN_PROPERTY_NAME) ).Get() ); - } + if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_HORIZONTAL_ALIGNMENT ) != Property::NONE ) + { + std::string value = child.GetProperty( Toolkit::TableView::ChildProperty::CELL_HORIZONTAL_ALIGNMENT ).Get(); + 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( child.GetProperty( child.GetPropertyIndex(COLUMN_SPAN_PROPERTY_NAME) ).Get() ); - } + if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_VERTICAL_ALIGNMENT ) != Property::NONE ) + { + std::string value = child.GetProperty( Toolkit::TableView::ChildProperty::CELL_VERTICAL_ALIGNMENT ).Get(); + 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(); - cellPosition.rowIndex = static_cast( indices.x ); - cellPosition.columnIndex = static_cast( 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 - return; - } + if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_INDEX ) != Property::NONE ) + { + Vector2 indices = child.GetProperty( Toolkit::TableView::ChildProperty::CELL_INDEX ).Get(); + cellPosition.rowIndex = static_cast( indices.x ); + cellPosition.columnIndex = static_cast( 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 ) { - // Put the actor in the cell + 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 ) + { + // 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 ) @@ -1072,11 +1100,14 @@ void TableView::OnControlChildRemove( Actor& child ) RelayoutRequest(); } } + + Control::OnChildRemove( child ); } TableView::TableView( unsigned int initialRows, unsigned int initialColumns ) -: Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ), +: Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ), mCellData( initialRows, initialColumns ), + mPreviousFocusedActor(), mLayoutingChild( false ), mRowDirty( true ), // Force recalculation first time mColumnDirty( true ) @@ -1089,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 ) @@ -1184,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); @@ -1197,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 ); @@ -1210,11 +1246,11 @@ void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl, { if( policy == Toolkit::TableView::FIXED ) { - (tableViewImpl.*funcFixed)( index, value->Get() ); + (tableViewImpl.*funcFixed)( index, childMapValue->Get() ); } else if( policy == Toolkit::TableView::RELATIVE ) { - (tableViewImpl.*funcRelative)( index, value->Get() ); + (tableViewImpl.*funcRelative)( index, childMapValue->Get() ); } else if( policy == Toolkit::TableView::FIT ) { @@ -1323,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; } } @@ -1376,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(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)); + } + } } }