36e0312c919614970c5acd863621d21201f3a073
[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 protected:
69   /**
70    * Virtual destructor may only be called by Unreference()
71    */
72   virtual ~LayoutGroup();
73
74 public:
75   LayoutGroup( const LayoutGroup& copy ) = delete;
76   LayoutGroup& operator=( const LayoutGroup& rhs ) = delete;
77
78   /**
79    * @brief Add a layout child to this group.
80    *
81    * @param[in] layoutChild The child to add
82    * @return The layout id of this child.
83    */
84   Toolkit::LayoutGroup::LayoutId Add( LayoutItem& layoutChild ) override;
85
86   /**
87    * @brief Remove a layout child from this group.
88    * @param[in] childId The layout child id
89    */
90   void Remove( Toolkit::LayoutGroup::LayoutId childId ) override;
91
92   /**
93    * @brief Remove a layout child from this group
94    * @param[in] child The layout child
95    */
96   void Remove( LayoutItem& child ) override;
97
98   /**
99    * @brief Remove all layout children.
100    *
101    * @note This will not unparent owner's children
102    */
103   void RemoveAll();
104
105
106   /**
107    * @brief Get the number of children contained by this layout group
108    *
109    * @return the number of children
110    */
111   unsigned int GetChildCount() const;
112
113   /**
114    * Get the child layout at the given index
115    */
116   LayoutItemPtr GetChildAt( unsigned int childIndex ) const;
117
118   /**
119    * Get the child layout id of the given child
120    */
121   Toolkit::LayoutGroup::LayoutId GetChildId( LayoutItem& child ) const;
122
123   /**
124    * @brief Get the layout child with the given layout id.
125    * @note child id's start at 1, and follow the insertion order
126    * @param[in] childId the layout id of the child within this group
127    * @return A pointer to the child layout
128    */
129   LayoutItemPtr GetChild( Toolkit::LayoutGroup::LayoutId childId ) const;
130
131   template <typename T>
132     LayoutItemPtr GetChild( T childId ) = delete; // Prevent implicit casting of int/uint to LayoutId
133
134   /**
135    * Callback when child is added to container.
136    * Derived classes can use this to set their own child properties on the child layout's owner.
137    */
138   virtual void OnChildAdd( LayoutItem& child );
139
140   /**
141    * Callback when child is removed from container.
142    */
143   virtual void OnChildRemove( LayoutItem& child );
144
145   /**
146    * @brief Calculate the right measure spec for this child.
147    *
148    * Does the hard part of MeasureChildren: figuring out the MeasureSpec to
149    * pass to a particular child. This method figures out the right MeasureSpec
150    * for one dimension (height or width) of one child view.
151    *
152    * The goal is to combine information from our MeasureSpec with the
153    * LayoutParams of the child to get the best possible results. For example,
154    * if the this view knows its size (because its MeasureSpec has a mode of
155    * EXACTLY), and the child has indicated in its LayoutParams that it wants
156    * to be the same size as the parent, the parent should ask the child to
157    * layout given an exact size.
158    *
159    * @param measureSpec The requirements for this view
160    *
161    * @param padding The padding of this view for the current dimension
162    *        and margins, if applicable
163    *
164    * @param childDimension How big the child wants to be in the
165    *        current dimension
166    * @return a MeasureSpec for the child
167    */
168   static MeasureSpec GetChildMeasureSpec( MeasureSpec measureSpec,
169                                           LayoutLength padding,
170                                           LayoutLength childDimension );
171
172 protected:
173   /**
174    * @brief Second stage initialization method for deriving classes to override
175    */
176   virtual void DoInitialize();
177
178   /**
179    * @brief Method for derived classes to implement in order to register child
180    * property types with the container.
181    *
182    * @param[in] containerType The fully qualified typename of the container
183    */
184   virtual void DoRegisterChildProperties( const std::string& containerType );
185
186   /**
187    * Create default child property values suitable for this layout group or derived layouter
188    */
189   virtual void GenerateDefaultChildPropertyValues( Handle child );
190
191   /**
192    * Ask all of the children of this view to measure themselves, taking into
193    * account both the MeasureSpec requirements for this view and its padding.
194    * The heavy lifting is done in GetChildMeasureSpec.
195    *
196    * @param widthMeasureSpec The width requirements for this view
197    * @param heightMeasureSpec The height requirements for this view
198    */
199   virtual void MeasureChildren( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec );
200
201   /**
202    * Ask one of the children of this view to measure itself, taking into
203    * account both the MeasureSpec requirements for this view and its padding.
204    * The heavy lifting is done in GetChildMeasureSpec.
205    *
206    * @param child The child to measure
207    * @param parentWidthMeasureSpec The width requirements for this view
208    * @param parentHeightMeasureSpec The height requirements for this view
209    */
210   virtual void MeasureChild( LayoutItemPtr child, MeasureSpec parentWidthMeasureSpec, MeasureSpec parentHeightMeasureSpec );
211
212   /**
213    * Ask one of the children of this view to measure itself, taking into
214    * account both the MeasureSpec requirements for this view and its padding
215    * and margins. The child must have MarginLayoutParams The heavy lifting is
216    * done in GetChildMeasureSpec.
217    *
218    * @param child The child to measure
219    * @param parentWidthMeasureSpec The width requirements for this view
220    * @param widthUsed Extra space that has been used up by the parent
221    *        horizontally (possibly by other children of the parent)
222    * @param parentHeightMeasureSpec The height requirements for this view
223    * @param heightUsed Extra space that has been used up by the parent
224    *        vertically (possibly by other children of the parent)
225    */
226   virtual void MeasureChildWithMargins( LayoutItemPtr child,
227                                         MeasureSpec parentWidthMeasureSpec,
228                                         LayoutLength widthUsed,
229                                         MeasureSpec parentHeightMeasureSpec,
230                                         LayoutLength heightUsed );
231
232 private:
233   /**
234    * Second stage initialization for LayoutGroup only.
235    * This will call DoInitialize on most derived class.
236    */
237   void OnInitialize() override final;
238
239   /**
240    * @copydoc LayoutItem::OnRegisterChildProperties()
241    */
242   void OnRegisterChildProperties( const std::string& containerType ) override final;
243
244   /**
245    * @copydoc LayoutItem::OnUnparent
246    */
247   void OnUnparent() override final;
248
249   /**
250    * Method to remove a child from this group
251    */
252   void RemoveChild( LayoutItem& item );
253
254   /**
255    * Callback when child is added to owner
256    */
257   void ChildAddedToOwner( Actor child );
258
259   /**
260    * Callback when child is removed from owner
261    */
262   void ChildRemovedFromOwner( Actor child );
263
264   /**
265    * Callback when child order is changed
266    */
267   void ChildOrderChanged();
268
269   /**
270    * Callback when an owner property is set. Triggers a relayout if it's a child property
271    */
272   void OnOwnerPropertySet( Handle& handle, Property::Index index, Property::Value value );
273
274   /**
275    * Callback when a child property is set on any given child
276    * @param[in] handle The handle to the child
277    * @param[in] index The index of the property that has been set
278    * @param[in] value The new value of the property
279    */
280   void OnSetChildProperties( Handle& handle, Property::Index index, Property::Value value );
281
282   /**
283    * @brief Called when a layer animation state is changed.
284    */
285   void OnAnimationStateChanged( bool animateLayout ) override final;
286
287 public:
288   class Impl; // Class declaration is public so we can add devel API's in the future
289
290 private:
291   std::unique_ptr<Impl> mImpl; // The implementation data for this class.
292   SlotDelegate<LayoutGroup> mSlotDelegate; ///< Slot delegate allows this class to connect safely to signals
293 };
294
295 } //namespace Internal
296
297 inline Internal::LayoutGroup& GetImplementation( Dali::Toolkit::LayoutGroup& handle )
298 {
299   DALI_ASSERT_ALWAYS( handle && "LayoutGroup handle is empty" );
300   BaseObject& object = handle.GetBaseObject();
301   return static_cast< Internal::LayoutGroup& >( object );
302 }
303
304 inline const Internal::LayoutGroup& GetImplementation( const Dali::Toolkit::LayoutGroup& handle )
305 {
306   DALI_ASSERT_ALWAYS( handle && "LayoutGroup handle is empty" );
307   const BaseObject& object = handle.GetBaseObject();
308   return static_cast< const Internal::LayoutGroup& >( object );
309 }
310
311 }//namespace Toolkit
312 }//namespace Dali
313
314 #endif // DALI_TOOLKIT_INTERNAL_LAYOUTING_LAYOUT_GROUP_H