Remove dali-any from Property::Value
[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 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   Property::Map* map = value.GetMap();
1054   if( map )
1055   {
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       Property::Map* childMap = item.GetMap();
1061
1062       std::istringstream( map->GetKey(i) ) >> rowIndex;
1063       if( childMap )
1064       {
1065         Property::Value* policy = childMap->Find( "policy" );
1066         Property::Value* value = childMap->Find( "value" );
1067         if( policy && value )
1068         {
1069           std::string policyValue;
1070           policy->Get( policyValue );
1071           Toolkit::TableView::LayoutPolicy policy;
1072           if( Scripting::GetEnumeration< Toolkit::TableView::LayoutPolicy >( policyValue.c_str(),
1073                                                                              LAYOUT_POLICY_STRING_TABLE,
1074                                                                              LAYOUT_POLICY_STRING_TABLE_COUNT,
1075                                                                              policy ) )
1076           {
1077             if( policy == Toolkit::TableView::FIXED )
1078             {
1079               (tableViewImpl.*funcFixed)( rowIndex, value->Get<float>() );
1080             }
1081             else if( policy == Toolkit::TableView::RELATIVE )
1082             {
1083               (tableViewImpl.*funcRelative)( rowIndex, value->Get<float>() );
1084             }
1085           }
1086         }
1087       }
1088     }
1089   }
1090 }
1091
1092 Property::Value TableView::GetRowHeightsPropertyValue()
1093 {
1094   Property::Map map;
1095   GetMapPropertyValue( mRowData, map);
1096   return Property::Value(map);
1097 }
1098
1099 Property::Value TableView::GetColumnWidthsPropertyValue()
1100 {
1101   Property::Map map;
1102   GetMapPropertyValue( mColumnData, map);
1103   return Property::Value(map);
1104 }
1105
1106 void TableView::GetMapPropertyValue( const RowColumnArray& data, Property::Map& map )
1107 {
1108   const char* name = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::FIXED,
1109                                                                                         LAYOUT_POLICY_STRING_TABLE,
1110                                                                                         LAYOUT_POLICY_STRING_TABLE_COUNT );
1111   std::string fixedPolicy;
1112   if( name )
1113   {
1114     fixedPolicy = name;
1115   }
1116   name = Scripting::GetEnumerationName< Toolkit::TableView::LayoutPolicy >( Toolkit::TableView::RELATIVE,
1117                                                                             LAYOUT_POLICY_STRING_TABLE,
1118                                                                             LAYOUT_POLICY_STRING_TABLE_COUNT );
1119   std::string relativePolicy;
1120   if( name )
1121   {
1122     relativePolicy = name;
1123   }
1124
1125   const RowColumnArray::SizeType count = data.Size();
1126   for( RowColumnArray::SizeType i = 0; i < count; i++ )
1127   {
1128     const RowColumnData& dataInstance = data[ i ];
1129
1130     switch( dataInstance.sizePolicy )
1131     {
1132       case FIXED:
1133       {
1134         Property::Map item;
1135         item[ "policy" ] = fixedPolicy;
1136         item[ "value" ] = dataInstance.size;
1137
1138         std::ostringstream ss;
1139         ss << i;
1140
1141         map[ ss.str() ] = item;
1142
1143         break;
1144       }
1145
1146       case FILL:
1147       {
1148         Property::Map item;
1149         item[ "policy" ] = relativePolicy;
1150         item[ "value" ] = dataInstance.fillRatio;
1151
1152         std::ostringstream ss;
1153         ss << i;
1154
1155         map[ ss.str() ] = item;
1156
1157         break;
1158       }
1159
1160       default:
1161       {
1162         break;
1163       }
1164     }
1165   }
1166 }
1167
1168 TableView::~TableView()
1169 {
1170   // nothing to do
1171 }
1172
1173 Actor TableView::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
1174 {
1175   Actor nextFocusableActor;
1176
1177   if ( !currentFocusedActor )
1178   {
1179     // Nothing is currently focused, so the child in the first cell should be focused.
1180     nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
1181   }
1182   else
1183   {
1184     Toolkit::TableView::CellPosition position;
1185     if( FindChildPosition( currentFocusedActor, position ) )
1186     {
1187       // The current focused actor is a child of TableView
1188       bool focusLost = false;
1189       int currentRow = position.rowIndex;
1190       int currentColumn = position.columnIndex;
1191       int numberOfColumns = GetColumns();
1192       int numberOfRows = GetRows();
1193
1194       switch ( direction )
1195       {
1196         case Toolkit::Control::KeyboardFocus::LEFT:
1197         {
1198           if(--currentColumn < 0)
1199           {
1200             currentColumn = numberOfColumns - 1;
1201             if(--currentRow < 0)
1202             {
1203               currentRow = loopEnabled ? numberOfRows - 1 : 0;
1204               focusLost = (currentRow == 0);
1205             }
1206           }
1207           break;
1208         }
1209         case Toolkit::Control::KeyboardFocus::RIGHT:
1210         {
1211           if(++currentColumn > numberOfColumns - 1)
1212           {
1213             currentColumn = 0;
1214             if(++currentRow > numberOfRows - 1)
1215             {
1216               currentRow = loopEnabled ? 0 : numberOfRows - 1;
1217               focusLost = (currentRow == numberOfRows - 1);
1218             }
1219           }
1220           break;
1221         }
1222         case Toolkit::Control::KeyboardFocus::UP:
1223         {
1224           if(--currentRow < 0)
1225           {
1226             currentRow = loopEnabled ? numberOfRows - 1 : 0;
1227             focusLost = (currentRow == 0);
1228           }
1229           break;
1230         }
1231         case Toolkit::Control::KeyboardFocus::DOWN:
1232
1233         {
1234           if(++currentRow > numberOfRows - 1)
1235           {
1236             currentRow = loopEnabled ? 0 : numberOfRows - 1;
1237             focusLost = (currentRow == numberOfRows - 1);
1238           }
1239           break;
1240         }
1241       }
1242
1243       // Move the focus if we haven't lost it.
1244       if(!focusLost)
1245       {
1246         nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(currentRow, currentColumn));
1247       }
1248     }
1249     else
1250     {
1251       // The current focused actor is not within table view, so the child in the first cell should be focused.
1252       nextFocusableActor = GetChildAt(Toolkit::TableView::CellPosition(0, 0));
1253     }
1254   }
1255
1256   return nextFocusableActor;
1257 }
1258
1259 Vector3 TableView::GetNaturalSize()
1260 {
1261   // Natural size is the size of all fixed cell widths or heights. This ignores cells with relative heights.
1262   return Vector3( mFixedTotals.width, mFixedTotals.height, 1.0f );
1263 }
1264
1265 float TableView::CalculateChildSize( const Actor& child, Dimension::Type dimension )
1266 {
1267   CalculateRowColumnData();
1268
1269   const unsigned int rowCount = mCellData.GetRows();
1270   const unsigned int columnCount = mCellData.GetColumns();
1271
1272   for( unsigned int row = 0; row < rowCount; ++row )
1273   {
1274     for( unsigned int column = 0; column < columnCount; ++column )
1275     {
1276       // check if this cell has an actor
1277       Actor& actor = mCellData[ row ][ column ].actor;
1278
1279       if( actor && ( actor == child ) )
1280       {
1281         const Toolkit::TableView::CellPosition position = mCellData[ row ][ column ].position;
1282
1283         // If there is an actor and this is the main cell of the actor.
1284         // An actor can be in multiple cells if its row or columnspan is more than 1.
1285         if ( ( position.rowIndex == row ) && ( position.columnIndex == column ) )
1286         {
1287           switch( dimension )
1288           {
1289             case Dimension::WIDTH:
1290             {
1291               float cellSize = 0.0f;
1292
1293               // Accumulate the width
1294               for( unsigned int i = 0; i < position.columnSpan; ++i )
1295               {
1296                 DALI_ASSERT_DEBUG( column + i < mColumnData.Size() );
1297                 cellSize += mColumnData[ column + i ].size;
1298               }
1299
1300               // Apply padding
1301               cellSize -= mPadding.width * 2.0f;
1302               if( cellSize < 0.0f )
1303               {
1304                 cellSize = 0.0f;
1305               }
1306
1307               return cellSize;
1308             }
1309
1310             case Dimension::HEIGHT:
1311             {
1312               float cellSize = 0.0f;
1313
1314               // Accumulate the height
1315               for( unsigned int i = 0; i < position.rowSpan; ++i )
1316               {
1317                 DALI_ASSERT_DEBUG( row + i < mRowData.Size() );
1318                 cellSize += mRowData[ row + i ].size;
1319               }
1320
1321               // Apply padding
1322               cellSize -= mPadding.width * 2.0f;
1323               if( cellSize < 0.0f )
1324               {
1325                 cellSize = 0.0f;
1326               }
1327
1328               return cellSize;
1329             }
1330
1331             default:
1332             {
1333               return 0.0f;
1334             }
1335           }
1336         }
1337       }
1338     }
1339   }
1340
1341   return 0.0f;    // Child not found
1342 }
1343
1344 bool TableView::RelayoutDependentOnChildren( Dimension::Type dimension )
1345 {
1346   if ( Control::RelayoutDependentOnChildren( dimension ) )
1347   {
1348     return true;
1349   }
1350
1351   return FindFit( mRowData ) || FindFit( mColumnData );
1352 }
1353
1354 void TableView::SetCellAlignment( Toolkit::TableView::CellPosition position, HorizontalAlignment::Type horizontal, VerticalAlignment::Type vertical )
1355 {
1356   // Check if we need to expand our data array
1357   if( position.rowIndex >= mCellData.GetRows() )
1358   {
1359     // Only adding new rows
1360     ResizeContainers( position.rowIndex + 1, mCellData.GetColumns() );
1361   }
1362
1363   if( position.columnIndex >= mCellData.GetColumns() )
1364   {
1365     // Only adding new columns
1366     ResizeContainers( mCellData.GetRows(), position.columnIndex + 1 );
1367   }
1368
1369   // Set the alignment of the cell
1370   CellData& data = mCellData[ position.rowIndex ][ position.columnIndex ];
1371   data.horizontalAlignment = horizontal;
1372   data.verticalAlignment = vertical;
1373 }
1374
1375 void TableView::ComputeRelativeSizes( RowColumnArray& data )
1376 {
1377   // First pass: Count number of fill entries and calculate used relative space
1378   Dali::Vector< RowColumnData* > fillData;
1379   float relativeTotal = 0.0f;
1380
1381   const unsigned int dataCount = data.Size();
1382
1383   for( unsigned int i = 0; i < dataCount; ++i )
1384   {
1385     RowColumnData& dataInstance = data[ i ];
1386
1387     if( dataInstance.sizePolicy == FILL )
1388     {
1389       if( dataInstance.userFillRatio )
1390       {
1391         relativeTotal += dataInstance.fillRatio;
1392       }
1393       else
1394       {
1395         fillData.PushBack( &dataInstance );
1396       }
1397     }
1398   }
1399
1400   // Second pass: Distribute remaining relative space
1401   const unsigned int fillCount = fillData.Size();
1402   if( fillCount > 0 )
1403   {
1404     if( relativeTotal > 1.0f )
1405     {
1406       relativeTotal = 1.0f;
1407     }
1408
1409     const float evenFillRatio = (1.0f - relativeTotal ) / fillCount;
1410
1411     for( unsigned int i = 0; i < fillCount; ++i )
1412     {
1413       fillData[ i ]->fillRatio = evenFillRatio;
1414     }
1415   }
1416 }
1417
1418 float TableView::CalculateTotalFixedSize( const RowColumnArray& data )
1419 {
1420   float totalSize = 0.0f;
1421
1422   const unsigned int dataCount = data.Size();
1423
1424   for( unsigned int i = 0; i < dataCount; ++i )
1425   {
1426     const RowColumnData& dataInstance = data[ i ];
1427
1428     switch( dataInstance.sizePolicy )
1429     {
1430       case FIXED:
1431       case FIT:
1432       {
1433         totalSize += dataInstance.size;
1434         break;
1435       }
1436
1437       default:
1438       {
1439         break;
1440       }
1441     }
1442   }
1443
1444   return totalSize;
1445 }
1446
1447 Vector2 TableView::GetCellPadding( Dimension::Type dimension )
1448 {
1449   switch( dimension )
1450   {
1451     case Dimension::WIDTH:
1452     {
1453       return Vector2( mPadding.x, mPadding.x );
1454     }
1455     case Dimension::HEIGHT:
1456     {
1457       return Vector2( mPadding.y, mPadding.y );
1458     }
1459     default:
1460     {
1461       break;
1462     }
1463   }
1464
1465   return Vector2();
1466 }
1467
1468 void TableView::CalculateFixedSizes( RowColumnArray& data, Dimension::Type dimension )
1469 {
1470   Vector2 cellPadding = GetCellPadding( dimension );
1471
1472   const unsigned int dataCount = data.Size();
1473
1474   for( unsigned int i = 0; i < dataCount; ++i )
1475   {
1476     RowColumnData& dataInstance = data[ i ];
1477
1478     if( dataInstance.sizePolicy == FIT )
1479     {
1480       // Find the size of the biggest actor in the row or column
1481       float maxActorHeight = 0.0f;
1482
1483       unsigned int fitCount = ( dimension == Dimension::WIDTH ) ? mCellData.GetRows() : mCellData.GetColumns();
1484
1485       for( unsigned int j = 0; j < fitCount; ++j )
1486       {
1487         unsigned int row = ( dimension == Dimension::WIDTH ) ? j : i;
1488         unsigned int column = ( dimension == Dimension::WIDTH ) ? i : j;
1489         DALI_ASSERT_DEBUG( row < mCellData.GetRows() );
1490         DALI_ASSERT_DEBUG( column < mCellData.GetColumns() );
1491
1492         const CellData& cellData = mCellData[ row ][ column ];
1493         const Actor& actor = cellData.actor;
1494         if( actor )
1495         {
1496           if( FitToChild( actor, dimension ) && ( dimension == Dimension::WIDTH ) ? ( cellData.position.columnSpan == 1 ) : ( cellData.position.rowSpan == 1 )  )
1497           {
1498             maxActorHeight = std::max( maxActorHeight, actor.GetRelayoutSize( dimension ) + cellPadding.x + cellPadding.y );
1499           }
1500         }
1501       }
1502
1503       dataInstance.size = maxActorHeight;
1504     }
1505   }
1506 }
1507
1508 void TableView::CalculateRelativeSizes( RowColumnArray& data, float size )
1509 {
1510   const unsigned int dataCount = data.Size();
1511
1512   for( unsigned int i = 0; i < dataCount; ++i )
1513   {
1514     RowColumnData& dataInstance = data[ i ];
1515
1516     if( dataInstance.sizePolicy == FILL )
1517     {
1518       dataInstance.size = dataInstance.fillRatio * size;
1519     }
1520   }
1521 }
1522
1523 bool TableView::FindFit( const RowColumnArray& data )
1524 {
1525   for( unsigned int i = 0, count = data.Size(); i < count; ++i )
1526   {
1527     if( data[ i ].sizePolicy == FIT )
1528     {
1529       return true;
1530     }
1531   }
1532
1533   return false;
1534 }
1535
1536 } // namespace Internal
1537
1538 } // namespace Toolkit
1539
1540 } // namespace Dali