/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <dali-toolkit/internal/controls/table-view/table-view-impl.h>
// EXTERNAL INCLUDES
-#include <sstream>
+#include <dali/devel-api/actors/actor-devel.h>
+#include <dali/devel-api/scripting/scripting.h>
+#include <dali/integration-api/debug.h>
#include <dali/public-api/object/ref-object.h>
-#include <dali/public-api/object/type-registry.h>
#include <dali/public-api/object/type-registry-helper.h>
-#include <dali/public-api/scripting/scripting.h>
-#include <dali/integration-api/debug.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/size-negotiation/relayout-container.h>
+#include <sstream>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/controls/control-devel.h>
using namespace Dali;
namespace
{
-const float DEFAULT_CONSTRAINT_DURATION = 0.0f;
-
/**
- * sets a child property relative to parents size and applies a unit based padding before the relative calculation.
- * @param[in] scale of parent minus padding between 0 and 1
- * @param[in] padding in world coordinate units
- * @param[in] fixed part in world coordinate units
- * @param[in] size of the parent
- * @return The relative size with padding.
+ * @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
*/
-Vector2 RelativeToSize( const Vector2& scale, const Vector2& padding, const Vector2& fixed, const Vector2& parentSize)
+bool FitToChild(Actor actor, Dimension::Type dimension)
{
- return fixed + ( parentSize - padding ) * scale;
+ return actor.GetResizePolicy(dimension) != ResizePolicy::FILL_TO_PARENT && actor.GetRelayoutSize(dimension) > 0.0f;
}
#if defined(DEBUG_ENABLED)
// 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::DebugInfo, TABLEVIEW_TAG fmt, ##args)
+//#define TABLEVIEW_DEBUG 1
-void PrintArray( Array2d<Dali::Toolkit::Internal::TableView::CellData>& array )
+#if defined(TABLEVIEW_DEBUG)
+void PrintArray(Array2d<Dali::Toolkit::Internal::TableView::CellData>& array)
{
- TV_LOG( "Array2d<CellData> size [%d,%d] \n", array.GetRows(), array.GetColumns() );
+ TV_LOG("Array2d<CellData> 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 = ' ';
- if( data.actor )
+ Dali::Toolkit::Internal::TableView::CellData data = array[i][j];
+ char actor = ' ';
+ std::string actorName;
+ if(data.actor)
{
- actor = 'A';
+ actor = 'A';
+ actorName = data.actor.GetProperty<std::string>(Dali::Actor::Property::NAME);
}
- TV_LOG("Array[%d,%d]=%c %d,%d,%d,%d ", i, j, actor,
- 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<Size>& array )
+void PrintArray(Array2d<Size>& array)
{
- TV_LOG( "Array2d<Size> size [%d,%d] \n", array.GetRows(), array.GetColumns() );
+ TV_LOG("Array2d<Size> 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<float>& array )
+void PrintVector(std::vector<float>& 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)
} // namespace
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( TableView, "rows", UNSIGNED_INTEGER, ROWS )
-DALI_PROPERTY_REGISTRATION( TableView, "columns", UNSIGNED_INTEGER, COLUMNS )
-DALI_PROPERTY_REGISTRATION( TableView, "cell-padding", VECTOR2, CELL_PADDING )
-DALI_PROPERTY_REGISTRATION( TableView, "layout-rows", MAP, LAYOUT_ROWS )
-DALI_PROPERTY_REGISTRATION( TableView, "layout-columns", 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< Toolkit::TableView::LayoutPolicy > LAYOUT_POLICY_STRING_TABLE[] =
+const Scripting::StringEnum LAYOUT_POLICY_STRING_TABLE[] =
{
- { "fixed", Toolkit::TableView::Fixed },
- { "relative", Toolkit::TableView::Relative },
- { "fill", Toolkit::TableView::Fill }
+ {"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 },
+ {"center", HorizontalAlignment::CENTER},
+ {"right", HorizontalAlignment::RIGHT }
+};
+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 },
+ {"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]);
+// 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<TableView> 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...
return handle;
}
-bool TableView::AddChild( Actor child, 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
- if( child.GetParent() )
- {
- child.GetParent().Remove( child );
- }
+ 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);
- // put the actor to the main cell
- CellData data;
- data.actor = child;
- data.position = position;
- mCellData[ position.rowIndex ][ position.columnIndex ] = data;
// if child spans multiple rows of columns
- bool spanned = false;
- if( position.rowSpan > 1 )
+ if((position.rowSpan > 1) && (position.rowIndex + position.rowSpan > mCellData.GetRows()))
{
- // span might go outside table
- if( position.rowIndex + position.rowSpan > mCellData.GetRows() )
- {
- // increase table size for the full span, only increasing rows
- ResizeContainers( position.rowIndex + position.rowSpan, mCellData.GetColumns() );
- }
- spanned = true;
+ // increase table size for the full span, only increasing rows
+ ResizeContainers(position.rowIndex + position.rowSpan, mCellData.GetColumns());
}
- if( position.columnSpan > 1 )
+
+ if((position.columnSpan > 1) && (position.columnIndex + position.columnSpan > mCellData.GetColumns()))
{
- // span might go outside table
- if( position.columnIndex + position.columnSpan > mCellData.GetColumns() )
- {
- // increase table size for the full span, only increasing columns
- ResizeContainers( mCellData.GetRows(), position.columnIndex + position.columnSpan );
- }
- spanned = true;
+ // increase table size for the full span, only increasing columns
+ ResizeContainers(mCellData.GetRows(), position.columnIndex + position.columnSpan);
}
- // if it spanned multiple rows, put the cellinfo in all of those
- if( spanned )
+
+ // Fill in all cells that need the data
+ CellData data;
+ 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)
{
// 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 )
- {
- // 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
+
+ // Relayout the whole table
+ if(mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT && position.rowSpan == 1)
+ {
+ mRowDirty = true;
+ }
+ if(mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT && position.columnSpan == 1)
+ {
+ mColumnDirty = true;
+ }
+
RelayoutRequest();
- return true; // addition successful
+
+ return true; // Addition successful
}
-Actor TableView::GetChildAt( Toolkit::TableView::CellPosition position )
+Actor TableView::GetChildAt(const Toolkit::TableView::CellPosition& position)
{
- // check if we have this row and column in the table
- if( ( position.columnIndex >= mCellData.GetColumns() )||
- ( position.rowIndex >= mCellData.GetRows() ) )
+ if((position.rowIndex < mCellData.GetRows()) && (position.columnIndex < mCellData.GetColumns()))
{
- // return an empty handle
- return Actor();
+ return mCellData[position.rowIndex][position.columnIndex].actor;
}
- // return the child handle
- return mCellData[ position.rowIndex ][ position.columnIndex ].actor;
+
+ // Return an empty handle
+ return Actor();
}
-Actor TableView::RemoveChildAt( 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 );
- // Remove the child, this will trigger a call to OnControlChildRemove
- Self().Remove( child );
+ RelayoutingLock lock(*this);
+ // Remove the child, this will trigger a call to OnChildRemove
+ Self().Remove(child);
// relayout the table only if instances were found
- if( RemoveAllInstances( child ) )
+ if(RemoveAllInstances(child))
{
+ if(mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT)
+ {
+ mRowDirty = true;
+ }
+ if(mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT)
+ {
+ mColumnDirty = true;
+ }
RelayoutRequest();
}
}
return child;
}
-bool TableView::FindChildPosition( Actor child, Toolkit::TableView::CellPosition& position )
+bool TableView::FindChildPosition(const Actor& child, Toolkit::TableView::CellPosition& positionOut)
{
- // only find valid child actors
- if( child )
+ // Only find valid child actors
+ if(child)
{
- // walk through the layout data
- const unsigned int rowCount = mCellData.GetRows();
+ // Walk through the layout data
+ 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)
{
- position = mCellData[ row ][ column ].position;
+ positionOut = mCellData[row][column].position;
return true;
}
}
}
}
+
return false;
}
-void TableView::InsertRow( unsigned int rowIndex )
+void TableView::InsertRow(unsigned int rowIndex)
{
- RelayoutingLock lock( *this );
- mCellData.InsertRow( rowIndex );
- // need to update the cellinfos for the items that moved
- const unsigned int rowCount = mCellData.GetRows();
+ RelayoutingLock lock(*this);
+
+ mCellData.InsertRow(rowIndex);
+
+ // Need to update the cell infos for the items that moved
+ 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;
- // if cell is spanning and above and spans to inserted row
- if( ( position.rowSpan > 1 )&&( position.rowIndex <= rowIndex )&&
- ( position.rowIndex + position.rowSpan > rowIndex ) )
+ 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))
{
- // increase span by one
+ // Increment span
position.rowSpan++;
- // copy cell to occupy the new column
- mCellData[ rowIndex ][ column ] = mCellData[ row ][ column ];
+
+ // Copy cell to occupy the new column
+ mCellData[rowIndex][column] = mCellData[row][column];
}
- // if below of inserted row, increase row index
- else if( row > rowIndex )
+ else if(row > rowIndex) // If below of inserted row, increase row index
{
- // increase index by one
+ // Increment index
position.rowIndex++;
}
}
}
- mRelativeSizes.InsertRow( rowIndex );
- // inserting a row requires adjusting the height vectors
- mFixedHeights.insert( mFixedHeights.begin() + rowIndex, 0 );
- mRelativeHeights.insert( mRelativeHeights.begin() + rowIndex, 0 );
+
+ // Expand row data array
+ 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<Actor> ignored;
+ DeleteRow(rowIndex, ignored);
}
-void TableView::DeleteRow( unsigned int rowIndex, std::vector<Actor>& removed )
+void TableView::DeleteRow(unsigned int rowIndex, std::vector<Actor>& removed)
{
- RelayoutingLock lock( *this );
- std::vector< CellData > lost;
- mCellData.DeleteRow( rowIndex, lost );
- // need to update the cellinfos for the items that moved
- const unsigned int rowCount = mCellData.GetRows();
+ RelayoutingLock lock(*this);
+
+ // Delete the row
+ std::vector<CellData> 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 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;
- // if cell is spanning and above and spans to deleted row
- if( ( position.rowSpan > 1 )&&( position.rowIndex <= rowIndex )&&
- ( position.rowIndex + position.rowSpan > rowIndex ) )
+ 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))
{
- // decrease span by one
- if( position.rowSpan > 1 )
+ // Decrement span
+ if(position.rowSpan > 1)
{
position.rowSpan--;
}
}
- // if below of or at the inserted row, decrease row index
- else if( row >= rowIndex )
+ else if(row >= rowIndex) // If below of or at the inserted row, decrease row index
{
- // decrease index by one
- if( position.rowIndex > 1 )
+ // Decrement index
+ if(position.rowIndex > 0)
{
position.rowIndex--;
}
}
}
}
+
// 1 row removed, 0 columns
- RemoveAndGetLostActors( lost, removed, 1u, 0u );
- // resize the data structures
- mRelativeSizes.DeleteRow( rowIndex );
- // deleting a row requires adjusting the height vectors
- mFixedHeights.erase( mFixedHeights.begin() + rowIndex );
- mRelativeHeights.erase( mRelativeHeights.begin() + rowIndex );
+ RemoveAndGetLostActors(lost, removed, 1u, 0u);
+
+ // Contract row data array
+ mRowData.Erase(mRowData.Begin() + rowIndex);
+
+ // Sizes may have changed, so relayout
+ mRowDirty = true;
+ // it is possible that the deletion of row leads to remove of child which might further lead to the change of FIT column
+ mColumnDirty = true;
+
RelayoutRequest();
}
-void TableView::InsertColumn( unsigned int columnIndex )
+void TableView::InsertColumn(unsigned int columnIndex)
{
- RelayoutingLock lock( *this );
- mCellData.InsertColumn( columnIndex );
- // need to update the cellinfos for the items that moved
- const unsigned int rowCount = mCellData.GetRows();
+ RelayoutingLock lock(*this);
+
+ // Insert the new column
+ mCellData.InsertColumn(columnIndex);
+
+ // Need to update the cell infos for the items that moved
+ 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;
- // if cell is spanning and left side and spans to inserted column
- if( ( position.columnSpan > 1 )&&( position.columnIndex <= columnIndex )&&
- ( position.columnIndex + position.columnSpan > columnIndex ) )
+ 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))
{
- // increase span by one
+ // Increment span
position.columnSpan++;
- // copy cell to occupy the new column
- mCellData[ row ][ columnIndex ] = mCellData[ row ][ column ];
+
+ // Copy cell to occupy the new column
+ mCellData[row][columnIndex] = mCellData[row][column];
}
- // if on the right side of inserted column, increase column index
- else if( column > columnIndex )
+ else if(column > columnIndex) // If on the right side of inserted column, increase column index
{
- // increase index by one
+ // Increment index
position.columnIndex++;
}
}
}
- // relative sizes gets recalculated on Relayout
- mRelativeSizes.InsertColumn( columnIndex );
- // inserting a column requires adjusting the width vectors
- mFixedWidths.insert( mFixedWidths.begin() + columnIndex, 0 );
- mRelativeWidths.insert( mRelativeWidths.begin() + columnIndex, 0 );
+
+ // Expand column data array
+ 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<Actor> ignored;
+ DeleteColumn(columnIndex, ignored);
}
-void TableView::DeleteColumn( unsigned int columnIndex, std::vector<Actor>& removed )
+void TableView::DeleteColumn(unsigned int columnIndex, std::vector<Actor>& removed)
{
- RelayoutingLock lock( *this );
- std::vector< CellData > lost;
- mCellData.DeleteColumn( columnIndex, lost );
- // need to update the cellinfos for the items that moved
- const unsigned int rowCount = mCellData.GetRows();
+ RelayoutingLock lock(*this);
+
+ // Remove the column
+ std::vector<CellData> 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 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;
- // if cell is spanning and left side and spans to inserted column
- if( ( position.columnSpan > 1 )&&( position.columnIndex <= columnIndex )&&
- ( position.columnIndex + position.columnSpan > columnIndex ) )
+ 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))
{
- // decrease span by one
- if( position.columnSpan > 1 )
+ // Decrement span
+ if(position.columnSpan > 1)
{
position.columnSpan--;
}
}
- // if on the right side of or at the inserted column, decrease column index
- else if( column >= columnIndex )
+ else if(column >= columnIndex) // If on the right side of or at the inserted column, decrease column index
{
- // decrease index by one
- if( position.columnIndex > 0 )
+ // Decrement index
+ if(position.columnIndex > 0)
{
position.columnIndex--;
}
}
}
}
+
// 0 rows, 1 column removed
- RemoveAndGetLostActors( lost, removed, 0u, 1u );
- // resize the data structures
- mRelativeSizes.DeleteColumn( columnIndex );
- // deleting a column requires adjusting the width vectors
- mFixedWidths.erase( mFixedWidths.begin() + columnIndex );
- mRelativeWidths.erase( mRelativeWidths.begin() + columnIndex );
- // relayout
+ RemoveAndGetLostActors(lost, removed, 0u, 1u);
+
+ // Contract column data array
+ mColumnData.Erase(mColumnData.Begin() + columnIndex);
+
+ // Size may have changed so relayout
+ mColumnDirty = true;
+ // it is possible that the deletion of column leads to remove of child which might further lead to the change of FIT row
+ mRowDirty = true;
+
RelayoutRequest();
}
-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<Actor> ignored;
+ Resize(rows, columns, ignored);
}
-void TableView::Resize( unsigned int rows, unsigned int columns, std::vector<Actor>& removed )
+void TableView::Resize(unsigned int rows, unsigned int columns, std::vector<Actor>& removed)
{
- RelayoutingLock lock( *this );
- unsigned int oldRows = GetRows();
+ RelayoutingLock lock(*this);
+
+ unsigned int oldRows = GetRows();
unsigned int oldColumns = GetColumns();
- // resize data array
- std::vector< CellData > lost;
- ResizeContainers( rows, columns, lost );
- // calculate if we lost rows or columns
+
+ // Resize data array
+ std::vector<CellData> lost;
+ ResizeContainers(rows, columns, lost);
+
+ // Calculate if we lost rows
unsigned int rowsRemoved = 0;
- unsigned int newRows = GetRows();
- if( oldRows < newRows )
+ unsigned int newRows = GetRows();
+
+ 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 );
- // finally relayout once all actors are removed
+
+ RemoveAndGetLostActors(lost, removed, rowsRemoved, columnsRemoved);
+
+ // Sizes may have changed so request a relayout
+ mRowDirty = true;
+ mColumnDirty = true;
RelayoutRequest();
}
-void TableView::SetCellPadding( Size padding )
+void TableView::SetCellPadding(Size padding)
{
- // if padding really changed
- if( padding != mPadding )
+ // If padding really changed
+ if(padding != mPadding)
{
mPadding = padding;
- // do a relayout
+
RelayoutRequest();
}
}
return mPadding;
}
-void TableView::SetFixedHeight( unsigned int rowIndex, float height )
+void TableView::SetFitHeight(unsigned int rowIndex)
+{
+ DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size());
+
+ if(mRowData[rowIndex].sizePolicy != Toolkit::TableView::FIT)
+ {
+ mRowData[rowIndex].sizePolicy = Toolkit::TableView::FIT;
+
+ mRowDirty = true;
+ RelayoutRequest();
+ }
+}
+
+bool TableView::IsFitHeight(unsigned int rowIndex) const
+{
+ DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size());
+
+ return mRowData[rowIndex].sizePolicy == Toolkit::TableView::FIT;
+}
+
+void TableView::SetFitWidth(unsigned int columnIndex)
{
- DALI_ASSERT_ALWAYS( rowIndex < mFixedHeights.size() );
- // add the fixed height to the array of fixed heights
- mFixedHeights[ rowIndex ] = height;
- // remove the relative height of the same row
- mRelativeHeights[ rowIndex ] = 0.f;
- // relayout all cells, no lock needed as nothing added or removed
+ DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size());
+
+ if(mColumnData[columnIndex].sizePolicy != Toolkit::TableView::FIT)
+ {
+ mColumnData[columnIndex].sizePolicy = Toolkit::TableView::FIT;
+
+ mColumnDirty = true;
+ RelayoutRequest();
+ }
+}
+
+bool TableView::IsFitWidth(unsigned int columnIndex) const
+{
+ DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size());
+
+ return mColumnData[columnIndex].sizePolicy == Toolkit::TableView::FIT;
+}
+
+void TableView::SetFixedHeight(unsigned int rowIndex, float height)
+{
+ DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size());
+
+ 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 < mFixedHeights.size() );
+ DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size());
- return mFixedHeights[ rowIndex ];
+ return mRowData[rowIndex].size;
}
-void TableView::SetRelativeHeight( unsigned int rowIndex, float heightPercentage )
+void TableView::SetFixedWidth(unsigned int columnIndex, float width)
{
- DALI_ASSERT_ALWAYS( rowIndex < mRelativeHeights.size() );
- // add the relative height to the array of relative heights
- mRelativeHeights[ rowIndex ] = heightPercentage;
- // remove the fixed height of the same row
- mFixedHeights[ rowIndex ] = 0.f;
- // relayout all cells, no lock needed as nothing added or removed
+ DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size());
+
+ RowColumnData& data = mColumnData[columnIndex];
+ data.size = width;
+ data.sizePolicy = Toolkit::TableView::FIXED;
+
+ mColumnDirty = true;
RelayoutRequest();
}
-float TableView::GetRelativeHeight( unsigned int rowIndex ) const
+float TableView::GetFixedWidth(unsigned int columnIndex) const
{
- DALI_ASSERT_ALWAYS( rowIndex < mRelativeHeights.size() );
+ DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size());
- return mRelativeHeights[ rowIndex ];
+ return mColumnData[columnIndex].size;
}
-void TableView::SetFixedWidth( unsigned int columnIndex, float width )
+void TableView::SetRelativeHeight(unsigned int rowIndex, float heightPercentage)
{
- DALI_ASSERT_ALWAYS( columnIndex < mFixedWidths.size() );
- // add the fixed width to the array of fixed column widths
- mFixedWidths[ columnIndex ] = width;
- // remove the relative width of the same column
- mRelativeWidths[ columnIndex ] = 0.f;
- // relayout all cells, no lock needed as nothing added or removed
+ DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size());
+
+ RowColumnData& data = mRowData[rowIndex];
+ data.fillRatio = heightPercentage;
+ data.sizePolicy = Toolkit::TableView::RELATIVE;
+
+ mRowDirty = true;
RelayoutRequest();
}
-float TableView::GetFixedWidth( unsigned int columnIndex ) const
+float TableView::GetRelativeHeight(unsigned int rowIndex) const
{
- DALI_ASSERT_ALWAYS( columnIndex < mFixedWidths.size() );
+ DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size());
- return mFixedWidths[ columnIndex ];
+ return mRowData[rowIndex].fillRatio;
}
-void TableView::SetRelativeWidth( unsigned int columnIndex, float widthPercentage )
+void TableView::SetRelativeWidth(unsigned int columnIndex, float widthPercentage)
{
- DALI_ASSERT_ALWAYS( columnIndex < mRelativeWidths.size() );
- // add the relative widths to the array of relative widths
- mRelativeWidths[ columnIndex ] = widthPercentage;
- // remove the fixed width of the same column
- mFixedWidths[ columnIndex ] = 0.f;
- // relayout all cells, no lock needed as nothing added or removed
+ DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size());
+
+ 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 < mRelativeWidths.size() );
+ DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size());
- return mRelativeWidths[ columnIndex ];
+ return mColumnData[columnIndex].fillRatio;
}
-void TableView::OnRelayout( const Vector2& size, ActorSizeContainer& container )
+void TableView::OnCalculateRelayoutSize(Dimension::Type dimension)
{
- float fixedHeightsTotal = 0.0f;
- float fixedWidthsTotal = 0.0f;
+ if((dimension & Dimension::WIDTH) && mColumnDirty)
+ {
+ /*
+ * FIXED and FIT have size in pixel
+ * Nothing to do with FIXED, as its value is assigned by user and will not get changed
+ *
+ * Need to update the size for FIT column here
+ */
+ CalculateFitSizes(mColumnData, Dimension::WIDTH);
+
+ /* RELATIVE and FILL have size in ratio
+ * Their size in pixel is not available until we get the negotiated size for the whole table
+ * Nothing to do with RELATIVE, as its ratio is assigned by user and will not get changed
+ *
+ * Need to update the ratio for FILL column here
+ */
+ CalculateFillSizes(mColumnData);
+
+ mFixedTotals.width = CalculateTotalFixedSize(mColumnData);
+ }
- // 1. update the relative sizes and calculate total fixed height and width
- UpdateRelativeSizes( fixedHeightsTotal, fixedWidthsTotal );
+ if((dimension & Dimension::HEIGHT) && mRowDirty)
+ {
+ // refer to the comment above
+ CalculateFitSizes(mRowData, Dimension::HEIGHT);
- // 2. go through the layout data and create constraints
- float cumulatedFixedHeight = 0.0f;
- float cumulatedRelativeHeight = 0.0f;
+ // refer to the comment above
+ CalculateFillSizes(mRowData);
- // iterate the table
- const unsigned int rowCount = mCellData.GetRows();
- const unsigned int columnCount = mCellData.GetColumns();
- // float versions of the count + 1 to keep precision
- const float maxRowPlusOne( rowCount + 1 );
- const float maxColumnPlusOne( columnCount + 1 );
- for( unsigned int row = 0; row < rowCount; ++row )
+ mFixedTotals.height = CalculateTotalFixedSize(mRowData);
+ }
+}
+
+void TableView::OnLayoutNegotiated(float size, Dimension::Type dimension)
+{
+ // Update the column sizes
+ if((dimension & Dimension::WIDTH) && mColumnDirty)
+ {
+ float remainingSize = size - mFixedTotals.width;
+ if(remainingSize < 0.0f)
+ {
+ remainingSize = 0.0f;
+ }
+
+ // update every column position in ColumnData array
+ float cumulatedWidth = 0.0f;
+ for(auto&& element : mColumnData)
+ {
+ if(element.sizePolicy == Toolkit::TableView::FILL || element.sizePolicy == Toolkit::TableView::RELATIVE)
+ {
+ element.size = element.fillRatio * remainingSize;
+ }
+
+ cumulatedWidth += element.size;
+ element.position = cumulatedWidth;
+ }
+
+ mColumnDirty = false;
+ }
+
+ // Update the row sizes
+ if((dimension & Dimension::HEIGHT) && mRowDirty)
+ {
+ float remainingSize = size - mFixedTotals.height;
+ 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)
+ {
+ if(mRowData[row].sizePolicy == Toolkit::TableView::FILL || mRowData[row].sizePolicy == Toolkit::TableView::RELATIVE)
+ {
+ mRowData[row].size = mRowData[row].fillRatio * remainingSize;
+ }
+
+ cumulatedHeight += mRowData[row].size;
+ mRowData[row].position = cumulatedHeight;
+ }
+
+ mRowDirty = false;
+ }
+}
+
+void TableView::OnSizeSet(const Vector3& size)
+{
+ // If this table view is size negotiated by another actor or control, then the
+ // rows and columns must be recalculated or the new size will not take effect.
+ mRowDirty = mColumnDirty = true;
+ RelayoutRequest();
+
+ Control::OnSizeSet(size);
+}
+
+void TableView::OnRelayout(const Vector2& size, RelayoutContainer& container)
+{
+ // Go through the layout data
+ float totalWidth = 0.0;
+
+ Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
+
+ 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)
{
- // reset widths at the start of each row
- float cumulatedFixedWidth = 0.0f;
- float cumulatedRelativeWidth = 0.0f;
- for( unsigned int column = 0; column < columnCount; ++column )
+ for(unsigned int column = 0, columnCount = mCellData.GetColumns(); column < columnCount; ++column)
{
- // check if this cell has an actor
- Actor actor = mCellData[ row ][ column ].actor;
- const Toolkit::TableView::CellPosition position = mCellData[ row ][ column ].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 columnspan is more than 1
- // we however must only lay out each actor only once
- if( ( actor )&&( position.rowIndex == row )&&( position.columnIndex == 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)
{
- // anchor actor correctly
- actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
- actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
- // remove old constraints
- actor.RemoveConstraints();
-
- // 1. set position
- // get the row and column indices
- float rowPos( position.rowIndex );
- float colPos( position.columnIndex );
- // constrain the actor position to be relative to the width and height of table
- // minus the padding of course (padding is all around cells)
- Vector2 relativePosition( cumulatedRelativeWidth, cumulatedRelativeHeight );
- // fixed height rows and fixed width cells are considered as padding so
- // they are removed from the total size for relative
- // for position only consider cumulated fixed rows and columns from top and left
- Vector2 positionPadding( maxColumnPlusOne * mPadding.width + fixedWidthsTotal,
- maxRowPlusOne * mPadding.height + fixedHeightsTotal );
- Vector2 fixedPosition( ( colPos + 1.0f ) * mPadding.width + cumulatedFixedWidth,
- ( rowPos + 1.0f ) * mPadding.height + cumulatedFixedHeight );
-
- Vector3 actorPosition( RelativeToSize( relativePosition, positionPadding, fixedPosition, size ) );
- actor.SetPosition( actorPosition );
-
- // 2. set size
- // constrain the actor size to be relative to the size of table
- // get the relative size for this cell
- Vector2 relativeSize( mRelativeSizes[ row ][ column ] );
- Vector2 fixedSize( mFixedWidths[ column ], mFixedHeights[ row ] );
- // if we span multiple cells, need to sum them all up, both fixed and relative parts
- if( position.rowSpan > 1 )
+ // Anchor actor to top left of the cell
+ if(actor.GetProperty(Actor::Property::POSITION_USES_ANCHOR_POINT).Get<bool>())
{
- for( unsigned int i = 1; i < position.rowSpan; ++i )
- {
- // accumulate the height only
- relativeSize.height += mRelativeSizes[ row + i ][ column ].height;
- fixedSize.height += mFixedHeights[ row + i ];
- }
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
}
- if( position.columnSpan > 1 )
+ actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+
+ Padding padding = actor.GetProperty<Vector4>(Actor::Property::PADDING);
+
+ float left = (column > 0) ? mColumnData[column - 1].position : 0.f;
+ float right;
+
+ if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
{
- for( unsigned int i = 1; i < position.columnSpan; ++i )
- {
- // accumulate the width only
- relativeSize.width += mRelativeSizes[ row ][ column + i ].width;
- fixedSize.width += mFixedWidths[ column + i ];
- }
+ right = totalWidth - left;
+ left = right - mColumnData[column].size;
+ }
+ else
+ {
+ 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.SetProperty(Actor::Property::POSITION_X, (left + right + padding.left - padding.right - actor.GetRelayoutSize(Dimension::WIDTH)) * 0.5f);
+ }
+
+ if(cellData.verticalAlignment == VerticalAlignment::TOP)
+ {
+ actor.SetProperty(Actor::Property::POSITION_Y, top + mPadding.height + padding.top);
+ }
+ else if(cellData.verticalAlignment == VerticalAlignment::BOTTOM)
+ {
+ actor.SetProperty(Actor::Property::POSITION_Y, bottom - mPadding.height - padding.bottom - actor.GetRelayoutSize(Dimension::HEIGHT));
+ }
+ else //if( cellData.verticalAlignment = VerticalAlignment::CENTER )
+ {
+ actor.SetProperty(Actor::Property::POSITION_Y, (top + bottom + padding.top - padding.bottom - actor.GetRelayoutSize(Dimension::HEIGHT)) * 0.5f);
}
- // minus the padding from size (padding is all around cells)
- // if item spans multiple columns or rows then less padding is added (default span is 1)
- // fixed height rows and fixed width cells are considered as padding so they are removed
- // from the total available size for relative cells
- Vector2 sizePadding( maxColumnPlusOne * mPadding.width + fixedWidthsTotal,
- maxRowPlusOne * mPadding.height + fixedHeightsTotal );
- // and added to the fixed size multiplied by the span of rows and columns
- fixedSize.width += ( position.columnSpan - 1.0f ) * mPadding.width;
- fixedSize.height += ( position.rowSpan - 1.0f ) * mPadding.height;
-
- Vector2 actorSize( RelativeToSize( relativeSize, sizePadding, fixedSize, size ) );
- actor.SetSize(actorSize.x, actorSize.y);
-
- // Relayout Children
- Relayout ( actor, actorSize, container );
}
- // for position we need to keep track of current fixed width and relative width
- // increase for next column
- cumulatedFixedWidth += mFixedWidths[ column ];
- cumulatedRelativeWidth += mRelativeSizes[ row ][ column ].width;
}
- // for position we need to keep track of current fixed height and relative height
- // increase for next row
- cumulatedFixedHeight += mFixedHeights[ row ];
- cumulatedRelativeHeight += mRelativeSizes[ row ][ 0 ].height; // all columns share same height
}
}
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:
{
- if( value.Get<unsigned int>() != tableViewImpl.GetRows() )
+ int rows = 0;
+ if(value.Get(rows) && rows >= 0)
{
- tableViewImpl.Resize( value.Get<unsigned int>(), tableViewImpl.GetColumns() );
+ if(static_cast<unsigned int>(rows) != tableViewImpl.GetRows())
+ {
+ tableViewImpl.Resize(rows, tableViewImpl.GetColumns());
+ }
}
break;
}
case Toolkit::TableView::Property::COLUMNS:
{
- if( value.Get<unsigned int>() != tableViewImpl.GetColumns() )
+ int columns = 0;
+ if(value.Get(columns) && columns >= 0)
{
- tableViewImpl.Resize( tableViewImpl.GetRows(), value.Get<unsigned int>() );
+ if(static_cast<unsigned int>(columns) != tableViewImpl.GetColumns())
+ {
+ tableViewImpl.Resize(tableViewImpl.GetRows(), value.Get<int>());
+ }
}
break;
}
case Toolkit::TableView::Property::CELL_PADDING:
{
- tableViewImpl.SetCellPadding( value.Get<Vector2>() );
+ tableViewImpl.SetCellPadding(value.Get<Vector2>());
break;
}
case Toolkit::TableView::Property::LAYOUT_ROWS:
{
- SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, value );
+ SetHeightOrWidthProperty(tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, &TableView::SetFitHeight, value);
break;
}
case Toolkit::TableView::Property::LAYOUT_COLUMNS:
{
- SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, 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 = tableViewImpl.GetRows();
+ value = static_cast<int>(tableViewImpl.GetRows());
break;
}
case Toolkit::TableView::Property::COLUMNS:
{
- value = tableViewImpl.GetColumns();
+ value = static_cast<int>(tableViewImpl.GetColumns());
break;
}
case Toolkit::TableView::Property::CELL_PADDING:
return value;
}
-void TableView::OnControlChildAdd( Actor& child )
+void TableView::OnChildAdd(Actor& child)
{
- if( mLayoutingChild )
+ if(!mLayoutingChild)
{
- // we're in the middle of laying out children so no point doing anything here
- return;
- }
+ // Ensure we're not in the middle of laying out children
- Toolkit::TableView::CellPosition cellPosition;
- if( child.GetPropertyIndex(Toolkit::TableView::ROW_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
- {
- cellPosition.rowSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::ROW_SPAN_PROPERTY_NAME) ).Get<float>() );
- }
- if( child.GetPropertyIndex(Toolkit::TableView::COLUMN_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
- {
- cellPosition.columnSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::COLUMN_SPAN_PROPERTY_NAME) ).Get<float>() );
- }
- if( child.GetPropertyIndex(Toolkit::TableView::CELL_INDICES_PROPERTY_NAME) != Property::INVALID_INDEX )
- {
- Vector2 indices = child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::CELL_INDICES_PROPERTY_NAME) ).Get<Vector2 >();
- cellPosition.rowIndex = static_cast<unsigned int>( indices.x );
- cellPosition.columnIndex = static_cast<unsigned int>( indices.y );
+ // Check child properties on actor to decide its position inside the table
+ HorizontalAlignment::Type horizontalAlignment = HorizontalAlignment::LEFT;
+ VerticalAlignment::Type verticalAlignment = VerticalAlignment::TOP;
- AddChild( child, cellPosition );
- // donot continue
- return;
- }
+ if(child.GetPropertyType(Toolkit::TableView::ChildProperty::CELL_HORIZONTAL_ALIGNMENT) != Property::NONE)
+ {
+ std::string value = child.GetProperty(Toolkit::TableView::ChildProperty::CELL_HORIZONTAL_ALIGNMENT).Get<std::string>();
+ Scripting::GetEnumeration<HorizontalAlignment::Type>(value.c_str(),
+ HORIZONTAL_ALIGNMENT_STRING_TABLE,
+ HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
+ horizontalAlignment);
+ }
- // check if we're already laying out this child somewhere on the table
- // walk through the layout data
- const unsigned int rowCount = mCellData.GetRows();
- const unsigned int columnCount = mCellData.GetColumns();
- // child not yet laid out, find the first free slot
- for( unsigned int row = 0; row < rowCount; ++row )
- {
- for( unsigned int column = 0; column < columnCount; ++column )
+ if(child.GetPropertyType(Toolkit::TableView::ChildProperty::CELL_VERTICAL_ALIGNMENT) != Property::NONE)
+ {
+ std::string value = child.GetProperty(Toolkit::TableView::ChildProperty::CELL_VERTICAL_ALIGNMENT).Get<std::string>();
+ Scripting::GetEnumeration<VerticalAlignment::Type>(value.c_str(),
+ VERTICAL_ALIGNMENT_STRING_TABLE,
+ VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
+ verticalAlignment);
+ }
+
+ 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>();
+ }
+
+ if(child.GetPropertyType(Toolkit::TableView::ChildProperty::COLUMN_SPAN) != Property::NONE)
+ {
+ cellPosition.columnSpan = child.GetProperty(Toolkit::TableView::ChildProperty::COLUMN_SPAN).Get<int>();
+ }
+
+ if(child.GetPropertyType(Toolkit::TableView::ChildProperty::CELL_INDEX) != Property::NONE)
{
- // no actor means free cell
- if( !(mCellData[ row ][ column ].actor) )
+ Vector2 indices = child.GetProperty(Toolkit::TableView::ChildProperty::CELL_INDEX).Get<Vector2>();
+ cellPosition.rowIndex = static_cast<unsigned int>(indices.x);
+ cellPosition.columnIndex = static_cast<unsigned int>(indices.y);
+
+ AddChild(child, cellPosition);
+ SetCellAlignment(cellPosition, horizontalAlignment, verticalAlignment);
+ }
+ else
+ {
+ bool availableCellFound = false;
+
+ // Find the first available cell to store the actor in
+ const unsigned int rowCount = mCellData.GetRows();
+ const unsigned int columnCount = mCellData.GetColumns();
+ for(unsigned int row = 0; row < rowCount && !availableCellFound; ++row)
+ {
+ for(unsigned int column = 0; column < columnCount && !availableCellFound; ++column)
+ {
+ if(!(mCellData[row][column].actor))
+ {
+ // Put the actor in the cell
+ CellData data;
+ data.actor = child;
+ data.position.columnIndex = column;
+ data.position.rowIndex = row;
+ data.horizontalAlignment = horizontalAlignment;
+ data.verticalAlignment = verticalAlignment;
+ mCellData[row][column] = data;
+
+ availableCellFound = true;
+ break;
+ }
+ }
+ }
+
+ if(!availableCellFound)
{
- // put the actor in the cell
+ // No empty cells, so increase size of the table
+ unsigned int newColumnCount = (columnCount > 0) ? columnCount : 1;
+ ResizeContainers(rowCount + 1, newColumnCount);
+
+ // Put the actor in the first cell of the new row
CellData data;
- data.actor = child;
- data.position.columnIndex = column;
- data.position.rowIndex = row;
- mCellData[ row ][ column ] = data;
- RelayoutRequest();
- // don' continue
- return;
+ data.actor = child;
+ data.position.rowIndex = rowCount;
+ data.position.columnIndex = 0;
+ data.horizontalAlignment = horizontalAlignment;
+ data.verticalAlignment = verticalAlignment;
+ mCellData[rowCount][0] = data;
}
+
+ RelayoutRequest();
}
}
- // still here, no room for the poor child so increase the array. Need a new row
- ResizeContainers( rowCount + 1, columnCount );
- // put the actor to the first cell of the new row
- CellData data;
- data.actor = child;
- data.position.rowIndex = rowCount;
- data.position.columnIndex = 0;
- mCellData[ rowCount ][ 0 ] = data;
- // finally relayout the table
- 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 )
+ if(!mLayoutingChild)
{
// relayout the table only if instances were found
- if( RemoveAllInstances( child ) )
+ if(RemoveAllInstances(child))
{
RelayoutRequest();
}
}
+
+ Control::OnChildRemove(child);
}
-TableView::TableView( unsigned int initialRows, unsigned int initialColumns )
-: Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
- mCellData( initialRows, initialColumns ),
- mLayoutingChild( false )
+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);
+
+ DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) {
+ return std::unique_ptr<Dali::Accessibility::Accessible>(
+ new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::TABLE));
+ });
}
-void TableView::ResizeContainers( unsigned int rows, unsigned int columns )
+void TableView::ResizeContainers(unsigned int rows, unsigned int columns)
{
std::vector<CellData> ignored;
- ResizeContainers( rows, columns, ignored );
+ ResizeContainers(rows, columns, ignored);
}
-void TableView::ResizeContainers( unsigned int rows, unsigned int columns, std::vector<CellData>& removed )
+void TableView::ResizeContainers(unsigned int rows, unsigned int columns, std::vector<CellData>& removed)
{
- mCellData.Resize( rows, columns, removed );
- // we dont care if these go smaller, data will be regenerated or is not needed anymore
- mRelativeSizes.Resize( rows, columns );
- mFixedHeights.resize( rows );
- mRelativeHeights.resize( rows );
- mFixedWidths.resize( columns );
- mRelativeWidths.resize( columns );
+ // Resize cell data
+ 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);
}
-void TableView::RemoveAndGetLostActors( const std::vector<CellData>& lost, std::vector<Actor>& removed,
- unsigned int rowsRemoved, unsigned int columnsRemoved )
+void TableView::RemoveAndGetLostActors(const std::vector<CellData>& lost, std::vector<Actor>& 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<CellData>::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;
}
}
}
{
// 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( 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;
}
}
}
return found;
}
-void TableView::UpdateRelativeSizes( float& fixedHeightsTotal, float& fixedWidthsTotal )
-{
- // 1. check all the fixed heights and widths to know how much size they take in total
- // as well as the relative heights and widths to know how much is left for the 'fill' cells
- unsigned int fixedRowCount = 0;
- unsigned int relativeRowCount = 0;
- float relativeHeightsTotal = 0.0f;
- const unsigned int rowCount = mCellData.GetRows();
- for( unsigned int row = 0; row < rowCount; ++row )
- {
- if( mFixedHeights[ row ] > 0.0f )
- {
- ++fixedRowCount;
- fixedHeightsTotal += mFixedHeights[ row ];
- }
- if( mRelativeHeights[ row ] > 0.0f )
- {
- ++relativeRowCount;
- relativeHeightsTotal += mRelativeHeights[ row ];
- }
- }
- unsigned int fixedColumnCount = 0;
- unsigned int relativeColumnCount = 0;
- const unsigned int columnCount = mCellData.GetColumns();
- float relativeWidthsTotal = 0.0f;
- for( unsigned int column = 0; column < columnCount; ++column )
- {
- if( mFixedWidths[ column ] > 0.0f )
- {
- ++fixedColumnCount;
- fixedWidthsTotal += mFixedWidths[ column ];
- }
- if( mRelativeWidths[ column ] > 0.0f )
- {
- ++relativeColumnCount;
- relativeWidthsTotal += mRelativeWidths[ column ];
- }
- }
-
- // 2. cap the relative width and height totals to 100%
- if( relativeHeightsTotal > 1.0f )
- {
- relativeHeightsTotal = 1.0f;
- }
- if( relativeWidthsTotal > 1.0f )
- {
- relativeWidthsTotal = 1.0f;
- }
-
- // 3. create a table of relative sizes so we can lookup for cells that span multiple rows & colums
- const float fillRowCount( rowCount - relativeRowCount - fixedRowCount );
- const float fillColumnCount( columnCount - relativeColumnCount - fixedColumnCount );
-
- // walk through the data containers
- for( unsigned int row = 0; row < rowCount; ++row )
- {
- float relativeHeight = 0.0f;
- // if we have a fixed height, relative height is 0
- if( mFixedHeights[ row ] > 0.0f )
- {
- relativeHeight = 0.0f;
- }
- // else if we're given a specific row height %, use that
- else if( mRelativeHeights[ row ] > 0.0f )
- {
- relativeHeight = mRelativeHeights[ row ];
- }
- // else if there are fill rows
- else if( fillRowCount > 0 )
- {
- // this is a 'fill' row. it gets the remainder of the 100% divided evenly between 'fill' rows
- relativeHeight = (1.0f - relativeHeightsTotal ) / fillRowCount;
- }
- for( unsigned int column = 0; column < columnCount; ++column )
- {
- float relativeWidth = 0.0f;
- // if we have a fixed width, relative width is 0
- if( mFixedWidths[ column ] > 0.0f )
- {
- relativeWidth = 0.0f;
- }
- // else if we're given a specific column width %, use that
- else if( mRelativeWidths[ column ] > 0.0f )
- {
- relativeWidth = mRelativeWidths[ column ];
- }
- // else if there are fill columns
- else if( fillColumnCount > 0 )
- {
- // this is a 'fill' column. it gets the remainder of the 100% divided evenly between 'fill' columns
- relativeWidth = (1.0f - relativeWidthsTotal ) / fillColumnCount;
- }
- // store the value
- mRelativeSizes[ row ][ column ] = Size( relativeWidth, relativeHeight );
- }
- }
-}
-
void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl,
- void(TableView::*funcFixed)(unsigned int, float),
- void(TableView::*funcRelative)(unsigned int, float),
- 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)
{
- if( Property::MAP == value.GetType() )
+ const Property::Map* map = value.GetMap();
+ if(map)
{
- Property::Map map = value.Get<Property::Map>();
- unsigned int rowIndex(0);
- for ( unsigned int i = 0, count = map.Count(); i < count; ++i )
+ unsigned int index(0);
+ for(unsigned int i = 0, count = map->Count(); i < count; ++i)
{
- Property::Value& item = map.GetValue(i);
+ Property::Value& item = map->GetValue(i);
+ Property::Map* childMap = item.GetMap();
- if( std::istringstream(map.GetKey(i)) >> rowIndex // the key is a number
- && Property::MAP == item.GetType())
+ std::istringstream(map->GetKey(i)) >> index;
+ if(childMap)
{
- if( item.HasKey( "policy" ) && item.HasKey( "value" ) )
+ Property::Value* policy = childMap->Find("policy");
+ Property::Value* childMapValue = childMap->Find("value");
+ if(policy && childMapValue)
{
- Toolkit::TableView::LayoutPolicy policy = Scripting::GetEnumeration< Toolkit::TableView::LayoutPolicy >( item.GetValue("policy").Get<std::string>().c_str(), LAYOUT_POLICY_STRING_TABLE, LAYOUT_POLICY_STRING_TABLE_COUNT );
- if( policy == Toolkit::TableView::Fixed )
- {
- (tableViewImpl.*funcFixed)( rowIndex, item.GetValue("value").Get<float>() );
- }
- else if( policy == Toolkit::TableView::Relative )
+ 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))
{
- (tableViewImpl.*funcRelative)( rowIndex, item.GetValue("value").Get<float>() );
+ if(policy == Toolkit::TableView::FIXED)
+ {
+ (tableViewImpl.*funcFixed)(index, childMapValue->Get<float>());
+ }
+ else if(policy == Toolkit::TableView::RELATIVE)
+ {
+ (tableViewImpl.*funcRelative)(index, childMapValue->Get<float>());
+ }
+ else if(policy == Toolkit::TableView::FIT)
+ {
+ (tableViewImpl.*funcFit)(index);
+ }
+ // do nothing for FILL policy
}
}
}
Property::Value TableView::GetRowHeightsPropertyValue()
{
Property::Map map;
- GetMapPropertyValue( mFixedHeights, mRelativeHeights, map);
+ GetMapPropertyValue(mRowData, map);
return Property::Value(map);
}
Property::Value TableView::GetColumnWidthsPropertyValue()
{
Property::Map map;
- GetMapPropertyValue( mFixedWidths, mRelativeWidths, map);
+ GetMapPropertyValue(mColumnData, map);
return Property::Value(map);
}
-void TableView::GetMapPropertyValue( const std::vector<float>& fixedSize, const std::vector<float>& relativeSize, Property::Map& map )
+void TableView::GetMapPropertyValue(const RowColumnArray& data, Property::Map& map)
{
- std::string fixedPolicy( Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::Fixed, LAYOUT_POLICY_STRING_TABLE, LAYOUT_POLICY_STRING_TABLE_COUNT ) );
- std::string relativePolicy( Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::Relative, LAYOUT_POLICY_STRING_TABLE, LAYOUT_POLICY_STRING_TABLE_COUNT ) );
-
- size_t count = fixedSize.size();
- for( size_t index = 0; index < count; index++ )
+ const char* fixedPolicy = Scripting::GetEnumerationName<Toolkit::TableView::LayoutPolicy>(Toolkit::TableView::FIXED,
+ 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);
+
+ const RowColumnArray::SizeType count = data.Size();
+ for(RowColumnArray::SizeType i = 0; i < count; i++)
{
- if( ! EqualsZero( fixedSize[index] ) )
- {
- Property::Map item;
- item[ "policy" ] = fixedPolicy;
- item[ "value" ] = fixedSize[index];
+ const RowColumnData& dataInstance = data[i];
- map[ static_cast<std::ostringstream*>( &(std::ostringstream() << index ) )->str() ] = item;
- }
- else if( ! EqualsZero( relativeSize[index] ) )
+ Property::Map item;
+ switch(dataInstance.sizePolicy)
{
- Property::Map item;
- item[ "policy" ] = relativePolicy;
- item[ "value" ] = relativeSize[index];
-
- map[ static_cast<std::ostringstream*>( &(std::ostringstream() << index ) )->str() ] = item;
+ case Toolkit::TableView::FIXED:
+ {
+ item["policy"] = fixedPolicy;
+ item["value"] = dataInstance.size;
+ break;
+ }
+ case Toolkit::TableView::RELATIVE:
+ {
+ item["policy"] = relativePolicy;
+ item["value"] = dataInstance.fillRatio;
+ break;
+ }
+ case Toolkit::TableView::FIT:
+ {
+ item["policy"] = fitPolicy;
+ item["value"] = 0.f;
+ break;
+ }
+ case Toolkit::TableView::FILL:
+ default:
+ {
+ item["policy"] = fillPolicy;
+ item["value"] = 0.f;
+ break;
+ }
}
+ std::ostringstream ss;
+ ss << i;
+ map[ss.str()] = item;
}
}
// nothing to do
}
-Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocusNavigationDirection direction, bool loopEnabled)
+Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
{
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));
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::Left:
+ 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::Right:
+ 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::Up:
+ 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::Down:
+ 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;
}
}
if(!focusLost)
{
nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
+
+ // Save the focused actor in the TableView.
+ mPreviousFocusedActor = nextFocusableActor;
}
}
else
{
- // The current focused actor is not within table view, so the child in the first cell should be focused.
- nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
+ // The current focused actor is not within this TableView.
+
+ unsigned int numberOfColumns = GetColumns();
+ unsigned int numberOfRows = GetRows();
+
+ // Check whether the previous focused actor is a focus group (i.e. a layout container)
+ bool wasFocusedOnLayoutContainer = false;
+ Actor previousFocusedActor = mPreviousFocusedActor.GetHandle();
+ if(previousFocusedActor)
+ {
+ Toolkit::Control control = Toolkit::Control::DownCast(previousFocusedActor);
+ if(control)
+ {
+ Internal::Control& controlImpl = static_cast<Internal::Control&>(control.GetImplementation());
+ wasFocusedOnLayoutContainer = controlImpl.IsKeyboardFocusGroup();
+ }
+ }
+
+ // Check whether the previous focused actor is a layout container and also a child of this TableView
+ Toolkit::TableView::CellPosition position;
+ if(wasFocusedOnLayoutContainer && FindChildPosition(previousFocusedActor, position))
+ {
+ nextFocusableActor = GetNextKeyboardFocusableActor(previousFocusedActor, direction, loopEnabled);
+ }
+ else
+ {
+ // Otherwise, move the focus to either the first or the last cell according to the given direction.
+ if(direction == Toolkit::Control::KeyboardFocus::LEFT || direction == Toolkit::Control::KeyboardFocus::UP)
+ {
+ nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(numberOfRows - 1, numberOfColumns - 1));
+ }
+ else
+ {
+ nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
+ }
+ }
}
}
return nextFocusableActor;
}
+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);
+}
+
+float TableView::CalculateChildSize(const Actor& child, Dimension::Type dimension)
+{
+ Toolkit::TableView::CellPosition position;
+ if(FindChildPosition(child, position))
+ {
+ 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;
+
+ if(cellSize < 0.0f)
+ {
+ cellSize = 0.0f;
+ }
+
+ return cellSize;
+ }
+
+ case Dimension::HEIGHT:
+ {
+ 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;
+
+ if(cellSize < 0.0f)
+ {
+ cellSize = 0.0f;
+ }
+
+ return cellSize;
+ }
+ default:
+ {
+ return 0.0f;
+ }
+ }
+ }
+
+ return 0.0f; // Child not found
+}
+
+bool TableView::RelayoutDependentOnChildren(Dimension::Type dimension)
+{
+ if(Control::RelayoutDependentOnChildren(dimension))
+ {
+ return true;
+ }
+
+ return FindFit(mRowData) || FindFit(mColumnData);
+}
+
+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())
+ {
+ // Only adding new rows
+ ResizeContainers(position.rowIndex + 1, mCellData.GetColumns());
+ }
+
+ if(position.columnIndex >= mCellData.GetColumns())
+ {
+ // Only adding new columns
+ ResizeContainers(mCellData.GetRows(), position.columnIndex + 1);
+ }
+
+ // Set the alignment of the cell
+ CellData& data = mCellData[position.rowIndex][position.columnIndex];
+ data.horizontalAlignment = horizontal;
+ data.verticalAlignment = vertical;
+}
+
+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;
+
+ const unsigned int dataCount = data.Size();
+
+ for(unsigned int i = 0; i < dataCount; ++i)
+ {
+ RowColumnData& dataInstance = data[i];
+
+ if(dataInstance.sizePolicy == Toolkit::TableView::RELATIVE)
+ {
+ relativeTotal += dataInstance.fillRatio;
+ }
+ else if(dataInstance.sizePolicy == Toolkit::TableView::FILL)
+ {
+ fillData.PushBack(&dataInstance);
+ }
+ }
+
+ // Second pass: Distribute remaining relative space
+ const unsigned int fillCount = fillData.Size();
+ if(fillCount > 0)
+ {
+ if(relativeTotal > 1.0f)
+ {
+ relativeTotal = 1.0f;
+ }
+
+ const float evenFillRatio = (1.0f - relativeTotal) / fillCount;
+
+ for(unsigned int i = 0; i < fillCount; ++i)
+ {
+ fillData[i]->fillRatio = evenFillRatio;
+ }
+ }
+}
+
+float TableView::CalculateTotalFixedSize(const RowColumnArray& data)
+{
+ float totalSize = 0.0f;
+
+ const unsigned int dataCount = data.Size();
+
+ for(unsigned int i = 0; i < dataCount; ++i)
+ {
+ const RowColumnData& dataInstance = data[i];
+
+ 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:
+ case Toolkit::TableView::FIT:
+ {
+ totalSize += dataInstance.size;
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ return totalSize;
+}
+
+Vector2 TableView::GetCellPadding(Dimension::Type dimension)
+{
+ switch(dimension)
+ {
+ case Dimension::WIDTH:
+ {
+ return Vector2(mPadding.x, mPadding.x);
+ }
+ case Dimension::HEIGHT:
+ {
+ return Vector2(mPadding.y, mPadding.y);
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return Vector2();
+}
+
+void TableView::CalculateFitSizes(RowColumnArray& data, Dimension::Type dimension)
+{
+ Vector2 cellPadding = GetCellPadding(dimension);
+
+ const unsigned int dataCount = data.Size();
+
+ for(unsigned int i = 0; i < dataCount; ++i)
+ {
+ RowColumnData& dataInstance = data[i];
+
+ 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();
+
+ 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)
+ {
+ 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);
+ }
+ }
+ }
+
+ dataInstance.size = maxActorHeight;
+ }
+ }
+}
+
+bool TableView::FindFit(const RowColumnArray& data)
+{
+ for(unsigned int i = 0, count = data.Size(); i < count; ++i)
+ {
+ if(data[i].sizePolicy == Toolkit::TableView::FIT)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace Internal
} // namespace Toolkit