[dali_2.0.25] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / table-view / table-view-impl.h
1 #ifndef DALI_TOOLKIT_INTERNAL_TABLE_VIEW_H
2 #define DALI_TOOLKIT_INTERNAL_TABLE_VIEW_H
3
4 /*
5  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/object/weak-handle.h>
23
24 // INTERNAL INCLUDES
25 #include <dali-toolkit/devel-api/controls/table-view/table-view.h>
26 #include <dali-toolkit/public-api/controls/control-impl.h>
27 #include "array-2d.h"
28
29 namespace Dali
30 {
31 namespace Toolkit
32 {
33 namespace Internal
34 {
35 /**
36  * TableView is a custom control for laying out actors in a table layout
37  * @see Dali::Toolkit:TableView for more details
38  */
39 class TableView : public Control
40 {
41 public:
42   /**
43    * Create a new TableView.
44    * @return A smart-pointer to the newly allocated TableView.
45    */
46   static Toolkit::TableView New(unsigned int initialRows, unsigned int initialColumns);
47
48   /**
49    * @copydoc Toolkit::TableView::AddChild
50    */
51   bool AddChild(Actor& child, const Toolkit::TableView::CellPosition& position);
52
53   /**
54    * @copydoc Toolkit::TableView::GetChildAt
55    */
56   Actor GetChildAt(const Toolkit::TableView::CellPosition& position);
57
58   /**
59    * @copydoc Toolkit::TableView::RemoveChildAt
60    */
61   Actor RemoveChildAt(const Toolkit::TableView::CellPosition& position);
62
63   /**
64    * @copydoc Toolkit::TableView::FindChildPosition
65    */
66   bool FindChildPosition(const Actor& child, Toolkit::TableView::CellPosition& positionOut);
67
68   /**
69    * @copydoc Toolkit::TableView::InsertRow
70    */
71   void InsertRow(unsigned int rowIndex);
72
73   /**
74    * @copydoc Toolkit::TableView::DeleteRow( unsigned int rowIndex )
75    */
76   void DeleteRow(unsigned int rowIndex);
77
78   /**
79    * @copydoc Toolkit::TableView::DeleteRow( unsigned int rowIndex, std::vector<Actor>& removed )
80    */
81   void DeleteRow(unsigned int rowIndex, std::vector<Actor>& removed);
82
83   /**
84    * @copydoc Toolkit::TableView::InsertColumn
85    */
86   void InsertColumn(unsigned int columnIndex);
87
88   /**
89    * @copydoc Toolkit::TableView::DeleteColumn( unsigned int columnIndex )
90    */
91   void DeleteColumn(unsigned int columnIndex);
92
93   /**
94    * @copydoc Toolkit::TableView::DeleteColumn( unsigned int columnIndex, std::vector<Actor>& removed )
95    */
96   void DeleteColumn(unsigned int columnIndex, std::vector<Actor>& removed);
97
98   /**
99    * @copydoc Toolkit::TableView::Resize( unsigned int rows, unsigned int columns )
100    */
101   void Resize(unsigned int rows, unsigned int columns);
102
103   /**
104    * @copydoc Toolkit::TableView::Resize( unsigned int rows, unsigned int columns, std::vector<Actor>& removed )
105    */
106   void Resize(unsigned int rows, unsigned int columns, std::vector<Actor>& removed);
107
108   /**
109    * @copydoc Toolkit::TableView::SetCellPadding
110    */
111   void SetCellPadding(Size padding);
112
113   /**
114    * @copydoc Toolkit::TableView::GetCellPadding
115    */
116   Size GetCellPadding();
117
118   /**
119    * @copydoc Toolkit::TableView::SetFitHeight
120    */
121   void SetFitHeight(unsigned int rowIndex);
122
123   /**
124    * @copydoc Toolkit::TableView::IsFitHeight
125    */
126   bool IsFitHeight(unsigned int rowIndex) const;
127
128   /**
129    * @copydoc Toolkit::TableView::SetFitWidth
130    */
131   void SetFitWidth(unsigned int columnIndex);
132
133   /**
134    * @copydoc Toolkit::TableView::IsFitWidth
135    */
136   bool IsFitWidth(unsigned int columnIndex) const;
137
138   /**
139    * @copydoc Toolkit::TableView::SetFixedWidth
140    */
141   void SetFixedWidth(unsigned int columnIndex, float width);
142
143   /**
144    * @copydoc Toolkit::TableView::GetFixedWidth
145    */
146   float GetFixedWidth(unsigned int columnIndex) const;
147
148   /**
149    * @copydoc Toolkit::TableView::SetFixedHeight
150    */
151   void SetFixedHeight(unsigned int rowIndex, float height);
152
153   /**
154    * @copydoc Toolkit::TableView::GetFixedHeight
155    */
156   float GetFixedHeight(unsigned int rowIndex) const;
157
158   /**
159    * @copydoc Toolkit::TableView::SetRelativeHeight
160    */
161   void SetRelativeHeight(unsigned int rowIndex, float heightPercentage);
162
163   /**
164    * @copydoc Toolkit::TableView::GetRelativeHeight
165    */
166   float GetRelativeHeight(unsigned int rowIndex) const;
167
168   /**
169    * @copydoc Toolkit::TableView::SetRelativeWidth
170    */
171   void SetRelativeWidth(unsigned int columnIndex, float widthPercentage);
172
173   /**
174    * @copydoc Toolkit::TableView::GetRelativeWidth
175    */
176   float GetRelativeWidth(unsigned int columnIndex) const;
177
178   /**
179    * @copydoc Toolkit::TableView::GetRows
180    */
181   unsigned int GetRows();
182
183   /**
184    * @copydoc Toolkit::TableView::GetColumns
185    */
186   unsigned int GetColumns();
187
188   /**
189    * @copydoc Toolkit::TableView::SetCellAlignment
190    */
191   void SetCellAlignment(Toolkit::TableView::CellPosition position, HorizontalAlignment::Type horizontal, VerticalAlignment::Type vertical);
192
193   // Properties
194
195   /**
196    * Called when a property of an object of this type is set.
197    * @param[in] object The object whose property is set.
198    * @param[in] index The property index.
199    * @param[in] value The new property value.
200    */
201   static void SetProperty(BaseObject* object, Property::Index index, const Property::Value& value);
202
203   /**
204    * Called to retrieve a property of an object of this type.
205    * @param[in] object The object whose property is to be retrieved.
206    * @param[in] index The property index.
207    * @return The current value of the property.
208    */
209   static Property::Value GetProperty(BaseObject* object, Property::Index index);
210
211 private: // From Control
212   /**
213    * @copydoc Control::OnChildAdd(Actor& child)
214    */
215   void OnChildAdd(Actor& child) override;
216
217   /**
218    * @copydoc Control::OnChildRemove(Actor& child)
219    */
220   void OnChildRemove(Actor& child) override;
221
222   /**
223    * @copydoc Control::OnRelayout
224    */
225   void OnRelayout(const Vector2& size, RelayoutContainer& container) override;
226
227   /**
228    * @copydoc Control::CalculateChildSize
229    */
230   float CalculateChildSize(const Actor& child, Dimension::Type dimension) override;
231
232   /**
233    * @copydoc Control::OnInitialize()
234    */
235   void OnInitialize() override;
236
237   /**
238    * @copydoc Control::GetNextKeyboardFocusableActor
239    */
240   Actor GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled) override;
241
242   /**
243    * @copydoc Control::GetNaturalSize()
244    */
245   Vector3 GetNaturalSize() override;
246
247   /**
248    * @copydoc Control::RelayoutDependentOnChildren()
249    */
250   bool RelayoutDependentOnChildren(Dimension::Type dimension = Dimension::ALL_DIMENSIONS) override;
251
252   /**
253    * @copydoc Control::OnCalculateRelayoutSize
254    */
255   void OnCalculateRelayoutSize(Dimension::Type dimension) override;
256
257   /**
258    * @copydoc Control::OnLayoutNegotiated
259    */
260   void OnLayoutNegotiated(float size, Dimension::Type dimension) override;
261
262   /**
263    * @copydoc CustomActorImpl::OnSizeSet( const Vector3& size )
264    */
265   void OnSizeSet(const Vector3& size) override;
266
267 private: // Implementation
268   /**
269    * Struct to hold data for rows and columns
270    *
271    * If sizePolicy is FIXED then size is the absolute size to use.
272    * If sizePolicy is FIT, RELATIVE or FILL then size is the calculated value of size.
273    */
274   struct RowColumnData
275   {
276     /**
277      * Default constructor
278      */
279     RowColumnData()
280     : size(0.0f),
281       fillRatio(0.0f),
282       position(0.0f),
283       sizePolicy(Toolkit::TableView::FILL)
284     {
285     }
286
287     /**
288      * Constructor
289      *
290      * @param[in] newSize The size to set for this data
291      * @param[in] newSizePolicy The policy used to interpret the size value
292      */
293     RowColumnData(float newSize, float newFillRatio, Toolkit::TableView::LayoutPolicy newSizePolicy)
294     : size(newSize),
295       fillRatio(newFillRatio),
296       position(0.0f),
297       sizePolicy(newSizePolicy)
298     {
299     }
300
301     float                            size;       ///< Set or calculated size
302     float                            fillRatio;  ///< Ratio to fill remaining space, only valid with RELATIVE or FILL policy
303     float                            position;   ///< Position of the row/column, this value is updated during every Relayout round
304     Toolkit::TableView::LayoutPolicy sizePolicy; ///< The size policy used to interpret the size value
305   };
306
307   typedef Dali::Vector<RowColumnData> RowColumnArray;
308
309 public:
310   /**
311    * Structure for the layout data
312    */
313   struct CellData
314   {
315     CellData()
316     : horizontalAlignment(HorizontalAlignment::LEFT),
317       verticalAlignment(VerticalAlignment::TOP)
318     {
319     }
320
321     // data members
322     Dali::Actor                      actor;
323     Toolkit::TableView::CellPosition position;
324     HorizontalAlignment::Type        horizontalAlignment;
325     VerticalAlignment::Type          verticalAlignment;
326   };
327
328 private:
329   /**
330    * Construct a new TableView.
331    */
332   TableView(unsigned int initialRows, unsigned int initialColumns);
333
334   /**
335    * Resizes the data containers to match the new size
336    * @param [in] rows in the table
337    * @param [in] columns in the table
338    */
339   void ResizeContainers(unsigned int rows, unsigned int columns);
340
341   /**
342    * Resizes the data containers to match the new size
343    * @param [in] rows in the table
344    * @param [in] columns in the table
345    * @param [out] removed celldata
346    */
347   void ResizeContainers(unsigned int rows, unsigned int columns, std::vector<CellData>& removed);
348
349   /**
350    * Helper to get the list of lost actors in the case when table looses cells.
351    * Also handles the case when actors span multiple cells
352    * @param lost cells
353    * @param removed actors
354    * @param rowsRemoved from table
355    * @param columnsRemoved from table
356    */
357   void RemoveAndGetLostActors(const std::vector<CellData>& lost, std::vector<Actor>& removed, unsigned int rowsRemoved, unsigned int columnsRemoved);
358
359   /**
360    * Helper to remove all instances of the actor
361    * @param child actor to remove
362    * @return true if the actor was found
363    */
364   bool RemoveAllInstances(const Actor& child);
365
366   /**
367    * @brief Calculate the ratio of FILL rows/columns
368    *
369    * @param[in] data The RowColumn data to compute the relative sizes for
370    */
371   void CalculateFillSizes(RowColumnArray& data);
372
373   /**
374    * @brief Calculate the total fixed sizes for a row or column
375    *
376    * @param[in] data The row or column data to process
377    */
378   float CalculateTotalFixedSize(const RowColumnArray& data);
379
380   /**
381    * @brief Calculate the sizes of FIT rows/columns
382    *
383    * @param[in] data The row or column data to process
384    * @param[in] dimension The dimension being calculated: row == Dimension::HEIGHT, column == Dimension::WIDTH
385    */
386   void CalculateFitSizes(RowColumnArray& data, Dimension::Type dimension);
387
388   /**
389    * @brief Search for a FIT cell in the array
390    *
391    * @param[in] data The row or column data to process
392    * @return Return if a FIT cell was found or not
393    */
394   bool FindFit(const RowColumnArray& data);
395
396   /**
397    * @brief Return the cell padding for a given dimension
398    *
399    * @param[in] dimension The dimension to return the padding for
400    * @return Return the padding (x = low, y = high)
401    */
402   Vector2 GetCellPadding(Dimension::Type dimension);
403
404   /**
405    * A reference counted object may only be deleted by calling Unreference()
406    */
407   virtual ~TableView();
408
409 private: // scripting support
410   /**
411    * Called to set the heights/widths property.
412    * @param[in] tableViewImpl The object whose property is set.
413    * @param[in] funcFixed The set function to call, it can be SetFixedHeight or SetFixedWidth.
414    * @param[in] funcRelative The set function to call, it can be SetRelativeHeight or SetRelativeWidth.
415    * @param[in] funcFit The set function to call, it can be SetFitHeight or SetFiltWidth.
416    * @param[in] value The new property value.
417    */
418   static void SetHeightOrWidthProperty(TableView& tableViewImpl,
419                                        void (TableView::*funcFixed)(unsigned int, float),
420                                        void (TableView::*funcRelative)(unsigned int, float),
421                                        void (TableView::*funcFit)(unsigned int),
422                                        const Property::Value& map);
423
424   /**
425    * Called to retrieve the property value of row heights.
426    * @return The property value of row heights.
427    */
428   Property::Value GetRowHeightsPropertyValue();
429
430   /**
431    * Called to retrieve the property value of column widths.
432    * @return The fixed-widths property value.
433    */
434   Property::Value GetColumnWidthsPropertyValue();
435
436   /**
437    * Generate the map type property value from the size vectors.
438    * @param[in] data The array of row or column data
439    * @param[out] map The property value.
440    */
441   void GetMapPropertyValue(const RowColumnArray& data, Property::Map& map);
442
443   /**
444    * Helper class to prevent child adds and removes from causing relayout
445    * when we're already anyways going to do one in the end
446    */
447   class RelayoutingLock
448   {
449   public: // API
450     /**
451      * Constructor, sets the lock boolean
452      */
453     RelayoutingLock(TableView& parent)
454     : mLock(parent.mLayoutingChild)
455     {
456       mLock = true;
457     }
458
459     /**
460      * Destructor, releases lock boolean
461      */
462     ~RelayoutingLock()
463     {
464       mLock = false;
465       // Note, we could also call Relayout here. This would save one line of code
466       // from each method that uses this lock but destructors are not meant to do
467       // big processing so better to not do it here. This destructor would also
468       // be called in case of an exception and we don't definitely want to do Relayout
469       // in that situation
470     }
471
472   private:
473     bool& mLock;
474   };
475
476 private:
477   // Undefined copy constructor and assignment operators
478   TableView(const TableView&);
479   TableView& operator=(const TableView& rhs);
480
481 private:                       // Data
482   Array2d<CellData> mCellData; ///< Data for each cell: Actor, alignment settings etc
483
484   RowColumnArray mRowData;     ///< Data for each row
485   RowColumnArray mColumnData;  ///< Data for each column
486   Size           mFixedTotals; ///< Accumulated totals for fixed width and height
487
488   Size mPadding; ///< Padding to apply to each cell
489
490   WeakHandle<Actor> mPreviousFocusedActor; ///< Perviously focused actor
491   bool              mLayoutingChild;       ///< Can't be a bitfield due to Relayouting lock
492   bool              mRowDirty : 1;         ///< Flag to indicate the row data is dirty
493   bool              mColumnDirty : 1;      ///< Flag to indicate the column data is dirty
494 };
495
496 } // namespace Internal
497
498 // Helpers for public-api forwarding methods
499
500 inline Toolkit::Internal::TableView& GetImpl(Toolkit::TableView& tableView)
501 {
502   DALI_ASSERT_ALWAYS(tableView);
503
504   Dali::RefObject& handle = tableView.GetImplementation();
505
506   return static_cast<Toolkit::Internal::TableView&>(handle);
507 }
508
509 inline const Toolkit::Internal::TableView& GetImpl(const Toolkit::TableView& tableView)
510 {
511   DALI_ASSERT_ALWAYS(tableView);
512
513   const Dali::RefObject& handle = tableView.GetImplementation();
514
515   return static_cast<const Toolkit::Internal::TableView&>(handle);
516 }
517
518 } // namespace Toolkit
519
520 } // namespace Dali
521
522 #endif // DALI_TOOLKIT_INTERNAL_TABLE_VIEW_H