Controls are LayoutGroups instead of LayoutItems
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / devel-api / layouting / layout-group-impl.h
1 #ifndef DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_GROUP_H
2 #define DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_GROUP_H
3 /*
4  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <memory>
20
21 #include <dali/public-api/common/intrusive-ptr.h>
22 #include <dali/public-api/actors/actor-enumerations.h>
23 #include <dali/public-api/signals/connection-tracker.h>
24 #include <dali-toolkit/devel-api/layouting/child-layout-data.h>
25 #include <dali-toolkit/devel-api/layouting/layout-group.h>
26 #include <dali-toolkit/devel-api/layouting/layout-parent-impl.h>
27 #include <dali-toolkit/devel-api/layouting/layout-item-impl.h>
28
29 namespace Dali
30 {
31 namespace Toolkit
32 {
33 namespace Internal
34 {
35
36 class LayoutGroup;
37 using LayoutGroupPtr = IntrusivePtr<LayoutGroup>;
38
39 /**
40  * LayoutGroup is an abstract class that provides child layout management and basic measuring and layouting.
41  *
42  * Deriving classes should override LayoutItem::DoInitialize for second stage initialization,
43  * LayoutGroup::DoRegisterChildProperties to register child property types with the owner,
44  * LayoutGroup::OnChildAdd to apply default child property values to the child.
45  * Deriving classes may override LayoutGroup::OnChildRemove.
46  *
47  * Deriving classes must also override OnMeasure and OnLayout as follows:
48  *
49  * OnMeasure should measure each child using LayoutGroup::MeasureChildWithMargins or LayoutGroup::MeasureChild.
50  * We recommend calling LayoutItem::ResolveSizeAndState() to resolve measure specs.
51  * If some children don't fit, then they can be measured again with different MeasureSpecs as required.
52  *
53  * After measurement, the derived class must also call SetMeasuredDimensions to set it's own requested size.
54  *
55  * OnLayout should use it's own layout parameters and the measured children's size to determine the children's
56  * position and size; it should then call Layout() on the child layout to layout the child and it's hierarchy.
57  */
58 class DALI_TOOLKIT_API LayoutGroup : public LayoutItem,
59                                      public LayoutParent,
60                                      public ConnectionTracker
61 {
62 public:
63   /**
64    * Constructor. Returns an initialized object
65    */
66   LayoutGroup();
67
68   /**
69    * @brief Construct
70    *
71    * @param[in] owner The owner (container view / child view / visual ) of this layout
72    * @return a new LayoutGroup object
73    */
74   static LayoutGroupPtr New( Handle& owner );
75
76 protected:
77   /**
78    * Virtual destructor may only be called by Unreference()
79    */
80   virtual ~LayoutGroup();
81
82 public:
83   LayoutGroup( const LayoutGroup& copy ) = delete;
84   LayoutGroup& operator=( const LayoutGroup& rhs ) = delete;
85
86   /**
87    * @brief Add a layout child to this group.
88    *
89    * @param[in] layoutChild The child to add
90    * @return The layout id of this child.
91    */
92   Toolkit::LayoutGroup::LayoutId Add( LayoutItem& layoutChild ) override;
93
94   /**
95    * @brief Remove a layout child from this group.
96    * @param[in] childId The layout child id
97    */
98   void Remove( Toolkit::LayoutGroup::LayoutId childId ) override;
99
100   /**
101    * @brief Remove a layout child from this group
102    * @param[in] child The layout child
103    */
104   void Remove( LayoutItem& child ) override;
105
106   /**
107    * @brief Insert a child to the parent
108    * @param[in] target The target item
109    * @param[in] child The item to insert to this layout parent
110    */
111   Toolkit::LayoutGroup::LayoutId Insert( LayoutItem& target, LayoutItem& child ) override;
112
113   /**
114    * @brief Move a child to another position
115    * @param[in] target The target item
116    * @param[in] child The item to move
117    */
118   Toolkit::LayoutGroup::LayoutId Move( LayoutItem& target, LayoutItem& child ) override;
119
120   /**
121    * @brief Move a child to back
122    * @param[in] child The item to move
123    */
124   Toolkit::LayoutGroup::LayoutId MoveBack( LayoutItem& child ) override;
125
126   /**
127    * @brief Remove all layout children.
128    *
129    * @note This will not unparent owner's children
130    */
131   void RemoveAll();
132
133
134   /**
135    * @brief Get the number of children contained by this layout group
136    *
137    * @return the number of children
138    */
139   unsigned int GetChildCount() const;
140
141   /**
142    * Get the child layout at the given index
143    */
144   LayoutItemPtr GetChildAt( unsigned int childIndex ) const;
145
146   /**
147    * Get the child layout id of the given child
148    */
149   Toolkit::LayoutGroup::LayoutId GetChildId( LayoutItem& child ) const;
150
151   /**
152    * @brief Get the layout child with the given layout id.
153    * @note child id's start at 1, and follow the insertion order
154    * @param[in] childId the layout id of the child within this group
155    * @return A pointer to the child layout
156    */
157   LayoutItemPtr GetChild( Toolkit::LayoutGroup::LayoutId childId ) const;
158
159   template <typename T>
160     LayoutItemPtr GetChild( T childId ) = delete; // Prevent implicit casting of int/uint to LayoutId
161
162   /**
163    * Callback when child is added to container.
164    * Derived classes can use this to set their own child properties on the child layout's owner.
165    */
166   virtual void OnChildAdd( LayoutItem& child );
167
168   /**
169    * Callback when child is removed from container.
170    */
171   virtual void OnChildRemove( LayoutItem& child );
172
173   /**
174    * @brief Calculate the right measure spec for this child.
175    *
176    * Does the hard part of MeasureChildren: figuring out the MeasureSpec to
177    * pass to a particular child. This method figures out the right MeasureSpec
178    * for one dimension (height or width) of one child view.
179    *
180    * The goal is to combine information from our MeasureSpec with the
181    * LayoutParams of the child to get the best possible results. For example,
182    * if the this view knows its size (because its MeasureSpec has a mode of
183    * EXACTLY), and the child has indicated in its LayoutParams that it wants
184    * to be the same size as the parent, the parent should ask the child to
185    * layout given an exact size.
186    *
187    * @param measureSpec The requirements for this view
188    *
189    * @param padding The padding of this view for the current dimension
190    *        and margins, if applicable
191    *
192    * @param childDimension How big the child wants to be in the
193    *        current dimension
194    * @return a MeasureSpec for the child
195    */
196   static MeasureSpec GetChildMeasureSpec( MeasureSpec measureSpec,
197                                           LayoutLength padding,
198                                           LayoutLength childDimension );
199
200 protected:
201   /**
202    * @brief Second stage initialization method for deriving classes to override
203    */
204   virtual void DoInitialize();
205
206   /**
207    * @brief Method for derived classes to implement in order to register child
208    * property types with the container.
209    *
210    * @param[in] containerType The fully qualified typename of the container
211    */
212   virtual void DoRegisterChildProperties( const std::string& containerType );
213
214   /**
215    * Create default child property values suitable for this layout group or derived layouter
216    */
217   virtual void GenerateDefaultChildPropertyValues( Handle child );
218
219   /**
220    * Ask all of the children of this view to measure themselves, taking into
221    * account both the MeasureSpec requirements for this view and its padding.
222    * The heavy lifting is done in GetChildMeasureSpec.
223    *
224    * @param widthMeasureSpec The width requirements for this view
225    * @param heightMeasureSpec The height requirements for this view
226    */
227   virtual void MeasureChildren( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec );
228
229   /**
230    * Ask one of the children of this view to measure itself, taking into
231    * account both the MeasureSpec requirements for this view and its padding.
232    * The heavy lifting is done in GetChildMeasureSpec.
233    *
234    * @param child The child to measure
235    * @param parentWidthMeasureSpec The width requirements for this view
236    * @param parentHeightMeasureSpec The height requirements for this view
237    */
238   virtual void MeasureChild( LayoutItemPtr child, MeasureSpec parentWidthMeasureSpec, MeasureSpec parentHeightMeasureSpec );
239
240   /**
241    * Ask one of the children of this view to measure itself, taking into
242    * account both the MeasureSpec requirements for this view and its padding
243    * and margins. The child must have MarginLayoutParams The heavy lifting is
244    * done in GetChildMeasureSpec.
245    *
246    * @param child The child to measure
247    * @param parentWidthMeasureSpec The width requirements for this view
248    * @param widthUsed Extra space that has been used up by the parent
249    *        horizontally (possibly by other children of the parent)
250    * @param parentHeightMeasureSpec The height requirements for this view
251    * @param heightUsed Extra space that has been used up by the parent
252    *        vertically (possibly by other children of the parent)
253    */
254   virtual void MeasureChildWithMargins( LayoutItemPtr child,
255                                         MeasureSpec parentWidthMeasureSpec,
256                                         LayoutLength widthUsed,
257                                         MeasureSpec parentHeightMeasureSpec,
258                                         LayoutLength heightUsed );
259   /**
260    * @copydoc LayoutItem::OnMeasure
261    */
262   virtual void OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec ) override;
263
264   /**
265    * @copydoc LayoutItem::OnLayout
266    */
267   virtual void OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom ) override;
268
269 private:
270   /**
271    * Second stage initialization for LayoutGroup only.
272    * This will call DoInitialize on most derived class.
273    */
274   void OnInitialize() override final;
275
276   /**
277    * @copydoc LayoutItem::OnRegisterChildProperties()
278    */
279   void OnRegisterChildProperties( const std::string& containerType ) override final;
280
281   /**
282    * @copydoc LayoutItem::OnUnparent
283    */
284   void OnUnparent() override final;
285
286   /**
287    * Method to remove a child from this group
288    */
289   void RemoveChild( LayoutItem& item );
290
291   /**
292    * Callback when child is added to owner
293    */
294   void ChildAddedToOwner( Actor child );
295
296   /**
297    * Callback when child is removed from owner
298    */
299   void ChildRemovedFromOwner( Actor child );
300
301   /**
302    * Callback when child order is changed
303    */
304   void ChildOrderChanged( Actor child );
305
306   /**
307    * Callback when an owner property is set. Triggers a relayout if it's a child property
308    */
309   void OnOwnerPropertySet( Handle& handle, Property::Index index, Property::Value value );
310
311   /**
312    * Callback when a child property is set on any given child
313    * @param[in] handle The handle to the child
314    * @param[in] index The index of the property that has been set
315    * @param[in] value The new value of the property
316    */
317   void OnSetChildProperties( Handle& handle, Property::Index index, Property::Value value );
318
319   /**
320    * @brief Called when a layer animation state is changed.
321    */
322   void OnAnimationStateChanged( bool animateLayout ) override final;
323
324 public:
325   class Impl; // Class declaration is public so we can add devel API's in the future
326
327 private:
328   std::unique_ptr<Impl> mImpl; // The implementation data for this class.
329   SlotDelegate<LayoutGroup> mSlotDelegate; ///< Slot delegate allows this class to connect safely to signals
330 };
331
332 } //namespace Internal
333
334 inline Internal::LayoutGroup& GetImplementation( Dali::Toolkit::LayoutGroup& handle )
335 {
336   DALI_ASSERT_ALWAYS( handle && "LayoutGroup handle is empty" );
337   BaseObject& object = handle.GetBaseObject();
338   return static_cast< Internal::LayoutGroup& >( object );
339 }
340
341 inline const Internal::LayoutGroup& GetImplementation( const Dali::Toolkit::LayoutGroup& handle )
342 {
343   DALI_ASSERT_ALWAYS( handle && "LayoutGroup handle is empty" );
344   const BaseObject& object = handle.GetBaseObject();
345   return static_cast< const Internal::LayoutGroup& >( object );
346 }
347
348 }//namespace Toolkit
349 }//namespace Dali
350
351 #endif // DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_GROUP_H