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=4b3e019225a8316a3054014e0c8b27259a7ed16e;hp=bac04020cc87a74aac2e46d6a5d1940e28038898;hb=HEAD;hpb=e5ca10134c73ca0588f893adde82694ad907dd8d diff --git a/dali-toolkit/internal/controls/table-view/table-view-impl.cpp b/dali-toolkit/internal/controls/table-view/table-view-impl.cpp index bac0402..686c1ca 100644 --- 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) 2024 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. @@ -19,41 +19,31 @@ #include // EXTERNAL INCLUDES -#include +#include +#include +#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("cellIndex"); -const char * const ROW_SPAN_PROPERTY_NAME("rowSpan"); -const char * const COLUMN_SPAN_PROPERTY_NAME("columnSpan"); -const char * const CELL_HORIZONTAL_ALIGNMENT_PROPERTY_NAME("cellHorizontalAlignment"); -const char * const CELL_VERTICAL_ALIGNMENT_PROPERTY_NAME("cellVerticalAlignment"); - /** * @brief Should the tableview fit around the given actor * * @param[in] actor The child actor to test against * @param[dimension] The dimension to test against */ -bool FitToChild( Actor actor, Dimension::Type dimension ) +bool FitToChild(Actor actor, Dimension::Type dimension) { - return actor.GetResizePolicy( dimension ) != ResizePolicy::FILL_TO_PARENT && actor.GetRelayoutSize( dimension ) > 0.0f; + return actor.GetResizePolicy(dimension) != ResizePolicy::FILL_TO_PARENT && actor.GetRelayoutSize(dimension) > 0.0f; } #if defined(DEBUG_ENABLED) @@ -61,60 +51,58 @@ 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::LogMessageWithFunctionLine(Debug::INFO, TABLEVIEW_TAG fmt, ##args) //#define TABLEVIEW_DEBUG 1 #if defined(TABLEVIEW_DEBUG) -void PrintArray( Array2d& array ) +void PrintArray(Array2d& array) { - TV_LOG( "Array2d size [%d,%d] \n", array.GetRows(), array.GetColumns() ); + TV_LOG("Array2d size [%d,%d] \n", array.GetRows(), array.GetColumns()); // print values - for( unsigned int i = 0; i < array.GetRows(); ++i ) + for(unsigned int i = 0; i < array.GetRows(); ++i) { - for( unsigned int j = 0; j < array.GetColumns(); ++j ) + for(unsigned int j = 0; j < array.GetColumns(); ++j) { - Dali::Toolkit::Internal::TableView::CellData data = array[i][j]; - char actor = ' '; - std::string actorName; - if( data.actor ) + Dali::Toolkit::Internal::TableView::CellData data = array[i][j]; + char actor = ' '; + std::string actorName; + if(data.actor) { - actor = 'A'; - actorName = data.actor.GetName(); + actor = 'A'; + actorName = data.actor.GetProperty(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, - data.position.rowSpan, data.position.columnSpan ); + TV_LOG("Array[%d,%d]=%c %s %d,%d,%d,%d ", i, j, actor, actorName.c_str(), data.position.rowIndex, data.position.columnIndex, data.position.rowSpan, data.position.columnSpan); } - TV_LOG( "\n" ); + TV_LOG("\n"); } } // debugging support, very useful when new features are added or bugs are hunted down // currently not called from code so compiler will optimize these away, kept here for future debugging -void PrintArray( Array2d& array ) +void PrintArray(Array2d& array) { - TV_LOG( "Array2d size [%d,%d] \n", array.GetRows(), array.GetColumns() ); + TV_LOG("Array2d size [%d,%d] \n", array.GetRows(), array.GetColumns()); // print values - for( unsigned int i = 0; i < array.GetRows(); ++i ) + for(unsigned int i = 0; i < array.GetRows(); ++i) { - for( unsigned int j = 0; j < array.GetColumns(); ++j ) + for(unsigned int j = 0; j < array.GetColumns(); ++j) { - TV_LOG( "Array[%d,%d]=%.2f,%.2f ", i, j, array[i][j].width, array[i][j].height ); + TV_LOG("Array[%d,%d]=%.2f,%.2f ", i, j, array[i][j].width, array[i][j].height); } - TV_LOG( "\n" ); + TV_LOG("\n"); } } // debugging support, very useful when new features are added or bugs are hunted down // currently not called from code so compiler will optimize these away, kept here for future debugging -void PrintVector( std::vector& array ) +void PrintVector(std::vector& array) { - TV_LOG( "vector, size [%d]\n", array.size() ); + TV_LOG("vector, size [%d]\n", array.size()); // print values - for( unsigned int i = 0; i < array.size(); ++i ) + for(unsigned int i = 0; i < array.size(); ++i) { - TV_LOG( "vector[%d]=%.2f ", i, array[i] ); + TV_LOG("vector[%d]=%.2f ", i, array[i]); } - TV_LOG( "\n" ); + TV_LOG("\n"); } #endif // defined(TABLEVIEW_DEBUG) #endif // defined(DEBUG_ENABLED) @@ -123,67 +111,70 @@ void PrintVector( std::vector& array ) namespace Dali { - namespace Toolkit { - namespace Internal { - namespace { - // Type registration BaseHandle Create() { - return Toolkit::TableView::New( 0, 0 ); + return Toolkit::TableView::New(0, 0); } +// clang-format off // Setup properties, signals and actions using the type-registry. -DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TableView, Toolkit::Control, Create ); +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, "cellPadding", VECTOR2, CELL_PADDING ) +DALI_PROPERTY_REGISTRATION(Toolkit, TableView, "layoutRows", MAP, LAYOUT_ROWS ) +DALI_PROPERTY_REGISTRATION(Toolkit, TableView, "layoutColumns", 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() const Scripting::StringEnum LAYOUT_POLICY_STRING_TABLE[] = { - { "fixed", Toolkit::TableView::FIXED }, - { "relative", Toolkit::TableView::RELATIVE }, - { "fill", Toolkit::TableView::FILL }, - { "fit", Toolkit::TableView::FIT } + {"fixed", Toolkit::TableView::FIXED }, + {"relative", Toolkit::TableView::RELATIVE}, + {"fill", Toolkit::TableView::FILL }, + {"fit", Toolkit::TableView::FIT } }; -const unsigned int LAYOUT_POLICY_STRING_TABLE_COUNT = sizeof(LAYOUT_POLICY_STRING_TABLE) / sizeof( LAYOUT_POLICY_STRING_TABLE[0] ); +const unsigned int LAYOUT_POLICY_STRING_TABLE_COUNT = sizeof(LAYOUT_POLICY_STRING_TABLE) / sizeof(LAYOUT_POLICY_STRING_TABLE[0]); const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] = { - {"left", HorizontalAlignment::LEFT}, + {"left", HorizontalAlignment::LEFT }, {"center", HorizontalAlignment::CENTER}, - {"right", HorizontalAlignment::RIGHT} + {"right", HorizontalAlignment::RIGHT } }; -const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(HORIZONTAL_ALIGNMENT_STRING_TABLE) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] ); +const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(HORIZONTAL_ALIGNMENT_STRING_TABLE) / sizeof(HORIZONTAL_ALIGNMENT_STRING_TABLE[0]); const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] = { - {"top", VerticalAlignment::TOP}, + {"top", VerticalAlignment::TOP }, {"center", VerticalAlignment::CENTER}, {"bottom", VerticalAlignment::BOTTOM} }; -const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(VERTICAL_ALIGNMENT_STRING_TABLE) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] ); - +const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(VERTICAL_ALIGNMENT_STRING_TABLE) / sizeof(VERTICAL_ALIGNMENT_STRING_TABLE[0]); +// clang-format on } // Unnamed namespace -Toolkit::TableView TableView::New( unsigned int initialRows, unsigned int initialColumns ) +Toolkit::TableView TableView::New(unsigned int initialRows, unsigned int initialColumns) { // Create the implementation, temporarily owned by this handle on stack - IntrusivePtr< TableView > impl = new TableView( initialRows, initialColumns ); + IntrusivePtr impl = new TableView(initialRows, initialColumns); // Pass ownership to CustomActor handle - Toolkit::TableView handle( *impl ); + Toolkit::TableView handle(*impl); // Second-phase init of the implementation // This can only be done after the CustomActor connection has been made... @@ -192,112 +183,112 @@ Toolkit::TableView TableView::New( unsigned int initialRows, unsigned int initia return handle; } -bool TableView::AddChild( Actor& child, const Toolkit::TableView::CellPosition& position ) +bool TableView::AddChild(Actor& child, const Toolkit::TableView::CellPosition& position) { // check that the child is valid - DALI_ASSERT_ALWAYS( child ); + DALI_ASSERT_ALWAYS(child); // if child is already parented, we adopt it child.Unparent(); // check if we need to expand our data array - if( position.rowIndex >= mCellData.GetRows() ) + if(position.rowIndex >= mCellData.GetRows()) { // only adding new rows - ResizeContainers( position.rowIndex + 1, mCellData.GetColumns() ); + ResizeContainers(position.rowIndex + 1, mCellData.GetColumns()); } - if( position.columnIndex >= mCellData.GetColumns() ) + if(position.columnIndex >= mCellData.GetColumns()) { // only adding new columns - ResizeContainers( mCellData.GetRows(), position.columnIndex + 1 ); + ResizeContainers(mCellData.GetRows(), position.columnIndex + 1); } // check if there already is something in this cell - if( mCellData[ position.rowIndex ][ position.columnIndex ].actor ) + if(mCellData[position.rowIndex][position.columnIndex].actor) { return false; // cannot share a cell, it would complicate all logic and not bring much benefit } - RelayoutingLock lock( *this ); + RelayoutingLock lock(*this); // adopt the child - Self().Add( child ); + Self().Add(child); // if child spans multiple rows of columns - if( ( position.rowSpan > 1 ) && ( position.rowIndex + position.rowSpan > mCellData.GetRows() ) ) + if((position.rowSpan > 1) && (position.rowIndex + position.rowSpan > mCellData.GetRows())) { // increase table size for the full span, only increasing rows - ResizeContainers( position.rowIndex + position.rowSpan, mCellData.GetColumns() ); + ResizeContainers(position.rowIndex + position.rowSpan, mCellData.GetColumns()); } - if( ( position.columnSpan > 1 ) && ( position.columnIndex + position.columnSpan > mCellData.GetColumns() ) ) + if((position.columnSpan > 1) && (position.columnIndex + position.columnSpan > mCellData.GetColumns())) { // increase table size for the full span, only increasing columns - ResizeContainers( mCellData.GetRows(), position.columnIndex + position.columnSpan ); + ResizeContainers(mCellData.GetRows(), position.columnIndex + position.columnSpan); } // Fill in all cells that need the data CellData data; - data.actor = child; + data.actor = child; data.position = position; - for( unsigned int row = position.rowIndex; row < ( position.rowIndex + position.rowSpan ); ++row ) + for(unsigned int row = position.rowIndex; row < (position.rowIndex + position.rowSpan); ++row) { // store same information to all cells, this way we can identify // if a cell is the prime location of an actor or a spanned one - for( unsigned int column = position.columnIndex; column < ( position.columnIndex + position.columnSpan ); ++column ) + for(unsigned int column = position.columnIndex; column < (position.columnIndex + position.columnSpan); ++column) { // store same information to all cells, this way we can identify // if a cell is the prime location of an actor or a spanned one - mCellData[ row ][ column ] = data; + mCellData[row][column] = data; } } // Relayout the whole table - if( mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT && position.rowSpan == 1 ) + if(mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT && position.rowSpan == 1) { mRowDirty = true; } - if( mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT && position.columnSpan == 1 ) + if(mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT && position.columnSpan == 1) { mColumnDirty = true; } RelayoutRequest(); - return true; // Addition successful + return true; // Addition successful } -Actor TableView::GetChildAt( const Toolkit::TableView::CellPosition& position ) +Actor TableView::GetChildAt(const Toolkit::TableView::CellPosition& position) { - if( ( position.rowIndex < mCellData.GetRows() ) && ( position.columnIndex < mCellData.GetColumns() ) ) + if((position.rowIndex < mCellData.GetRows()) && (position.columnIndex < mCellData.GetColumns())) { - return mCellData[ position.rowIndex ][ position.columnIndex ].actor; + return mCellData[position.rowIndex][position.columnIndex].actor; } // Return an empty handle return Actor(); } -Actor TableView::RemoveChildAt( const Toolkit::TableView::CellPosition& position ) +Actor TableView::RemoveChildAt(const Toolkit::TableView::CellPosition& position) { // get the child handle - Actor child = GetChildAt( position ); + Actor child = GetChildAt(position); // if no real actor there, nothing else to be done - if( child ) + if(child) { - RelayoutingLock lock( *this ); + RelayoutingLock lock(*this); // Remove the child, this will trigger a call to OnChildRemove - Self().Remove( child ); + Self().Remove(child); // relayout the table only if instances were found - if( RemoveAllInstances( child ) ) + if(RemoveAllInstances(child)) { - if( mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT ) + if(mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT) { mRowDirty = true; } - if( mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT ) + if(mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT) { mColumnDirty = true; } @@ -308,22 +299,22 @@ Actor TableView::RemoveChildAt( const Toolkit::TableView::CellPosition& position return child; } -bool TableView::FindChildPosition( const Actor& child, Toolkit::TableView::CellPosition& positionOut ) +bool TableView::FindChildPosition(const Actor& child, Toolkit::TableView::CellPosition& positionOut) { // Only find valid child actors - if( child ) + if(child) { // Walk through the layout data - const unsigned int rowCount = mCellData.GetRows(); + const unsigned int rowCount = mCellData.GetRows(); const unsigned int columnCount = mCellData.GetColumns(); - for( unsigned int row = 0; row < rowCount; ++row ) + for(unsigned int row = 0; row < rowCount; ++row) { - for( unsigned int column = 0; column < columnCount; ++column ) + for(unsigned int column = 0; column < columnCount; ++column) { - if( mCellData[ row ][ column ].actor == child ) + if(mCellData[row][column].actor == child) { - positionOut = mCellData[ row ][ column ].position; + positionOut = mCellData[row][column].position; return true; } } @@ -333,33 +324,33 @@ bool TableView::FindChildPosition( const Actor& child, Toolkit::TableView::CellP return false; } -void TableView::InsertRow( unsigned int rowIndex ) +void TableView::InsertRow(unsigned int rowIndex) { - RelayoutingLock lock( *this ); + RelayoutingLock lock(*this); - mCellData.InsertRow( rowIndex ); + mCellData.InsertRow(rowIndex); // Need to update the cell infos for the items that moved - const unsigned int rowCount = mCellData.GetRows(); + const unsigned int rowCount = mCellData.GetRows(); const unsigned int columnCount = mCellData.GetColumns(); - for( unsigned int row = 0; row < rowCount; ++row ) + for(unsigned int row = 0; row < rowCount; ++row) { - for( unsigned int column = 0; column < columnCount; ++column ) + for(unsigned int column = 0; column < columnCount; ++column) { - Toolkit::TableView::CellPosition& position = mCellData[ row ][ column ].position; + Toolkit::TableView::CellPosition& position = mCellData[row][column].position; // If cell is spanning and above and spans to inserted row - if( ( position.rowSpan > 1 ) && ( position.rowIndex <= rowIndex ) && - ( position.rowIndex + position.rowSpan > rowIndex ) ) + if((position.rowSpan > 1) && (position.rowIndex <= rowIndex) && + (position.rowIndex + position.rowSpan > rowIndex)) { // Increment span position.rowSpan++; // Copy cell to occupy the new column - mCellData[ rowIndex ][ column ] = mCellData[ row ][ column ]; + mCellData[rowIndex][column] = mCellData[row][column]; } - else if( row > rowIndex ) // If below of inserted row, increase row index + else if(row > rowIndex) // If below of inserted row, increase row index { // Increment index position.rowIndex++; @@ -368,51 +359,51 @@ void TableView::InsertRow( unsigned int rowIndex ) } // Expand row data array - mRowData.Insert( mRowData.Begin() + rowIndex, RowColumnData() ); + mRowData.Insert(mRowData.Begin() + rowIndex, RowColumnData()); // Sizes may have changed, so relayout mRowDirty = true; RelayoutRequest(); } -void TableView::DeleteRow( unsigned int rowIndex ) +void TableView::DeleteRow(unsigned int rowIndex) { - std::vector< Actor > ignored; - DeleteRow( rowIndex, ignored ); + std::vector ignored; + DeleteRow(rowIndex, ignored); } -void TableView::DeleteRow( unsigned int rowIndex, std::vector& removed ) +void TableView::DeleteRow(unsigned int rowIndex, std::vector& removed) { - RelayoutingLock lock( *this ); + RelayoutingLock lock(*this); // Delete the row - std::vector< CellData > lost; - mCellData.DeleteRow( rowIndex, lost ); + std::vector lost; + mCellData.DeleteRow(rowIndex, lost); // Need to update the cell infos for the items that moved - const unsigned int rowCount = mCellData.GetRows(); + const unsigned int rowCount = mCellData.GetRows(); const unsigned int columnCount = mCellData.GetColumns(); - for( unsigned int row = 0; row < rowCount; ++row ) + for(unsigned int row = 0; row < rowCount; ++row) { - for( unsigned int column = 0; column < columnCount; ++column ) + for(unsigned int column = 0; column < columnCount; ++column) { - Toolkit::TableView::CellPosition& position = mCellData[ row ][ column ].position; + Toolkit::TableView::CellPosition& position = mCellData[row][column].position; // If cell is spanning and above and spans to deleted row - if( ( position.rowSpan > 1 ) && ( position.rowIndex <= rowIndex ) && - ( position.rowIndex + position.rowSpan > rowIndex ) ) + if((position.rowSpan > 1) && (position.rowIndex <= rowIndex) && + (position.rowIndex + position.rowSpan > rowIndex)) { // Decrement span - if( position.rowSpan > 1 ) + if(position.rowSpan > 1) { position.rowSpan--; } } - else if( row >= rowIndex ) // If below of or at the inserted row, decrease row index + else if(row >= rowIndex) // If below of or at the inserted row, decrease row index { // Decrement index - if( position.rowIndex > 0 ) + if(position.rowIndex > 0) { position.rowIndex--; } @@ -421,10 +412,10 @@ void TableView::DeleteRow( unsigned int rowIndex, std::vector& removed ) } // 1 row removed, 0 columns - RemoveAndGetLostActors( lost, removed, 1u, 0u ); + RemoveAndGetLostActors(lost, removed, 1u, 0u); // Contract row data array - mRowData.Erase( mRowData.Begin() + rowIndex ); + mRowData.Erase(mRowData.Begin() + rowIndex); // Sizes may have changed, so relayout mRowDirty = true; @@ -434,34 +425,34 @@ void TableView::DeleteRow( unsigned int rowIndex, std::vector& removed ) RelayoutRequest(); } -void TableView::InsertColumn( unsigned int columnIndex ) +void TableView::InsertColumn(unsigned int columnIndex) { - RelayoutingLock lock( *this ); + RelayoutingLock lock(*this); // Insert the new column - mCellData.InsertColumn( columnIndex ); + mCellData.InsertColumn(columnIndex); // Need to update the cell infos for the items that moved - const unsigned int rowCount = mCellData.GetRows(); + const unsigned int rowCount = mCellData.GetRows(); const unsigned int columnCount = mCellData.GetColumns(); - for( unsigned int row = 0; row < rowCount; ++row ) + for(unsigned int row = 0; row < rowCount; ++row) { - for( unsigned int column = 0; column < columnCount; ++column ) + for(unsigned int column = 0; column < columnCount; ++column) { - Toolkit::TableView::CellPosition& position = mCellData[ row ][ column ].position; + Toolkit::TableView::CellPosition& position = mCellData[row][column].position; // If cell is spanning and left side and spans to inserted column - if( ( position.columnSpan > 1 ) && ( position.columnIndex <= columnIndex ) && - ( position.columnIndex + position.columnSpan > columnIndex ) ) + if((position.columnSpan > 1) && (position.columnIndex <= columnIndex) && + (position.columnIndex + position.columnSpan > columnIndex)) { // Increment span position.columnSpan++; // Copy cell to occupy the new column - mCellData[ row ][ columnIndex ] = mCellData[ row ][ column ]; + mCellData[row][columnIndex] = mCellData[row][column]; } - else if( column > columnIndex ) // If on the right side of inserted column, increase column index + else if(column > columnIndex) // If on the right side of inserted column, increase column index { // Increment index position.columnIndex++; @@ -470,51 +461,51 @@ void TableView::InsertColumn( unsigned int columnIndex ) } // Expand column data array - mColumnData.Insert( mColumnData.Begin() + columnIndex, RowColumnData() ); + mColumnData.Insert(mColumnData.Begin() + columnIndex, RowColumnData()); // Sizes may have changed so relayout mColumnDirty = true; RelayoutRequest(); } -void TableView::DeleteColumn( unsigned int columnIndex ) +void TableView::DeleteColumn(unsigned int columnIndex) { - std::vector< Actor > ignored; - DeleteColumn( columnIndex, ignored ); + std::vector ignored; + DeleteColumn(columnIndex, ignored); } -void TableView::DeleteColumn( unsigned int columnIndex, std::vector& removed ) +void TableView::DeleteColumn(unsigned int columnIndex, std::vector& removed) { - RelayoutingLock lock( *this ); + RelayoutingLock lock(*this); // Remove the column - std::vector< CellData > lost; - mCellData.DeleteColumn( columnIndex, lost ); + std::vector lost; + mCellData.DeleteColumn(columnIndex, lost); // Need to update the cell infos for the items that moved - const unsigned int rowCount = mCellData.GetRows(); + const unsigned int rowCount = mCellData.GetRows(); const unsigned int columnCount = mCellData.GetColumns(); - for( unsigned int row = 0; row < rowCount; ++row ) + for(unsigned int row = 0; row < rowCount; ++row) { - for( unsigned int column = 0; column < columnCount; ++column ) + for(unsigned int column = 0; column < columnCount; ++column) { - Toolkit::TableView::CellPosition& position = mCellData[ row ][ column ].position; + Toolkit::TableView::CellPosition& position = mCellData[row][column].position; // If cell is spanning and left side and spans to inserted column - if( ( position.columnSpan > 1 ) && ( position.columnIndex <= columnIndex ) && - ( position.columnIndex + position.columnSpan > columnIndex ) ) + if((position.columnSpan > 1) && (position.columnIndex <= columnIndex) && + (position.columnIndex + position.columnSpan > columnIndex)) { // Decrement span - if( position.columnSpan > 1 ) + if(position.columnSpan > 1) { position.columnSpan--; } } - else if( column >= columnIndex ) // If on the right side of or at the inserted column, decrease column index + else if(column >= columnIndex) // If on the right side of or at the inserted column, decrease column index { // Decrement index - if( position.columnIndex > 0 ) + if(position.columnIndex > 0) { position.columnIndex--; } @@ -523,10 +514,10 @@ void TableView::DeleteColumn( unsigned int columnIndex, std::vector& remo } // 0 rows, 1 column removed - RemoveAndGetLostActors( lost, removed, 0u, 1u ); + RemoveAndGetLostActors(lost, removed, 0u, 1u); // Contract column data array - mColumnData.Erase( mColumnData.Begin() + columnIndex ); + mColumnData.Erase(mColumnData.Begin() + columnIndex); // Size may have changed so relayout mColumnDirty = true; @@ -536,52 +527,52 @@ void TableView::DeleteColumn( unsigned int columnIndex, std::vector& remo RelayoutRequest(); } -void TableView::Resize( unsigned int rows, unsigned int columns ) +void TableView::Resize(unsigned int rows, unsigned int columns) { - std::vector< Actor > ignored; - Resize( rows, columns, ignored ); + std::vector ignored; + Resize(rows, columns, ignored); } -void TableView::Resize( unsigned int rows, unsigned int columns, std::vector& removed ) +void TableView::Resize(unsigned int rows, unsigned int columns, std::vector& removed) { - RelayoutingLock lock( *this ); + RelayoutingLock lock(*this); - unsigned int oldRows = GetRows(); + unsigned int oldRows = GetRows(); unsigned int oldColumns = GetColumns(); // Resize data array - std::vector< CellData > lost; - ResizeContainers( rows, columns, lost ); + std::vector lost; + ResizeContainers(rows, columns, lost); // Calculate if we lost rows unsigned int rowsRemoved = 0; - unsigned int newRows = GetRows(); + unsigned int newRows = GetRows(); - if( oldRows < newRows ) + if(oldRows < newRows) { rowsRemoved = newRows - oldRows; } // Calculate if we lost columns unsigned int columnsRemoved = 0; - unsigned int newColumns = GetColumns(); - if( oldColumns < newColumns ) + unsigned int newColumns = GetColumns(); + if(oldColumns < newColumns) { rowsRemoved = newColumns - oldColumns; } - RemoveAndGetLostActors( lost, removed, rowsRemoved, columnsRemoved ); + RemoveAndGetLostActors(lost, removed, rowsRemoved, columnsRemoved); // Sizes may have changed so request a relayout - mRowDirty = true; + mRowDirty = true; mColumnDirty = true; RelayoutRequest(); } -void TableView::SetCellPadding( Size padding ) +void TableView::SetCellPadding(Size padding) { // If padding really changed - if( padding != mPadding ) + if(padding != mPadding) { mPadding = padding; @@ -594,125 +585,125 @@ Size TableView::GetCellPadding() return mPadding; } -void TableView::SetFitHeight( unsigned int rowIndex ) +void TableView::SetFitHeight(unsigned int rowIndex) { - DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() ); + DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size()); - if( mRowData[ rowIndex ].sizePolicy != Toolkit::TableView::FIT ) + if(mRowData[rowIndex].sizePolicy != Toolkit::TableView::FIT) { - mRowData[ rowIndex ].sizePolicy = Toolkit::TableView::FIT; + mRowData[rowIndex].sizePolicy = Toolkit::TableView::FIT; mRowDirty = true; RelayoutRequest(); } } -bool TableView::IsFitHeight( unsigned int rowIndex ) const +bool TableView::IsFitHeight(unsigned int rowIndex) const { - DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() ); + DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size()); - return mRowData[ rowIndex ].sizePolicy == Toolkit::TableView::FIT; + return mRowData[rowIndex].sizePolicy == Toolkit::TableView::FIT; } -void TableView::SetFitWidth( unsigned int columnIndex ) +void TableView::SetFitWidth(unsigned int columnIndex) { - DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() ); + DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size()); - if( mColumnData[ columnIndex ].sizePolicy != Toolkit::TableView::FIT ) + if(mColumnData[columnIndex].sizePolicy != Toolkit::TableView::FIT) { - mColumnData[ columnIndex ].sizePolicy = Toolkit::TableView::FIT; + mColumnData[columnIndex].sizePolicy = Toolkit::TableView::FIT; mColumnDirty = true; RelayoutRequest(); } } -bool TableView::IsFitWidth( unsigned int columnIndex ) const +bool TableView::IsFitWidth(unsigned int columnIndex) const { - DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() ); + DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size()); - return mColumnData[ columnIndex ].sizePolicy == Toolkit::TableView::FIT; + return mColumnData[columnIndex].sizePolicy == Toolkit::TableView::FIT; } -void TableView::SetFixedHeight( unsigned int rowIndex, float height ) +void TableView::SetFixedHeight(unsigned int rowIndex, float height) { - DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() ); + DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size()); - RowColumnData& data = mRowData[ rowIndex ]; - data.size = height; - data.sizePolicy = Toolkit::TableView::FIXED; + RowColumnData& data = mRowData[rowIndex]; + data.size = height; + data.sizePolicy = Toolkit::TableView::FIXED; mRowDirty = true; RelayoutRequest(); } -float TableView::GetFixedHeight( unsigned int rowIndex ) const +float TableView::GetFixedHeight(unsigned int rowIndex) const { - DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() ); + DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size()); - return mRowData[ rowIndex ].size; + return mRowData[rowIndex].size; } -void TableView::SetFixedWidth( unsigned int columnIndex, float width ) +void TableView::SetFixedWidth(unsigned int columnIndex, float width) { - DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() ); + DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size()); - RowColumnData& data = mColumnData[ columnIndex ]; - data.size = width; - data.sizePolicy = Toolkit::TableView::FIXED; + RowColumnData& data = mColumnData[columnIndex]; + data.size = width; + data.sizePolicy = Toolkit::TableView::FIXED; mColumnDirty = true; RelayoutRequest(); } -float TableView::GetFixedWidth( unsigned int columnIndex ) const +float TableView::GetFixedWidth(unsigned int columnIndex) const { - DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() ); + DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size()); - return mColumnData[ columnIndex ].size; + return mColumnData[columnIndex].size; } -void TableView::SetRelativeHeight( unsigned int rowIndex, float heightPercentage ) +void TableView::SetRelativeHeight(unsigned int rowIndex, float heightPercentage) { - DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() ); + DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size()); - RowColumnData& data = mRowData[ rowIndex ]; - data.fillRatio = heightPercentage; - data.sizePolicy = Toolkit::TableView::RELATIVE; + RowColumnData& data = mRowData[rowIndex]; + data.fillRatio = heightPercentage; + data.sizePolicy = Toolkit::TableView::RELATIVE; mRowDirty = true; RelayoutRequest(); } -float TableView::GetRelativeHeight( unsigned int rowIndex ) const +float TableView::GetRelativeHeight(unsigned int rowIndex) const { - DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() ); + DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size()); - return mRowData[ rowIndex ].fillRatio; + return mRowData[rowIndex].fillRatio; } -void TableView::SetRelativeWidth( unsigned int columnIndex, float widthPercentage ) +void TableView::SetRelativeWidth(unsigned int columnIndex, float widthPercentage) { - DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() ); + DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size()); - RowColumnData& data = mColumnData[ columnIndex ]; - data.fillRatio = widthPercentage; - data.sizePolicy = Toolkit::TableView::RELATIVE; + RowColumnData& data = mColumnData[columnIndex]; + data.fillRatio = widthPercentage; + data.sizePolicy = Toolkit::TableView::RELATIVE; mColumnDirty = true; RelayoutRequest(); } -float TableView::GetRelativeWidth( unsigned int columnIndex ) const +float TableView::GetRelativeWidth(unsigned int columnIndex) const { - DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() ); + DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size()); - return mColumnData[ columnIndex ].fillRatio; + return mColumnData[columnIndex].fillRatio; } -void TableView::OnCalculateRelayoutSize( Dimension::Type dimension ) +void TableView::OnCalculateRelayoutSize(Dimension::Type dimension) { - if( (dimension & Dimension::WIDTH) && mColumnDirty ) + if((dimension & Dimension::WIDTH) && mColumnDirty) { /* * FIXED and FIT have size in pixel @@ -720,7 +711,7 @@ void TableView::OnCalculateRelayoutSize( Dimension::Type dimension ) * * Need to update the size for FIT column here */ - CalculateFitSizes( mColumnData, Dimension::WIDTH ); + 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 @@ -728,69 +719,69 @@ void TableView::OnCalculateRelayoutSize( Dimension::Type dimension ) * * Need to update the ratio for FILL column here */ - CalculateFillSizes( mColumnData ); + CalculateFillSizes(mColumnData); - mFixedTotals.width = CalculateTotalFixedSize( mColumnData ); + mFixedTotals.width = CalculateTotalFixedSize(mColumnData); } - if( (dimension & Dimension::HEIGHT) && mRowDirty ) + if((dimension & Dimension::HEIGHT) && mRowDirty) { // refer to the comment above - CalculateFitSizes( mRowData, Dimension::HEIGHT ); + CalculateFitSizes(mRowData, Dimension::HEIGHT); // refer to the comment above - CalculateFillSizes( mRowData ); + CalculateFillSizes(mRowData); - mFixedTotals.height = CalculateTotalFixedSize( mRowData ); + mFixedTotals.height = CalculateTotalFixedSize(mRowData); } } -void TableView::OnLayoutNegotiated( float size, Dimension::Type dimension ) +void TableView::OnLayoutNegotiated(float size, Dimension::Type dimension) { // Update the column sizes - if( (dimension & Dimension::WIDTH) && mColumnDirty ) + if((dimension & Dimension::WIDTH) && mColumnDirty) { float remainingSize = size - mFixedTotals.width; - if( remainingSize < 0.0f ) + if(remainingSize < 0.0f) { remainingSize = 0.0f; } // 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; } // Update the row sizes - if( (dimension & Dimension::HEIGHT) && mRowDirty ) + if((dimension & Dimension::HEIGHT) && mRowDirty) { float remainingSize = size - mFixedTotals.height; - if( remainingSize < 0.0f ) + if(remainingSize < 0.0f) { remainingSize = 0.0f; } // update every row position in RowData array float cumulatedHeight = 0.0f; - for( unsigned int row = 0, rowCount = mCellData.GetRows(); row < rowCount; ++row ) + for(unsigned int row = 0, rowCount = mCellData.GetRows(); row < rowCount; ++row) { - if( mRowData[ row ].sizePolicy == Toolkit::TableView::FILL || mRowData[ row ].sizePolicy == Toolkit::TableView::RELATIVE) + if(mRowData[row].sizePolicy == Toolkit::TableView::FILL || mRowData[row].sizePolicy == Toolkit::TableView::RELATIVE) { - mRowData[ row ].size = mRowData[ row ].fillRatio * remainingSize; + mRowData[row].size = mRowData[row].fillRatio * remainingSize; } - cumulatedHeight += mRowData[ row ].size; + cumulatedHeight += mRowData[row].size; mRowData[row].position = cumulatedHeight; } @@ -798,66 +789,93 @@ void TableView::OnLayoutNegotiated( float size, Dimension::Type dimension ) } } -void TableView::OnSizeSet( const Vector3& size ) +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 ) +void TableView::OnRelayout(const Vector2& size, RelayoutContainer& container) { // Go through the layout data - for( unsigned int row = 0, rowCount = mCellData.GetRows(); row < rowCount; ++row ) + 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( unsigned int column = 0, columnCount = mCellData.GetColumns(); column < columnCount; ++column ) + for(auto&& element : mColumnData) { - CellData& cellData= mCellData[ row ][ column ]; - Actor& actor = cellData.actor; + 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) + { + CellData& cellData = mCellData[row][column]; + Actor& actor = cellData.actor; const Toolkit::TableView::CellPosition position = cellData.position; // 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 column span is more than 1. // We however must lay out each actor only once. - if( actor && position.rowIndex == row && position.columnIndex == column ) + 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()) + { + actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + } + actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); - Padding padding; - actor.GetPadding( padding ); + Padding padding = actor.GetProperty(Actor::Property::PADDING); - 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; + 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( left + mPadding.width + padding.left ); + right = totalWidth - left; + left = right - mColumnData[column].size; } - else if( cellData.horizontalAlignment == HorizontalAlignment::RIGHT ) + else { - actor.SetX( right - mPadding.width - padding.right - actor.GetRelayoutSize( Dimension::WIDTH ) ); + right = left + mColumnData[column].size; + } + + 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.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 ) + 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 ) + 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); } } } @@ -874,23 +892,23 @@ unsigned int TableView::GetColumns() return mCellData.GetColumns(); } -void TableView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) +void TableView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value) { - Toolkit::TableView tableView = Toolkit::TableView::DownCast( Dali::BaseHandle( object ) ); + Toolkit::TableView tableView = Toolkit::TableView::DownCast(Dali::BaseHandle(object)); - if( tableView ) + if(tableView) { - TableView& tableViewImpl( GetImpl( tableView ) ); - switch( index ) + TableView& tableViewImpl(GetImpl(tableView)); + switch(index) { case Toolkit::TableView::Property::ROWS: { int rows = 0; - if( value.Get( rows ) && rows >= 0 ) + if(value.Get(rows) && rows >= 0) { - if( static_cast(rows) != tableViewImpl.GetRows() ) + if(static_cast(rows) != tableViewImpl.GetRows()) { - tableViewImpl.Resize( rows, tableViewImpl.GetColumns() ); + tableViewImpl.Resize(rows, tableViewImpl.GetColumns()); } } break; @@ -898,53 +916,53 @@ void TableView::SetProperty( BaseObject* object, Property::Index index, const Pr case Toolkit::TableView::Property::COLUMNS: { int columns = 0; - if( value.Get( columns ) && columns >= 0 ) + if(value.Get(columns) && columns >= 0) { - if( static_cast( columns ) != tableViewImpl.GetColumns() ) + if(static_cast(columns) != tableViewImpl.GetColumns()) { - tableViewImpl.Resize( tableViewImpl.GetRows(), value.Get() ); + tableViewImpl.Resize(tableViewImpl.GetRows(), value.Get()); } } break; } case Toolkit::TableView::Property::CELL_PADDING: { - tableViewImpl.SetCellPadding( value.Get() ); + tableViewImpl.SetCellPadding(value.Get()); break; } case Toolkit::TableView::Property::LAYOUT_ROWS: { - SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, &TableView::SetFitHeight, value ); + SetHeightOrWidthProperty(tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, &TableView::SetFitHeight, value); break; } case Toolkit::TableView::Property::LAYOUT_COLUMNS: { - SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, &TableView::SetFitWidth, value ); + SetHeightOrWidthProperty(tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, &TableView::SetFitWidth, value); break; } } } } -Property::Value TableView::GetProperty( BaseObject* object, Property::Index index ) +Property::Value TableView::GetProperty(BaseObject* object, Property::Index index) { Property::Value value; - Toolkit::TableView tableView = Toolkit::TableView::DownCast( Dali::BaseHandle( object ) ); + Toolkit::TableView tableView = Toolkit::TableView::DownCast(Dali::BaseHandle(object)); - if( tableView ) + if(tableView) { - TableView& tableViewImpl( GetImpl( tableView ) ); - switch( index ) + TableView& tableViewImpl(GetImpl(tableView)); + switch(index) { case Toolkit::TableView::Property::ROWS: { - value = static_cast( tableViewImpl.GetRows() ); + value = static_cast(tableViewImpl.GetRows()); break; } case Toolkit::TableView::Property::COLUMNS: { - value = static_cast( tableViewImpl.GetColumns() ); + value = static_cast(tableViewImpl.GetColumns()); break; } case Toolkit::TableView::Property::CELL_PADDING: @@ -968,184 +986,190 @@ Property::Value TableView::GetProperty( BaseObject* object, Property::Index inde return value; } -void TableView::OnChildAdd( Actor& child ) +void TableView::OnChildAdd(Actor& child) { - Control::OnChildAdd( child ); - - if( mLayoutingChild ) + 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 ) - { - 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(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(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(); + } - 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(); + } - // 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.horizontalAlignment = horizontalAlignment; - data.verticalAlignment = verticalAlignment; - mCellData[ row ][ column ] = data; - - // Don't continue - RelayoutRequest(); - return; + data.actor = child; + data.position.rowIndex = rowCount; + data.position.columnIndex = 0; + data.horizontalAlignment = horizontalAlignment; + data.verticalAlignment = verticalAlignment; + 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::OnChildRemove( 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 ) + if(!mLayoutingChild) { // relayout the table only if instances were found - if( RemoveAllInstances( child ) ) + if(RemoveAllInstances(child)) { RelayoutRequest(); } } - Control::OnChildRemove( child ); + Control::OnChildRemove(child); } -TableView::TableView( unsigned int initialRows, unsigned int initialColumns ) -: Control( ControlBehaviour( REQUIRES_STYLE_CHANGE_SIGNALS ) ), - mCellData( initialRows, initialColumns ), - mLayoutingChild( false ), - mRowDirty( true ), // Force recalculation first time - mColumnDirty( true ) +TableView::TableView(unsigned int initialRows, unsigned int initialColumns) +: Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)), + mCellData(initialRows, initialColumns), + mPreviousFocusedActor(), + mLayoutingChild(false), + mRowDirty(true), // Force recalculation first time + mColumnDirty(true) { - SetKeyboardNavigationSupport( true ); - ResizeContainers( initialRows, initialColumns ); + SetKeyboardNavigationSupport(true); + ResizeContainers(initialRows, initialColumns); } 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); + + self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::TABLE); } -void TableView::ResizeContainers( unsigned int rows, unsigned int columns ) +void TableView::ResizeContainers(unsigned int rows, unsigned int columns) { std::vector ignored; - ResizeContainers( rows, columns, ignored ); + ResizeContainers(rows, columns, ignored); } -void TableView::ResizeContainers( unsigned int rows, unsigned int columns, std::vector& removed ) +void TableView::ResizeContainers(unsigned int rows, unsigned int columns, std::vector& removed) { // Resize cell data - mCellData.Resize( rows, columns, removed ); + mCellData.Resize(rows, columns, removed); // We don't care if these go smaller, data will be regenerated or is not needed anymore - mRowData.Resize( rows ); - mColumnData.Resize( columns ); + mRowData.Resize(rows); + mColumnData.Resize(columns); } -void TableView::RemoveAndGetLostActors( const std::vector& lost, std::vector& removed, - unsigned int rowsRemoved, unsigned int columnsRemoved ) +void TableView::RemoveAndGetLostActors(const std::vector& lost, std::vector& removed, unsigned int rowsRemoved, unsigned int columnsRemoved) { // iterate through all lost cells - std::vector< CellData >::const_iterator iter = lost.begin(); - for( ; iter != lost.end(); ++iter ) + std::vector::const_iterator iter = lost.begin(); + for(; iter != lost.end(); ++iter) { // if it is a valid actor - if( (*iter).actor ) + if((*iter).actor) { // is this actor still somewhere else in the table Toolkit::TableView::CellPosition position; - if( FindChildPosition( (*iter).actor, position ) ) + if(FindChildPosition((*iter).actor, position)) { // it must be spanning multiple cells, position contains the top left most one // check if position is left of the removed location - if( position.columnIndex < (*iter).position.columnIndex ) + if(position.columnIndex < (*iter).position.columnIndex) { // if column span is greater than 1 - if( mCellData[ position.rowIndex ][ position.columnIndex ].position.columnSpan > 1 ) + if(mCellData[position.rowIndex][position.columnIndex].position.columnSpan > 1) { // decrease column span - mCellData[ position.rowIndex ][ position.columnIndex ].position.columnSpan -= columnsRemoved; + mCellData[position.rowIndex][position.columnIndex].position.columnSpan -= columnsRemoved; } } // check if position is left of the removed location - if( position.rowIndex < (*iter).position.rowIndex ) + if(position.rowIndex < (*iter).position.rowIndex) { // if row span is greater than 1 - if( mCellData[ position.rowIndex ][ position.columnIndex ].position.rowSpan > 1 ) + if(mCellData[position.rowIndex][position.columnIndex].position.rowSpan > 1) { // decrease row span - mCellData[ position.rowIndex ][ position.columnIndex ].position.rowSpan -= rowsRemoved; + mCellData[position.rowIndex][position.columnIndex].position.rowSpan -= rowsRemoved; } } } @@ -1153,29 +1177,29 @@ void TableView::RemoveAndGetLostActors( const std::vector& lost, std:: { // this actor is gone for good // add actor to removed container - removed.push_back( (*iter).actor ); + removed.push_back((*iter).actor); // we dont want the child actor anymore - Self().Remove( (*iter).actor ); + Self().Remove((*iter).actor); } } } } -bool TableView::RemoveAllInstances( const Actor& child ) +bool TableView::RemoveAllInstances(const Actor& child) { bool found = false; // walk through the layout data - const unsigned int rowCount = mCellData.GetRows(); + const unsigned int rowCount = mCellData.GetRows(); const unsigned int columnCount = mCellData.GetColumns(); - for( unsigned int row = 0; row < rowCount; ++row ) + for(unsigned int row = 0; row < rowCount; ++row) { - for( unsigned int column = 0; column < columnCount; ++column ) + for(unsigned int column = 0; column < columnCount; ++column) { - if( mCellData[ row ][ column ].actor == child ) + if(mCellData[row][column].actor == child) { // clear the cell, NOTE that the cell might be spanning multiple cells - mCellData[ row ][ column ] = CellData(); - found = true; + mCellData[row][column] = CellData(); + found = true; } } } @@ -1183,48 +1207,67 @@ bool TableView::RemoveAllInstances( const Actor& child ) } void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl, - void(TableView::*funcFixed)(unsigned int, float), - void(TableView::*funcRelative)(unsigned int, float), - void(TableView::*funcFit)(unsigned int), - const Property::Value& value ) + void (TableView::*funcFixed)(unsigned int, float), + void (TableView::*funcRelative)(unsigned int, float), + void (TableView::*funcFit)(unsigned int), + const Property::Value& value) { - Property::Map* map = value.GetMap(); - if( map ) + const Property::Map* map = value.GetMap(); + if(map) { unsigned int index(0); - for ( unsigned int i = 0, count = map->Count(); i < count; ++i ) + for(unsigned int i = 0, count = map->Count(); i < count; ++i) { - Property::Value& item = map->GetValue(i); - Property::Map* childMap = item.GetMap(); + Property::Value& item = map->GetValue(i); + Property::Map* childMap = item.GetMap(); - std::istringstream( map->GetKey(i) ) >> index; - if( childMap ) + std::istringstream(map->GetKey(i)) >> index; + if(childMap) { - Property::Value* policy = childMap->Find( "policy" ); - Property::Value* childMapValue = childMap->Find( "value" ); - if( policy && childMapValue ) + Property::Value* policy = childMap->Find("policy"); + if(policy) { std::string policyValue; - policy->Get( policyValue ); - Toolkit::TableView::LayoutPolicy policy; - if( Scripting::GetEnumeration< Toolkit::TableView::LayoutPolicy >( policyValue.c_str(), - LAYOUT_POLICY_STRING_TABLE, - LAYOUT_POLICY_STRING_TABLE_COUNT, - policy ) ) + if(DALI_LIKELY(policy->Get(policyValue))) { - if( policy == Toolkit::TableView::FIXED ) - { - (tableViewImpl.*funcFixed)( index, childMapValue->Get() ); - } - else if( policy == Toolkit::TableView::RELATIVE ) + Toolkit::TableView::LayoutPolicy policy; + if(Scripting::GetEnumeration(policyValue.c_str(), + LAYOUT_POLICY_STRING_TABLE, + LAYOUT_POLICY_STRING_TABLE_COUNT, + policy)) { - (tableViewImpl.*funcRelative)( index, childMapValue->Get() ); + switch(policy) + { + case Toolkit::TableView::FIXED: + case Toolkit::TableView::RELATIVE: + { + Property::Value* childMapValue = childMap->Find("value"); + float childValue = 0.0f; + if(DALI_LIKELY(childMapValue && childMapValue->Get(childValue))) + { + if(policy == Toolkit::TableView::FIXED) + { + (tableViewImpl.*funcFixed)(index, childValue); + } + else // if(policy == Toolkit::TableView::RELATIVE) + { + (tableViewImpl.*funcRelative)(index, childValue); + } + } + break; + } + case Toolkit::TableView::FIT: + { + (tableViewImpl.*funcFit)(index); + break; + } + default: + { + // do nothing for FILL policy + break; + } + } } - else if( policy == Toolkit::TableView::FIT ) - { - (tableViewImpl.*funcFit)( index ); - } - // do nothing for FILL policy } } } @@ -1235,69 +1278,69 @@ void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl, Property::Value TableView::GetRowHeightsPropertyValue() { Property::Map map; - GetMapPropertyValue( mRowData, map); + GetMapPropertyValue(mRowData, map); return Property::Value(map); } Property::Value TableView::GetColumnWidthsPropertyValue() { Property::Map map; - GetMapPropertyValue( mColumnData, map); + GetMapPropertyValue(mColumnData, map); return Property::Value(map); } -void TableView::GetMapPropertyValue( const RowColumnArray& data, Property::Map& map ) +void TableView::GetMapPropertyValue(const RowColumnArray& data, Property::Map& map) { - const char* fixedPolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIXED, + const char* fixedPolicy = Scripting::GetEnumerationName(Toolkit::TableView::FIXED, + LAYOUT_POLICY_STRING_TABLE, + LAYOUT_POLICY_STRING_TABLE_COUNT); + const char* relativePolicy = Scripting::GetEnumerationName(Toolkit::TableView::RELATIVE, LAYOUT_POLICY_STRING_TABLE, - LAYOUT_POLICY_STRING_TABLE_COUNT ); - const char* relativePolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::RELATIVE, - LAYOUT_POLICY_STRING_TABLE, - LAYOUT_POLICY_STRING_TABLE_COUNT ); - const char* fillPolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FILL, - LAYOUT_POLICY_STRING_TABLE, - LAYOUT_POLICY_STRING_TABLE_COUNT ); - const char* fitPolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIT, - LAYOUT_POLICY_STRING_TABLE, - LAYOUT_POLICY_STRING_TABLE_COUNT ); + LAYOUT_POLICY_STRING_TABLE_COUNT); + const char* fillPolicy = Scripting::GetEnumerationName(Toolkit::TableView::FILL, + LAYOUT_POLICY_STRING_TABLE, + LAYOUT_POLICY_STRING_TABLE_COUNT); + const char* fitPolicy = Scripting::GetEnumerationName(Toolkit::TableView::FIT, + LAYOUT_POLICY_STRING_TABLE, + LAYOUT_POLICY_STRING_TABLE_COUNT); const RowColumnArray::SizeType count = data.Size(); - for( RowColumnArray::SizeType i = 0; i < count; i++ ) + for(RowColumnArray::SizeType i = 0; i < count; i++) { - const RowColumnData& dataInstance = data[ i ]; + const RowColumnData& dataInstance = data[i]; Property::Map item; - switch( dataInstance.sizePolicy ) + switch(dataInstance.sizePolicy) { case Toolkit::TableView::FIXED: { - item[ "policy" ] = fixedPolicy; - item[ "value" ] = dataInstance.size; + item["policy"] = fixedPolicy; + item["value"] = dataInstance.size; break; } case Toolkit::TableView::RELATIVE: { - item[ "policy" ] = relativePolicy; - item[ "value" ] = dataInstance.fillRatio; + item["policy"] = relativePolicy; + item["value"] = dataInstance.fillRatio; break; } case Toolkit::TableView::FIT: { - item[ "policy" ] = fitPolicy; - item[ "value" ] = 0.f; + item["policy"] = fitPolicy; + item["value"] = 0.f; break; } case Toolkit::TableView::FILL: default: { - item[ "policy" ] = fillPolicy; - item[ "value" ] = 0.f; + item["policy"] = fillPolicy; + item["value"] = 0.f; break; } } std::ostringstream ss; ss << i; - map[ ss.str() ] = item; + map[ss.str()] = item; } } @@ -1310,7 +1353,7 @@ Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolki { Actor nextFocusableActor; - if ( !currentFocusedActor ) + if(!currentFocusedActor) { // Nothing is currently focused, so the child in the first cell should be focused. nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0)); @@ -1318,60 +1361,87 @@ Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolki else { Toolkit::TableView::CellPosition position; - if( FindChildPosition( currentFocusedActor, position ) ) + if(FindChildPosition(currentFocusedActor, position)) { // The current focused actor is a child of TableView - bool focusLost = false; - int currentRow = position.rowIndex; - int currentColumn = position.columnIndex; - int numberOfColumns = GetColumns(); - int numberOfRows = GetRows(); + bool focusLost = false; + int currentRow = position.rowIndex; + int currentColumn = position.columnIndex; + int numberOfColumns = GetColumns(); + int numberOfRows = GetRows(); - switch ( direction ) + 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; } } @@ -1380,12 +1450,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)); + } + } } } @@ -1395,24 +1502,22 @@ Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolki Vector3 TableView::GetNaturalSize() { // Natural size is the size of all fixed cell widths or heights. This ignores cells with relative heights. - return Vector3( mFixedTotals.width, mFixedTotals.height, 1.0f ); + return Vector3(mFixedTotals.width, mFixedTotals.height, 1.0f); } -float TableView::CalculateChildSize( const Actor& child, Dimension::Type dimension ) +float TableView::CalculateChildSize(const Actor& child, Dimension::Type dimension) { Toolkit::TableView::CellPosition position; - if( FindChildPosition( child, position) ) + if(FindChildPosition(child, position)) { - switch( dimension ) + switch(dimension) { case Dimension::WIDTH: { 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; + cellSize = mColumnData[position.columnIndex + position.columnSpan - 1].position - (position.columnIndex > 0 ? mColumnData[position.columnIndex - 1].position : 0.f) - mPadding.width * 2.0f; - if( cellSize < 0.0f ) + if(cellSize < 0.0f) { cellSize = 0.0f; } @@ -1424,11 +1529,9 @@ float TableView::CalculateChildSize( const Actor& child, Dimension::Type dimensi { float cellSize = 0.0f; - cellSize = mRowData[position.rowIndex+position.rowSpan-1].position - - (position.rowIndex > 0 ? mRowData[position.rowIndex-1].position : 0.f) - - mPadding.height * 2.0f; + cellSize = mRowData[position.rowIndex + position.rowSpan - 1].position - (position.rowIndex > 0 ? mRowData[position.rowIndex - 1].position : 0.f) - mPadding.height * 2.0f; - if( cellSize < 0.0f ) + if(cellSize < 0.0f) { cellSize = 0.0f; } @@ -1442,91 +1545,91 @@ float TableView::CalculateChildSize( const Actor& child, Dimension::Type dimensi } } - return 0.0f; // Child not found + return 0.0f; // Child not found } -bool TableView::RelayoutDependentOnChildren( Dimension::Type dimension ) +bool TableView::RelayoutDependentOnChildren(Dimension::Type dimension) { - if ( Control::RelayoutDependentOnChildren( dimension ) ) + if(Control::RelayoutDependentOnChildren(dimension)) { return true; } - return FindFit( mRowData ) || FindFit( mColumnData ); + return FindFit(mRowData) || FindFit(mColumnData); } -void TableView::SetCellAlignment( Toolkit::TableView::CellPosition position, HorizontalAlignment::Type horizontal, VerticalAlignment::Type vertical ) +void TableView::SetCellAlignment(Toolkit::TableView::CellPosition position, HorizontalAlignment::Type horizontal, VerticalAlignment::Type vertical) { // Check if we need to expand our data array - if( position.rowIndex >= mCellData.GetRows() ) + if(position.rowIndex >= mCellData.GetRows()) { // Only adding new rows - ResizeContainers( position.rowIndex + 1, mCellData.GetColumns() ); + ResizeContainers(position.rowIndex + 1, mCellData.GetColumns()); } - if( position.columnIndex >= mCellData.GetColumns() ) + if(position.columnIndex >= mCellData.GetColumns()) { // Only adding new columns - ResizeContainers( mCellData.GetRows(), position.columnIndex + 1 ); + ResizeContainers(mCellData.GetRows(), position.columnIndex + 1); } // Set the alignment of the cell - CellData& data = mCellData[ position.rowIndex ][ position.columnIndex ]; + CellData& data = mCellData[position.rowIndex][position.columnIndex]; data.horizontalAlignment = horizontal; - data.verticalAlignment = vertical; + data.verticalAlignment = vertical; } -void TableView::CalculateFillSizes( RowColumnArray& data ) +void TableView::CalculateFillSizes(RowColumnArray& data) { // First pass: Count number of fill entries and calculate used relative space - Dali::Vector< RowColumnData* > fillData; - float relativeTotal = 0.0f; + Dali::Vector fillData; + float relativeTotal = 0.0f; const unsigned int dataCount = data.Size(); - for( unsigned int i = 0; i < dataCount; ++i ) + for(unsigned int i = 0; i < dataCount; ++i) { - RowColumnData& dataInstance = data[ i ]; + RowColumnData& dataInstance = data[i]; - if( dataInstance.sizePolicy == Toolkit::TableView::RELATIVE ) + if(dataInstance.sizePolicy == Toolkit::TableView::RELATIVE) { relativeTotal += dataInstance.fillRatio; } else if(dataInstance.sizePolicy == Toolkit::TableView::FILL) { - fillData.PushBack( &dataInstance ); + fillData.PushBack(&dataInstance); } } // Second pass: Distribute remaining relative space const unsigned int fillCount = fillData.Size(); - if( fillCount > 0 ) + if(fillCount > 0) { - if( relativeTotal > 1.0f ) + if(relativeTotal > 1.0f) { relativeTotal = 1.0f; } - const float evenFillRatio = (1.0f - relativeTotal ) / fillCount; + const float evenFillRatio = (1.0f - relativeTotal) / fillCount; - for( unsigned int i = 0; i < fillCount; ++i ) + for(unsigned int i = 0; i < fillCount; ++i) { - fillData[ i ]->fillRatio = evenFillRatio; + fillData[i]->fillRatio = evenFillRatio; } } } -float TableView::CalculateTotalFixedSize( const RowColumnArray& data ) +float TableView::CalculateTotalFixedSize(const RowColumnArray& data) { float totalSize = 0.0f; const unsigned int dataCount = data.Size(); - for( unsigned int i = 0; i < dataCount; ++i ) + for(unsigned int i = 0; i < dataCount; ++i) { - const RowColumnData& dataInstance = data[ i ]; + const RowColumnData& dataInstance = data[i]; - switch( dataInstance.sizePolicy ) + switch(dataInstance.sizePolicy) { // we have absolute size to FIXED and FIT column/row and relative size for RELATIVE and FILL column/row case Toolkit::TableView::FIXED: @@ -1546,17 +1649,17 @@ float TableView::CalculateTotalFixedSize( const RowColumnArray& data ) return totalSize; } -Vector2 TableView::GetCellPadding( Dimension::Type dimension ) +Vector2 TableView::GetCellPadding(Dimension::Type dimension) { - switch( dimension ) + switch(dimension) { case Dimension::WIDTH: { - return Vector2( mPadding.x, mPadding.x ); + return Vector2(mPadding.x, mPadding.x); } case Dimension::HEIGHT: { - return Vector2( mPadding.y, mPadding.y ); + return Vector2(mPadding.y, mPadding.y); } default: { @@ -1567,37 +1670,37 @@ Vector2 TableView::GetCellPadding( Dimension::Type dimension ) return Vector2(); } -void TableView::CalculateFitSizes( RowColumnArray& data, Dimension::Type dimension ) +void TableView::CalculateFitSizes(RowColumnArray& data, Dimension::Type dimension) { - Vector2 cellPadding = GetCellPadding( dimension ); + Vector2 cellPadding = GetCellPadding(dimension); const unsigned int dataCount = data.Size(); - for( unsigned int i = 0; i < dataCount; ++i ) + for(unsigned int i = 0; i < dataCount; ++i) { - RowColumnData& dataInstance = data[ i ]; + RowColumnData& dataInstance = data[i]; - if( dataInstance.sizePolicy == Toolkit::TableView::FIT ) + if(dataInstance.sizePolicy == Toolkit::TableView::FIT) { // Find the size of the biggest actor in the row or column float maxActorHeight = 0.0f; - unsigned int fitCount = ( dimension == Dimension::WIDTH ) ? mCellData.GetRows() : mCellData.GetColumns(); + unsigned int fitCount = (dimension == Dimension::WIDTH) ? mCellData.GetRows() : mCellData.GetColumns(); - for( unsigned int j = 0; j < fitCount; ++j ) + for(unsigned int j = 0; j < fitCount; ++j) { - unsigned int row = ( dimension == Dimension::WIDTH ) ? j : i; - unsigned int column = ( dimension == Dimension::WIDTH ) ? i : j; - DALI_ASSERT_DEBUG( row < mCellData.GetRows() ); - DALI_ASSERT_DEBUG( column < mCellData.GetColumns() ); - - const CellData& cellData = mCellData[ row ][ column ]; - const Actor& actor = cellData.actor; - if( actor ) + unsigned int row = (dimension == Dimension::WIDTH) ? j : i; + unsigned int column = (dimension == Dimension::WIDTH) ? i : j; + DALI_ASSERT_DEBUG(row < mCellData.GetRows()); + DALI_ASSERT_DEBUG(column < mCellData.GetColumns()); + + const CellData& cellData = mCellData[row][column]; + const Actor& actor = cellData.actor; + if(actor) { - if( FitToChild( actor, dimension ) && ( dimension == Dimension::WIDTH ) ? ( cellData.position.columnSpan == 1 ) : ( cellData.position.rowSpan == 1 ) ) + if(FitToChild(actor, dimension) && (dimension == Dimension::WIDTH) ? (cellData.position.columnSpan == 1) : (cellData.position.rowSpan == 1)) { - maxActorHeight = std::max( maxActorHeight, actor.GetRelayoutSize( dimension ) + cellPadding.x + cellPadding.y ); + maxActorHeight = std::max(maxActorHeight, actor.GetRelayoutSize(dimension) + cellPadding.x + cellPadding.y); } } } @@ -1607,11 +1710,11 @@ void TableView::CalculateFitSizes( RowColumnArray& data, Dimension::Type dimensi } } -bool TableView::FindFit( const RowColumnArray& data ) +bool TableView::FindFit(const RowColumnArray& data) { - for( unsigned int i = 0, count = data.Size(); i < count; ++i ) + for(unsigned int i = 0, count = data.Size(); i < count; ++i) { - if( data[ i ].sizePolicy == Toolkit::TableView::FIT ) + if(data[i].sizePolicy == Toolkit::TableView::FIT) { return true; }