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