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