2 * Copyright (c) 2021 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>
22 #include <dali/devel-api/actors/actor-devel.h>
23 #include <dali/devel-api/scripting/scripting.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/public-api/object/ref-object.h>
26 #include <dali/public-api/object/type-registry-helper.h>
27 #include <dali/public-api/object/type-registry.h>
28 #include <dali/public-api/size-negotiation/relayout-container.h>
32 #include <dali-toolkit/devel-api/controls/control-devel.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::LogMessageWithFunctionLine(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(), data.position.rowIndex, data.position.columnIndex, data.position.rowSpan, data.position.columnSpan);
80 // debugging support, very useful when new features are added or bugs are hunted down
81 // currently not called from code so compiler will optimize these away, kept here for future debugging
82 void PrintArray(Array2d<Size>& array)
84 TV_LOG("Array2d<Size> size [%d,%d] \n", array.GetRows(), array.GetColumns());
86 for(unsigned int i = 0; i < array.GetRows(); ++i)
88 for(unsigned int j = 0; j < array.GetColumns(); ++j)
90 TV_LOG("Array[%d,%d]=%.2f,%.2f ", i, j, array[i][j].width, array[i][j].height);
95 // debugging support, very useful when new features are added or bugs are hunted down
96 // currently not called from code so compiler will optimize these away, kept here for future debugging
97 void PrintVector(std::vector<float>& array)
99 TV_LOG("vector, size [%d]\n", array.size());
101 for(unsigned int i = 0; i < array.size(); ++i)
103 TV_LOG("vector[%d]=%.2f ", i, array[i]);
107 #endif // defined(TABLEVIEW_DEBUG)
108 #endif // defined(DEBUG_ENABLED)
123 return Toolkit::TableView::New(0, 0);
127 // Setup properties, signals and actions using the type-registry.
128 DALI_TYPE_REGISTRATION_BEGIN(Toolkit::TableView, Toolkit::Control, Create);
130 DALI_PROPERTY_REGISTRATION(Toolkit, TableView, "rows", INTEGER, ROWS )
131 DALI_PROPERTY_REGISTRATION(Toolkit, TableView, "columns", INTEGER, COLUMNS )
132 DALI_PROPERTY_REGISTRATION(Toolkit, TableView, "cellPadding", VECTOR2, CELL_PADDING )
133 DALI_PROPERTY_REGISTRATION(Toolkit, TableView, "layoutRows", MAP, LAYOUT_ROWS )
134 DALI_PROPERTY_REGISTRATION(Toolkit, TableView, "layoutColumns", MAP, LAYOUT_COLUMNS)
136 DALI_CHILD_PROPERTY_REGISTRATION(Toolkit, TableView, "cellIndex", VECTOR2, CELL_INDEX )
137 DALI_CHILD_PROPERTY_REGISTRATION(Toolkit, TableView, "rowSpan", INTEGER, ROW_SPAN )
138 DALI_CHILD_PROPERTY_REGISTRATION(Toolkit, TableView, "columnSpan", INTEGER, COLUMN_SPAN )
139 DALI_CHILD_PROPERTY_REGISTRATION(Toolkit, TableView, "cellHorizontalAlignment", STRING, CELL_HORIZONTAL_ALIGNMENT)
140 DALI_CHILD_PROPERTY_REGISTRATION(Toolkit, TableView, "cellVerticalAlignment", STRING, CELL_VERTICAL_ALIGNMENT )
142 DALI_TYPE_REGISTRATION_END()
144 const Scripting::StringEnum LAYOUT_POLICY_STRING_TABLE[] =
146 {"fixed", Toolkit::TableView::FIXED },
147 {"relative", Toolkit::TableView::RELATIVE},
148 {"fill", Toolkit::TableView::FILL },
149 {"fit", Toolkit::TableView::FIT }
151 const unsigned int LAYOUT_POLICY_STRING_TABLE_COUNT = sizeof(LAYOUT_POLICY_STRING_TABLE) / sizeof(LAYOUT_POLICY_STRING_TABLE[0]);
153 const Scripting::StringEnum HORIZONTAL_ALIGNMENT_STRING_TABLE[] =
155 {"left", HorizontalAlignment::LEFT },
156 {"center", HorizontalAlignment::CENTER},
157 {"right", HorizontalAlignment::RIGHT }
159 const unsigned int HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(HORIZONTAL_ALIGNMENT_STRING_TABLE) / sizeof(HORIZONTAL_ALIGNMENT_STRING_TABLE[0]);
161 const Scripting::StringEnum VERTICAL_ALIGNMENT_STRING_TABLE[] =
163 {"top", VerticalAlignment::TOP },
164 {"center", VerticalAlignment::CENTER},
165 {"bottom", VerticalAlignment::BOTTOM}
167 const unsigned int VERTICAL_ALIGNMENT_STRING_TABLE_COUNT = sizeof(VERTICAL_ALIGNMENT_STRING_TABLE) / sizeof(VERTICAL_ALIGNMENT_STRING_TABLE[0]);
169 } // Unnamed namespace
171 Toolkit::TableView TableView::New(unsigned int initialRows, unsigned int initialColumns)
173 // Create the implementation, temporarily owned by this handle on stack
174 IntrusivePtr<TableView> impl = new TableView(initialRows, initialColumns);
176 // Pass ownership to CustomActor handle
177 Toolkit::TableView handle(*impl);
179 // Second-phase init of the implementation
180 // This can only be done after the CustomActor connection has been made...
186 bool TableView::AddChild(Actor& child, const Toolkit::TableView::CellPosition& position)
188 // check that the child is valid
189 DALI_ASSERT_ALWAYS(child);
191 // if child is already parented, we adopt it
194 // check if we need to expand our data array
195 if(position.rowIndex >= mCellData.GetRows())
197 // only adding new rows
198 ResizeContainers(position.rowIndex + 1, mCellData.GetColumns());
201 if(position.columnIndex >= mCellData.GetColumns())
203 // only adding new columns
204 ResizeContainers(mCellData.GetRows(), position.columnIndex + 1);
207 // check if there already is something in this cell
208 if(mCellData[position.rowIndex][position.columnIndex].actor)
210 return false; // cannot share a cell, it would complicate all logic and not bring much benefit
213 RelayoutingLock lock(*this);
217 // if child spans multiple rows of columns
218 if((position.rowSpan > 1) && (position.rowIndex + position.rowSpan > mCellData.GetRows()))
220 // increase table size for the full span, only increasing rows
221 ResizeContainers(position.rowIndex + position.rowSpan, mCellData.GetColumns());
224 if((position.columnSpan > 1) && (position.columnIndex + position.columnSpan > mCellData.GetColumns()))
226 // increase table size for the full span, only increasing columns
227 ResizeContainers(mCellData.GetRows(), position.columnIndex + position.columnSpan);
230 // Fill in all cells that need the data
233 data.position = position;
235 for(unsigned int row = position.rowIndex; row < (position.rowIndex + position.rowSpan); ++row)
237 // store same information to all cells, this way we can identify
238 // if a cell is the prime location of an actor or a spanned one
239 for(unsigned int column = position.columnIndex; column < (position.columnIndex + position.columnSpan); ++column)
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 mCellData[row][column] = data;
247 // Relayout the whole table
248 if(mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT && position.rowSpan == 1)
252 if(mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT && position.columnSpan == 1)
259 return true; // Addition successful
262 Actor TableView::GetChildAt(const Toolkit::TableView::CellPosition& position)
264 if((position.rowIndex < mCellData.GetRows()) && (position.columnIndex < mCellData.GetColumns()))
266 return mCellData[position.rowIndex][position.columnIndex].actor;
269 // Return an empty handle
273 Actor TableView::RemoveChildAt(const Toolkit::TableView::CellPosition& position)
275 // get the child handle
276 Actor child = GetChildAt(position);
277 // if no real actor there, nothing else to be done
280 RelayoutingLock lock(*this);
281 // Remove the child, this will trigger a call to OnChildRemove
282 Self().Remove(child);
284 // relayout the table only if instances were found
285 if(RemoveAllInstances(child))
287 if(mRowData[position.rowIndex].sizePolicy == Toolkit::TableView::FIT)
291 if(mColumnData[position.columnIndex].sizePolicy == Toolkit::TableView::FIT)
298 // return the child back to caller
302 bool TableView::FindChildPosition(const Actor& child, Toolkit::TableView::CellPosition& positionOut)
304 // Only find valid child actors
307 // Walk through the layout data
308 const unsigned int rowCount = mCellData.GetRows();
309 const unsigned int columnCount = mCellData.GetColumns();
311 for(unsigned int row = 0; row < rowCount; ++row)
313 for(unsigned int column = 0; column < columnCount; ++column)
315 if(mCellData[row][column].actor == child)
317 positionOut = mCellData[row][column].position;
327 void TableView::InsertRow(unsigned int rowIndex)
329 RelayoutingLock lock(*this);
331 mCellData.InsertRow(rowIndex);
333 // Need to update the cell infos for the items that moved
334 const unsigned int rowCount = mCellData.GetRows();
335 const unsigned int columnCount = mCellData.GetColumns();
337 for(unsigned int row = 0; row < rowCount; ++row)
339 for(unsigned int column = 0; column < columnCount; ++column)
341 Toolkit::TableView::CellPosition& position = mCellData[row][column].position;
343 // If cell is spanning and above and spans to inserted row
344 if((position.rowSpan > 1) && (position.rowIndex <= rowIndex) &&
345 (position.rowIndex + position.rowSpan > rowIndex))
350 // Copy cell to occupy the new column
351 mCellData[rowIndex][column] = mCellData[row][column];
353 else if(row > rowIndex) // If below of inserted row, increase row index
361 // Expand row data array
362 mRowData.Insert(mRowData.Begin() + rowIndex, RowColumnData());
364 // Sizes may have changed, so relayout
369 void TableView::DeleteRow(unsigned int rowIndex)
371 std::vector<Actor> ignored;
372 DeleteRow(rowIndex, ignored);
375 void TableView::DeleteRow(unsigned int rowIndex, std::vector<Actor>& removed)
377 RelayoutingLock lock(*this);
380 std::vector<CellData> lost;
381 mCellData.DeleteRow(rowIndex, lost);
383 // Need to update the cell infos for the items that moved
384 const unsigned int rowCount = mCellData.GetRows();
385 const unsigned int columnCount = mCellData.GetColumns();
387 for(unsigned int row = 0; row < rowCount; ++row)
389 for(unsigned int column = 0; column < columnCount; ++column)
391 Toolkit::TableView::CellPosition& position = mCellData[row][column].position;
393 // If cell is spanning and above and spans to deleted row
394 if((position.rowSpan > 1) && (position.rowIndex <= rowIndex) &&
395 (position.rowIndex + position.rowSpan > rowIndex))
398 if(position.rowSpan > 1)
403 else if(row >= rowIndex) // If below of or at the inserted row, decrease row index
406 if(position.rowIndex > 0)
414 // 1 row removed, 0 columns
415 RemoveAndGetLostActors(lost, removed, 1u, 0u);
417 // Contract row data array
418 mRowData.Erase(mRowData.Begin() + rowIndex);
420 // Sizes may have changed, so relayout
422 // it is possible that the deletion of row leads to remove of child which might further lead to the change of FIT column
428 void TableView::InsertColumn(unsigned int columnIndex)
430 RelayoutingLock lock(*this);
432 // Insert the new column
433 mCellData.InsertColumn(columnIndex);
435 // Need to update the cell infos for the items that moved
436 const unsigned int rowCount = mCellData.GetRows();
437 const unsigned int columnCount = mCellData.GetColumns();
439 for(unsigned int row = 0; row < rowCount; ++row)
441 for(unsigned int column = 0; column < columnCount; ++column)
443 Toolkit::TableView::CellPosition& position = mCellData[row][column].position;
445 // If cell is spanning and left side and spans to inserted column
446 if((position.columnSpan > 1) && (position.columnIndex <= columnIndex) &&
447 (position.columnIndex + position.columnSpan > columnIndex))
450 position.columnSpan++;
452 // Copy cell to occupy the new column
453 mCellData[row][columnIndex] = mCellData[row][column];
455 else if(column > columnIndex) // If on the right side of inserted column, increase column index
458 position.columnIndex++;
463 // Expand column data array
464 mColumnData.Insert(mColumnData.Begin() + columnIndex, RowColumnData());
466 // Sizes may have changed so relayout
471 void TableView::DeleteColumn(unsigned int columnIndex)
473 std::vector<Actor> ignored;
474 DeleteColumn(columnIndex, ignored);
477 void TableView::DeleteColumn(unsigned int columnIndex, std::vector<Actor>& removed)
479 RelayoutingLock lock(*this);
482 std::vector<CellData> lost;
483 mCellData.DeleteColumn(columnIndex, lost);
485 // Need to update the cell infos for the items that moved
486 const unsigned int rowCount = mCellData.GetRows();
487 const unsigned int columnCount = mCellData.GetColumns();
489 for(unsigned int row = 0; row < rowCount; ++row)
491 for(unsigned int column = 0; column < columnCount; ++column)
493 Toolkit::TableView::CellPosition& position = mCellData[row][column].position;
495 // If cell is spanning and left side and spans to inserted column
496 if((position.columnSpan > 1) && (position.columnIndex <= columnIndex) &&
497 (position.columnIndex + position.columnSpan > columnIndex))
500 if(position.columnSpan > 1)
502 position.columnSpan--;
505 else if(column >= columnIndex) // If on the right side of or at the inserted column, decrease column index
508 if(position.columnIndex > 0)
510 position.columnIndex--;
516 // 0 rows, 1 column removed
517 RemoveAndGetLostActors(lost, removed, 0u, 1u);
519 // Contract column data array
520 mColumnData.Erase(mColumnData.Begin() + columnIndex);
522 // Size may have changed so relayout
524 // it is possible that the deletion of column leads to remove of child which might further lead to the change of FIT row
530 void TableView::Resize(unsigned int rows, unsigned int columns)
532 std::vector<Actor> ignored;
533 Resize(rows, columns, ignored);
536 void TableView::Resize(unsigned int rows, unsigned int columns, std::vector<Actor>& removed)
538 RelayoutingLock lock(*this);
540 unsigned int oldRows = GetRows();
541 unsigned int oldColumns = GetColumns();
544 std::vector<CellData> lost;
545 ResizeContainers(rows, columns, lost);
547 // Calculate if we lost rows
548 unsigned int rowsRemoved = 0;
549 unsigned int newRows = GetRows();
551 if(oldRows < newRows)
553 rowsRemoved = newRows - oldRows;
556 // Calculate if we lost columns
557 unsigned int columnsRemoved = 0;
558 unsigned int newColumns = GetColumns();
559 if(oldColumns < newColumns)
561 rowsRemoved = newColumns - oldColumns;
564 RemoveAndGetLostActors(lost, removed, rowsRemoved, columnsRemoved);
566 // Sizes may have changed so request a relayout
572 void TableView::SetCellPadding(Size padding)
574 // If padding really changed
575 if(padding != mPadding)
583 Size TableView::GetCellPadding()
588 void TableView::SetFitHeight(unsigned int rowIndex)
590 DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size());
592 if(mRowData[rowIndex].sizePolicy != Toolkit::TableView::FIT)
594 mRowData[rowIndex].sizePolicy = Toolkit::TableView::FIT;
601 bool TableView::IsFitHeight(unsigned int rowIndex) const
603 DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size());
605 return mRowData[rowIndex].sizePolicy == Toolkit::TableView::FIT;
608 void TableView::SetFitWidth(unsigned int columnIndex)
610 DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size());
612 if(mColumnData[columnIndex].sizePolicy != Toolkit::TableView::FIT)
614 mColumnData[columnIndex].sizePolicy = Toolkit::TableView::FIT;
621 bool TableView::IsFitWidth(unsigned int columnIndex) const
623 DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size());
625 return mColumnData[columnIndex].sizePolicy == Toolkit::TableView::FIT;
628 void TableView::SetFixedHeight(unsigned int rowIndex, float height)
630 DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size());
632 RowColumnData& data = mRowData[rowIndex];
634 data.sizePolicy = Toolkit::TableView::FIXED;
640 float TableView::GetFixedHeight(unsigned int rowIndex) const
642 DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size());
644 return mRowData[rowIndex].size;
647 void TableView::SetFixedWidth(unsigned int columnIndex, float width)
649 DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size());
651 RowColumnData& data = mColumnData[columnIndex];
653 data.sizePolicy = Toolkit::TableView::FIXED;
659 float TableView::GetFixedWidth(unsigned int columnIndex) const
661 DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size());
663 return mColumnData[columnIndex].size;
666 void TableView::SetRelativeHeight(unsigned int rowIndex, float heightPercentage)
668 DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size());
670 RowColumnData& data = mRowData[rowIndex];
671 data.fillRatio = heightPercentage;
672 data.sizePolicy = Toolkit::TableView::RELATIVE;
678 float TableView::GetRelativeHeight(unsigned int rowIndex) const
680 DALI_ASSERT_ALWAYS(rowIndex < mRowData.Size());
682 return mRowData[rowIndex].fillRatio;
685 void TableView::SetRelativeWidth(unsigned int columnIndex, float widthPercentage)
687 DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size());
689 RowColumnData& data = mColumnData[columnIndex];
690 data.fillRatio = widthPercentage;
691 data.sizePolicy = Toolkit::TableView::RELATIVE;
697 float TableView::GetRelativeWidth(unsigned int columnIndex) const
699 DALI_ASSERT_ALWAYS(columnIndex < mColumnData.Size());
701 return mColumnData[columnIndex].fillRatio;
704 void TableView::OnCalculateRelayoutSize(Dimension::Type dimension)
706 if((dimension & Dimension::WIDTH) && mColumnDirty)
709 * FIXED and FIT have size in pixel
710 * Nothing to do with FIXED, as its value is assigned by user and will not get changed
712 * Need to update the size for FIT column here
714 CalculateFitSizes(mColumnData, Dimension::WIDTH);
716 /* RELATIVE and FILL have size in ratio
717 * Their size in pixel is not available until we get the negotiated size for the whole table
718 * Nothing to do with RELATIVE, as its ratio is assigned by user and will not get changed
720 * Need to update the ratio for FILL column here
722 CalculateFillSizes(mColumnData);
724 mFixedTotals.width = CalculateTotalFixedSize(mColumnData);
727 if((dimension & Dimension::HEIGHT) && mRowDirty)
729 // refer to the comment above
730 CalculateFitSizes(mRowData, Dimension::HEIGHT);
732 // refer to the comment above
733 CalculateFillSizes(mRowData);
735 mFixedTotals.height = CalculateTotalFixedSize(mRowData);
739 void TableView::OnLayoutNegotiated(float size, Dimension::Type dimension)
741 // Update the column sizes
742 if((dimension & Dimension::WIDTH) && mColumnDirty)
744 float remainingSize = size - mFixedTotals.width;
745 if(remainingSize < 0.0f)
747 remainingSize = 0.0f;
750 // update every column position in ColumnData array
751 float cumulatedWidth = 0.0f;
752 for(auto&& element : mColumnData)
754 if(element.sizePolicy == Toolkit::TableView::FILL || element.sizePolicy == Toolkit::TableView::RELATIVE)
756 element.size = element.fillRatio * remainingSize;
759 cumulatedWidth += element.size;
760 element.position = cumulatedWidth;
763 mColumnDirty = false;
766 // Update the row sizes
767 if((dimension & Dimension::HEIGHT) && mRowDirty)
769 float remainingSize = size - mFixedTotals.height;
770 if(remainingSize < 0.0f)
772 remainingSize = 0.0f;
775 // update every row position in RowData array
776 float cumulatedHeight = 0.0f;
777 for(unsigned int row = 0, rowCount = mCellData.GetRows(); row < rowCount; ++row)
779 if(mRowData[row].sizePolicy == Toolkit::TableView::FILL || mRowData[row].sizePolicy == Toolkit::TableView::RELATIVE)
781 mRowData[row].size = mRowData[row].fillRatio * remainingSize;
784 cumulatedHeight += mRowData[row].size;
785 mRowData[row].position = cumulatedHeight;
792 void TableView::OnSizeSet(const Vector3& size)
794 // If this table view is size negotiated by another actor or control, then the
795 // rows and columns must be recalculated or the new size will not take effect.
796 mRowDirty = mColumnDirty = true;
799 Control::OnSizeSet(size);
802 void TableView::OnRelayout(const Vector2& size, RelayoutContainer& container)
804 // Go through the layout data
805 float totalWidth = 0.0;
807 Dali::LayoutDirection::Type layoutDirection = static_cast<Dali::LayoutDirection::Type>(Self().GetProperty(Dali::Actor::Property::LAYOUT_DIRECTION).Get<int>());
809 if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
811 for(auto&& element : mColumnData)
813 totalWidth += element.size;
817 for(unsigned int row = 0, rowCount = mCellData.GetRows(); row < rowCount; ++row)
819 for(unsigned int column = 0, columnCount = mCellData.GetColumns(); column < columnCount; ++column)
821 CellData& cellData = mCellData[row][column];
822 Actor& actor = cellData.actor;
823 const Toolkit::TableView::CellPosition position = cellData.position;
825 // If there is an actor and this is the main cell of the actor.
826 // An actor can be in multiple cells if its row or column span is more than 1.
827 // We however must lay out each actor only once.
828 if(actor && position.rowIndex == row && position.columnIndex == column)
830 // Anchor actor to top left of the cell
831 if(actor.GetProperty(Actor::Property::POSITION_USES_ANCHOR_POINT).Get<bool>())
833 actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
835 actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
837 Padding padding = actor.GetProperty<Vector4>(Actor::Property::PADDING);
839 float left = (column > 0) ? mColumnData[column - 1].position : 0.f;
842 if(Dali::LayoutDirection::RIGHT_TO_LEFT == layoutDirection)
844 right = totalWidth - left;
845 left = right - mColumnData[column].size;
849 right = left + mColumnData[column].size;
852 float top = row > 0 ? mRowData[row - 1].position : 0.f;
853 float bottom = mRowData[row + position.rowSpan - 1].position;
855 if(cellData.horizontalAlignment == HorizontalAlignment::LEFT)
857 actor.SetProperty(Actor::Property::POSITION_X, left + mPadding.width + padding.left);
859 else if(cellData.horizontalAlignment == HorizontalAlignment::RIGHT)
861 actor.SetProperty(Actor::Property::POSITION_X, right - mPadding.width - padding.right - actor.GetRelayoutSize(Dimension::WIDTH));
863 else //if( cellData.horizontalAlignment == HorizontalAlignment::CENTER )
865 actor.SetProperty(Actor::Property::POSITION_X, (left + right + padding.left - padding.right - actor.GetRelayoutSize(Dimension::WIDTH)) * 0.5f);
868 if(cellData.verticalAlignment == VerticalAlignment::TOP)
870 actor.SetProperty(Actor::Property::POSITION_Y, top + mPadding.height + padding.top);
872 else if(cellData.verticalAlignment == VerticalAlignment::BOTTOM)
874 actor.SetProperty(Actor::Property::POSITION_Y, bottom - mPadding.height - padding.bottom - actor.GetRelayoutSize(Dimension::HEIGHT));
876 else //if( cellData.verticalAlignment = VerticalAlignment::CENTER )
878 actor.SetProperty(Actor::Property::POSITION_Y, (top + bottom + padding.top - padding.bottom - actor.GetRelayoutSize(Dimension::HEIGHT)) * 0.5f);
885 unsigned int TableView::GetRows()
887 return mCellData.GetRows();
890 unsigned int TableView::GetColumns()
892 return mCellData.GetColumns();
895 void TableView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
897 Toolkit::TableView tableView = Toolkit::TableView::DownCast(Dali::BaseHandle(object));
901 TableView& tableViewImpl(GetImpl(tableView));
904 case Toolkit::TableView::Property::ROWS:
907 if(value.Get(rows) && rows >= 0)
909 if(static_cast<unsigned int>(rows) != tableViewImpl.GetRows())
911 tableViewImpl.Resize(rows, tableViewImpl.GetColumns());
916 case Toolkit::TableView::Property::COLUMNS:
919 if(value.Get(columns) && columns >= 0)
921 if(static_cast<unsigned int>(columns) != tableViewImpl.GetColumns())
923 tableViewImpl.Resize(tableViewImpl.GetRows(), value.Get<int>());
928 case Toolkit::TableView::Property::CELL_PADDING:
930 tableViewImpl.SetCellPadding(value.Get<Vector2>());
933 case Toolkit::TableView::Property::LAYOUT_ROWS:
935 SetHeightOrWidthProperty(tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, &TableView::SetFitHeight, value);
938 case Toolkit::TableView::Property::LAYOUT_COLUMNS:
940 SetHeightOrWidthProperty(tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, &TableView::SetFitWidth, value);
947 Property::Value TableView::GetProperty(BaseObject* object, Property::Index index)
949 Property::Value value;
951 Toolkit::TableView tableView = Toolkit::TableView::DownCast(Dali::BaseHandle(object));
955 TableView& tableViewImpl(GetImpl(tableView));
958 case Toolkit::TableView::Property::ROWS:
960 value = static_cast<int>(tableViewImpl.GetRows());
963 case Toolkit::TableView::Property::COLUMNS:
965 value = static_cast<int>(tableViewImpl.GetColumns());
968 case Toolkit::TableView::Property::CELL_PADDING:
970 value = tableViewImpl.GetCellPadding();
973 case Toolkit::TableView::Property::LAYOUT_ROWS:
975 value = tableViewImpl.GetRowHeightsPropertyValue();
978 case Toolkit::TableView::Property::LAYOUT_COLUMNS:
980 value = tableViewImpl.GetColumnWidthsPropertyValue();
989 void TableView::OnChildAdd(Actor& child)
993 // Ensure we're not in the middle of laying out children
995 // Check child properties on actor to decide its position inside the table
996 HorizontalAlignment::Type horizontalAlignment = HorizontalAlignment::LEFT;
997 VerticalAlignment::Type verticalAlignment = VerticalAlignment::TOP;
999 if(child.GetPropertyType(Toolkit::TableView::ChildProperty::CELL_HORIZONTAL_ALIGNMENT) != Property::NONE)
1001 std::string value = child.GetProperty(Toolkit::TableView::ChildProperty::CELL_HORIZONTAL_ALIGNMENT).Get<std::string>();
1002 Scripting::GetEnumeration<HorizontalAlignment::Type>(value.c_str(),
1003 HORIZONTAL_ALIGNMENT_STRING_TABLE,
1004 HORIZONTAL_ALIGNMENT_STRING_TABLE_COUNT,
1005 horizontalAlignment);
1008 if(child.GetPropertyType(Toolkit::TableView::ChildProperty::CELL_VERTICAL_ALIGNMENT) != Property::NONE)
1010 std::string value = child.GetProperty(Toolkit::TableView::ChildProperty::CELL_VERTICAL_ALIGNMENT).Get<std::string>();
1011 Scripting::GetEnumeration<VerticalAlignment::Type>(value.c_str(),
1012 VERTICAL_ALIGNMENT_STRING_TABLE,
1013 VERTICAL_ALIGNMENT_STRING_TABLE_COUNT,
1017 Toolkit::TableView::CellPosition cellPosition;
1018 if(child.GetPropertyType(Toolkit::TableView::ChildProperty::ROW_SPAN) != Property::NONE)
1020 cellPosition.rowSpan = child.GetProperty(Toolkit::TableView::ChildProperty::ROW_SPAN).Get<int>();
1023 if(child.GetPropertyType(Toolkit::TableView::ChildProperty::COLUMN_SPAN) != Property::NONE)
1025 cellPosition.columnSpan = child.GetProperty(Toolkit::TableView::ChildProperty::COLUMN_SPAN).Get<int>();
1028 if(child.GetPropertyType(Toolkit::TableView::ChildProperty::CELL_INDEX) != Property::NONE)
1030 Vector2 indices = child.GetProperty(Toolkit::TableView::ChildProperty::CELL_INDEX).Get<Vector2>();
1031 cellPosition.rowIndex = static_cast<unsigned int>(indices.x);
1032 cellPosition.columnIndex = static_cast<unsigned int>(indices.y);
1034 AddChild(child, cellPosition);
1035 SetCellAlignment(cellPosition, horizontalAlignment, verticalAlignment);
1039 bool availableCellFound = false;
1041 // Find the first available cell to store the actor in
1042 const unsigned int rowCount = mCellData.GetRows();
1043 const unsigned int columnCount = mCellData.GetColumns();
1044 for(unsigned int row = 0; row < rowCount && !availableCellFound; ++row)
1046 for(unsigned int column = 0; column < columnCount && !availableCellFound; ++column)
1048 if(!(mCellData[row][column].actor))
1050 // Put the actor in the cell
1053 data.position.columnIndex = column;
1054 data.position.rowIndex = row;
1055 data.horizontalAlignment = horizontalAlignment;
1056 data.verticalAlignment = verticalAlignment;
1057 mCellData[row][column] = data;
1059 availableCellFound = true;
1065 if(!availableCellFound)
1067 // No empty cells, so increase size of the table
1068 unsigned int newColumnCount = (columnCount > 0) ? columnCount : 1;
1069 ResizeContainers(rowCount + 1, newColumnCount);
1071 // Put the actor in the first cell of the new row
1074 data.position.rowIndex = rowCount;
1075 data.position.columnIndex = 0;
1076 data.horizontalAlignment = horizontalAlignment;
1077 data.verticalAlignment = verticalAlignment;
1078 mCellData[rowCount][0] = data;
1085 Control::OnChildAdd(child);
1088 void TableView::OnChildRemove(Actor& child)
1090 // dont process if we're in the middle of bigger operation like delete row, column or resize
1091 if(!mLayoutingChild)
1093 // relayout the table only if instances were found
1094 if(RemoveAllInstances(child))
1100 Control::OnChildRemove(child);
1103 TableView::TableView(unsigned int initialRows, unsigned int initialColumns)
1104 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
1105 mCellData(initialRows, initialColumns),
1106 mPreviousFocusedActor(),
1107 mLayoutingChild(false),
1108 mRowDirty(true), // Force recalculation first time
1111 SetKeyboardNavigationSupport(true);
1112 ResizeContainers(initialRows, initialColumns);
1115 void TableView::OnInitialize()
1117 // Make self as keyboard focusable and focus group
1118 Actor self = Self();
1119 self.SetProperty(Actor::Property::KEYBOARD_FOCUSABLE, true);
1120 SetAsKeyboardFocusGroup(true);
1122 self.SetProperty(DevelControl::Property::ACCESSIBILITY_ROLE, Dali::Accessibility::Role::TABLE);
1125 void TableView::ResizeContainers(unsigned int rows, unsigned int columns)
1127 std::vector<CellData> ignored;
1128 ResizeContainers(rows, columns, ignored);
1131 void TableView::ResizeContainers(unsigned int rows, unsigned int columns, std::vector<CellData>& removed)
1134 mCellData.Resize(rows, columns, removed);
1136 // We don't care if these go smaller, data will be regenerated or is not needed anymore
1137 mRowData.Resize(rows);
1138 mColumnData.Resize(columns);
1141 void TableView::RemoveAndGetLostActors(const std::vector<CellData>& lost, std::vector<Actor>& removed, unsigned int rowsRemoved, unsigned int columnsRemoved)
1143 // iterate through all lost cells
1144 std::vector<CellData>::const_iterator iter = lost.begin();
1145 for(; iter != lost.end(); ++iter)
1147 // if it is a valid actor
1150 // is this actor still somewhere else in the table
1151 Toolkit::TableView::CellPosition position;
1152 if(FindChildPosition((*iter).actor, position))
1154 // it must be spanning multiple cells, position contains the top left most one
1155 // check if position is left of the removed location
1156 if(position.columnIndex < (*iter).position.columnIndex)
1158 // if column span is greater than 1
1159 if(mCellData[position.rowIndex][position.columnIndex].position.columnSpan > 1)
1161 // decrease column span
1162 mCellData[position.rowIndex][position.columnIndex].position.columnSpan -= columnsRemoved;
1165 // check if position is left of the removed location
1166 if(position.rowIndex < (*iter).position.rowIndex)
1168 // if row span is greater than 1
1169 if(mCellData[position.rowIndex][position.columnIndex].position.rowSpan > 1)
1171 // decrease row span
1172 mCellData[position.rowIndex][position.columnIndex].position.rowSpan -= rowsRemoved;
1178 // this actor is gone for good
1179 // add actor to removed container
1180 removed.push_back((*iter).actor);
1181 // we dont want the child actor anymore
1182 Self().Remove((*iter).actor);
1188 bool TableView::RemoveAllInstances(const Actor& child)
1191 // walk through the layout data
1192 const unsigned int rowCount = mCellData.GetRows();
1193 const unsigned int columnCount = mCellData.GetColumns();
1194 for(unsigned int row = 0; row < rowCount; ++row)
1196 for(unsigned int column = 0; column < columnCount; ++column)
1198 if(mCellData[row][column].actor == child)
1200 // clear the cell, NOTE that the cell might be spanning multiple cells
1201 mCellData[row][column] = CellData();
1209 void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl,
1210 void (TableView::*funcFixed)(unsigned int, float),
1211 void (TableView::*funcRelative)(unsigned int, float),
1212 void (TableView::*funcFit)(unsigned int),
1213 const Property::Value& value)
1215 const Property::Map* map = value.GetMap();
1218 unsigned int index(0);
1219 for(unsigned int i = 0, count = map->Count(); i < count; ++i)
1221 Property::Value& item = map->GetValue(i);
1222 Property::Map* childMap = item.GetMap();
1224 std::istringstream(map->GetKey(i)) >> index;
1227 Property::Value* policy = childMap->Find("policy");
1228 Property::Value* childMapValue = childMap->Find("value");
1229 if(policy && childMapValue)
1231 std::string policyValue;
1232 policy->Get(policyValue);
1233 Toolkit::TableView::LayoutPolicy policy;
1234 if(Scripting::GetEnumeration<Toolkit::TableView::LayoutPolicy>(policyValue.c_str(),
1235 LAYOUT_POLICY_STRING_TABLE,
1236 LAYOUT_POLICY_STRING_TABLE_COUNT,
1239 if(policy == Toolkit::TableView::FIXED)
1241 (tableViewImpl.*funcFixed)(index, childMapValue->Get<float>());
1243 else if(policy == Toolkit::TableView::RELATIVE)
1245 (tableViewImpl.*funcRelative)(index, childMapValue->Get<float>());
1247 else if(policy == Toolkit::TableView::FIT)
1249 (tableViewImpl.*funcFit)(index);
1251 // do nothing for FILL policy
1259 Property::Value TableView::GetRowHeightsPropertyValue()
1262 GetMapPropertyValue(mRowData, map);
1263 return Property::Value(map);
1266 Property::Value TableView::GetColumnWidthsPropertyValue()
1269 GetMapPropertyValue(mColumnData, map);
1270 return Property::Value(map);
1273 void TableView::GetMapPropertyValue(const RowColumnArray& data, Property::Map& map)
1275 const char* fixedPolicy = Scripting::GetEnumerationName<Toolkit::TableView::LayoutPolicy>(Toolkit::TableView::FIXED,
1276 LAYOUT_POLICY_STRING_TABLE,
1277 LAYOUT_POLICY_STRING_TABLE_COUNT);
1278 const char* relativePolicy = Scripting::GetEnumerationName<Toolkit::TableView::LayoutPolicy>(Toolkit::TableView::RELATIVE,
1279 LAYOUT_POLICY_STRING_TABLE,
1280 LAYOUT_POLICY_STRING_TABLE_COUNT);
1281 const char* fillPolicy = Scripting::GetEnumerationName<Toolkit::TableView::LayoutPolicy>(Toolkit::TableView::FILL,
1282 LAYOUT_POLICY_STRING_TABLE,
1283 LAYOUT_POLICY_STRING_TABLE_COUNT);
1284 const char* fitPolicy = Scripting::GetEnumerationName<Toolkit::TableView::LayoutPolicy>(Toolkit::TableView::FIT,
1285 LAYOUT_POLICY_STRING_TABLE,
1286 LAYOUT_POLICY_STRING_TABLE_COUNT);
1288 const RowColumnArray::SizeType count = data.Size();
1289 for(RowColumnArray::SizeType i = 0; i < count; i++)
1291 const RowColumnData& dataInstance = data[i];
1294 switch(dataInstance.sizePolicy)
1296 case Toolkit::TableView::FIXED:
1298 item["policy"] = fixedPolicy;
1299 item["value"] = dataInstance.size;
1302 case Toolkit::TableView::RELATIVE:
1304 item["policy"] = relativePolicy;
1305 item["value"] = dataInstance.fillRatio;
1308 case Toolkit::TableView::FIT:
1310 item["policy"] = fitPolicy;
1311 item["value"] = 0.f;
1314 case Toolkit::TableView::FILL:
1317 item["policy"] = fillPolicy;
1318 item["value"] = 0.f;
1322 std::ostringstream ss;
1324 map[ss.str()] = item;
1328 TableView::~TableView()
1333 Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
1335 Actor nextFocusableActor;
1337 if(!currentFocusedActor)
1339 // Nothing is currently focused, so the child in the first cell should be focused.
1340 nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
1344 Toolkit::TableView::CellPosition position;
1345 if(FindChildPosition(currentFocusedActor, position))
1347 // The current focused actor is a child of TableView
1348 bool focusLost = false;
1349 int currentRow = position.rowIndex;
1350 int currentColumn = position.columnIndex;
1351 int numberOfColumns = GetColumns();
1352 int numberOfRows = GetRows();
1354 bool lastCell = false;
1355 Actor nextValidActor;
1359 case Toolkit::Control::KeyboardFocus::LEFT:
1363 if(--currentColumn < 0)
1365 currentColumn = numberOfColumns - 1;
1366 if(--currentRow < 0)
1369 currentRow = loopEnabled ? numberOfRows - 1 : 0;
1370 focusLost = (currentRow == 0);
1373 nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
1374 } while(!nextValidActor && !lastCell);
1377 case Toolkit::Control::KeyboardFocus::RIGHT:
1381 if(++currentColumn > numberOfColumns - 1)
1384 if(++currentRow > numberOfRows - 1)
1387 currentRow = loopEnabled ? 0 : numberOfRows - 1;
1388 focusLost = (currentRow == numberOfRows - 1);
1391 nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
1392 } while(!nextValidActor && !lastCell);
1395 case Toolkit::Control::KeyboardFocus::UP:
1399 if(--currentRow < 0)
1402 currentRow = loopEnabled ? numberOfRows - 1 : 0;
1403 focusLost = (currentRow == 0);
1405 nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
1406 } while(!nextValidActor && !lastCell);
1409 case Toolkit::Control::KeyboardFocus::DOWN:
1414 if(++currentRow > numberOfRows - 1)
1417 currentRow = loopEnabled ? 0 : numberOfRows - 1;
1418 focusLost = (currentRow == numberOfRows - 1);
1420 nextValidActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
1421 } while(!nextValidActor && !lastCell);
1430 // Move the focus if we haven't lost it.
1433 nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
1435 // Save the focused actor in the TableView.
1436 mPreviousFocusedActor = nextFocusableActor;
1441 // The current focused actor is not within this TableView.
1443 unsigned int numberOfColumns = GetColumns();
1444 unsigned int numberOfRows = GetRows();
1446 // Check whether the previous focused actor is a focus group (i.e. a layout container)
1447 bool wasFocusedOnLayoutContainer = false;
1448 Actor previousFocusedActor = mPreviousFocusedActor.GetHandle();
1449 if(previousFocusedActor)
1451 Toolkit::Control control = Toolkit::Control::DownCast(previousFocusedActor);
1454 Internal::Control& controlImpl = static_cast<Internal::Control&>(control.GetImplementation());
1455 wasFocusedOnLayoutContainer = controlImpl.IsKeyboardFocusGroup();
1459 // Check whether the previous focused actor is a layout container and also a child of this TableView
1460 Toolkit::TableView::CellPosition position;
1461 if(wasFocusedOnLayoutContainer && FindChildPosition(previousFocusedActor, position))
1463 nextFocusableActor = GetNextKeyboardFocusableActor(previousFocusedActor, direction, loopEnabled);
1467 // Otherwise, move the focus to either the first or the last cell according to the given direction.
1468 if(direction == Toolkit::Control::KeyboardFocus::LEFT || direction == Toolkit::Control::KeyboardFocus::UP)
1470 nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(numberOfRows - 1, numberOfColumns - 1));
1474 nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
1480 return nextFocusableActor;
1483 Vector3 TableView::GetNaturalSize()
1485 // Natural size is the size of all fixed cell widths or heights. This ignores cells with relative heights.
1486 return Vector3(mFixedTotals.width, mFixedTotals.height, 1.0f);
1489 float TableView::CalculateChildSize(const Actor& child, Dimension::Type dimension)
1491 Toolkit::TableView::CellPosition position;
1492 if(FindChildPosition(child, position))
1496 case Dimension::WIDTH:
1498 float cellSize = 0.0f;
1499 cellSize = mColumnData[position.columnIndex + position.columnSpan - 1].position - (position.columnIndex > 0 ? mColumnData[position.columnIndex - 1].position : 0.f) - mPadding.width * 2.0f;
1509 case Dimension::HEIGHT:
1511 float cellSize = 0.0f;
1513 cellSize = mRowData[position.rowIndex + position.rowSpan - 1].position - (position.rowIndex > 0 ? mRowData[position.rowIndex - 1].position : 0.f) - mPadding.height * 2.0f;
1529 return 0.0f; // Child not found
1532 bool TableView::RelayoutDependentOnChildren(Dimension::Type dimension)
1534 if(Control::RelayoutDependentOnChildren(dimension))
1539 return FindFit(mRowData) || FindFit(mColumnData);
1542 void TableView::SetCellAlignment(Toolkit::TableView::CellPosition position, HorizontalAlignment::Type horizontal, VerticalAlignment::Type vertical)
1544 // Check if we need to expand our data array
1545 if(position.rowIndex >= mCellData.GetRows())
1547 // Only adding new rows
1548 ResizeContainers(position.rowIndex + 1, mCellData.GetColumns());
1551 if(position.columnIndex >= mCellData.GetColumns())
1553 // Only adding new columns
1554 ResizeContainers(mCellData.GetRows(), position.columnIndex + 1);
1557 // Set the alignment of the cell
1558 CellData& data = mCellData[position.rowIndex][position.columnIndex];
1559 data.horizontalAlignment = horizontal;
1560 data.verticalAlignment = vertical;
1563 void TableView::CalculateFillSizes(RowColumnArray& data)
1565 // First pass: Count number of fill entries and calculate used relative space
1566 Dali::Vector<RowColumnData*> fillData;
1567 float relativeTotal = 0.0f;
1569 const unsigned int dataCount = data.Size();
1571 for(unsigned int i = 0; i < dataCount; ++i)
1573 RowColumnData& dataInstance = data[i];
1575 if(dataInstance.sizePolicy == Toolkit::TableView::RELATIVE)
1577 relativeTotal += dataInstance.fillRatio;
1579 else if(dataInstance.sizePolicy == Toolkit::TableView::FILL)
1581 fillData.PushBack(&dataInstance);
1585 // Second pass: Distribute remaining relative space
1586 const unsigned int fillCount = fillData.Size();
1589 if(relativeTotal > 1.0f)
1591 relativeTotal = 1.0f;
1594 const float evenFillRatio = (1.0f - relativeTotal) / fillCount;
1596 for(unsigned int i = 0; i < fillCount; ++i)
1598 fillData[i]->fillRatio = evenFillRatio;
1603 float TableView::CalculateTotalFixedSize(const RowColumnArray& data)
1605 float totalSize = 0.0f;
1607 const unsigned int dataCount = data.Size();
1609 for(unsigned int i = 0; i < dataCount; ++i)
1611 const RowColumnData& dataInstance = data[i];
1613 switch(dataInstance.sizePolicy)
1615 // we have absolute size to FIXED and FIT column/row and relative size for RELATIVE and FILL column/row
1616 case Toolkit::TableView::FIXED:
1617 case Toolkit::TableView::FIT:
1619 totalSize += dataInstance.size;
1633 Vector2 TableView::GetCellPadding(Dimension::Type dimension)
1637 case Dimension::WIDTH:
1639 return Vector2(mPadding.x, mPadding.x);
1641 case Dimension::HEIGHT:
1643 return Vector2(mPadding.y, mPadding.y);
1654 void TableView::CalculateFitSizes(RowColumnArray& data, Dimension::Type dimension)
1656 Vector2 cellPadding = GetCellPadding(dimension);
1658 const unsigned int dataCount = data.Size();
1660 for(unsigned int i = 0; i < dataCount; ++i)
1662 RowColumnData& dataInstance = data[i];
1664 if(dataInstance.sizePolicy == Toolkit::TableView::FIT)
1666 // Find the size of the biggest actor in the row or column
1667 float maxActorHeight = 0.0f;
1669 unsigned int fitCount = (dimension == Dimension::WIDTH) ? mCellData.GetRows() : mCellData.GetColumns();
1671 for(unsigned int j = 0; j < fitCount; ++j)
1673 unsigned int row = (dimension == Dimension::WIDTH) ? j : i;
1674 unsigned int column = (dimension == Dimension::WIDTH) ? i : j;
1675 DALI_ASSERT_DEBUG(row < mCellData.GetRows());
1676 DALI_ASSERT_DEBUG(column < mCellData.GetColumns());
1678 const CellData& cellData = mCellData[row][column];
1679 const Actor& actor = cellData.actor;
1682 if(FitToChild(actor, dimension) && (dimension == Dimension::WIDTH) ? (cellData.position.columnSpan == 1) : (cellData.position.rowSpan == 1))
1684 maxActorHeight = std::max(maxActorHeight, actor.GetRelayoutSize(dimension) + cellPadding.x + cellPadding.y);
1689 dataInstance.size = maxActorHeight;
1694 bool TableView::FindFit(const RowColumnArray& data)
1696 for(unsigned int i = 0, count = data.Size(); i < count; ++i)
1698 if(data[i].sizePolicy == Toolkit::TableView::FIT)
1707 } // namespace Internal
1709 } // namespace Toolkit