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