Increased Line/Function Coverage for BloomView & TableView
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / table-view / table-view-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/controls/table-view/table-view-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <sstream>
23 #include <dali/public-api/object/ref-object.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/devel-api/object/type-registry-helper.h>
26 #include <dali/devel-api/scripting/scripting.h>
27 #include <dali/public-api/size-negotiation/relayout-container.h>
28 #include <dali/integration-api/debug.h>
29
30 using namespace Dali;
31
32 namespace
33 {
34
35 /**
36  * @brief Should the tableview fit around the given actor
37  *
38  * @param[in] actor The child actor to test against
39  * @param[dimension] The dimnesion to test against
40  */
41 bool FitToChild( Actor actor, Dimension::Type dimension )
42 {
43   return actor.GetResizePolicy( dimension ) != ResizePolicy::FILL_TO_PARENT && actor.GetRelayoutSize( dimension ) > 0.0f;
44 }
45
46 #if defined(DEBUG_ENABLED)
47 // debugging support, very useful when new features are added or bugs are hunted down
48 // currently not called from code so compiler will optimize these away, kept here for future debugging
49
50 #define TABLEVIEW_TAG "DALI Toolkit::TableView "
51 #define TV_LOG(fmt, args...) Debug::LogMessage(Debug::DebugInfo, TABLEVIEW_TAG fmt, ## args)
52 //#define TABLEVIEW_DEBUG 1
53
54 #if defined(TABLEVIEW_DEBUG)
55 void PrintArray( Array2d<Dali::Toolkit::Internal::TableView::CellData>& array )
56 {
57   TV_LOG( "Array2d<CellData> size [%d,%d] \n", array.GetRows(), array.GetColumns() );
58   // print values
59   for( unsigned int i = 0; i < array.GetRows(); ++i )
60   {
61     for( unsigned int j = 0; j < array.GetColumns(); ++j )
62     {
63       Dali::Toolkit::Internal::TableView::CellData data = array[i][j];
64       char actor = ' ';
65       std::string actorName;
66       if( data.actor )
67       {
68         actor = 'A';
69         actorName = data.actor.GetName();
70       }
71       TV_LOG("Array[%d,%d]=%c %s %d,%d,%d,%d  ", i, j, actor, actorName.c_str(),
72           data.position.rowIndex, data.position.columnIndex,
73           data.position.rowSpan, data.position.columnSpan );
74     }
75     TV_LOG( "\n" );
76   }
77 }
78
79 // debugging support, very useful when new features are added or bugs are hunted down
80 // currently not called from code so compiler will optimize these away, kept here for future debugging
81 void PrintArray( Array2d<Size>& array )
82 {
83   TV_LOG( "Array2d<Size> size [%d,%d] \n", array.GetRows(), array.GetColumns() );
84   // print values
85   for( unsigned int i = 0; i < array.GetRows(); ++i )
86   {
87     for( unsigned int j = 0; j < array.GetColumns(); ++j )
88     {
89       TV_LOG( "Array[%d,%d]=%.2f,%.2f ", i, j, array[i][j].width, array[i][j].height );
90     }
91     TV_LOG( "\n" );
92   }
93 }
94 // debugging support, very useful when new features are added or bugs are hunted down
95 // currently not called from code so compiler will optimize these away, kept here for future debugging
96 void PrintVector( std::vector<float>& array )
97 {
98   TV_LOG( "vector, size [%d]\n", array.size() );
99   // print values
100   for( unsigned int i = 0; i < array.size(); ++i )
101   {
102     TV_LOG( "vector[%d]=%.2f ", i, array[i] );
103   }
104   TV_LOG( "\n" );
105 }
106 #endif // defined(TABLEVIEW_DEBUG)
107 #endif // defined(DEBUG_ENABLED)
108
109 } // namespace
110
111 namespace Dali
112 {
113
114 namespace Toolkit
115 {
116
117 namespace Internal
118 {
119
120 namespace
121 {
122
123 // Type registration
124 BaseHandle Create()
125 {
126   return Toolkit::TableView::New( 0, 0 );
127 }
128
129 // Setup properties, signals and actions using the type-registry.
130 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::TableView, Toolkit::Control, Create );
131
132 DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "rows",           UNSIGNED_INTEGER, ROWS           )
133 DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "columns",        UNSIGNED_INTEGER, COLUMNS        )
134 DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "cell-padding",   VECTOR2,          CELL_PADDING   )
135 DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-rows",    MAP,              LAYOUT_ROWS    )
136 DALI_PROPERTY_REGISTRATION( Toolkit, TableView, "layout-columns", MAP,              LAYOUT_COLUMNS )
137
138 DALI_TYPE_REGISTRATION_END()
139
140 const Scripting::StringEnum< Toolkit::TableView::LayoutPolicy > LAYOUT_POLICY_STRING_TABLE[] =
141 {
142  { "fixed",    Toolkit::TableView::FIXED    },
143  { "relative", Toolkit::TableView::RELATIVE },
144  { "fill",     Toolkit::TableView::FILL     }
145 };
146
147 const unsigned int LAYOUT_POLICY_STRING_TABLE_COUNT = sizeof(LAYOUT_POLICY_STRING_TABLE) / sizeof( LAYOUT_POLICY_STRING_TABLE[0] );
148
149 } // Unnamed namespace
150
151 Toolkit::TableView TableView::New( unsigned int initialRows, unsigned int initialColumns )
152 {
153   // Create the implementation, temporarily owned by this handle on stack
154   IntrusivePtr< TableView > impl = new TableView( initialRows, initialColumns );
155
156   // Pass ownership to CustomActor handle
157   Toolkit::TableView handle( *impl );
158
159   // Second-phase init of the implementation
160   // This can only be done after the CustomActor connection has been made...
161   impl->Initialize();
162
163   return handle;
164 }
165
166 bool TableView::AddChild( Actor& child, const Toolkit::TableView::CellPosition& position )
167 {
168   // check that the child is valid
169   DALI_ASSERT_ALWAYS( child );
170
171   // if child is already parented, we adopt it
172   if( child.GetParent() )
173   {
174     child.GetParent().Remove( child );
175   }
176
177   // check if we need to expand our data array
178   if( position.rowIndex >= mCellData.GetRows() )
179   {
180     // only adding new rows
181     ResizeContainers( position.rowIndex + 1, mCellData.GetColumns() );
182   }
183
184   if( position.columnIndex >= mCellData.GetColumns() )
185   {
186     // only adding new columns
187     ResizeContainers( mCellData.GetRows(), position.columnIndex + 1 );
188   }
189
190   // check if there already is something in this cell
191   if( mCellData[ position.rowIndex ][ position.columnIndex ].actor )
192   {
193     return false; // cannot share a cell, it would complicate all logic and not bring much benefit
194   }
195
196   RelayoutingLock lock( *this );
197   // adopt the child
198   Self().Add( child );
199
200   // if child spans multiple rows of columns
201   if( ( position.rowSpan > 1 ) && ( position.rowIndex + position.rowSpan > mCellData.GetRows() ) )
202   {
203     // increase table size for the full span, only increasing rows
204     ResizeContainers( position.rowIndex + position.rowSpan, mCellData.GetColumns() );
205   }
206
207   if( ( position.columnSpan > 1 ) && ( position.columnIndex + position.columnSpan > mCellData.GetColumns() ) )
208   {
209     // increase table size for the full span, only increasing columns
210     ResizeContainers( mCellData.GetRows(), position.columnIndex + position.columnSpan );
211   }
212
213   // Fill in all cells that need the data
214   CellData data;
215   data.actor = child;
216   data.position = position;
217
218   for( unsigned int row = position.rowIndex; row < ( position.rowIndex + position.rowSpan ); ++row )
219   {
220     // store same information to all cells, this way we can identify
221     // if a cell is the prime location of an actor or a spanned one
222     for( unsigned int column = position.columnIndex; column < ( position.columnIndex + position.columnSpan ); ++column )
223     {
224       // store same information to all cells, this way we can identify
225       // if a cell is the prime location of an actor or a spanned one
226       mCellData[ row ][ column ] = data;
227     }
228   }
229
230   // Relayout the whole table
231   RelayoutRequest();
232
233   return true;    // Addition successful
234 }
235
236 Actor TableView::GetChildAt( const Toolkit::TableView::CellPosition& position )
237 {
238   if( ( position.rowIndex < mCellData.GetRows() ) && ( position.columnIndex < mCellData.GetColumns() ) )
239   {
240     return mCellData[ position.rowIndex ][ position.columnIndex ].actor;
241   }
242
243   // Return an empty handle
244   return Actor();
245 }
246
247 Actor TableView::RemoveChildAt( const Toolkit::TableView::CellPosition& position )
248 {
249   // get the child handle
250   Actor child = GetChildAt( position );
251   // if no real actor there, nothing else to be done
252   if( child )
253   {
254     RelayoutingLock lock( *this );
255     // Remove the child, this will trigger a call to OnControlChildRemove
256     Self().Remove( child );
257
258     // relayout the table only if instances were found
259     if( RemoveAllInstances( child ) )
260     {
261       RelayoutRequest();
262     }
263   }
264   // return the child back to caller
265   return child;
266 }
267
268 bool TableView::FindChildPosition( const Actor& child, Toolkit::TableView::CellPosition& positionOut )
269 {
270   // Only find valid child actors
271   if( child )
272   {
273     // Walk through the layout data
274     const unsigned int rowCount = mCellData.GetRows();
275     const unsigned int columnCount = mCellData.GetColumns();
276
277     for( unsigned int row = 0; row < rowCount; ++row )
278     {
279       for( unsigned int column = 0; column < columnCount; ++column )
280       {
281         if( mCellData[ row ][ column ].actor == child )
282         {
283           positionOut = mCellData[ row ][ column ].position;
284           return true;
285         }
286       }
287     }
288   }
289
290   return false;
291 }
292
293 void TableView::InsertRow( unsigned int rowIndex )
294 {
295   RelayoutingLock lock( *this );
296
297   mCellData.InsertRow( rowIndex );
298
299   // Need to update the cell infos for the items that moved
300   const unsigned int rowCount = mCellData.GetRows();
301   const unsigned int columnCount = mCellData.GetColumns();
302
303   for( unsigned int row = 0; row < rowCount; ++row )
304   {
305     for( unsigned int column = 0; column < columnCount; ++column )
306     {
307       Toolkit::TableView::CellPosition& position = mCellData[ row ][ column ].position;
308
309       // If cell is spanning and above and spans to inserted row
310       if( ( position.rowSpan > 1 ) && ( position.rowIndex <= rowIndex ) &&
311           ( position.rowIndex + position.rowSpan > rowIndex ) )
312       {
313         // Increment span
314         position.rowSpan++;
315
316         // Copy cell to occupy the new column
317         mCellData[ rowIndex ][ column ] = mCellData[ row ][ column ];
318       }
319       else if( row > rowIndex )   // If below of inserted row, increase row index
320       {
321         // Increment index
322         position.rowIndex++;
323       }
324     }
325   }
326
327   // Expand row data array
328   mRowData.Insert( mRowData.Begin() + rowIndex, RowColumnData() );
329
330   // Sizes may have changed, so relayout
331   mRowColumnDirty = true;
332   RelayoutRequest();
333 }
334
335 void TableView::DeleteRow( unsigned int rowIndex )
336 {
337   std::vector< Actor > ignored;
338   DeleteRow( rowIndex, ignored );
339 }
340
341 void TableView::DeleteRow( unsigned int rowIndex, std::vector<Actor>& removed )
342 {
343   RelayoutingLock lock( *this );
344
345   // Delete the row
346   std::vector< CellData > lost;
347   mCellData.DeleteRow( rowIndex, lost );
348
349   // Need to update the cell infos for the items that moved
350   const unsigned int rowCount = mCellData.GetRows();
351   const unsigned int columnCount = mCellData.GetColumns();
352
353   for( unsigned int row = 0; row < rowCount; ++row )
354   {
355     for( unsigned int column = 0; column < columnCount; ++column )
356     {
357       Toolkit::TableView::CellPosition& position = mCellData[ row ][ column ].position;
358
359       // If cell is spanning and above and spans to deleted row
360       if( ( position.rowSpan > 1 ) && ( position.rowIndex <= rowIndex ) &&
361           ( position.rowIndex + position.rowSpan > rowIndex ) )
362       {
363         // Decrement span
364         if( position.rowSpan > 1 )
365         {
366           position.rowSpan--;
367         }
368       }
369       else if( row >= rowIndex )    // If below of or at the inserted row, decrease row index
370       {
371         // Decrement index
372         if( position.rowIndex > 1 )
373         {
374           position.rowIndex--;
375         }
376       }
377     }
378   }
379
380   // 1 row removed, 0 columns
381   RemoveAndGetLostActors( lost, removed, 1u, 0u );
382
383   // Contract row data array
384   mRowData.Erase( mRowData.Begin() + rowIndex );
385
386   // Sizes may have changed, so relayout
387   mRowColumnDirty = true;
388   RelayoutRequest();
389 }
390
391 void TableView::InsertColumn( unsigned int columnIndex )
392 {
393   RelayoutingLock lock( *this );
394
395   // Insert the new column
396   mCellData.InsertColumn( columnIndex );
397
398   // Need to update the cell infos for the items that moved
399   const unsigned int rowCount = mCellData.GetRows();
400   const unsigned int columnCount = mCellData.GetColumns();
401
402   for( unsigned int row = 0; row < rowCount; ++row )
403   {
404     for( unsigned int column = 0; column < columnCount; ++column )
405     {
406       Toolkit::TableView::CellPosition& position = mCellData[ row ][ column ].position;
407
408       // If cell is spanning and left side and spans to inserted column
409       if( ( position.columnSpan > 1 ) && ( position.columnIndex <= columnIndex ) &&
410           ( position.columnIndex + position.columnSpan > columnIndex ) )
411       {
412         // Increment span
413         position.columnSpan++;
414
415         // Copy cell to occupy the new column
416         mCellData[ row ][ columnIndex ] = mCellData[ row ][ column ];
417       }
418       else if( column > columnIndex )   // If on the right side of inserted column, increase column index
419       {
420         // Increment index
421         position.columnIndex++;
422       }
423     }
424   }
425
426   // Expand column data array
427   mColumnData.Insert( mColumnData.Begin() + columnIndex, RowColumnData() );
428
429   // Sizes may have changed so relayout
430   mRowColumnDirty = true;
431   RelayoutRequest();
432 }
433
434 void TableView::DeleteColumn( unsigned int columnIndex )
435 {
436   std::vector< Actor > ignored;
437   DeleteColumn( columnIndex, ignored );
438 }
439
440 void TableView::DeleteColumn( unsigned int columnIndex, std::vector<Actor>& removed )
441 {
442   RelayoutingLock lock( *this );
443
444   // Remove the column
445   std::vector< CellData > lost;
446   mCellData.DeleteColumn( columnIndex, lost );
447
448   // Need to update the cell infos for the items that moved
449   const unsigned int rowCount = mCellData.GetRows();
450   const unsigned int columnCount = mCellData.GetColumns();
451
452   for( unsigned int row = 0; row < rowCount; ++row )
453   {
454     for( unsigned int column = 0; column < columnCount; ++column )
455     {
456       Toolkit::TableView::CellPosition& position = mCellData[ row ][ column ].position;
457
458       // If cell is spanning and left side and spans to inserted column
459       if( ( position.columnSpan > 1 ) && ( position.columnIndex <= columnIndex ) &&
460           ( position.columnIndex + position.columnSpan > columnIndex ) )
461       {
462         // Decrement span
463         if( position.columnSpan > 1 )
464         {
465           position.columnSpan--;
466         }
467       }
468       else if( column >= columnIndex )    // If on the right side of or at the inserted column, decrease column index
469       {
470         // Decrement index
471         if( position.columnIndex > 0 )
472         {
473           position.columnIndex--;
474         }
475       }
476     }
477   }
478
479   // 0 rows, 1 column removed
480   RemoveAndGetLostActors( lost, removed, 0u, 1u );
481
482   // Contract column data array
483   mColumnData.Erase( mColumnData.Begin() + columnIndex );
484
485   // Size may have changed so relayout
486   mRowColumnDirty = true;
487   RelayoutRequest();
488 }
489
490 void TableView::Resize( unsigned int rows, unsigned int columns )
491 {
492   std::vector< Actor > ignored;
493   Resize( rows, columns, ignored );
494 }
495
496 void TableView::Resize( unsigned int rows, unsigned int columns, std::vector<Actor>& removed )
497 {
498   RelayoutingLock lock( *this );
499
500   unsigned int oldRows = GetRows();
501   unsigned int oldColumns = GetColumns();
502
503   // Resize data array
504   std::vector< CellData > lost;
505   ResizeContainers( rows, columns, lost );
506
507   // Calculate if we lost rows
508   unsigned int rowsRemoved = 0;
509   unsigned int newRows = GetRows();
510
511   if( oldRows < newRows )
512   {
513     rowsRemoved = newRows - oldRows;
514   }
515
516   // Calculate if we lost columns
517   unsigned int columnsRemoved = 0;
518   unsigned int newColumns = GetColumns();
519   if( oldColumns < newColumns )
520   {
521     rowsRemoved = newColumns - oldColumns;
522   }
523
524   RemoveAndGetLostActors( lost, removed, rowsRemoved, columnsRemoved );
525
526   // Sizes may have changed so request a relayout
527   mRowColumnDirty = true;
528   RelayoutRequest();
529 }
530
531 void TableView::SetCellPadding( Size padding )
532 {
533   // If padding really changed
534   if( padding != mPadding )
535   {
536     mPadding = padding;
537
538     RelayoutRequest();
539   }
540 }
541
542 Size TableView::GetCellPadding()
543 {
544   return mPadding;
545 }
546
547 void TableView::SetRowPolicy( unsigned int rowIndex, CellSizePolicy policy )
548 {
549   DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
550
551   if( mRowData[ rowIndex ].sizePolicy != policy )
552   {
553     mRowData[ rowIndex ].sizePolicy = policy;
554
555     mRowColumnDirty = true;
556     RelayoutRequest();
557   }
558 }
559
560 TableView::CellSizePolicy TableView::GetRowPolicy( unsigned int rowIndex ) const
561 {
562   DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
563
564   return mRowData[ rowIndex ].sizePolicy;
565 }
566
567 void TableView::SetColumnPolicy( unsigned int columnIndex, CellSizePolicy policy )
568 {
569   DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
570
571   if( mColumnData[ columnIndex ].sizePolicy != policy )
572   {
573     mColumnData[ columnIndex ].sizePolicy = policy;
574
575     mRowColumnDirty = true;
576     RelayoutRequest();
577   }
578 }
579
580 TableView::CellSizePolicy TableView::GetColumnPolicy( unsigned int columnIndex ) const
581 {
582   DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
583
584   return mColumnData[ columnIndex ].sizePolicy;
585 }
586
587 void TableView::SetFixedHeight( unsigned int rowIndex, float height )
588 {
589   DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
590
591   RowColumnData& data = mRowData[ rowIndex ];
592   data.size = height;
593   data.sizePolicy = FIXED;
594
595   mRowColumnDirty = true;
596   RelayoutRequest();
597 }
598
599 float TableView::GetFixedHeight( unsigned int rowIndex ) const
600 {
601   DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
602
603   return mRowData[ rowIndex ].size;
604 }
605
606 void TableView::SetFixedWidth( unsigned int columnIndex, float width )
607 {
608   DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
609
610   RowColumnData& data = mColumnData[ columnIndex ];
611   data.size = width;
612   data.sizePolicy = FIXED;
613
614   mRowColumnDirty = true;
615   RelayoutRequest();
616 }
617
618 float TableView::GetFixedWidth( unsigned int columnIndex ) const
619 {
620   DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
621
622   return mColumnData[ columnIndex ].size;
623 }
624
625 void TableView::SetRelativeHeight( unsigned int rowIndex, float heightPercentage )
626 {
627   DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
628
629   RowColumnData& data = mRowData[ rowIndex ];
630   data.fillRatio = heightPercentage;
631   data.userFillRatio = true;
632   data.sizePolicy = FILL;
633
634   mRowColumnDirty = true;
635   RelayoutRequest();
636 }
637
638 float TableView::GetRelativeHeight( unsigned int rowIndex ) const
639 {
640   DALI_ASSERT_ALWAYS( rowIndex < mRowData.Size() );
641
642   return mRowData[ rowIndex ].fillRatio;
643 }
644
645 void TableView::SetRelativeWidth( unsigned int columnIndex, float widthPercentage )
646 {
647   DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
648
649   RowColumnData& data = mColumnData[ columnIndex ];
650   data.fillRatio = widthPercentage;
651   data.userFillRatio = true;
652   data.sizePolicy = FILL;
653
654   mRowColumnDirty = true;
655   RelayoutRequest();
656 }
657
658 float TableView::GetRelativeWidth( unsigned int columnIndex ) const
659 {
660   DALI_ASSERT_ALWAYS( columnIndex < mColumnData.Size() );
661
662   return mColumnData[ columnIndex ].fillRatio;
663 }
664
665 void TableView::CalculateRowColumnData()
666 {
667   // Calculate the relative sizes
668   if( mRowColumnDirty )
669   {
670     ComputeRelativeSizes( mRowData );
671     ComputeRelativeSizes( mColumnData );
672
673     mRowColumnDirty = false;
674   }
675 }
676
677 void TableView::OnCalculateRelayoutSize( Dimension::Type dimension )
678 {
679   CalculateRowColumnData();
680
681   if( dimension & Dimension::WIDTH )
682   {
683     CalculateFixedSizes( mColumnData, Dimension::WIDTH );
684     mFixedTotals.width = CalculateTotalFixedSize( mColumnData );
685   }
686
687   if( dimension & Dimension::HEIGHT )
688   {
689     CalculateFixedSizes( mRowData, Dimension::HEIGHT );
690     mFixedTotals.height = CalculateTotalFixedSize( mRowData );
691   }
692 }
693
694 void TableView::OnLayoutNegotiated( float size, Dimension::Type dimension )
695 {
696   CalculateRowColumnData();
697
698   // Calculate the value of all relative sized rows and columns
699   if( dimension & Dimension::WIDTH )
700   {
701     float remainingSize = size - mFixedTotals.width;
702     if( remainingSize < 0.0f )
703     {
704       remainingSize = 0.0f;
705     }
706
707     CalculateRelativeSizes( mColumnData, remainingSize );
708   }
709
710   if( dimension & Dimension::HEIGHT )
711   {
712     float remainingSize = size - mFixedTotals.height;
713     if( remainingSize < 0.0f )
714     {
715       remainingSize = 0.0f;
716     }
717
718     CalculateRelativeSizes( mRowData, remainingSize );
719   }
720 }
721
722 void TableView::OnRelayout( const Vector2& size, RelayoutContainer& container )
723 {
724   CalculateRowColumnData();
725
726   // Go through the layout data
727   float cumulatedHeight = 0.0f;
728
729   const unsigned int rowCount = mCellData.GetRows();
730   const unsigned int columnCount = mCellData.GetColumns();
731
732   for( unsigned int row = 0; row < rowCount; ++row )
733   {
734     float cumulatedWidth = 0.0f;
735
736     for( unsigned int column = 0; column < columnCount; ++column )
737     {
738       Actor& actor = mCellData[ row ][ column ].actor;
739       const Toolkit::TableView::CellPosition position = mCellData[ row ][ column ].position;
740
741       // If there is an actor and this is the main cell of the actor.
742       // An actor can be in multiple cells if its row or columnspan is more than 1.
743       // We however must lay out each actor only once.
744       if( actor && ( position.rowIndex == row ) && ( position.columnIndex == column ) )
745       {
746         // Anchor actor to top left of table view
747         actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
748         actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
749
750         Padding padding;
751         actor.GetPadding( padding );
752
753         Vector3 actorPosition( cumulatedWidth + mPadding.width + padding.left,       // Left padding
754                                cumulatedHeight + mPadding.height + padding.top,      // Top padding
755                                0.0f );
756         actor.SetPosition( actorPosition );
757       }
758
759       DALI_ASSERT_DEBUG( column < mColumnData.Size() );
760       cumulatedWidth += mColumnData[ column ].size;
761     }
762
763     DALI_ASSERT_DEBUG( row < mRowData.Size() );
764     cumulatedHeight += mRowData[ row ].size;
765   }
766 }
767
768 unsigned int TableView::GetRows()
769 {
770   return mCellData.GetRows();
771 }
772
773 unsigned int TableView::GetColumns()
774 {
775   return mCellData.GetColumns();
776 }
777
778 void TableView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
779 {
780   Toolkit::TableView tableView = Toolkit::TableView::DownCast( Dali::BaseHandle( object ) );
781
782   if( tableView )
783   {
784     TableView& tableViewImpl( GetImpl( tableView ) );
785     switch( index )
786     {
787       case Toolkit::TableView::Property::ROWS:
788       {
789         if( value.Get<unsigned int>() != tableViewImpl.GetRows() )
790         {
791           tableViewImpl.Resize( value.Get<unsigned int>(), tableViewImpl.GetColumns() );
792         }
793         break;
794       }
795       case Toolkit::TableView::Property::COLUMNS:
796       {
797         if( value.Get<unsigned int>() != tableViewImpl.GetColumns() )
798         {
799           tableViewImpl.Resize( tableViewImpl.GetRows(), value.Get<unsigned int>() );
800         }
801         break;
802       }
803       case Toolkit::TableView::Property::CELL_PADDING:
804       {
805         tableViewImpl.SetCellPadding( value.Get<Vector2>() );
806         break;
807       }
808       case Toolkit::TableView::Property::LAYOUT_ROWS:
809       {
810         SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedHeight, &TableView::SetRelativeHeight, value );
811         break;
812       }
813       case Toolkit::TableView::Property::LAYOUT_COLUMNS:
814       {
815         SetHeightOrWidthProperty( tableViewImpl, &TableView::SetFixedWidth, &TableView::SetRelativeWidth, value );
816         break;
817       }
818     }
819   }
820 }
821
822 Property::Value TableView::GetProperty( BaseObject* object, Property::Index index )
823 {
824   Property::Value value;
825
826   Toolkit::TableView tableView = Toolkit::TableView::DownCast( Dali::BaseHandle( object ) );
827
828   if( tableView )
829   {
830     TableView& tableViewImpl( GetImpl( tableView ) );
831     switch( index )
832     {
833       case Toolkit::TableView::Property::ROWS:
834       {
835         value = tableViewImpl.GetRows();
836         break;
837       }
838       case Toolkit::TableView::Property::COLUMNS:
839       {
840         value = tableViewImpl.GetColumns();
841         break;
842       }
843       case Toolkit::TableView::Property::CELL_PADDING:
844       {
845         value = tableViewImpl.GetCellPadding();
846         break;
847       }
848       case Toolkit::TableView::Property::LAYOUT_ROWS:
849       {
850         value = tableViewImpl.GetRowHeightsPropertyValue();
851         break;
852       }
853       case Toolkit::TableView::Property::LAYOUT_COLUMNS:
854       {
855         value = tableViewImpl.GetColumnWidthsPropertyValue();
856         break;
857       }
858     }
859   }
860
861   return value;
862 }
863
864 void TableView::OnControlChildAdd( Actor& child )
865 {
866   if( mLayoutingChild )
867   {
868     // we're in the middle of laying out children so no point doing anything here
869     return;
870   }
871
872   RelayoutRequest();
873
874   // Test properties on actor
875   Toolkit::TableView::CellPosition cellPosition;
876   if( child.GetPropertyIndex(Toolkit::TableView::ROW_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
877   {
878     cellPosition.rowSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::ROW_SPAN_PROPERTY_NAME) ).Get<float>() );
879   }
880
881   if( child.GetPropertyIndex(Toolkit::TableView::COLUMN_SPAN_PROPERTY_NAME) != Property::INVALID_INDEX )
882   {
883     cellPosition.columnSpan = static_cast<unsigned int>( child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::COLUMN_SPAN_PROPERTY_NAME) ).Get<float>() );
884   }
885
886   if( child.GetPropertyIndex(Toolkit::TableView::CELL_INDICES_PROPERTY_NAME) != Property::INVALID_INDEX )
887   {
888     Vector2 indices = child.GetProperty( child.GetPropertyIndex(Toolkit::TableView::CELL_INDICES_PROPERTY_NAME) ).Get<Vector2 >();
889     cellPosition.rowIndex = static_cast<unsigned int>( indices.x );
890     cellPosition.columnIndex = static_cast<unsigned int>( indices.y );
891
892     AddChild( child, cellPosition );
893
894     // Do not continue
895     return;
896   }
897
898   // Find the first available cell to store the actor in
899   const unsigned int rowCount = mCellData.GetRows();
900   const unsigned int columnCount = mCellData.GetColumns();
901   for( unsigned int row = 0; row < rowCount; ++row )
902   {
903     for( unsigned int column = 0; column < columnCount; ++column )
904     {
905       if( !(mCellData[ row ][ column ].actor) )
906       {
907         // Put the actor in the cell
908         CellData data;
909         data.actor = child;
910         data.position.columnIndex = column;
911         data.position.rowIndex = row;
912         mCellData[ row ][ column ] = data;
913
914         // Don't continue
915         return;
916       }
917     }
918   }
919
920   // No empty cells, so increase size of the table
921   unsigned int newColumnCount = ( columnCount > 0 ) ? columnCount : 1;
922   ResizeContainers( rowCount + 1, newColumnCount );
923
924   // Put the actor in the first cell of the new row
925   CellData data;
926   data.actor = child;
927   data.position.rowIndex = rowCount;
928   data.position.columnIndex = 0;
929   mCellData[ rowCount ][ 0 ] = data;
930 }
931
932 void TableView::OnControlChildRemove( Actor& child )
933 {
934   // dont process if we're in the middle of bigger operation like delete row, column or resize
935   if( !mLayoutingChild )
936   {
937     // relayout the table only if instances were found
938     if( RemoveAllInstances( child ) )
939     {
940       RelayoutRequest();
941     }
942   }
943 }
944
945 TableView::TableView( unsigned int initialRows, unsigned int initialColumns )
946 : Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS | REQUIRES_STYLE_CHANGE_SIGNALS ) ),
947   mCellData( initialRows, initialColumns ),
948   mLayoutingChild( false ),
949   mRowColumnDirty( true )     // Force recalculation first time
950 {
951   SetKeyboardNavigationSupport( true );
952   ResizeContainers( initialRows, initialColumns );
953 }
954
955 void TableView::OnInitialize()
956 {
957   // Make self as keyboard focusable and focus group
958   Actor self = Self();
959   self.SetKeyboardFocusable(true);
960   SetAsKeyboardFocusGroup(true);
961 }
962
963 void TableView::ResizeContainers( unsigned int rows, unsigned int columns )
964 {
965   std::vector<CellData> ignored;
966   ResizeContainers( rows, columns, ignored );
967 }
968
969 void TableView::ResizeContainers( unsigned int rows, unsigned int columns, std::vector<CellData>& removed )
970 {
971   // Resize cell data
972   mCellData.Resize( rows, columns, removed );
973
974   // We don't care if these go smaller, data will be regenerated or is not needed anymore
975   mRowData.Resize( rows );
976   mColumnData.Resize( columns );
977 }
978
979 void TableView::RemoveAndGetLostActors( const std::vector<CellData>& lost, std::vector<Actor>& removed,
980                                         unsigned int rowsRemoved, unsigned int columnsRemoved )
981 {
982   // iterate through all lost cells
983   std::vector< CellData >::const_iterator iter = lost.begin();
984   for( ; iter != lost.end(); ++iter )
985   {
986     // if it is a valid actor
987     if( (*iter).actor )
988     {
989       // is this actor still somewhere else in the table
990       Toolkit::TableView::CellPosition position;
991       if( FindChildPosition( (*iter).actor, position ) )
992       {
993         // it must be spanning multiple cells, position contains the top left most one
994         // check if position is left of the removed location
995         if( position.columnIndex < (*iter).position.columnIndex )
996         {
997           // if column span is greater than 1
998           if( mCellData[ position.rowIndex ][ position.columnIndex ].position.columnSpan > 1 )
999           {
1000             // decrease column span
1001             mCellData[ position.rowIndex ][ position.columnIndex ].position.columnSpan -= columnsRemoved;
1002           }
1003         }
1004         // check if position is left of the removed location
1005         if( position.rowIndex < (*iter).position.rowIndex )
1006         {
1007           // if row span is greater than 1
1008           if( mCellData[ position.rowIndex ][ position.columnIndex ].position.rowSpan > 1 )
1009           {
1010             // decrease row span
1011             mCellData[ position.rowIndex ][ position.columnIndex ].position.rowSpan -= rowsRemoved;
1012           }
1013         }
1014       }
1015       else
1016       {
1017         // this actor is gone for good
1018         // add actor to removed container
1019         removed.push_back( (*iter).actor );
1020         // we dont want the child actor anymore
1021         Self().Remove( (*iter).actor );
1022       }
1023     }
1024   }
1025 }
1026
1027 bool TableView::RemoveAllInstances( const Actor& child )
1028 {
1029   bool found = false;
1030   // walk through the layout data
1031   const unsigned int rowCount = mCellData.GetRows();
1032   const unsigned int columnCount = mCellData.GetColumns();
1033   for( unsigned int row = 0; row < rowCount; ++row )
1034   {
1035     for( unsigned int column = 0; column < columnCount; ++column )
1036     {
1037       if( mCellData[ row ][ column ].actor == child )
1038       {
1039         // clear the cell, NOTE that the cell might be spanning multiple cells
1040         mCellData[ row ][ column ] = CellData();
1041         found = true;
1042       }
1043     }
1044   }
1045   return found;
1046 }
1047
1048 void TableView::SetHeightOrWidthProperty(TableView& tableViewImpl,
1049                                          void(TableView::*funcFixed)(unsigned int, float),
1050                                          void(TableView::*funcRelative)(unsigned int, float),
1051                                          const Property::Value& value )
1052 {
1053   if( Property::MAP == value.GetType() )
1054   {
1055     Property::Map map = value.Get<Property::Map>();
1056     unsigned int rowIndex(0);
1057     for ( unsigned int i = 0, count = map.Count(); i < count; ++i )
1058     {
1059       Property::Value& item = map.GetValue(i);
1060
1061       if( std::istringstream(map.GetKey(i)) >> rowIndex  // the key is a number
1062           && Property::MAP == item.GetType())
1063       {
1064         if( item.HasKey( "policy" ) && item.HasKey( "value" ) )
1065         {
1066           Toolkit::TableView::LayoutPolicy policy = Scripting::GetEnumeration< Toolkit::TableView::LayoutPolicy >( item.GetValue("policy").Get<std::string>().c_str(), LAYOUT_POLICY_STRING_TABLE, LAYOUT_POLICY_STRING_TABLE_COUNT );
1067           if( policy == Toolkit::TableView::FIXED )
1068           {
1069             (tableViewImpl.*funcFixed)( rowIndex, item.GetValue("value").Get<float>() );
1070           }
1071           else if( policy == Toolkit::TableView::RELATIVE )
1072           {
1073             (tableViewImpl.*funcRelative)( rowIndex, item.GetValue("value").Get<float>() );
1074           }
1075         }
1076       }
1077     }
1078   }
1079 }
1080
1081 Property::Value TableView::GetRowHeightsPropertyValue()
1082 {
1083   Property::Map map;
1084   GetMapPropertyValue( mRowData, map);
1085   return Property::Value(map);
1086 }
1087
1088 Property::Value TableView::GetColumnWidthsPropertyValue()
1089 {
1090   Property::Map map;
1091   GetMapPropertyValue( mColumnData, map);
1092   return Property::Value(map);
1093 }
1094
1095 void TableView::GetMapPropertyValue( const RowColumnArray& data, Property::Map& map )
1096 {
1097   std::string fixedPolicy( Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIXED, LAYOUT_POLICY_STRING_TABLE, LAYOUT_POLICY_STRING_TABLE_COUNT ) );
1098   std::string relativePolicy( Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::RELATIVE, LAYOUT_POLICY_STRING_TABLE, LAYOUT_POLICY_STRING_TABLE_COUNT ) );
1099
1100   const RowColumnArray::SizeType count = data.Size();
1101   for( RowColumnArray::SizeType i = 0; i < count; i++ )
1102   {
1103     const RowColumnData& dataInstance = data[ i ];
1104
1105     switch( dataInstance.sizePolicy )
1106     {
1107       case FIXED:
1108       {
1109         Property::Map item;
1110         item[ "policy" ] = fixedPolicy;
1111         item[ "value" ] = dataInstance.size;
1112
1113         std::ostringstream ss;
1114         ss << i;
1115
1116         map[ ss.str() ] = item;
1117
1118         break;
1119       }
1120
1121       case FILL:
1122       {
1123         Property::Map item;
1124         item[ "policy" ] = relativePolicy;
1125         item[ "value" ] = dataInstance.fillRatio;
1126
1127         std::ostringstream ss;
1128         ss << i;
1129
1130         map[ ss.str() ] = item;
1131
1132         break;
1133       }
1134
1135       default:
1136       {
1137         break;
1138       }
1139     }
1140   }
1141 }
1142
1143 TableView::~TableView()
1144 {
1145   // nothing to do
1146 }
1147
1148 Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
1149 {
1150   Actor nextFocusableActor;
1151
1152   if ( !currentFocusedActor )
1153   {
1154     // Nothing is currently focused, so the child in the first cell should be focused.
1155     nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
1156   }
1157   else
1158   {
1159     Toolkit::TableView::CellPosition position;
1160     if( FindChildPosition( currentFocusedActor, position ) )
1161     {
1162       // The current focused actor is a child of TableView
1163       bool focusLost = false;
1164       int currentRow = position.rowIndex;
1165       int currentColumn = position.columnIndex;
1166       int numberOfColumns = GetColumns();
1167       int numberOfRows = GetRows();
1168
1169       switch ( direction )
1170       {
1171         case Toolkit::Control::KeyboardFocus::LEFT:
1172         {
1173           if(--currentColumn < 0)
1174           {
1175             currentColumn = numberOfColumns - 1;
1176             if(--currentRow < 0)
1177             {
1178               currentRow = loopEnabled ? numberOfRows - 1 : 0;
1179               focusLost = (currentRow == 0);
1180             }
1181           }
1182           break;
1183         }
1184         case Toolkit::Control::KeyboardFocus::RIGHT:
1185         {
1186           if(++currentColumn > numberOfColumns - 1)
1187           {
1188             currentColumn = 0;
1189             if(++currentRow > numberOfRows - 1)
1190             {
1191               currentRow = loopEnabled ? 0 : numberOfRows - 1;
1192               focusLost = (currentRow == numberOfRows - 1);
1193             }
1194           }
1195           break;
1196         }
1197         case Toolkit::Control::KeyboardFocus::UP:
1198         {
1199           if(--currentRow < 0)
1200           {
1201             currentRow = loopEnabled ? numberOfRows - 1 : 0;
1202             focusLost = (currentRow == 0);
1203           }
1204           break;
1205         }
1206         case Toolkit::Control::KeyboardFocus::DOWN:
1207
1208         {
1209           if(++currentRow > numberOfRows - 1)
1210           {
1211             currentRow = loopEnabled ? 0 : numberOfRows - 1;
1212             focusLost = (currentRow == numberOfRows - 1);
1213           }
1214           break;
1215         }
1216       }
1217
1218       // Move the focus if we haven't lost it.
1219       if(!focusLost)
1220       {
1221         nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
1222       }
1223     }
1224     else
1225     {
1226       // The current focused actor is not within table view, so the child in the first cell should be focused.
1227       nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
1228     }
1229   }
1230
1231   return nextFocusableActor;
1232 }
1233
1234 Vector3 TableView::GetNaturalSize()
1235 {
1236   // Natural size is the size of all fixed cell widths or heights. This ignores cells with relative heights.
1237   return Vector3( mFixedTotals.width, mFixedTotals.height, 1.0f );
1238 }
1239
1240 float TableView::CalculateChildSize( const Actor& child, Dimension::Type dimension )
1241 {
1242   CalculateRowColumnData();
1243
1244   const unsigned int rowCount = mCellData.GetRows();
1245   const unsigned int columnCount = mCellData.GetColumns();
1246
1247   for( unsigned int row = 0; row < rowCount; ++row )
1248   {
1249     for( unsigned int column = 0; column < columnCount; ++column )
1250     {
1251       // check if this cell has an actor
1252       Actor& actor = mCellData[ row ][ column ].actor;
1253
1254       if( actor && ( actor == child ) )
1255       {
1256         const Toolkit::TableView::CellPosition position = mCellData[ row ][ column ].position;
1257
1258         // If there is an actor and this is the main cell of the actor.
1259         // An actor can be in multiple cells if its row or columnspan is more than 1.
1260         if ( ( position.rowIndex == row ) && ( position.columnIndex == column ) )
1261         {
1262           switch( dimension )
1263           {
1264             case Dimension::WIDTH:
1265             {
1266               float cellSize = 0.0f;
1267
1268               // Accumulate the width
1269               for( unsigned int i = 0; i < position.columnSpan; ++i )
1270               {
1271                 DALI_ASSERT_DEBUG( column + i < mColumnData.Size() );
1272                 cellSize += mColumnData[ column + i ].size;
1273               }
1274
1275               // Apply padding
1276               cellSize -= mPadding.width * 2.0f;
1277               if( cellSize < 0.0f )
1278               {
1279                 cellSize = 0.0f;
1280               }
1281
1282               return cellSize;
1283             }
1284
1285             case Dimension::HEIGHT:
1286             {
1287               float cellSize = 0.0f;
1288
1289               // Accumulate the height
1290               for( unsigned int i = 0; i < position.rowSpan; ++i )
1291               {
1292                 DALI_ASSERT_DEBUG( row + i < mRowData.Size() );
1293                 cellSize += mRowData[ row + i ].size;
1294               }
1295
1296               // Apply padding
1297               cellSize -= mPadding.width * 2.0f;
1298               if( cellSize < 0.0f )
1299               {
1300                 cellSize = 0.0f;
1301               }
1302
1303               return cellSize;
1304             }
1305
1306             default:
1307             {
1308               return 0.0f;
1309             }
1310           }
1311         }
1312       }
1313     }
1314   }
1315
1316   return 0.0f;    // Child not found
1317 }
1318
1319 bool TableView::RelayoutDependentOnChildren( Dimension::Type dimension )
1320 {
1321   if ( Control::RelayoutDependentOnChildren( dimension ) )
1322   {
1323     return true;
1324   }
1325
1326   return FindFit( mRowData ) || FindFit( mColumnData );
1327 }
1328
1329 void TableView::SetCellAlignment( Toolkit::TableView::CellPosition position, HorizontalAlignment::Type horizontal, VerticalAlignment::Type vertical )
1330 {
1331   // Check if we need to expand our data array
1332   if( position.rowIndex >= mCellData.GetRows() )
1333   {
1334     // Only adding new rows
1335     ResizeContainers( position.rowIndex + 1, mCellData.GetColumns() );
1336   }
1337
1338   if( position.columnIndex >= mCellData.GetColumns() )
1339   {
1340     // Only adding new columns
1341     ResizeContainers( mCellData.GetRows(), position.columnIndex + 1 );
1342   }
1343
1344   // Set the alignment of the cell
1345   CellData& data = mCellData[ position.rowIndex ][ position.columnIndex ];
1346   data.horizontalAlignment = horizontal;
1347   data.verticalAlignment = vertical;
1348 }
1349
1350 void TableView::ComputeRelativeSizes( RowColumnArray& data )
1351 {
1352   // First pass: Count number of fill entries and calculate used relative space
1353   Dali::Vector< RowColumnData* > fillData;
1354   float relativeTotal = 0.0f;
1355
1356   const unsigned int dataCount = data.Size();
1357
1358   for( unsigned int i = 0; i < dataCount; ++i )
1359   {
1360     RowColumnData& dataInstance = data[ i ];
1361
1362     if( dataInstance.sizePolicy == FILL )
1363     {
1364       if( dataInstance.userFillRatio )
1365       {
1366         relativeTotal += dataInstance.fillRatio;
1367       }
1368       else
1369       {
1370         fillData.PushBack( &dataInstance );
1371       }
1372     }
1373   }
1374
1375   // Second pass: Distribute remaining relative space
1376   const unsigned int fillCount = fillData.Size();
1377   if( fillCount > 0 )
1378   {
1379     if( relativeTotal > 1.0f )
1380     {
1381       relativeTotal = 1.0f;
1382     }
1383
1384     const float evenFillRatio = (1.0f - relativeTotal ) / fillCount;
1385
1386     for( unsigned int i = 0; i < fillCount; ++i )
1387     {
1388       fillData[ i ]->fillRatio = evenFillRatio;
1389     }
1390   }
1391 }
1392
1393 float TableView::CalculateTotalFixedSize( const RowColumnArray& data )
1394 {
1395   float totalSize = 0.0f;
1396
1397   const unsigned int dataCount = data.Size();
1398
1399   for( unsigned int i = 0; i < dataCount; ++i )
1400   {
1401     const RowColumnData& dataInstance = data[ i ];
1402
1403     switch( dataInstance.sizePolicy )
1404     {
1405       case FIXED:
1406       case FIT:
1407       {
1408         totalSize += dataInstance.size;
1409         break;
1410       }
1411
1412       default:
1413       {
1414         break;
1415       }
1416     }
1417   }
1418
1419   return totalSize;
1420 }
1421
1422 Vector2 TableView::GetCellPadding( Dimension::Type dimension )
1423 {
1424   switch( dimension )
1425   {
1426     case Dimension::WIDTH:
1427     {
1428       return Vector2( mPadding.x, mPadding.x );
1429     }
1430     case Dimension::HEIGHT:
1431     {
1432       return Vector2( mPadding.y, mPadding.y );
1433     }
1434     default:
1435     {
1436       break;
1437     }
1438   }
1439
1440   return Vector2();
1441 }
1442
1443 void TableView::CalculateFixedSizes( RowColumnArray& data, Dimension::Type dimension )
1444 {
1445   Vector2 cellPadding = GetCellPadding( dimension );
1446
1447   const unsigned int dataCount = data.Size();
1448
1449   for( unsigned int i = 0; i < dataCount; ++i )
1450   {
1451     RowColumnData& dataInstance = data[ i ];
1452
1453     if( dataInstance.sizePolicy == FIT )
1454     {
1455       // Find the size of the biggest actor in the row or column
1456       float maxActorHeight = 0.0f;
1457
1458       unsigned int fitCount = ( dimension == Dimension::WIDTH ) ? mCellData.GetRows() : mCellData.GetColumns();
1459
1460       for( unsigned int j = 0; j < fitCount; ++j )
1461       {
1462         unsigned int row = ( dimension == Dimension::WIDTH ) ? j : i;
1463         unsigned int column = ( dimension == Dimension::WIDTH ) ? i : j;
1464         DALI_ASSERT_DEBUG( row < mCellData.GetRows() );
1465         DALI_ASSERT_DEBUG( column < mCellData.GetColumns() );
1466
1467         const CellData& cellData = mCellData[ row ][ column ];
1468         const Actor& actor = cellData.actor;
1469         if( actor )
1470         {
1471           if( FitToChild( actor, dimension ) && ( dimension == Dimension::WIDTH ) ? ( cellData.position.columnSpan == 1 ) : ( cellData.position.rowSpan == 1 )  )
1472           {
1473             maxActorHeight = std::max( maxActorHeight, actor.GetRelayoutSize( dimension ) + cellPadding.x + cellPadding.y );
1474           }
1475         }
1476       }
1477
1478       dataInstance.size = maxActorHeight;
1479     }
1480   }
1481 }
1482
1483 void TableView::CalculateRelativeSizes( RowColumnArray& data, float size )
1484 {
1485   const unsigned int dataCount = data.Size();
1486
1487   for( unsigned int i = 0; i < dataCount; ++i )
1488   {
1489     RowColumnData& dataInstance = data[ i ];
1490
1491     if( dataInstance.sizePolicy == FILL )
1492     {
1493       dataInstance.size = dataInstance.fillRatio * size;
1494     }
1495   }
1496 }
1497
1498 bool TableView::FindFit( const RowColumnArray& data )
1499 {
1500   for( unsigned int i = 0, count = data.Size(); i < count; ++i )
1501   {
1502     if( data[ i ].sizePolicy == FIT )
1503     {
1504       return true;
1505     }
1506   }
1507
1508   return false;
1509 }
1510
1511 } // namespace Internal
1512
1513 } // namespace Toolkit
1514
1515 } // namespace Dali