2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/internal/controls/table-view/table-view-impl.h>
23 #include <dali/public-api/object/ref-object.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/public-api/object/type-registry-helper.h>
26 #include <dali/devel-api/actors/actor-devel.h>
27 #include <dali/devel-api/scripting/scripting.h>
28 #include <dali/public-api/size-negotiation/relayout-container.h>
29 #include <dali/integration-api/debug.h>
32 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
39 * @brief Should the tableview fit around the given actor
41 * @param[in] actor The child actor to test against
42 * @param[dimension] The dimension to test against
44 bool FitToChild( Actor actor, Dimension::Type dimension )
46 return actor.GetResizePolicy( dimension ) != ResizePolicy::FILL_TO_PARENT && actor.GetRelayoutSize( dimension ) > 0.0f;
49 #if defined(DEBUG_ENABLED)
50 // debugging support, very useful when new features are added or bugs are hunted down
51 // currently not called from code so compiler will optimize these away, kept here for future debugging
53 #define TABLEVIEW_TAG "DALI Toolkit::TableView "
54 #define TV_LOG(fmt, args,...) Debug::LogMessage(Debug::DebugInfo, TABLEVIEW_TAG fmt, ## args)
55 //#define TABLEVIEW_DEBUG 1
57 #if defined(TABLEVIEW_DEBUG)
58 void PrintArray( Array2d<Dali::Toolkit::Internal::TableView::CellData>& array )
60 TV_LOG( "Array2d<CellData> size [%d,%d] \n", array.GetRows(), array.GetColumns() );
62 for( unsigned int i = 0; i < array.GetRows(); ++i )
64 for( unsigned int j = 0; j < array.GetColumns(); ++j )
66 Dali::Toolkit::Internal::TableView::CellData data = array[i][j];
68 std::string actorName;
72 actorName = data.actor.GetProperty< std::string >( Dali::Actor::Property::NAME );
74 TV_LOG("Array[%d,%d]=%c %s %d,%d,%d,%d ", i, j, actor, actorName.c_str(),
75 data.position.rowIndex, data.position.columnIndex,
76 data.position.rowSpan, data.position.columnSpan );
82 // debugging support, very useful when new features are added or bugs are hunted down
83 // currently not called from code so compiler will optimize these away, kept here for future debugging
84 void PrintArray( Array2d<Size>& array )
86 TV_LOG( "Array2d<Size> size [%d,%d] \n", array.GetRows(), array.GetColumns() );
88 for( unsigned int i = 0; i < array.GetRows(); ++i )
90 for( unsigned int j = 0; j < array.GetColumns(); ++j )
92 TV_LOG( "Array[%d,%d]=%.2f,%.2f ", i, j, array[i][j].width, array[i][j].height );
97 // debugging support, very useful when new features are added or bugs are hunted down
98 // currently not called from code so compiler will optimize these away, kept here for future debugging
99 void PrintVector( std::vector<float>& array )
101 TV_LOG( "vector, size [%d]\n", array.size() );
103 for( unsigned int i = 0; i < array.size(); ++i )
105 TV_LOG( "vector[%d]=%.2f ", i, array[i] );
109 #endif // defined(TABLEVIEW_DEBUG)
110 #endif // defined(DEBUG_ENABLED)
129 return Toolkit::TableView::New( 0, 0 );
132 // Setup properties, signals and actions using the type-registry.
133 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TableView, Toolkit::Control, Create );
135 DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "rows", INTEGER, ROWS )
136 DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "columns", INTEGER, COLUMNS )
137 DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "cellPadding", VECTOR2, CELL_PADDING )
138 DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layoutRows", MAP, LAYOUT_ROWS )
139 DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layoutColumns", MAP, LAYOUT_COLUMNS )
140 DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "cellIndex", VECTOR2, CELL_INDEX )
141 DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "rowSpan", INTEGER, ROW_SPAN )
142 DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "columnSpan", INTEGER, COLUMN_SPAN )
143 DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "cellHorizontalAlignment", STRING, CELL_HORIZONTAL_ALIGNMENT )
144 DALI_CHILD_PROPERTY_REGISTRATION( Toolkit, TableView, "cellVerticalAlignment", STRING, CELL_VERTICAL_ALIGNMENT )
146 DALI_TYPE_REGISTRATION_END()
148 const Scripting::StringEnum LAYOUT_POLICY_STRING_TABLE[] =
150 { "fixed", Toolkit::TableView::FIXED },
151 { "relative", Toolkit::TableView::RELATIVE },
152 { "fill", Toolkit::TableView::FILL },
153 { "fit", Toolkit::TableView::FIT }
155 const unsigned int LAYOUT_POLICY_STRING_TABLE_COUNT = sizeof(LAYOUT_POLICY_STRING_TABLE) / sizeof( LAYOUT_POLICY_STRING_TABLE[0] );
157 const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
159 {"left", HorizontalAlignment::LEFT},
160 {"center", HorizontalAlignment::CENTER},
161 {"right", HorizontalAlignment::RIGHT}
163 const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(HORIZONTAL_ALIGNMENT_STRING_TABLE) / sizeof( HORIZONTAL_ALIGNMENT_STRING_TABLE[0] );
165 const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] =
167 {"top", VerticalAlignment::TOP},
168 {"center", VerticalAlignment::CENTER},
169 {"bottom", VerticalAlignment::BOTTOM}
171 const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(VERTICAL_ALIGNMENT_STRING_TABLE) / sizeof( VERTICAL_ALIGNMENT_STRING_TABLE[0] );
173 } // Unnamed namespace
175 Toolkit::TableView TableView::New( unsigned int initialRows, unsigned int initialColumns )
177 // Create the implementation, temporarily owned by this handle on stack
178 IntrusivePtr< TableView > impl = new TableView( initialRows, initialColumns );
180 // Pass ownership to CustomActor handle
181 Toolkit::TableView handle( *impl );
183 // Second-phase init of the implementation
184 // This can only be done after the CustomActor connection has been made...
190 bool TableView::AddChild( Actor& child, const Toolkit::TableView::CellPosition& position )
192 // check that the child is valid
193 DALI_ASSERT_ALWAYS( child );
195 // if child is already parented, we adopt it
198 // check if we need to expand our data array
199 if( position.rowIndex >= mCellData.GetRows() )
201 // only adding new rows
202 ResizeContainers( position.rowIndex + 1, mCellData.GetColumns() );
205 if( position.columnIndex >= mCellData.GetColumns() )
207 // only adding new columns
208 ResizeContainers( mCellData.GetRows(), position.columnIndex + 1 );
211 // check if there already is something in this cell
212 if( mCellData[ position.rowIndex ][ position.columnIndex ].actor )
214 return false; // cannot share a cell, it would complicate all logic and not bring much benefit
217 RelayoutingLock lock( *this );
221 // if child spans multiple rows of columns
222 if( ( position.rowSpan > 1 ) && ( position.rowIndex + position.rowSpan > mCellData.GetRows() ) )
224 // increase table size for the full span, only increasing rows
225 ResizeContainers( position.rowIndex + position.rowSpan, mCellData.GetColumns() );
228 if( ( position.columnSpan > 1 ) && ( position.columnIndex + position.columnSpan > mCellData.GetColumns() ) )
230 // increase table size for the full span, only increasing columns
231 ResizeContainers( mCellData.GetRows(), position.columnIndex + position.columnSpan );
234 // Fill in all cells that need the data
237 data.position = position;
239 for( unsigned int row = position.rowIndex; row < ( position.rowIndex + position.rowSpan ); ++row )
241 // store same information to all cells, this way we can identify
242 // if a cell is the prime location of an actor or a spanned one
243 for( unsigned int column = position.columnIndex; column < ( position.columnIndex + position.columnSpan ); ++column )
245 // store same information to all cells, this way we can identify
246 // if a cell is the prime location of an actor or a spanned one
247 mCellData[ row ][ column ] = data;
251 // Relayout the whole table
252 if( mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT && position.rowSpan == 1 )
256 if( mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT && position.columnSpan == 1 )
263 return true; // Addition successful
266 Actor TableView::GetChildAt( const Toolkit::TableView::CellPosition& position )
268 if( ( position.rowIndex < mCellData.GetRows() ) && ( position.columnIndex < mCellData.GetColumns() ) )
270 return mCellData[ position.rowIndex ][ position.columnIndex ].actor;
273 // Return an empty handle
277 Actor TableView::RemoveChildAt( const Toolkit::TableView::CellPosition& position )
279 // get the child handle
280 Actor child = GetChildAt( position );
281 // if no real actor there, nothing else to be done
284 RelayoutingLock lock( *this );
285 // Remove the child, this will trigger a call to OnChildRemove
286 Self().Remove( child );
288 // relayout the table only if instances were found
289 if( RemoveAllInstances( child ) )
291 if( mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT )
295 if( mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT )
302 // return the child back to caller
306 bool TableView::FindChildPosition( const Actor& child, Toolkit::TableView::CellPosition& positionOut )
308 // Only find valid child actors
311 // Walk through the layout data
312 const unsigned int rowCount = mCellData.GetRows();
313 const unsigned int columnCount = mCellData.GetColumns();
315 for( unsigned int row = 0; row < rowCount; ++row )
317 for( unsigned int column = 0; column < columnCount; ++column )
319 if( mCellData[ row ][ column ].actor == child )
321 positionOut = mCellData[ row ][ column ].position;
331 void TableView::InsertRow( unsigned int rowIndex )
333 RelayoutingLock lock( *this );
335 mCellData.InsertRow( rowIndex );
337 // Need to update the cell infos for the items that moved
338 const unsigned int rowCount = mCellData.GetRows();
339 const unsigned int columnCount = mCellData.GetColumns();
341 for( unsigned int row = 0; row < rowCount; ++row )
343 for( unsigned int column = 0; column < columnCount; ++column )
345 Toolkit::TableView::CellPosition& position = mCellData[ row ][ column ].position;
347 // If cell is spanning and above and spans to inserted row
348 if( ( position.rowSpan > 1 ) && ( position.rowIndex <= rowIndex ) &&
349 ( position.rowIndex + position.rowSpan > rowIndex ) )
354 // Copy cell to occupy the new column
355 mCellData[ rowIndex ][ column ] = mCellData[ row ][ column ];
357 else if( row > rowIndex ) // If below of inserted row, increase row index
365 // Expand row data array
366 mRowData.Insert( mRowData.Begin() + rowIndex, RowColumnData() );
368 // Sizes may have changed, so relayout
373 void TableView::DeleteRow( unsigned int rowIndex )
375 std::vector< Actor > ignored;
376 DeleteRow( rowIndex, ignored );
379 void TableView::DeleteRow( unsigned int rowIndex, std::vector<Actor>& removed )
381 RelayoutingLock lock( *this );
384 std::vector< CellData > lost;
385 mCellData.DeleteRow( rowIndex, lost );
387 // Need to update the cell infos for the items that moved
388 const unsigned int rowCount = mCellData.GetRows();
389 const unsigned int columnCount = mCellData.GetColumns();
391 for( unsigned int row = 0; row < rowCount; ++row )
393 for( unsigned int column = 0; column < columnCount; ++column )
395 Toolkit::TableView::CellPosition& position = mCellData[ row ][ column ].position;
397 // If cell is spanning and above and spans to deleted row
398 if( ( position.rowSpan > 1 ) && ( position.rowIndex <= rowIndex ) &&
399 ( position.rowIndex + position.rowSpan > rowIndex ) )
402 if( position.rowSpan > 1 )
407 else if( row >= rowIndex ) // If below of or at the inserted row, decrease row index
410 if( position.rowIndex > 0 )
418 // 1 row removed, 0 columns
419 RemoveAndGetLostActors( lost, removed, 1u, 0u );
421 // Contract row data array
422 mRowData.Erase( mRowData.Begin() + rowIndex );
424 // Sizes may have changed, so relayout
426 // it is possible that the deletion of row leads to remove of child which might further lead to the change of FIT column
432 void TableView::InsertColumn( unsigned int columnIndex )
434 RelayoutingLock lock( *this );
436 // Insert the new column
437 mCellData.InsertColumn( columnIndex );
439 // Need to update the cell infos for the items that moved
440 const unsigned int rowCount = mCellData.GetRows();
441 const unsigned int columnCount = mCellData.GetColumns();
443 for( unsigned int row = 0; row < rowCount; ++row )
445 for( unsigned int column = 0; column < columnCount; ++column )
447 Toolkit::TableView::CellPosition& position = mCellData[ row ][ column ].position;
449 // If cell is spanning and left side and spans to inserted column
450 if( ( position.columnSpan > 1 ) && ( position.columnIndex <= columnIndex ) &&
451 ( position.columnIndex + position.columnSpan > columnIndex ) )
454 position.columnSpan++;
456 // Copy cell to occupy the new column
457 mCellData[ row ][ columnIndex ] = mCellData[ row ][ column ];
459 else if( column > columnIndex ) // If on the right side of inserted column, increase column index
462 position.columnIndex++;
467 // Expand column data array
468 mColumnData.Insert( mColumnData.Begin() + columnIndex, RowColumnData() );
470 // Sizes may have changed so relayout
475 void TableView::DeleteColumn( unsigned int columnIndex )
477 std::vector< Actor > ignored;
478 DeleteColumn( columnIndex, ignored );
481 void TableView::DeleteColumn( unsigned int columnIndex, std::vector<Actor>& removed )
483 RelayoutingLock lock( *this );
486 std::vector< CellData > lost;
487 mCellData.DeleteColumn( columnIndex, lost );
489 // Need to update the cell infos for the items that moved
490 const unsigned int rowCount = mCellData.GetRows();
491 const unsigned int columnCount = mCellData.GetColumns();
493 for( unsigned int row = 0; row < rowCount; ++row )
495 for( unsigned int column = 0; column < columnCount; ++column )
497 Toolkit::TableView::CellPosition& position = mCellData[ row ][ column ].position;
499 // If cell is spanning and left side and spans to inserted column
500 if( ( position.columnSpan > 1 ) && ( position.columnIndex <= columnIndex ) &&
501 ( position.columnIndex + position.columnSpan > columnIndex ) )
504 if( position.columnSpan > 1 )
506 position.columnSpan--;
509 else if( column >= columnIndex ) // If on the right side of or at the inserted column, decrease column index
512 if( position.columnIndex > 0 )
514 position.columnIndex--;
520 // 0 rows, 1 column removed
521 RemoveAndGetLostActors( lost, removed, 0u, 1u );
523 // Contract column data array
524 mColumnData.Erase( mColumnData.Begin() + columnIndex );
526 // Size may have changed so relayout
528 // it is possible that the deletion of column leads to remove of child which might further lead to the change of FIT row
534 void TableView::Resize( unsigned int rows, unsigned int columns )
536 std::vector< Actor > ignored;
537 Resize( rows, columns, ignored );
540 void TableView::Resize( unsigned int rows, unsigned int columns, std::vector<Actor>& removed )
542 RelayoutingLock lock( *this );
544 unsigned int oldRows = GetRows();
545 unsigned int oldColumns = GetColumns();
548 std::vector< CellData > lost;
549 ResizeContainers( rows, columns, lost );
551 // Calculate if we lost rows
552 unsigned int rowsRemoved = 0;
553 unsigned int newRows = GetRows();
555 if( oldRows < newRows )
557 rowsRemoved = newRows - oldRows;
560 // Calculate if we lost columns
561 unsigned int columnsRemoved = 0;
562 unsigned int newColumns = GetColumns();
563 if( oldColumns < newColumns )
565 rowsRemoved = newColumns - oldColumns;
568 RemoveAndGetLostActors( lost, removed, rowsRemoved, columnsRemoved );
570 // Sizes may have changed so request a relayout
576 void TableView::SetCellPadding( Size padding )
578 // If padding really changed
579 if( padding != mPadding )
587 Size TableView::GetCellPadding()
592 void TableView::SetFitHeight( unsigned int rowIndex )
594 DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
596 if( mRowData[ rowIndex ].sizePolicy != Toolkit::TableView::FIT )
598 mRowData[ rowIndex ].sizePolicy = Toolkit::TableView::FIT;
605 bool TableView::IsFitHeight( unsigned int rowIndex ) const
607 DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
609 return mRowData[ rowIndex ].sizePolicy == Toolkit::TableView::FIT;
612 void TableView::SetFitWidth( unsigned int columnIndex )
614 DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
616 if( mColumnData[ columnIndex ].sizePolicy != Toolkit::TableView::FIT )
618 mColumnData[ columnIndex ].sizePolicy = Toolkit::TableView::FIT;
625 bool TableView::IsFitWidth( unsigned int columnIndex ) const
627 DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
629 return mColumnData[ columnIndex ].sizePolicy == Toolkit::TableView::FIT;
632 void TableView::SetFixedHeight( unsigned int rowIndex, float height )
634 DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
636 RowColumnData& data = mRowData[ rowIndex ];
638 data.sizePolicy = Toolkit::TableView::FIXED;
644 float TableView::GetFixedHeight( unsigned int rowIndex ) const
646 DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
648 return mRowData[ rowIndex ].size;
651 void TableView::SetFixedWidth( unsigned int columnIndex, float width )
653 DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
655 RowColumnData& data = mColumnData[ columnIndex ];
657 data.sizePolicy = Toolkit::TableView::FIXED;
663 float TableView::GetFixedWidth( unsigned int columnIndex ) const
665 DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
667 return mColumnData[ columnIndex ].size;
670 void TableView::SetRelativeHeight( unsigned int rowIndex, float heightPercentage )
672 DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
674 RowColumnData& data = mRowData[ rowIndex ];
675 data.fillRatio = heightPercentage;
676 data.sizePolicy = Toolkit::TableView::RELATIVE;
682 float TableView::GetRelativeHeight( unsigned int rowIndex ) const
684 DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
686 return mRowData[ rowIndex ].fillRatio;
689 void TableView::SetRelativeWidth( unsigned int columnIndex, float widthPercentage )
691 DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
693 RowColumnData& data = mColumnData[ columnIndex ];
694 data.fillRatio = widthPercentage;
695 data.sizePolicy = Toolkit::TableView::RELATIVE;
701 float TableView::GetRelativeWidth( unsigned int columnIndex ) const
703 DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
705 return mColumnData[ columnIndex ].fillRatio;
708 void TableView::OnCalculateRelayoutSize( Dimension::Type dimension )
710 if( (dimension & Dimension::WIDTH) && mColumnDirty )
713 * FIXED and FIT have size in pixel
714 * Nothing to do with FIXED, as its value is assigned by user and will not get changed
716 * Need to update the size for FIT column here
718 CalculateFitSizes( mColumnData, Dimension::WIDTH );
720 /* RELATIVE and FILL have size in ratio
721 * Their size in pixel is not available until we get the negotiated size for the whole table
722 * Nothing to do with RELATIVE, as its ratio is assigned by user and will not get changed
724 * Need to update the ratio for FILL column here
726 CalculateFillSizes( mColumnData );
728 mFixedTotals.width = CalculateTotalFixedSize( mColumnData );
731 if( (dimension & Dimension::HEIGHT) && mRowDirty )
733 // refer to the comment above
734 CalculateFitSizes( mRowData, Dimension::HEIGHT );
736 // refer to the comment above
737 CalculateFillSizes( mRowData );
739 mFixedTotals.height = CalculateTotalFixedSize( mRowData );
743 void TableView::OnLayoutNegotiated( float size, Dimension::Type dimension )
745 // Update the column sizes
746 if( (dimension & Dimension::WIDTH) && mColumnDirty )
748 float remainingSize = size - mFixedTotals.width;
749 if( remainingSize < 0.0f )
751 remainingSize = 0.0f;
754 // update every column position in ColumnData array
755 float cumulatedWidth = 0.0f;
756 for( auto&& element : mColumnData )
758 if( element.sizePolicy == Toolkit::TableView::FILL || element.sizePolicy == Toolkit::TableView::RELATIVE )
760 element.size = element.fillRatio * remainingSize;
763 cumulatedWidth += element.size;
764 element.position = cumulatedWidth;
767 mColumnDirty = false;
770 // Update the row sizes
771 if( (dimension & Dimension::HEIGHT) && mRowDirty )
773 float remainingSize = size - mFixedTotals.height;
774 if( remainingSize < 0.0f )
776 remainingSize = 0.0f;
779 // update every row position in RowData array
780 float cumulatedHeight = 0.0f;
781 for( unsigned int row = 0, rowCount = mCellData.GetRows(); row < rowCount; ++row )
783 if( mRowData[ row ].sizePolicy == Toolkit::TableView::FILL || mRowData[ row ].sizePolicy == Toolkit::TableView::RELATIVE)
785 mRowData[ row ].size = mRowData[ row ].fillRatio * remainingSize;
788 cumulatedHeight += mRowData[ row ].size;
789 mRowData[row].position = cumulatedHeight;
796 void TableView::OnSizeSet( const Vector3& size )
798 // If this table view is size negotiated by another actor or control, then the
799 // rows and columns must be recalculated or the new size will not take effect.
800 mRowDirty = mColumnDirty = true;
803 Control::OnSizeSet( size );
806 void TableView::OnRelayout( const Vector2& size, RelayoutContainer& container )
808 // Go through the layout data
809 float totalWidth = 0.0;
811 Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>( Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>() );
813 if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection )
815 for (auto&& element : mColumnData)
817 totalWidth += element.size;
821 for( unsigned int row = 0, rowCount = mCellData.GetRows(); row < rowCount; ++row )
823 for( unsigned int column = 0, columnCount = mCellData.GetColumns(); column < columnCount; ++column )
825 CellData& cellData= mCellData[ row ][ column ];
826 Actor& actor = cellData.actor;
827 const Toolkit::TableView::CellPosition position = cellData.position;
829 // If there is an actor and this is the main cell of the actor.
830 // An actor can be in multiple cells if its row or column span is more than 1.
831 // We however must lay out each actor only once.
832 if( actor && position.rowIndex == row && position.columnIndex == column )
834 // Anchor actor to top left of the cell
835 if( actor.GetProperty( Actor::Property::POSITION_USES_ANCHOR_POINT ).Get< bool >() )
837 actor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
839 actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
841 Padding padding = actor.GetProperty<Vector4>( Actor::Property::PADDING );
843 float left = (column > 0) ? mColumnData[column - 1].position : 0.f;
846 if( Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection )
848 right = totalWidth - left;
849 left = right - mColumnData[column].size;
853 right = left + mColumnData[column].size;
856 float top = row > 0 ? mRowData[row-1].position : 0.f;
857 float bottom = mRowData[row+position.rowSpan-1].position;
859 if( cellData.horizontalAlignment == HorizontalAlignment::LEFT )
861 actor.SetProperty( Actor::Property::POSITION_X, left + mPadding.width + padding.left );
863 else if( cellData.horizontalAlignment == HorizontalAlignment::RIGHT )
865 actor.SetProperty( Actor::Property::POSITION_X, right - mPadding.width - padding.right - actor.GetRelayoutSize( Dimension::WIDTH ) );
867 else //if( cellData.horizontalAlignment == HorizontalAlignment::CENTER )
869 actor.SetProperty( Actor::Property::POSITION_X, (left + right + padding.left - padding.right - actor.GetRelayoutSize( Dimension::WIDTH )) * 0.5f );
872 if( cellData.verticalAlignment == VerticalAlignment::TOP )
874 actor.SetProperty( Actor::Property::POSITION_Y, top + mPadding.height + padding.top );
876 else if( cellData.verticalAlignment == VerticalAlignment::BOTTOM )
878 actor.SetProperty( Actor::Property::POSITION_Y, bottom - mPadding.height - padding.bottom - actor.GetRelayoutSize( Dimension::HEIGHT ) );
880 else //if( cellData.verticalAlignment = VerticalAlignment::CENTER )
882 actor.SetProperty( Actor::Property::POSITION_Y, (top + bottom + padding.top - padding.bottom - actor.GetRelayoutSize( Dimension::HEIGHT )) * 0.5f );
889 unsigned int TableView::GetRows()
891 return mCellData.GetRows();
894 unsigned int TableView::GetColumns()
896 return mCellData.GetColumns();
899 void TableView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
901 Toolkit::TableView tableView = Toolkit::TableView::DownCast( Dali::BaseHandle( object ) );
905 TableView& tableViewImpl( GetImpl( tableView ) );
908 case Toolkit::TableView::Property::ROWS:
911 if( value.Get( rows ) && rows >= 0 )
913 if( static_cast<unsigned int>(rows) != tableViewImpl.GetRows() )
915 tableViewImpl.Resize( rows, tableViewImpl.GetColumns() );
920 case Toolkit::TableView::Property::COLUMNS:
923 if( value.Get( columns ) && columns >= 0 )
925 if( static_cast<unsigned int>( columns ) != tableViewImpl.GetColumns() )
927 tableViewImpl.Resize( tableViewImpl.GetRows(), value.Get<int>() );
932 case Toolkit::TableView::Property::CELL_PADDING:
934 tableViewImpl.SetCellPadding( value.Get<Vector2>() );
937 case Toolkit::TableView::Property::LAYOUT_ROWS:
939 SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, &TableView::SetFitHeight, value );
942 case Toolkit::TableView::Property::LAYOUT_COLUMNS:
944 SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, &TableView::SetFitWidth, value );
951 Property::Value TableView::GetProperty( BaseObject* object, Property::Index index )
953 Property::Value value;
955 Toolkit::TableView tableView = Toolkit::TableView::DownCast( Dali::BaseHandle( object ) );
959 TableView& tableViewImpl( GetImpl( tableView ) );
962 case Toolkit::TableView::Property::ROWS:
964 value = static_cast<int>( tableViewImpl.GetRows() );
967 case Toolkit::TableView::Property::COLUMNS:
969 value = static_cast<int>( tableViewImpl.GetColumns() );
972 case Toolkit::TableView::Property::CELL_PADDING:
974 value = tableViewImpl.GetCellPadding();
977 case Toolkit::TableView::Property::LAYOUT_ROWS:
979 value = tableViewImpl.GetRowHeightsPropertyValue();
982 case Toolkit::TableView::Property::LAYOUT_COLUMNS:
984 value = tableViewImpl.GetColumnWidthsPropertyValue();
993 void TableView::OnChildAdd( Actor& child )
995 if( ! mLayoutingChild )
997 // Ensure we're not in the middle of laying out children
999 // Check child properties on actor to decide its position inside the table
1000 HorizontalAlignment::Type horizontalAlignment = HorizontalAlignment::LEFT;
1001 VerticalAlignment::Type verticalAlignment = VerticalAlignment::TOP;
1003 if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_HORIZONTAL_ALIGNMENT ) != Property::NONE )
1005 std::string value = child.GetProperty( Toolkit::TableView::ChildProperty::CELL_HORIZONTAL_ALIGNMENT ).Get<std::string >();
1006 Scripting::GetEnumeration< HorizontalAlignment::Type >( value.c_str(),
1007 HORIZONTAL_ALIGNMENT_STRING_TABLE,
1008 HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
1009 horizontalAlignment );
1012 if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_VERTICAL_ALIGNMENT ) != Property::NONE )
1014 std::string value = child.GetProperty( Toolkit::TableView::ChildProperty::CELL_VERTICAL_ALIGNMENT ).Get<std::string >();
1015 Scripting::GetEnumeration< VerticalAlignment::Type >( value.c_str(),
1016 VERTICAL_ALIGNMENT_STRING_TABLE,
1017 VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
1018 verticalAlignment );
1021 Toolkit::TableView::CellPosition cellPosition;
1022 if( child.GetPropertyType( Toolkit::TableView::ChildProperty::ROW_SPAN ) != Property::NONE )
1024 cellPosition.rowSpan = child.GetProperty( Toolkit::TableView::ChildProperty::ROW_SPAN ).Get< int >();
1027 if( child.GetPropertyType( Toolkit::TableView::ChildProperty::COLUMN_SPAN ) != Property::NONE )
1029 cellPosition.columnSpan = child.GetProperty( Toolkit::TableView::ChildProperty::COLUMN_SPAN ).Get< int >();
1032 if( child.GetPropertyType( Toolkit::TableView::ChildProperty::CELL_INDEX ) != Property::NONE )
1034 Vector2 indices = child.GetProperty( Toolkit::TableView::ChildProperty::CELL_INDEX ).Get<Vector2 >();
1035 cellPosition.rowIndex = static_cast<unsigned int>( indices.x );
1036 cellPosition.columnIndex = static_cast<unsigned int>( indices.y );
1038 AddChild( child, cellPosition );
1039 SetCellAlignment(cellPosition, horizontalAlignment, verticalAlignment);
1043 bool availableCellFound = false;
1045 // Find the first available cell to store the actor in
1046 const unsigned int rowCount = mCellData.GetRows();
1047 const unsigned int columnCount = mCellData.GetColumns();
1048 for( unsigned int row = 0; row < rowCount && !availableCellFound; ++row )
1050 for( unsigned int column = 0; column < columnCount && !availableCellFound; ++column )
1052 if( !(mCellData[ row ][ column ].actor) )
1054 // Put the actor in the cell
1057 data.position.columnIndex = column;
1058 data.position.rowIndex = row;
1059 data.horizontalAlignment = horizontalAlignment;
1060 data.verticalAlignment = verticalAlignment;
1061 mCellData[ row ][ column ] = data;
1063 availableCellFound = true;
1069 if( ! availableCellFound )
1071 // No empty cells, so increase size of the table
1072 unsigned int newColumnCount = ( columnCount > 0 ) ? columnCount : 1;
1073 ResizeContainers( rowCount + 1, newColumnCount );
1075 // Put the actor in the first cell of the new row
1078 data.position.rowIndex = rowCount;
1079 data.position.columnIndex = 0;
1080 data.horizontalAlignment = horizontalAlignment;
1081 data.verticalAlignment = verticalAlignment;
1082 mCellData[ rowCount ][ 0 ] = data;
1089 Control::OnChildAdd( child );
1092 void TableView::OnChildRemove( Actor& child )
1094 // dont process if we're in the middle of bigger operation like delete row, column or resize
1095 if( !mLayoutingChild )
1097 // relayout the table only if instances were found
1098 if( RemoveAllInstances( child ) )
1104 Control::OnChildRemove( child );
1107 TableView::TableView( unsigned int initialRows, unsigned int initialColumns )
1108 : Control( ControlBehaviour( CONTROL_BEHAVIOUR_DEFAULT ) ),
1109 mCellData( initialRows, initialColumns ),
1110 mPreviousFocusedActor(),
1111 mLayoutingChild( false ),
1112 mRowDirty( true ), // Force recalculation first time
1113 mColumnDirty( true )
1115 SetKeyboardNavigationSupport( true );
1116 ResizeContainers( initialRows, initialColumns );
1119 void TableView::OnInitialize()
1121 // Make self as keyboard focusable and focus group
1122 Actor self = Self();
1123 self.SetProperty( Actor::Property::KEYBOARD_FOCUSABLE,true);
1124 SetAsKeyboardFocusGroup(true);
1126 DevelControl::SetAccessibilityConstructor( self, []( Dali::Actor actor ) {
1127 return std::unique_ptr< Dali::Accessibility::Accessible >(
1128 new Control::Impl::AccessibleImpl( actor, Dali::Accessibility::Role::TABLE ) );
1132 void TableView::ResizeContainers( unsigned int rows, unsigned int columns )
1134 std::vector<CellData> ignored;
1135 ResizeContainers( rows, columns, ignored );
1138 void TableView::ResizeContainers( unsigned int rows, unsigned int columns, std::vector<CellData>& removed )
1141 mCellData.Resize( rows, columns, removed );
1143 // We don't care if these go smaller, data will be regenerated or is not needed anymore
1144 mRowData.Resize( rows );
1145 mColumnData.Resize( columns );
1148 void TableView::RemoveAndGetLostActors( const std::vector<CellData>& lost, std::vector<Actor>& removed,
1149 unsigned int rowsRemoved, unsigned int columnsRemoved )
1151 // iterate through all lost cells
1152 std::vector< CellData >::const_iterator iter = lost.begin();
1153 for( ; iter != lost.end(); ++iter )
1155 // if it is a valid actor
1158 // is this actor still somewhere else in the table
1159 Toolkit::TableView::CellPosition position;
1160 if( FindChildPosition( (*iter).actor, position ) )
1162 // it must be spanning multiple cells, position contains the top left most one
1163 // check if position is left of the removed location
1164 if( position.columnIndex < (*iter).position.columnIndex )
1166 // if column span is greater than 1
1167 if( mCellData[ position.rowIndex ][ position.columnIndex ].position.columnSpan > 1 )
1169 // decrease column span
1170 mCellData[ position.rowIndex ][ position.columnIndex ].position.columnSpan -= columnsRemoved;
1173 // check if position is left of the removed location
1174 if( position.rowIndex < (*iter).position.rowIndex )
1176 // if row span is greater than 1
1177 if( mCellData[ position.rowIndex ][ position.columnIndex ].position.rowSpan > 1 )
1179 // decrease row span
1180 mCellData[ position.rowIndex ][ position.columnIndex ].position.rowSpan -= rowsRemoved;
1186 // this actor is gone for good
1187 // add actor to removed container
1188 removed.push_back( (*iter).actor );
1189 // we dont want the child actor anymore
1190 Self().Remove( (*iter).actor );
1196 bool TableView::RemoveAllInstances( const Actor& child )
1199 // walk through the layout data
1200 const unsigned int rowCount = mCellData.GetRows();
1201 const unsigned int columnCount = mCellData.GetColumns();
1202 for( unsigned int row = 0; row < rowCount; ++row )
1204 for( unsigned int column = 0; column < columnCount; ++column )
1206 if( mCellData[ row ][ column ].actor == child )
1208 // clear the cell, NOTE that the cell might be spanning multiple cells
1209 mCellData[ row ][ column ] = CellData();
1217 void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl,
1218 void(TableView::*funcFixed)(unsigned int, float),
1219 void(TableView::*funcRelative)(unsigned int, float),
1220 void(TableView::*funcFit)(unsigned int),
1221 const Property::Value& value )
1223 const Property::Map* map = value.GetMap();
1226 unsigned int index(0);
1227 for ( unsigned int i = 0, count = map->Count(); i < count; ++i )
1229 Property::Value& item = map->GetValue(i);
1230 Property::Map* childMap = item.GetMap();
1232 std::istringstream( map->GetKey(i) ) >> index;
1235 Property::Value* policy = childMap->Find( "policy" );
1236 Property::Value* childMapValue = childMap->Find( "value" );
1237 if( policy && childMapValue )
1239 std::string policyValue;
1240 policy->Get( policyValue );
1241 Toolkit::TableView::LayoutPolicy policy;
1242 if( Scripting::GetEnumeration< Toolkit::TableView::LayoutPolicy >( policyValue.c_str(),
1243 LAYOUT_POLICY_STRING_TABLE,
1244 LAYOUT_POLICY_STRING_TABLE_COUNT,
1247 if( policy == Toolkit::TableView::FIXED )
1249 (tableViewImpl.*funcFixed)( index, childMapValue->Get<float>() );
1251 else if( policy == Toolkit::TableView::RELATIVE )
1253 (tableViewImpl.*funcRelative)( index, childMapValue->Get<float>() );
1255 else if( policy == Toolkit::TableView::FIT )
1257 (tableViewImpl.*funcFit)( index );
1259 // do nothing for FILL policy
1267 Property::Value TableView::GetRowHeightsPropertyValue()
1270 GetMapPropertyValue( mRowData, map);
1271 return Property::Value(map);
1274 Property::Value TableView::GetColumnWidthsPropertyValue()
1277 GetMapPropertyValue( mColumnData, map);
1278 return Property::Value(map);
1281 void TableView::GetMapPropertyValue( const RowColumnArray& data, Property::Map& map )
1283 const char* fixedPolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIXED,
1284 LAYOUT_POLICY_STRING_TABLE,
1285 LAYOUT_POLICY_STRING_TABLE_COUNT );
1286 const char* relativePolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::RELATIVE,
1287 LAYOUT_POLICY_STRING_TABLE,
1288 LAYOUT_POLICY_STRING_TABLE_COUNT );
1289 const char* fillPolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FILL,
1290 LAYOUT_POLICY_STRING_TABLE,
1291 LAYOUT_POLICY_STRING_TABLE_COUNT );
1292 const char* fitPolicy = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIT,
1293 LAYOUT_POLICY_STRING_TABLE,
1294 LAYOUT_POLICY_STRING_TABLE_COUNT );
1296 const RowColumnArray::SizeType count = data.Size();
1297 for( RowColumnArray::SizeType i = 0; i < count; i++ )
1299 const RowColumnData& dataInstance = data[ i ];
1302 switch( dataInstance.sizePolicy )
1304 case Toolkit::TableView::FIXED:
1306 item[ "policy" ] = fixedPolicy;
1307 item[ "value" ] = dataInstance.size;
1310 case Toolkit::TableView::RELATIVE:
1312 item[ "policy" ] = relativePolicy;
1313 item[ "value" ] = dataInstance.fillRatio;
1316 case Toolkit::TableView::FIT:
1318 item[ "policy" ] = fitPolicy;
1319 item[ "value" ] = 0.f;
1322 case Toolkit::TableView::FILL:
1325 item[ "policy" ] = fillPolicy;
1326 item[ "value" ] = 0.f;
1330 std::ostringstream ss;
1332 map[ ss.str() ] = item;
1336 TableView::~TableView()
1341 Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
1343 Actor nextFocusableActor;
1345 if ( !currentFocusedActor )
1347 // Nothing is currently focused, so the child in the first cell should be focused.
1348 nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
1352 Toolkit::TableView::CellPosition position;
1353 if( FindChildPosition( currentFocusedActor, position ) )
1355 // The current focused actor is a child of TableView
1356 bool focusLost = false;
1357 int currentRow = position.rowIndex;
1358 int currentColumn = position.columnIndex;
1359 int numberOfColumns = GetColumns();
1360 int numberOfRows = GetRows();
1362 bool lastCell = false;
1363 Actor nextValidActor;
1365 switch ( direction )
1367 case Toolkit::Control::KeyboardFocus::LEFT:
1371 if(--currentColumn < 0)
1373 currentColumn = numberOfColumns - 1;
1374 if(--currentRow < 0)
1377 currentRow = loopEnabled ? numberOfRows - 1 : 0;
1378 focusLost = (currentRow == 0);
1381 nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
1382 } while ( !nextValidActor && !lastCell );
1385 case Toolkit::Control::KeyboardFocus::RIGHT:
1389 if(++currentColumn > numberOfColumns - 1)
1392 if(++currentRow > numberOfRows - 1)
1395 currentRow = loopEnabled ? 0 : numberOfRows - 1;
1396 focusLost = (currentRow == numberOfRows - 1);
1399 nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
1400 } while ( !nextValidActor && !lastCell );
1403 case Toolkit::Control::KeyboardFocus::UP:
1407 if(--currentRow < 0)
1410 currentRow = loopEnabled ? numberOfRows - 1 : 0;
1411 focusLost = (currentRow == 0);
1413 nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
1414 } while ( !nextValidActor && !lastCell );
1417 case Toolkit::Control::KeyboardFocus::DOWN:
1422 if(++currentRow > numberOfRows - 1)
1425 currentRow = loopEnabled ? 0 : numberOfRows - 1;
1426 focusLost = (currentRow == numberOfRows - 1);
1428 nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
1429 } while ( !nextValidActor && !lastCell );
1438 // Move the focus if we haven't lost it.
1441 nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
1443 // Save the focused actor in the TableView.
1444 mPreviousFocusedActor = nextFocusableActor;
1449 // The current focused actor is not within this TableView.
1451 unsigned int numberOfColumns = GetColumns();
1452 unsigned int numberOfRows = GetRows();
1454 // Check whether the previous focused actor is a focus group (i.e. a layout container)
1455 bool wasFocusedOnLayoutContainer = false;
1456 Actor previousFocusedActor = mPreviousFocusedActor.GetHandle();
1457 if( previousFocusedActor )
1459 Toolkit::Control control = Toolkit::Control::DownCast( previousFocusedActor );
1462 Internal::Control& controlImpl = static_cast<Internal::Control&>(control.GetImplementation());
1463 wasFocusedOnLayoutContainer = controlImpl.IsKeyboardFocusGroup();
1467 // Check whether the previous focused actor is a layout container and also a child of this TableView
1468 Toolkit::TableView::CellPosition position;
1469 if( wasFocusedOnLayoutContainer && FindChildPosition( previousFocusedActor, position ) )
1471 nextFocusableActor = GetNextKeyboardFocusableActor(previousFocusedActor, direction, loopEnabled);
1475 // Otherwise, move the focus to either the first or the last cell according to the given direction.
1476 if(direction == Toolkit::Control::KeyboardFocus::LEFT || direction == Toolkit::Control::KeyboardFocus::UP)
1478 nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(numberOfRows - 1, numberOfColumns - 1));
1482 nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
1488 return nextFocusableActor;
1491 Vector3 TableView::GetNaturalSize()
1493 // Natural size is the size of all fixed cell widths or heights. This ignores cells with relative heights.
1494 return Vector3( mFixedTotals.width, mFixedTotals.height, 1.0f );
1497 float TableView::CalculateChildSize( const Actor& child, Dimension::Type dimension )
1499 Toolkit::TableView::CellPosition position;
1500 if( FindChildPosition( child, position) )
1504 case Dimension::WIDTH:
1506 float cellSize = 0.0f;
1507 cellSize = mColumnData[position.columnIndex+position.columnSpan-1].position
1508 - (position.columnIndex > 0 ? mColumnData[position.columnIndex-1].position : 0.f)
1509 - mPadding.width * 2.0f;
1511 if( cellSize < 0.0f )
1519 case Dimension::HEIGHT:
1521 float cellSize = 0.0f;
1523 cellSize = mRowData[position.rowIndex+position.rowSpan-1].position
1524 - (position.rowIndex > 0 ? mRowData[position.rowIndex-1].position : 0.f)
1525 - mPadding.height * 2.0f;
1527 if( cellSize < 0.0f )
1541 return 0.0f; // Child not found
1544 bool TableView::RelayoutDependentOnChildren( Dimension::Type dimension )
1546 if ( Control::RelayoutDependentOnChildren( dimension ) )
1551 return FindFit( mRowData ) || FindFit( mColumnData );
1554 void TableView::SetCellAlignment( Toolkit::TableView::CellPosition position, HorizontalAlignment::Type horizontal, VerticalAlignment::Type vertical )
1556 // Check if we need to expand our data array
1557 if( position.rowIndex >= mCellData.GetRows() )
1559 // Only adding new rows
1560 ResizeContainers( position.rowIndex + 1, mCellData.GetColumns() );
1563 if( position.columnIndex >= mCellData.GetColumns() )
1565 // Only adding new columns
1566 ResizeContainers( mCellData.GetRows(), position.columnIndex + 1 );
1569 // Set the alignment of the cell
1570 CellData& data = mCellData[ position.rowIndex ][ position.columnIndex ];
1571 data.horizontalAlignment = horizontal;
1572 data.verticalAlignment = vertical;
1575 void TableView::CalculateFillSizes( RowColumnArray& data )
1577 // First pass: Count number of fill entries and calculate used relative space
1578 Dali::Vector< RowColumnData* > fillData;
1579 float relativeTotal = 0.0f;
1581 const unsigned int dataCount = data.Size();
1583 for( unsigned int i = 0; i < dataCount; ++i )
1585 RowColumnData& dataInstance = data[ i ];
1587 if( dataInstance.sizePolicy == Toolkit::TableView::RELATIVE )
1589 relativeTotal += dataInstance.fillRatio;
1591 else if(dataInstance.sizePolicy == Toolkit::TableView::FILL)
1593 fillData.PushBack( &dataInstance );
1597 // Second pass: Distribute remaining relative space
1598 const unsigned int fillCount = fillData.Size();
1601 if( relativeTotal > 1.0f )
1603 relativeTotal = 1.0f;
1606 const float evenFillRatio = (1.0f - relativeTotal ) / fillCount;
1608 for( unsigned int i = 0; i < fillCount; ++i )
1610 fillData[ i ]->fillRatio = evenFillRatio;
1615 float TableView::CalculateTotalFixedSize( const RowColumnArray& data )
1617 float totalSize = 0.0f;
1619 const unsigned int dataCount = data.Size();
1621 for( unsigned int i = 0; i < dataCount; ++i )
1623 const RowColumnData& dataInstance = data[ i ];
1625 switch( dataInstance.sizePolicy )
1627 // we have absolute size to FIXED and FIT column/row and relative size for RELATIVE and FILL column/row
1628 case Toolkit::TableView::FIXED:
1629 case Toolkit::TableView::FIT:
1631 totalSize += dataInstance.size;
1645 Vector2 TableView::GetCellPadding( Dimension::Type dimension )
1649 case Dimension::WIDTH:
1651 return Vector2( mPadding.x, mPadding.x );
1653 case Dimension::HEIGHT:
1655 return Vector2( mPadding.y, mPadding.y );
1666 void TableView::CalculateFitSizes( RowColumnArray& data, Dimension::Type dimension )
1668 Vector2 cellPadding = GetCellPadding( dimension );
1670 const unsigned int dataCount = data.Size();
1672 for( unsigned int i = 0; i < dataCount; ++i )
1674 RowColumnData& dataInstance = data[ i ];
1676 if( dataInstance.sizePolicy == Toolkit::TableView::FIT )
1678 // Find the size of the biggest actor in the row or column
1679 float maxActorHeight = 0.0f;
1681 unsigned int fitCount = ( dimension == Dimension::WIDTH ) ? mCellData.GetRows() : mCellData.GetColumns();
1683 for( unsigned int j = 0; j < fitCount; ++j )
1685 unsigned int row = ( dimension == Dimension::WIDTH ) ? j : i;
1686 unsigned int column = ( dimension == Dimension::WIDTH ) ? i : j;
1687 DALI_ASSERT_DEBUG( row < mCellData.GetRows() );
1688 DALI_ASSERT_DEBUG( column < mCellData.GetColumns() );
1690 const CellData& cellData = mCellData[ row ][ column ];
1691 const Actor& actor = cellData.actor;
1694 if( FitToChild( actor, dimension ) && ( dimension == Dimension::WIDTH ) ? ( cellData.position.columnSpan == 1 ) : ( cellData.position.rowSpan == 1 ) )
1696 maxActorHeight = std::max( maxActorHeight, actor.GetRelayoutSize( dimension ) + cellPadding.x + cellPadding.y );
1701 dataInstance.size = maxActorHeight;
1706 bool TableView::FindFit( const RowColumnArray& data )
1708 for( unsigned int i = 0, count = data.Size(); i < count; ++i )
1710 if( data[ i ].sizePolicy == Toolkit::TableView::FIT )
1719 } // namespace Internal
1721 } // namespace Toolkit