5efe0061f1766c15b1c45b8e53ceb8b153016d37
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / Layouting / LayoutGroup.cs
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 using System.ComponentModel;
19 using Tizen.NUI.BaseComponents;
20
21 namespace Tizen.NUI
22 {
23     /// <summary>
24     /// [Draft] LayoutGroup class providing container functionality.
25     /// </summary>
26     internal class LayoutGroup : LayoutGroupWrapper
27     {
28         public LayoutGroup() : base(new LayoutGroupWrapperImpl())
29         {
30             // Initialize delegates of LayoutItem
31             LayoutItemInitialize(layoutGroupWrapperImpl);
32
33             layoutGroupWrapperImpl.OnMeasure = new LayoutGroupWrapperImpl.OnMeasureDelegate(OnMeasure);
34             layoutGroupWrapperImpl.OnLayout = new LayoutGroupWrapperImpl.OnLayoutDelegate(OnLayout);
35             layoutGroupWrapperImpl.OnSizeChanged = new LayoutGroupWrapperImpl.OnSizeChangedDelegate(OnSizeChanged);
36             layoutGroupWrapperImpl.OnChildAdd = new LayoutGroupWrapperImpl.OnChildAddDelegate(OnChildAdd);
37             layoutGroupWrapperImpl.OnChildRemove = new LayoutGroupWrapperImpl.OnChildRemoveDelegate(OnChildRemove);
38             layoutGroupWrapperImpl.DoInitialize = new LayoutGroupWrapperImpl.DoInitializeDelegate(DoInitialize);
39             layoutGroupWrapperImpl.DoRegisterChildProperties = new LayoutGroupWrapperImpl.DoRegisterChildPropertiesDelegate(DoRegisterChildProperties);
40             layoutGroupWrapperImpl.MeasureChildren = new LayoutGroupWrapperImpl.MeasureChildrenDelegate(MeasureChildren);
41             layoutGroupWrapperImpl.MeasureChild = new LayoutGroupWrapperImpl.MeasureChildDelegate(MeasureChild);
42             layoutGroupWrapperImpl.MeasureChildWithMargins = new LayoutGroupWrapperImpl.MeasureChildWithMarginsDelegate(MeasureChildWithMargins);
43         }
44
45         /// <summary>
46         /// Remove all layout children.<br />
47         /// </summary>
48         public void RemoveAll()
49         {
50             layoutGroupWrapperImpl.RemoveAll();
51         }
52
53         /// <summary>
54         /// Get the child layout id of the given child.<br />
55         /// </summary>
56         /// <param name="child">The given Layout child.</param>
57         internal uint GetChildId(LayoutItemWrapperImpl child)
58         {
59             return layoutGroupWrapperImpl.GetChildId(child);
60         }
61
62         /// <summary>
63         /// Calculate the right measure spec for this child.
64         /// Does the hard part of MeasureChildren: figuring out the MeasureSpec to
65         /// pass to a particular child. This method figures out the right MeasureSpec
66         /// for one dimension (height or width) of one child view.<br />
67         /// </summary>
68         /// <param name="measureSpec">The requirements for this view.</param>
69         /// <param name="padding">The padding of this view for the current dimension and margins, if applicable.</param>
70         /// <param name="childDimension"> How big the child wants to be in the current dimension.</param>
71         /// <returns>a MeasureSpec for the child.</returns>
72         public static LayoutMeasureSpec GetChildMeasureSpec(LayoutMeasureSpec measureSpec, LayoutLength padding, LayoutLength childDimension)
73         {
74             return LayoutGroupWrapperImpl.GetChildMeasureSpec(measureSpec, padding, childDimension);
75         }
76
77         /// <summary>
78         /// Measure the layout and its content to determine the measured width and the measured height.<br />
79         /// If this method is overridden, it is the subclass's responsibility to make
80         /// sure the measured height and width are at least the layout's minimum height
81         /// and width. <br />
82         /// </summary>
83         /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
84         /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
85         protected override void OnMeasure(LayoutMeasureSpec widthMeasureSpec, LayoutMeasureSpec heightMeasureSpec)
86         {
87             Log.Info("NUI", "OnMeasure\n");
88             LayoutLength childWidth  = new LayoutLength( 0 );
89             LayoutLength childHeight =  new LayoutLength( 0 );
90
91             LayoutLength measuredWidth = childWidth;
92             LayoutLength measuredHeight = childHeight;
93
94             for( uint i = 0; i < ChildCount; ++i )
95             {
96                 var childLayout = GetChildAt( i );
97
98                 if( childLayout )
99                 {
100                     MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
101                     childWidth = childLayout.MeasuredWidth;
102                     childHeight = childLayout.MeasuredHeight;
103                     // Layout takes size of largest width and height dimension of children
104                     measuredWidth.Value = System.Math.Max( measuredWidth.Value, childWidth.Value );
105                     measuredHeight.Value = System.Math.Max( measuredHeight.Value, childHeight.Value );
106                 }
107             }
108
109             if( 0 == ChildCount )
110             {
111                 // Must be a leaf as has no children
112                 measuredWidth = GetDefaultSize( SuggestedMinimumWidth, widthMeasureSpec );
113                 measuredHeight = GetDefaultSize( SuggestedMinimumHeight, heightMeasureSpec );
114             }
115
116             SetMeasuredDimensions( new MeasuredSize( measuredWidth ),
117                                     new MeasuredSize( measuredHeight ) );
118         }
119
120         /// <summary>
121         /// Called from Layout() when this layout should assign a size and position to each of its children.<br />
122         /// Derived classes with children should override this method and call Layout() on each of their children.<br />
123         /// </summary>
124         /// <param name="changed">This is a new size or position for this layout.</param>
125         /// <param name="left">Left position, relative to parent.</param>
126         /// <param name="top"> Top position, relative to parent.</param>
127         /// <param name="right">Right position, relative to parent.</param>
128         /// <param name="bottom">Bottom position, relative to parent.</param>
129         protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
130         {
131             Log.Info("NUI", "OnLayout\n");
132
133             for( uint i = 0; i < ChildCount; ++i )
134             {
135                 var childLayout = GetChildAt( i );
136                 if( childLayout )
137                 {
138                     View childOwner = childLayout.GetOwner();
139
140                     // Use position if explicitly set to child otherwise will be top left.
141                     var childLeft = new LayoutLength( childOwner.Position2D.X );
142                     var childTop = new LayoutLength( childOwner.Position2D.Y );
143
144                     View owner = GetOwner();
145
146                     if ( owner )
147                     {
148                         // Margin and Padding only supported when child anchor point is TOP_LEFT.
149                         if ( owner.PivotPoint == PivotPoint.TopLeft || ( owner.PositionUsesPivotPoint == false ) )
150                         {
151                           childLeft = childLeft + owner.Padding.Start + childOwner.Margin.Start;
152                           childTop = childTop + owner.Padding.Top + childOwner.Margin.Top;
153                         }
154                     }
155                     childLayout.Layout( childLeft, childTop, childLeft + childLayout.MeasuredWidth, childTop + childLayout.MeasuredHeight );
156                 }
157             }
158         }
159
160         /// <summary>
161         /// Virtual method to inform derived classes when the layout size changed.<br />
162         /// </summary>
163         /// <param name="newSize">The new size of the layout.</param>
164         /// <param name="oldSize">The old size of the layout.</param>
165         protected virtual void OnSizeChanged(LayoutSize newSize, LayoutSize oldSize)
166         {
167
168         }
169
170         /// <summary>
171         /// Callback when child is added to container.<br />
172         /// Derived classes can use this to set their own child properties on the child layout's owner.<br />
173         /// </summary>
174         /// <param name="child">The Layout child.</param>
175         internal virtual void OnChildAdd(LayoutItemWrapperImpl child)
176         {
177         }
178
179         /// <summary>
180         /// Callback when child is removed from container.<br />
181         /// </summary>
182         /// <param name="child">The Layout child.</param>
183         internal virtual void OnChildRemove(LayoutItemWrapperImpl child)
184         {
185         }
186
187         /// <summary>
188         /// Second stage initialization method for deriving classes to override.<br />
189         /// </summary>
190         protected virtual void DoInitialize()
191         {
192         }
193
194         /// <summary>
195         /// Method for derived classes to implement in order to register child property types with the container.<br />
196         /// </summary>
197         /// <param name="containerType">The fully qualified typename of the container.</param>
198         protected virtual void DoRegisterChildProperties(string containerType)
199         {
200         }
201
202         /// <summary>
203         /// Ask all of the children of this view to measure themselves, taking into
204         /// account both the MeasureSpec requirements for this view and its padding.<br />
205         /// The heavy lifting is done in GetChildMeasureSpec.<br />
206         /// </summary>
207         /// <param name="widthMeasureSpec">The width requirements for this view.</param>
208         /// <param name="heightMeasureSpec">The height requirements for this view.</param>
209         protected virtual void MeasureChildren(LayoutMeasureSpec widthMeasureSpec, LayoutMeasureSpec heightMeasureSpec)
210         {
211             layoutGroupWrapperImpl.MeasureChildrenNative(widthMeasureSpec, heightMeasureSpec);
212         }
213
214         /// <summary>
215         /// Ask one of the children of this view to measure itself, taking into
216         /// account both the MeasureSpec requirements for this view and its padding.<br />
217         /// The heavy lifting is done in GetChildMeasureSpec.<br />
218         /// </summary>
219         /// <param name="child">The child to measure.</param>
220         /// <param name="parentWidthMeasureSpec">The width requirements for this view.</param>
221         /// <param name="parentHeightMeasureSpec">The height requirements for this view.</param>
222         protected virtual void MeasureChild(LayoutItem child, LayoutMeasureSpec parentWidthMeasureSpec, LayoutMeasureSpec parentHeightMeasureSpec)
223         {
224             layoutGroupWrapperImpl.MeasureChildNative(child, parentWidthMeasureSpec, parentHeightMeasureSpec);
225         }
226
227         /// <summary>
228         /// Ask one of the children of this view to measure itself, taking into
229         /// account both the MeasureSpec requirements for this view and its padding.<br />
230         /// and margins. The child must have MarginLayoutParams The heavy lifting is
231         /// done in GetChildMeasureSpec.<br />
232         /// </summary>
233         /// <param name="child">The child to measure.</param>
234         /// <param name="parentWidthMeasureSpec">The width requirements for this view.</param>
235         /// <param name="widthUsed">Extra space that has been used up by the parent horizontally (possibly by other children of the parent).</param>
236         /// <param name="parentHeightMeasureSpec">The height requirements for this view.</param>
237         /// <param name="heightUsed">Extra space that has been used up by the parent vertically (possibly by other children of the parent).</param>
238         protected virtual void MeasureChildWithMargins(LayoutItem child, LayoutMeasureSpec parentWidthMeasureSpec, LayoutLength widthUsed, LayoutMeasureSpec parentHeightMeasureSpec, LayoutLength heightUsed)
239         {
240             layoutGroupWrapperImpl.MeasureChildWithMarginsNative(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
241         }
242     }
243 }