// EXTERNAL INCLUDES
#include <sstream>
-#include <dali/public-api/animation/constraint.h>
-#include <dali/public-api/animation/time-period.h>
#include <dali/public-api/object/ref-object.h>
#include <dali/public-api/object/type-registry.h>
-#include <dali/public-api/scripting/scripting.h>
+#include <dali/devel-api/object/type-registry-helper.h>
+#include <dali/devel-api/scripting/scripting.h>
+#include <dali/public-api/size-negotiation/relayout-container.h>
#include <dali/integration-api/debug.h>
using namespace Dali;
namespace
{
-const float DEFAULT_CONSTRAINT_DURATION = 0.0f;
/**
- * Constraint that sets a child property relative to parents Width or Height
+ * @brief Should the tableview fit around the given actor
+ *
+ * @param[in] actor The child actor to test against
+ * @param[dimension] The dimnesion to test against
*/
-struct RelativeToWidthOrHeight
-{
- /**
- * Constraint that is relative (%) to parent width/height and applies a
- * unit based padding before the relative calculation.
- * @param scale of parent minus padding between 0 and 1
- * @param padding in world coordinate units
- * @param fixed part in world coordinate units
- */
- RelativeToWidthOrHeight( float scale, float padding, float fixed )
- : mScaleFactor( scale ),
- mPadding( padding ),
- mFixed( fixed )
- {
- }
-
- inline float operator()( const float& parentWidthOrHeight )
- {
- return mFixed + ( parentWidthOrHeight - mPadding ) * mScaleFactor;
- }
-
- float operator()( const float& current,
- const PropertyInput& parentWidthOrHeight )
- {
- return operator()( parentWidthOrHeight.GetFloat() );
- }
-
- float mScaleFactor;
- float mPadding;
- float mFixed;
-};
+bool FitToChild( Actor actor, Dimension::Type dimension )
+{
+ return actor.GetResizePolicy( dimension ) != ResizePolicy::FILL_TO_PARENT && actor.GetRelayoutSize( dimension ) > 0.0f;
+}
#if defined(DEBUG_ENABLED)
// debugging support, very useful when new features are added or bugs are hunted down
#define TABLEVIEW_TAG "DALI Toolkit::TableView "
#define TV_LOG(fmt, args...) Debug::LogMessage(Debug::DebugInfo, TABLEVIEW_TAG fmt, ## args)
+//#define TABLEVIEW_DEBUG 1
+#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() );
{
Dali::Toolkit::Internal::TableView::CellData data = array[i][j];
char actor = ' ';
+ std::string actorName;
if( data.actor )
{
actor = 'A';
+ actorName = data.actor.GetName();
}
- TV_LOG("Array[%d,%d]=%c %d,%d,%d,%d ", i, j, actor,
+ 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" );
}
+#endif // defined(TABLEVIEW_DEBUG)
#endif // defined(DEBUG_ENABLED)
} // namespace
namespace Toolkit
{
-const Property::Index TableView::PROPERTY_ROWS( Internal::TableView::TABLEVIEW_PROPERTY_START_INDEX );
-const Property::Index TableView::PROPERTY_COLUMNS( Internal::TableView::TABLEVIEW_PROPERTY_START_INDEX + 1 );
-const Property::Index TableView::PROPERTY_CELL_PADDING( Internal::TableView::TABLEVIEW_PROPERTY_START_INDEX + 2 );
-const Property::Index TableView::PROPERTY_LAYOUT_ANIMATION_DURATION( Internal::TableView::TABLEVIEW_PROPERTY_START_INDEX + 3 );
-const Property::Index TableView::PROPERTY_LAYOUT_ROWS( Internal::TableView::TABLEVIEW_PROPERTY_START_INDEX + 4 );
-const Property::Index TableView::PROPERTY_LAYOUT_COLUMNS( Internal::TableView::TABLEVIEW_PROPERTY_START_INDEX + 5 );
-
namespace Internal
{
namespace
{
-const Scripting::StringEnum< Toolkit::TableView::LayoutPolicy > LAYOUT_POLICY_STRING_TABLE[] =
-{
- { "fixed", Toolkit::TableView::Fixed },
- { "relative", Toolkit::TableView::Relative },
- { "fill", Toolkit::TableView::Fill }
-};
-
-const unsigned int LAYOUT_POLICY_STRING_TABLE_COUNT = sizeof(LAYOUT_POLICY_STRING_TABLE) / sizeof( LAYOUT_POLICY_STRING_TABLE[0] );
-
// Type registration
BaseHandle Create()
{
- return Toolkit::TableView::New(0, 0);
+ return Toolkit::TableView::New( 0, 0 );
}
-TypeRegistration mType( typeid(Toolkit::TableView), typeid(Toolkit::Control), Create );
-PropertyRegistration property1( mType, "rows", Toolkit::TableView::PROPERTY_ROWS, Property::UNSIGNED_INTEGER, &TableView::SetProperty, &TableView::GetProperty );
-PropertyRegistration property2( mType, "columns", Toolkit::TableView::PROPERTY_COLUMNS, Property::UNSIGNED_INTEGER, &TableView::SetProperty, &TableView::GetProperty );
-PropertyRegistration property3( mType, "cell-padding", Toolkit::TableView::PROPERTY_CELL_PADDING, Property::VECTOR2, &TableView::SetProperty, &TableView::GetProperty );
-PropertyRegistration property4( mType, "layout-animation-duration", Toolkit::TableView::PROPERTY_LAYOUT_ANIMATION_DURATION, Property::FLOAT, &TableView::SetProperty, &TableView::GetProperty );
-PropertyRegistration property5( mType, "layout-rows", Toolkit::TableView::PROPERTY_LAYOUT_ROWS, Property::MAP, &TableView::SetProperty, &TableView::GetProperty );
-PropertyRegistration property6( mType, "layout-columns", Toolkit::TableView::PROPERTY_LAYOUT_COLUMNS, Property::MAP, &TableView::SetProperty, &TableView::GetProperty );
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TableView, Toolkit::Control, Create );
-} // namespace
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "rows", UNSIGNED_INTEGER, ROWS )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "columns", UNSIGNED_INTEGER, COLUMNS )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "cell-padding", VECTOR2, CELL_PADDING )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-rows", MAP, LAYOUT_ROWS )
+DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-columns", MAP, LAYOUT_COLUMNS )
+
+DALI_TYPE_REGISTRATION_END()
+
+const Scripting::StringEnum LAYOUT_POLICY_STRING_TABLE[] =
+{
+ { "fixed", Toolkit::TableView::FIXED },
+ { "relative", Toolkit::TableView::RELATIVE },
+ { "fill", Toolkit::TableView::FILL }
+};
+
+const unsigned int LAYOUT_POLICY_STRING_TABLE_COUNT = sizeof(LAYOUT_POLICY_STRING_TABLE) / sizeof( LAYOUT_POLICY_STRING_TABLE[0] );
+
+} // Unnamed namespace
Toolkit::TableView TableView::New( unsigned int initialRows, unsigned int initialColumns )
{
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 );
{
child.GetParent().Remove( child );
}
+
// 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 );
}
+
// check if there already is something in this cell
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 );
// adopt the 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
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 );
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
+ // Only find valid child actors
if( child )
{
- // walk through the layout data
+ // 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 column = 0; column < columnCount; ++column )
{
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 )
{
RelayoutingLock lock( *this );
+
mCellData.InsertRow( rowIndex );
- // need to update the cellinfos for the items that moved
+
+ // 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 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 )&&
+
+ // 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
+
+ // 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
+ mRowColumnDirty = true;
RelayoutRequest();
}
void TableView::DeleteRow( unsigned int rowIndex, std::vector<Actor>& removed )
{
RelayoutingLock lock( *this );
+
+ // Delete the row
std::vector< CellData > lost;
mCellData.DeleteRow( rowIndex, lost );
- // need to update the cellinfos for the items that moved
+
+ // 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 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 )&&
+
+ // 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
+ // 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
+ // Decrement index
if( position.rowIndex > 1 )
{
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 );
+
+ // Contract row data array
+ mRowData.Erase( mRowData.Begin() + rowIndex );
+
+ // Sizes may have changed, so relayout
+ mRowColumnDirty = true;
RelayoutRequest();
}
void TableView::InsertColumn( unsigned int columnIndex )
{
RelayoutingLock lock( *this );
+
+ // Insert the new column
mCellData.InsertColumn( columnIndex );
- // need to update the cellinfos for the items that moved
+
+ // 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 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 )&&
+
+ // 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
+
+ // 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
+ mRowColumnDirty = true;
RelayoutRequest();
}
void TableView::DeleteColumn( unsigned int columnIndex, std::vector<Actor>& removed )
{
RelayoutingLock lock( *this );
+
+ // Remove the column
std::vector< CellData > lost;
mCellData.DeleteColumn( columnIndex, lost );
- // need to update the cellinfos for the items that moved
+
+ // 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 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 )&&
+
+ // 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
+ // 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
+ // 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
+
+ // Contract column data array
+ mColumnData.Erase( mColumnData.Begin() + columnIndex );
+
+ // Size may have changed so relayout
+ mRowColumnDirty = true;
RelayoutRequest();
}
void TableView::Resize( unsigned int rows, unsigned int columns, std::vector<Actor>& removed )
{
RelayoutingLock lock( *this );
+
unsigned int oldRows = GetRows();
unsigned int oldColumns = GetColumns();
- // resize data array
+
+ // Resize data array
std::vector< CellData > lost;
ResizeContainers( rows, columns, lost );
- // calculate if we lost rows or columns
+
+ // Calculate if we lost rows
unsigned int rowsRemoved = 0;
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 )
{
rowsRemoved = newColumns - oldColumns;
}
+
RemoveAndGetLostActors( lost, removed, rowsRemoved, columnsRemoved );
- // finally relayout once all actors are removed
+
+ // Sizes may have changed so request a relayout
+ mRowColumnDirty = true;
RelayoutRequest();
}
void TableView::SetCellPadding( Size padding )
{
- // if padding really changed
+ // If padding really changed
if( padding != mPadding )
{
mPadding = padding;
- // do a relayout
+
RelayoutRequest();
}
}
return mPadding;
}
+void TableView::SetRowPolicy( unsigned int rowIndex, CellSizePolicy policy )
+{
+ DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
+
+ if( mRowData[ rowIndex ].sizePolicy != policy )
+ {
+ mRowData[ rowIndex ].sizePolicy = policy;
+
+ mRowColumnDirty = true;
+ RelayoutRequest();
+ }
+}
+
+TableView::CellSizePolicy TableView::GetRowPolicy( unsigned int rowIndex ) const
+{
+ DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
+
+ return mRowData[ rowIndex ].sizePolicy;
+}
+
+void TableView::SetColumnPolicy( unsigned int columnIndex, CellSizePolicy policy )
+{
+ DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
+
+ if( mColumnData[ columnIndex ].sizePolicy != policy )
+ {
+ mColumnData[ columnIndex ].sizePolicy = policy;
+
+ mRowColumnDirty = true;
+ RelayoutRequest();
+ }
+}
+
+TableView::CellSizePolicy TableView::GetColumnPolicy( unsigned int columnIndex ) const
+{
+ DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
+
+ return mColumnData[ columnIndex ].sizePolicy;
+}
+
void TableView::SetFixedHeight( unsigned int rowIndex, float height )
{
- 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( rowIndex < mRowData.Size() );
+
+ RowColumnData& data = mRowData[ rowIndex ];
+ data.size = height;
+ data.sizePolicy = FIXED;
+
+ mRowColumnDirty = true;
RelayoutRequest();
}
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 = FIXED;
+
+ mRowColumnDirty = 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.userFillRatio = true;
+ data.sizePolicy = FILL;
+
+ mRowColumnDirty = 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 )
{
- 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.userFillRatio = true;
+ data.sizePolicy = FILL;
+
+ mRowColumnDirty = true;
RelayoutRequest();
}
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::SetLayoutAnimationDuration( float duration )
+void TableView::CalculateRowColumnData()
{
- mConstraintDuration = duration;
+ // Calculate the relative sizes
+ if( mRowColumnDirty )
+ {
+ ComputeRelativeSizes( mRowData );
+ ComputeRelativeSizes( mColumnData );
+
+ mRowColumnDirty = false;
+ }
}
-float TableView::GetLayoutAnimationDuration()
+void TableView::OnCalculateRelayoutSize( Dimension::Type dimension )
{
- return mConstraintDuration;
+ CalculateRowColumnData();
+
+ if( dimension & Dimension::WIDTH )
+ {
+ CalculateFixedSizes( mColumnData, Dimension::WIDTH );
+ mFixedTotals.width = CalculateTotalFixedSize( mColumnData );
+ }
+
+ if( dimension & Dimension::HEIGHT )
+ {
+ CalculateFixedSizes( mRowData, Dimension::HEIGHT );
+ mFixedTotals.height = CalculateTotalFixedSize( mRowData );
+ }
}
-void TableView::OnRelayout( const Vector2& size, ActorSizeContainer& container )
+void TableView::OnLayoutNegotiated( float size, Dimension::Type dimension )
{
- float fixedHeightsTotal = 0.0f;
- float fixedWidthsTotal = 0.0f;
+ CalculateRowColumnData();
- // 1. update the relative sizes and calculate total fixed height and width
- UpdateRelativeSizes( fixedHeightsTotal, fixedWidthsTotal );
+ // Calculate the value of all relative sized rows and columns
+ if( dimension & Dimension::WIDTH )
+ {
+ float remainingSize = size - mFixedTotals.width;
+ if( remainingSize < 0.0f )
+ {
+ remainingSize = 0.0f;
+ }
+
+ CalculateRelativeSizes( mColumnData, remainingSize );
+ }
+
+ if( dimension & Dimension::HEIGHT )
+ {
+ float remainingSize = size - mFixedTotals.height;
+ if( remainingSize < 0.0f )
+ {
+ remainingSize = 0.0f;
+ }
+
+ CalculateRelativeSizes( mRowData, remainingSize );
+ }
+}
+
+void TableView::OnRelayout( const Vector2& size, RelayoutContainer& container )
+{
+ CalculateRowColumnData();
- // 2. go through the layout data and create constraints
- float cumulatedFixedHeight = 0.0f;
- float cumulatedRelativeHeight = 0.0f;
+ // Go through the layout data
+ float cumulatedHeight = 0.0f;
- // 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 )
{
- // reset widths at the start of each row
- float cumulatedFixedWidth = 0.0f;
- float cumulatedRelativeWidth = 0.0f;
+ float cumulatedWidth = 0.0f;
+
for( unsigned int column = 0; column < columnCount; ++column )
{
- // check if this cell has an actor
- Actor actor = mCellData[ row ][ column ].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 ) )
+
+ // 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 lay out each actor only once.
+ if( actor && ( position.rowIndex == row ) && ( position.columnIndex == column ) )
{
- // anchor actor correctly
+ // Anchor actor to top left of table view
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 );
-
- Constraint widthConstraint = Constraint::New<float>( Actor::POSITION_X,
- ParentSource( Actor::SIZE_WIDTH ),
- RelativeToWidthOrHeight( relativePosition.x, positionPadding.x, fixedPosition.x ) );
-
- Constraint heightConstraint = Constraint::New<float>( Actor::POSITION_Y,
- ParentSource( Actor::SIZE_HEIGHT ),
- RelativeToWidthOrHeight( relativePosition.y, positionPadding.y, fixedPosition.y ) );
-
- widthConstraint.SetApplyTime( mConstraintDuration );
- heightConstraint.SetApplyTime( mConstraintDuration );
-
- // bake constrained position value if constraint is removed
- widthConstraint.SetRemoveAction( Constraint::Bake );
- heightConstraint.SetRemoveAction( Constraint::Bake );
-
- actor.ApplyConstraint( widthConstraint );
- actor.ApplyConstraint( heightConstraint );
-
- // 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 )
- {
- 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 ];
- }
- }
- if( position.columnSpan > 1 )
- {
- 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 ];
- }
- }
- // 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;
-
- RelativeToWidthOrHeight relativeWidthFunctor( relativeSize.x, sizePadding.x, fixedSize.x );
- RelativeToWidthOrHeight relativeHeightFunctor( relativeSize.y, sizePadding.y, fixedSize.y );
-
- widthConstraint = Constraint::New<float>( Actor::SIZE_WIDTH,
- ParentSource( Actor::SIZE_WIDTH ),
- relativeWidthFunctor );
-
- heightConstraint = Constraint::New<float>( Actor::SIZE_HEIGHT,
- ParentSource( Actor::SIZE_HEIGHT ),
- relativeHeightFunctor );
-
- widthConstraint.SetApplyTime( mConstraintDuration );
- heightConstraint.SetApplyTime( mConstraintDuration );
-
- // bake constrained size value if constraint is removed
- widthConstraint.SetRemoveAction( Constraint::Bake );
- heightConstraint.SetRemoveAction( Constraint::Bake );
-
- actor.ApplyConstraint( widthConstraint );
- actor.ApplyConstraint( heightConstraint );
-
- // Relayout Children
- Relayout ( actor, Vector2( relativeWidthFunctor( size.width ), relativeHeightFunctor( size.height ) ), container );
+
+ Padding padding;
+ actor.GetPadding( padding );
+
+ Vector3 actorPosition( cumulatedWidth + mPadding.width + padding.left, // Left padding
+ cumulatedHeight + mPadding.height + padding.top, // Top padding
+ 0.0f );
+ actor.SetPosition( actorPosition );
}
- // 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;
+
+ DALI_ASSERT_DEBUG( column < mColumnData.Size() );
+ cumulatedWidth += mColumnData[ column ].size;
}
- // 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
+
+ DALI_ASSERT_DEBUG( row < mRowData.Size() );
+ cumulatedHeight += mRowData[ row ].size;
}
}
TableView& tableViewImpl( GetImpl( tableView ) );
switch( index )
{
- case Toolkit::TableView::PROPERTY_ROWS:
+ case Toolkit::TableView::Property::ROWS:
{
if( value.Get<unsigned int>() != tableViewImpl.GetRows() )
{
}
break;
}
- case Toolkit::TableView::PROPERTY_COLUMNS:
+ case Toolkit::TableView::Property::COLUMNS:
{
if( value.Get<unsigned int>() != tableViewImpl.GetColumns() )
{
}
break;
}
- case Toolkit::TableView::PROPERTY_CELL_PADDING:
+ case Toolkit::TableView::Property::CELL_PADDING:
{
tableViewImpl.SetCellPadding( value.Get<Vector2>() );
break;
}
- case Toolkit::TableView::PROPERTY_LAYOUT_ANIMATION_DURATION:
- {
- tableViewImpl.SetLayoutAnimationDuration( value.Get<float>() );
- break;
- }
- case Toolkit::TableView::PROPERTY_LAYOUT_ROWS:
+ case Toolkit::TableView::Property::LAYOUT_ROWS:
{
SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, value );
break;
}
- case Toolkit::TableView::PROPERTY_LAYOUT_COLUMNS:
+ case Toolkit::TableView::Property::LAYOUT_COLUMNS:
{
SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, value );
break;
TableView& tableViewImpl( GetImpl( tableView ) );
switch( index )
{
- case Toolkit::TableView::PROPERTY_ROWS:
+ case Toolkit::TableView::Property::ROWS:
{
value = tableViewImpl.GetRows();
break;
}
- case Toolkit::TableView::PROPERTY_COLUMNS:
+ case Toolkit::TableView::Property::COLUMNS:
{
value = tableViewImpl.GetColumns();
break;
}
- case Toolkit::TableView::PROPERTY_CELL_PADDING:
+ case Toolkit::TableView::Property::CELL_PADDING:
{
value = tableViewImpl.GetCellPadding();
break;
}
- case Toolkit::TableView::PROPERTY_LAYOUT_ANIMATION_DURATION:
- {
- value = tableViewImpl.GetLayoutAnimationDuration();
- break;
- }
- case Toolkit::TableView::PROPERTY_LAYOUT_ROWS:
+ case Toolkit::TableView::Property::LAYOUT_ROWS:
{
value = tableViewImpl.GetRowHeightsPropertyValue();
break;
}
- case Toolkit::TableView::PROPERTY_LAYOUT_COLUMNS:
+ case Toolkit::TableView::Property::LAYOUT_COLUMNS:
{
value = tableViewImpl.GetColumnWidthsPropertyValue();
break;
return;
}
+ RelayoutRequest();
+
+ // Test properties on actor
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.columnIndex = static_cast<unsigned int>( indices.y );
AddChild( child, cellPosition );
- // donot continue
+
+ // Do not continue
return;
}
- // check if we're already laying out this child somewhere on the table
- // walk through the layout data
+ // Find the first available cell to store the actor in
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 )
{
- // no actor means free cell
if( !(mCellData[ row ][ column ].actor) )
{
- // put the actor in the cell
+ // Put the actor in the cell
CellData data;
data.actor = child;
data.position.columnIndex = column;
data.position.rowIndex = row;
mCellData[ row ][ column ] = data;
- RelayoutRequest();
- // don' continue
+
+ // Don't continue
return;
}
}
}
- // 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
+
+ // 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;
mCellData[ rowCount ][ 0 ] = data;
- // finally relayout the table
- RelayoutRequest();
}
void TableView::OnControlChildRemove( Actor& child )
: Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
mCellData( initialRows, initialColumns ),
mLayoutingChild( false ),
- mConstraintDuration( DEFAULT_CONSTRAINT_DURATION )
+ mRowColumnDirty( true ) // Force recalculation first time
{
SetKeyboardNavigationSupport( true );
ResizeContainers( initialRows, initialColumns );
void TableView::ResizeContainers( unsigned int rows, unsigned int columns, std::vector<CellData>& removed )
{
+ // Resize cell data
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 );
+
+ // 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,
}
}
-bool TableView::RemoveAllInstances( Actor child )
+bool TableView::RemoveAllInstances( const Actor& child )
{
bool found = false;
// walk through the layout data
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 )
{
- if( Property::MAP == value.GetType() )
+ 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 )
+ 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) ) >> rowIndex;
+ if( childMap )
{
- if( item.HasKey( "policy" ) && item.HasKey( "value" ) )
+ Property::Value* policy = childMap->Find( "policy" );
+ Property::Value* value = childMap->Find( "value" );
+ if( policy && value )
{
- Toolkit::TableView::LayoutPolicy policy = Scripting::GetEnumeration< Toolkit::TableView::LayoutPolicy >( item.GetValue("policy").Get<std::string>(), 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)( rowIndex, value->Get<float>() );
+ }
+ else if( policy == Toolkit::TableView::RELATIVE )
+ {
+ (tableViewImpl.*funcRelative)( rowIndex, value->Get<float>() );
+ }
}
}
}
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 ) );
+ const char* name = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIXED,
+ LAYOUT_POLICY_STRING_TABLE,
+ LAYOUT_POLICY_STRING_TABLE_COUNT );
+ std::string fixedPolicy;
+ if( name )
+ {
+ fixedPolicy = name;
+ }
+ name = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::RELATIVE,
+ LAYOUT_POLICY_STRING_TABLE,
+ LAYOUT_POLICY_STRING_TABLE_COUNT );
+ std::string relativePolicy;
+ if( name )
+ {
+ relativePolicy = name;
+ }
- size_t count = fixedSize.size();
- for( size_t index = 0; index < count; index++ )
+ 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] ) )
+ switch( dataInstance.sizePolicy )
{
- Property::Map item;
- item[ "policy" ] = relativePolicy;
- item[ "value" ] = relativeSize[index];
+ case FIXED:
+ {
+ Property::Map item;
+ item[ "policy" ] = fixedPolicy;
+ item[ "value" ] = dataInstance.size;
+
+ std::ostringstream ss;
+ ss << i;
+
+ map[ ss.str() ] = item;
+
+ break;
+ }
+
+ case FILL:
+ {
+ Property::Map item;
+ item[ "policy" ] = relativePolicy;
+ item[ "value" ] = dataInstance.fillRatio;
- map[ static_cast<std::ostringstream*>( &(std::ostringstream() << index ) )->str() ] = item;
+ std::ostringstream ss;
+ ss << i;
+
+ map[ ss.str() ] = item;
+
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
}
}
}
// 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;
switch ( direction )
{
- case Toolkit::Control::Left:
+ case Toolkit::Control::KeyboardFocus::LEFT:
{
if(--currentColumn < 0)
{
}
break;
}
- case Toolkit::Control::Right:
+ case Toolkit::Control::KeyboardFocus::RIGHT:
{
if(++currentColumn > numberOfColumns - 1)
{
}
break;
}
- case Toolkit::Control::Up:
+ case Toolkit::Control::KeyboardFocus::UP:
{
if(--currentRow < 0)
{
}
break;
}
- case Toolkit::Control::Down:
+ case Toolkit::Control::KeyboardFocus::DOWN:
+
{
if(++currentRow > numberOfRows - 1)
{
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 )
+{
+ CalculateRowColumnData();
+
+ 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 )
+ {
+ // check if this cell has an actor
+ Actor& actor = mCellData[ row ][ column ].actor;
+
+ if( actor && ( actor == child ) )
+ {
+ 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.
+ if ( ( position.rowIndex == row ) && ( position.columnIndex == column ) )
+ {
+ switch( dimension )
+ {
+ case Dimension::WIDTH:
+ {
+ float cellSize = 0.0f;
+
+ // Accumulate the width
+ for( unsigned int i = 0; i < position.columnSpan; ++i )
+ {
+ DALI_ASSERT_DEBUG( column + i < mColumnData.Size() );
+ cellSize += mColumnData[ column + i ].size;
+ }
+
+ // Apply padding
+ cellSize -= mPadding.width * 2.0f;
+ if( cellSize < 0.0f )
+ {
+ cellSize = 0.0f;
+ }
+
+ return cellSize;
+ }
+
+ case Dimension::HEIGHT:
+ {
+ float cellSize = 0.0f;
+
+ // Accumulate the height
+ for( unsigned int i = 0; i < position.rowSpan; ++i )
+ {
+ DALI_ASSERT_DEBUG( row + i < mRowData.Size() );
+ cellSize += mRowData[ row + i ].size;
+ }
+
+ // Apply padding
+ cellSize -= mPadding.width * 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::ComputeRelativeSizes( 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 == FILL )
+ {
+ if( dataInstance.userFillRatio )
+ {
+ relativeTotal += dataInstance.fillRatio;
+ }
+ else
+ {
+ 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 )
+ {
+ case FIXED:
+ case 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::CalculateFixedSizes( 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 == 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;
+ }
+ }
+}
+
+void TableView::CalculateRelativeSizes( RowColumnArray& data, float size )
+{
+ const unsigned int dataCount = data.Size();
+
+ for( unsigned int i = 0; i < dataCount; ++i )
+ {
+ RowColumnData& dataInstance = data[ i ];
+
+ if( dataInstance.sizePolicy == FILL )
+ {
+ dataInstance.size = dataInstance.fillRatio * size;
+ }
+ }
+}
+
+bool TableView::FindFit( const RowColumnArray& data )
+{
+ for( unsigned int i = 0, count = data.Size(); i < count; ++i )
+ {
+ if( data[ i ].sizePolicy == FIT )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace Internal
} // namespace Toolkit