[NUI] remove unnecessary code that flex margin is assigned to flexlayout (#2272)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / Layouting / FlexLayout.cs
1 /* Copyright (c) 2020 Samsung Electronics Co., Ltd.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  */
16
17 using System;
18 using System.ComponentModel;
19 using Tizen.NUI.BaseComponents;
20 using System.Runtime.InteropServices;
21 using System.Diagnostics;
22 using Tizen.NUI.Binding;
23
24 namespace Tizen.NUI
25 {
26     /// <summary>
27     /// This class implements a flex layout.
28     /// The flex layout implementation is based on open source Facebook Yoga layout engine.
29     /// For more information about the flex layout API and how to use it please refer to https://yogalayout.com/docs/
30     /// We implement the subset of the API in the class below.
31     /// </summary>
32     public class FlexLayout : LayoutGroup, global::System.IDisposable
33     {
34         /// <summary>
35         /// FlexItemProperty
36         /// </summary>
37         [EditorBrowsable(EditorBrowsableState.Never)]
38         internal static readonly BindableProperty FlexItemProperty = BindableProperty.CreateAttached("FlexItem", typeof(HandleRef), typeof(FlexLayout), default(HandleRef));
39
40         /// <summary>
41         /// FlexAlignmentSelfProperty
42         /// </summary>
43         [EditorBrowsable(EditorBrowsableState.Never)]
44         public static readonly BindableProperty FlexAlignmentSelfProperty = BindableProperty.CreateAttached("FlexAlignmentSelf", typeof(AlignmentType), typeof(FlexLayout), AlignmentType.Auto, validateValue: ValidateEnum((int)AlignmentType.Auto, (int)AlignmentType.Stretch), propertyChanged: OnChildPropertyChanged);
45
46         /// <summary>
47         /// FlexPositionTypeProperty
48         /// </summary>
49         [EditorBrowsable(EditorBrowsableState.Never)]
50         public static readonly BindableProperty FlexPositionTypeProperty = BindableProperty.CreateAttached("FlexPositionType", typeof(PositionType), typeof(FlexLayout), PositionType.Relative, validateValue: ValidateEnum((int)PositionType.Relative, (int)PositionType.Absolute),
51         propertyChanged: (bindable, oldValue, newValue) =>
52         {
53             if (bindable is View view)
54             {
55                 view.ExcludeLayouting = (PositionType)newValue == PositionType.Absolute;
56             }
57         },
58         defaultValueCreator: (bindable) =>
59         {
60             var view = (View)bindable;
61             if (view.ExcludeLayouting)
62                 return PositionType.Absolute;
63
64             return PositionType.Relative;
65         });
66
67
68         /// <summary>
69         /// AspectRatioProperty
70         /// </summary>
71         [EditorBrowsable(EditorBrowsableState.Never)]
72         public static readonly BindableProperty FlexAspectRatioProperty = BindableProperty.CreateAttached("FlexAspectRatio", typeof(float), typeof(FlexLayout), FlexUndefined, validateValue: (bindable, value) => (float)value > 0, propertyChanged: OnChildPropertyChanged);
73
74         /// <summary>
75         /// FlexBasisProperty
76         /// </summary>
77         [EditorBrowsable(EditorBrowsableState.Never)]
78         public static readonly BindableProperty FlexBasisProperty = BindableProperty.CreateAttached("FlexBasis", typeof(float), typeof(FlexLayout), FlexUndefined, validateValue: (bindable, value) => (float)value >= 0, propertyChanged: OnChildPropertyChanged);
79
80         /// <summary>
81         /// FlexShrinkProperty
82         /// </summary>
83         [EditorBrowsable(EditorBrowsableState.Never)]
84         public static readonly BindableProperty FlexShrinkProperty = BindableProperty.CreateAttached("FlexShrink", typeof(float), typeof(FlexLayout), 1.0f, validateValue: (bindable, value) => (float)value >= 0, propertyChanged: OnChildPropertyChanged);
85
86         /// <summary>
87         /// FlexGrowProperty
88         /// </summary>
89         [EditorBrowsable(EditorBrowsableState.Never)]
90         public static readonly BindableProperty FlexGrowProperty = BindableProperty.CreateAttached("FlexGrow", typeof(float), typeof(FlexLayout), FlexUndefined, validateValue: (bindable, value) => (float)value >= 0, propertyChanged: OnChildPropertyChanged);
91
92         private static bool LayoutDebugFlex = false; // Debug flag
93
94         private global::System.Runtime.InteropServices.HandleRef swigCPtr;
95         private bool swigCMemOwn;
96         private bool disposed;
97         private bool isDisposeQueued = false;
98
99         private MeasureSpecification parentMeasureSpecificationWidth;
100         private MeasureSpecification parentMeasureSpecificationHeight;
101
102         private IntPtr _rootFlex;  // Pointer to the unmanged flex layout class.
103
104         internal const float FlexUndefined = 10E20F; // Auto setting which is equivalent to WrapContent.
105
106         internal struct MeasuredSize
107         {
108             public MeasuredSize(float x, float y)
109             {
110                 width = x;
111                 height = y;
112             }
113             public float width;
114             public float height;
115         };
116
117         /// <summary>
118         /// Gets the alignment self of the child view.
119         /// </summary>
120         /// <seealso cref="SetFlexAlignmentSelf(View, AlignmentType)"/>
121         /// <param name="view">The child view.</param>
122         /// <returns> The value of alignment self.</returns>
123         /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
124         /// <since_tizen> 8 </since_tizen>
125         public static AlignmentType GetFlexAlignmentSelf(View view) => GetAttachedValue<AlignmentType>(view, FlexAlignmentSelfProperty);
126
127         /// <summary>
128         /// Gets the position type of the child view.
129         /// </summary>
130         /// <seealso cref="SetFlexPositionType(View, PositionType)"/>
131         /// <param name="view">The child view.</param>
132         /// <returns> The value of position type</returns>
133         /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
134         /// <since_tizen> 8 </since_tizen>
135         public static PositionType GetFlexPositionType(View view) => GetAttachedValue<PositionType>(view, FlexPositionTypeProperty);
136
137         /// <summary>
138         /// Gets the aspect ratio of the child view.
139         /// </summary>
140         /// <seealso cref="SetFlexAspectRatio(View, float)"/>
141         /// <param name="view">The child view.</param>
142         /// <returns> The value of aspect ratio</returns>
143         /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
144         /// <since_tizen> 8 </since_tizen>
145         public static float GetFlexAspectRatio(View view) => GetAttachedValue<float>(view, FlexAspectRatioProperty);
146
147         /// <summary>
148         /// Gets the basis of the child view.
149         /// </summary>
150         /// <seealso cref="SetFlexBasis(View, float)"/>
151         /// <param name="view">The child view.</param>
152         /// <returns> The value of basis</returns>
153         /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
154         /// <since_tizen> 8 </since_tizen>
155         public static float GetFlexBasis(View view) => GetAttachedValue<float>(view, FlexBasisProperty);
156
157         /// <summary>
158         /// Gets the shrink of the child view.
159         /// </summary>
160         /// <seealso cref="SetFlexShrink(View, float)"/>
161         /// <param name="view">The child view.</param>
162         /// <returns> The value of shrink</returns>
163         /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
164         /// <since_tizen> 8 </since_tizen>
165         public static float GetFlexShrink(View view) => GetAttachedValue<float>(view, FlexShrinkProperty);
166
167         /// <summary>
168         /// Gets the grow of the child view.
169         /// </summary>
170         /// <seealso cref="SetFlexGrow(View, float)"/>
171         /// <param name="view">The child view.</param>
172         /// <returns> The value of grow</returns>
173         /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
174         /// <since_tizen> 8 </since_tizen>
175         public static float GetFlexGrow(View view) => GetAttachedValue<float>(view, FlexGrowProperty);
176
177         /// <summary>
178         /// Sets the alignment self of the child view.<br/>
179         /// Alignment self has the same options and effect as <see cref="ItemsAlignment"/> but instead of affecting the children within a container,
180         /// you can apply this property to a single child to change its alignment within its parent.<br/>
181         /// Alignment self overrides any option set by the parent with <see cref="ItemsAlignment"/>.
182         /// </summary>
183         /// <param name="view">The child view.</param>
184         /// <param name="value">The value of alignment self.</param>
185         /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
186         /// <exception cref="ArgumentException">The <paramref name="value"/> should be <see cref="AlignmentType"/>.</exception>
187         /// <since_tizen> 8 </since_tizen>
188         public static void SetFlexAlignmentSelf(View view, AlignmentType value) => SetAttachedValue(view, FlexAlignmentSelfProperty, value);
189
190         /// <summary>
191         /// Sets the position type of the child view.<br/>
192         /// The position type of an element defines how it is positioned within its parent.
193         /// By default a child is positioned relatively. This means a child is positioned according to the normal flow of the layout,
194         /// and then offset relative to that position based on the values of <see cref="View.Margin"/>.<br/>
195         /// When positioned absolutely an element doesn't take part in the normal layout flow.
196         /// It is instead laid out independent of its siblings. The position is determined based on the <see cref="View.Margin"/>.
197         /// </summary>
198         /// <param name="view">The child view.</param>
199         /// <param name="value">The value of position type.</param>
200         /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
201         /// <exception cref="ArgumentException">The <paramref name="value"/> should be <see cref="PositionType"/>.</exception>
202         /// <since_tizen> 8 </since_tizen>
203         public static void SetFlexPositionType(View view, PositionType value) => SetAttachedValue(view, FlexPositionTypeProperty, value);
204
205         /// <summary>
206         /// Sets the aspect ratio of the child view.
207         /// Aspect ratio Defines as the ratio between the width and the height of a node
208         /// e.g. if a node has an aspect ratio of 2 then its width is twice the size of its height.<br/>
209         /// Aspect ratio accepts any floating point value > 0. this has higher priority than flex grow.
210         /// </summary>
211         /// <param name="view">The child view.</param>
212         /// <param name="value">The value of aspect ratio</param>
213         /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
214         /// <exception cref="ArgumentException">The <paramref name="value"/> cannot be less than or equal to 0.0f.</exception>
215         /// <since_tizen> 8 </since_tizen>
216         public static void SetFlexAspectRatio(View view, float value) => SetAttachedValue(view, FlexAspectRatioProperty, value);
217
218         /// <summary>
219         /// Sets the flex basis of the child view.
220         /// Flex basis is an axis-independent way of providing the default size of an item along the main axis.<br/>
221         /// Setting the flex basis of a child is similar to setting the width of that child if its parent is a container with <see cref="FlexDirection.Row"/>
222         /// or setting the height of a child if its parent is a container with <see cref="FlexDirection.Column"/>.<br/>
223         /// The flex basis of an item is the default size of that item, the size of the item before any flex grow and flex shrink calculations are performed.
224         /// </summary>
225         /// <param name="view">The child view.</param>
226         /// <param name="value">The value of basis</param>
227         /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
228         /// <exception cref="ArgumentException">The <paramref name="value"/> cannot be less than 0.0f.</exception>
229         /// <since_tizen> 8 </since_tizen>
230         public static void SetFlexBasis(View view, float value) => SetAttachedValue(view, FlexBasisProperty, value);
231
232         /// <summary>
233         /// Sets the flex shrink of the child view.
234         /// Flex shrink describes how to shrink children along the main axis in the case that the total size of the children overflow the size of the container on the main axis.<br/>
235         /// Flex shrink is very similar to flex grow and can be thought of in the same way if any overflowing size is considered to be negative remaining space.
236         /// These two properties also work well together by allowing children to grow and shrink as needed.<br/>
237         /// Flex shrink accepts any floating point value >= 0, with 1 being the default value. A container will shrink its children weighted by the child's flex shrink value.
238         /// </summary>
239         /// <param name="view">The child view.</param>
240         /// <param name="value">The value of shrink</param>
241         /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
242         /// <exception cref="ArgumentException">The <paramref name="value"/> cannot be less than 0.0f.</exception>
243         /// <since_tizen> 8 </since_tizen>
244         public static void SetFlexShrink(View view, float value) => SetAttachedValue(view, FlexShrinkProperty, value);
245
246         /// <summary>
247         /// Sets the grow of the child view.
248         /// Flex grow describes how any space within a container should be distributed among its children along the main axis.
249         /// After laying out its children, a container will distribute any remaining space according to the flex grow values specified by its children.<br/>
250         /// Flex grow accepts any floating point value >= 0, with 0 being the default value.<br/>
251         /// A container will distribute any remaining space among its children weighted by the child's flex grow value.
252         /// </summary>
253         /// <param name="view">The child view.</param>
254         /// <param name="value">The value of flex</param>
255         /// <exception cref="ArgumentNullException">The <paramref name="view"/> cannot be null.</exception>
256         /// <exception cref="ArgumentException">The <paramref name="value"/> cannot be less than 0.0f.</exception>
257         /// <since_tizen> 8 </since_tizen>
258         public static void SetFlexGrow(View view, float value) => SetAttachedValue(view, FlexGrowProperty, value);
259
260         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
261         internal delegate void ChildMeasureCallback(global::System.IntPtr child, float width, int measureModeWidth, float height, int measureModeHeight, out MeasuredSize measureSize);
262
263         event ChildMeasureCallback measureChildDelegate; // Stores a delegate to the child measure callback. Used for all children of this FlexLayout.
264
265         internal FlexLayout(global::System.IntPtr cPtr, bool cMemoryOwn)
266         {
267             swigCMemOwn = cMemoryOwn;
268             swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr);
269             _rootFlex = Interop.FlexLayout.FlexLayout_New();
270             measureChildDelegate = new ChildMeasureCallback(measureChild);
271         }
272
273         internal static global::System.Runtime.InteropServices.HandleRef getCPtr(FlexLayout obj)
274         {
275             return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
276         }
277
278         /// <inheritdoc/>
279         /// <since_tizen> 6 </since_tizen>
280         public void Dispose()
281         {
282             // Throw exception if Dispose() is called in separate thread.
283             if (!Window.IsInstalled())
284             {
285                 throw new System.InvalidOperationException("This API called from separate thread. This API must be called from MainThread.");
286             }
287
288             if (isDisposeQueued)
289             {
290                 Dispose(DisposeTypes.Implicit);
291             }
292             else
293             {
294                 Dispose(DisposeTypes.Explicit);
295                 System.GC.SuppressFinalize(this);
296             }
297         }
298
299         /// <inheritdoc/>
300         /// <since_tizen> 6 </since_tizen>
301         protected virtual void Dispose(DisposeTypes type)
302         {
303             if (disposed)
304             {
305                 return;
306             }
307
308             if (type == DisposeTypes.Explicit)
309             {
310                 // Called by User
311                 // Release your own managed resources here.
312                 // You should release all of your own disposable objects here.
313
314             }
315
316             // Release your own unmanaged resources here.
317             // You should not access any managed member here except static instance.
318             // because the execution order of Finalizes is non-deterministic.
319             if (swigCPtr.Handle != global::System.IntPtr.Zero)
320             {
321                 if (swigCMemOwn)
322                 {
323                     swigCMemOwn = false;
324                     Interop.FlexLayout.delete_FlexLayout(swigCPtr);
325                 }
326                 swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
327             }
328             disposed = true;
329         }
330
331         /// <summary>
332         /// Creates a FlexLayout object.
333         /// </summary>
334         /// <since_tizen> 6 </since_tizen>
335         public FlexLayout() : this(Interop.FlexLayout.FlexLayout_New(), true)
336         {
337             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
338         }
339
340         internal static FlexLayout DownCast(BaseHandle handle)
341         {
342             FlexLayout ret = new FlexLayout(Interop.FlexLayout.FlexLayout_DownCast(BaseHandle.getCPtr(handle)), true);
343             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
344             return ret;
345         }
346
347         internal FlexLayout(FlexLayout other) : this(Interop.FlexLayout.new_FlexLayout__SWIG_1(FlexLayout.getCPtr(other)), true)
348         {
349             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
350         }
351
352         internal FlexLayout.AlignmentType GetFlexAlignment()
353         {
354             FlexLayout.AlignmentType ret = (FlexLayout.AlignmentType)Interop.FlexLayout.FlexLayout_GetFlexAlignment(swigCPtr);
355             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
356             return ret;
357         }
358
359         internal FlexLayout.AlignmentType GetFlexItemsAlignment()
360         {
361             FlexLayout.AlignmentType ret = (FlexLayout.AlignmentType)Interop.FlexLayout.FlexLayout_GetFlexItemsAlignment(swigCPtr);
362             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
363             return ret;
364         }
365
366         /// <summary>
367         /// Gets/Sets the flex direction in the layout.
368         /// The direction of the main-axis which determines the direction that flex items are laid out.
369         /// </summary>
370         /// <exception cref="InvalidEnumArgumentException">Thrown when using invalid arguments that are enumerators.</exception>
371         /// <since_tizen> 6 </since_tizen>
372         public FlexDirection Direction
373         {
374             get => (FlexDirection)Interop.FlexLayout.FlexLayout_GetFlexDirection(swigCPtr);
375             set
376             {
377                 if (value < FlexDirection.Column || value > FlexDirection.RowReverse)
378                     throw new InvalidEnumArgumentException(nameof(Direction));
379
380                 Interop.FlexLayout.FlexLayout_SetFlexDirection(swigCPtr, (int)value);
381                 RequestLayout();
382             }
383         }
384
385         /// <summary>
386         /// Gets/Sets the justification in the layout.
387         /// Justify content describes how to align children within the main axis of their container.<br/>
388         /// For example, you can use this property to center a child horizontally within a container with <see cref="Direction"/> set to <see cref="FlexDirection.Row"/>
389         /// or vertically within a container with <see cref="Direction"/> set to <see cref="FlexDirection.Column"/>.
390         /// </summary>
391         /// <exception cref="InvalidEnumArgumentException">Thrown when using invalid arguments that are enumerators.</exception>
392         /// <since_tizen> 6 </since_tizen>
393         public FlexJustification Justification
394         {
395             get => (FlexJustification)Interop.FlexLayout.FlexLayout_GetFlexJustification(swigCPtr);
396             set
397             {
398                 if (value < FlexJustification.FlexStart || value > FlexJustification.SpaceAround)
399                     throw new InvalidEnumArgumentException(nameof(Justification));
400
401                 Interop.FlexLayout.FlexLayout_SetFlexJustification(swigCPtr, (int)value);
402                 RequestLayout();
403             }
404         }
405
406         /// <summary>
407         /// Gets/Sets the wrap in the layout.
408         /// The flex wrap property is set on containers and controls what happens when children overflow the size of the container along the main axis.<br/>
409         /// By default children are forced into a single line (which can shrink elements).<br/>
410         /// If wrapping is allowed items are wrapped into multiple lines along the main axis if needed. wrap reverse behaves the same, but the order of the lines is reversed.<br/>
411         /// When wrapping lines <see cref="Alignment"/> can be used to specify how the lines are placed in the container.
412         /// </summary>
413         /// <exception cref="InvalidEnumArgumentException">Thrown when using invalid arguments that are enumerators.</exception>
414         /// <since_tizen> 6 </since_tizen>
415         public FlexWrapType WrapType
416         {
417             get => (FlexWrapType)Interop.FlexLayout.FlexLayout_GetFlexWrap(swigCPtr);
418             set
419             {
420                 if (value != FlexWrapType.NoWrap && value != FlexWrapType.Wrap)
421                     throw new InvalidEnumArgumentException(nameof(WrapType));
422
423                 Interop.FlexLayout.FlexLayout_SetFlexWrap(swigCPtr, (int)value);
424                 RequestLayout();
425
426             }
427         }
428
429         /// <summary>
430         /// Gets/Sets the alignment of the layout content.
431         /// Alignment defines the distribution of lines along the cross-axis.<br/>
432         /// This only has effect when items are wrapped to multiple lines using flex wrap.
433         /// </summary>
434         /// <exception cref="InvalidEnumArgumentException">Thrown when using invalid arguments that are enumerators.</exception>
435         /// <since_tizen> 6 </since_tizen>
436         public AlignmentType Alignment
437         {
438             get => GetFlexAlignment();
439             set
440             {
441                 if (value < AlignmentType.Auto || value > AlignmentType.Stretch)
442                     throw new InvalidEnumArgumentException(nameof(Alignment));
443
444                 Interop.FlexLayout.FlexLayout_SetFlexAlignment(swigCPtr, (int)value);
445                 RequestLayout();
446             }
447         }
448
449         /// <summary>
450         /// Gets/Sets the alignment of the layout items.
451         /// Items alignment describes how to align children along the cross axis of their container.<br/>
452         /// Align items is very similar to <see cref="Justification"/> but instead of applying to the main axis, align items applies to the cross axis.
453         /// </summary>
454         /// <exception cref="InvalidEnumArgumentException">Thrown when using invalid arguments that are enumerators.</exception>
455         /// <since_tizen> 6 </since_tizen>
456         public AlignmentType ItemsAlignment
457         {
458             get => GetFlexItemsAlignment();
459             set
460             {
461                 if (value < AlignmentType.Auto || value > AlignmentType.Stretch)
462                     throw new InvalidEnumArgumentException(nameof(ItemsAlignment));
463
464                 Interop.FlexLayout.FlexLayout_SetFlexItemsAlignment(swigCPtr, (int)value);
465                 RequestLayout();
466             }
467         }
468
469         /// <summary>
470         /// Enumeration for the direction of the main axis in the flex container.
471         /// This determines the direction that flex items are laid out in the flex container.
472         /// </summary>
473         /// <since_tizen> 6 </since_tizen>
474         public enum FlexDirection
475         {
476             /// <summary>
477             /// The flexible items are displayed vertically as a column
478             /// </summary>
479             Column,
480             /// <summary>
481             /// The flexible items are displayed vertically as a column, but in reverse order
482             /// </summary>
483             ColumnReverse,
484             /// <summary>
485             /// The flexible items are displayed horizontally as a row
486             /// </summary>
487             Row,
488             /// <summary>
489             /// The flexible items are displayed horizontally as a row, but in reverse order
490             /// </summary>
491             RowReverse
492         }
493
494         /// <summary>
495         /// Enumeration for the alignment of the flex items when the items do not use all available space on the main-axis.
496         /// </summary>
497         /// <since_tizen> 6 </since_tizen>
498         public enum FlexJustification
499         {
500             /// <summary>
501             /// Items are positioned at the beginning of the container.
502             /// </summary>
503             FlexStart,
504             /// <summary>
505             /// Items are positioned at the center of the container.
506             /// </summary>
507             Center,
508             /// <summary>
509             /// Items are positioned at the end of the container.
510             /// </summary>
511             FlexEnd,
512             /// <summary>
513             /// Items are positioned with equal space between the lines.
514             /// </summary>
515             SpaceBetween,
516             /// <summary>
517             /// Items are positioned with equal space before, between, and after the lines.<br/>
518             /// Compared to <see cref="FlexJustification.SpaceBetween"/> using <see cref="FlexJustification.SpaceAround"/>
519             /// will result in space being distributed to the beginning of the first child and end of the last child.
520             /// </summary>
521             SpaceAround
522         }
523
524         /// <summary>
525         /// Enumeration for the wrap type of the flex container when there is no enough room for all the items on one flex line.
526         /// </summary>
527         /// <since_tizen> 6 </since_tizen>
528         public enum FlexWrapType
529         {
530             /// <summary>
531             /// Flex items laid out in single line (shrunk to fit the flex container along the main axis)
532             /// </summary>
533             NoWrap,
534             /// <summary>
535             /// Flex items laid out in multiple lines if needed
536             /// </summary>
537             Wrap
538         }
539
540         /// <summary>
541         /// Enumeration for the alignment of the flex items or lines when the items or lines do not use all the available space on the cross-axis.
542         /// </summary>
543         /// <since_tizen> 6 </since_tizen>
544         public enum AlignmentType
545         {
546             /// <summary>
547             /// Inherits the same alignment from the parent
548             /// </summary>
549             Auto,
550             /// <summary>
551             /// At the beginning of the container
552             /// </summary>
553             FlexStart,
554             /// <summary>
555             /// At the center of the container
556             /// </summary>
557             Center,
558             /// <summary>
559             /// At the end of the container
560             /// </summary>
561             FlexEnd,
562             /// <summary>
563             /// Stretch to fit the container
564             /// </summary>
565             Stretch
566         }
567
568         /// <summary>
569         /// Enumeration for the position type of the flex item how it is positioned within its parent.
570         /// </summary>
571         /// <since_tizen> 8 </since_tizen>
572         public enum PositionType
573         {
574             /// <summary>
575             /// Flex items laid out relatively.
576             /// </summary>
577             Relative,
578             /// <summary>
579             /// Flex items laid out absolutely.
580             /// </summary>
581             Absolute
582         }
583
584         private void measureChild(global::System.IntPtr childPtr, float width, int measureModeWidth, float height, int measureModeHeight, out MeasuredSize measureSize)
585         {
586             // We need to measure child layout
587             View child = Registry.GetManagedBaseHandleFromNativePtr(childPtr) as View;
588             if (child == null)
589             {
590                 measureSize.width = 0;
591                 measureSize.height = 0;
592                 return;
593             }
594
595             LayoutItem childLayout = child.Layout;
596
597             MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(
598                                     new MeasureSpecification(
599                                         new LayoutLength(parentMeasureSpecificationWidth.Size - (child.Margin.Start + child.Margin.End)),
600                                         parentMeasureSpecificationWidth.Mode),
601                                     new LayoutLength(Padding.Start + Padding.End),
602                                     new LayoutLength(child.WidthSpecification));
603
604             MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(
605                                     new MeasureSpecification(
606                                         new LayoutLength(parentMeasureSpecificationHeight.Size - (child.Margin.Top + child.Margin.Bottom)),
607                                         parentMeasureSpecificationHeight.Mode),
608                                     new LayoutLength(Padding.Top + Padding.Bottom),
609                                     new LayoutLength(child.HeightSpecification));
610
611             childLayout.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
612
613             measureSize.width = childLayout.MeasuredWidth.Size.AsRoundedValue();
614             measureSize.height = childLayout.MeasuredHeight.Size.AsRoundedValue();
615         }
616
617         void InsertChild(LayoutItem child)
618         {
619             // Store created node for child
620             IntPtr childPtr = Interop.FlexLayout.FlexLayout_AddChildWithMargin(swigCPtr, View.getCPtr(child.Owner), Extents.getCPtr(child.Owner.Margin), measureChildDelegate, LayoutChildren.Count - 1);
621             HandleRef childHandleRef = new HandleRef(child.Owner, childPtr);
622             SetAttachedValue(child.Owner, FlexItemProperty, childHandleRef);
623         }
624
625         /// <summary>
626         /// Callback when child is added to container.<br />
627         /// Derived classes can use this to set their own child properties on the child layout's owner.<br />
628         /// </summary>
629         /// <param name="child">The Layout child.</param>
630         /// <since_tizen> 6 </since_tizen>
631         protected override void OnChildAdd(LayoutItem child)
632         {
633             InsertChild(child);
634         }
635
636         /// <summary>
637         /// Callback when child is removed from container.<br />
638         /// </summary>
639         /// <param name="child">The Layout child.</param>
640         /// <since_tizen> 6 </since_tizen>
641         protected override void OnChildRemove(LayoutItem child)
642         {
643             // When child View is removed from it's parent View (that is a Layout) then remove it from the layout too.
644             // FlexLayout refers to the child as a View not LayoutItem.
645             Interop.FlexLayout.FlexLayout_RemoveChild(swigCPtr, child);
646         }
647
648         /// <summary>
649         /// Measure the layout and its content to determine the measured width and the measured height.<br />
650         /// </summary>
651         /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
652         /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
653         /// <since_tizen> 6 </since_tizen>
654         protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
655         {
656             bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL;
657             Extents padding = Owner.Padding;
658
659             Interop.FlexLayout.FlexLayout_SetPadding(swigCPtr, Extents.getCPtr(padding));
660
661             float width = FlexUndefined; // Behaves as WrapContent (Flex Auto)
662             float height = FlexUndefined; // Behaves as WrapContent (Flex Auto)
663
664             if (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly || widthMeasureSpec.Mode == MeasureSpecification.ModeType.AtMost)
665             {
666                 width = widthMeasureSpec.Size.AsDecimal();
667             }
668
669             if (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly || heightMeasureSpec.Mode == MeasureSpecification.ModeType.AtMost)
670             {
671                 height = heightMeasureSpec.Size.AsDecimal();
672             }
673
674             // Save measureSpec to measure children.
675             // In other Layout, we can pass it as parameter to measuring child but in FlexLayout we can't
676             // because measurChild function is called by native callback.
677             parentMeasureSpecificationWidth = widthMeasureSpec;
678             parentMeasureSpecificationHeight = heightMeasureSpec;
679
680             // Assign child properties
681             for (int i = 0; i < LayoutChildren.Count; i++)
682             {
683                 LayoutItem layoutItem = LayoutChildren[i];
684                 View Child = layoutItem?.Owner;
685                 HandleRef childHandleRef = (HandleRef)Child.GetValue(FlexItemProperty);
686                 if (childHandleRef.Handle == IntPtr.Zero || Child == null)
687                     continue;
688
689                 if (layoutItem.Owner.ExcludeLayouting)
690                 {
691                     MeasureChildWithoutPadding(layoutItem, widthMeasureSpec, heightMeasureSpec);
692                     continue;
693                 }
694
695                 AlignmentType flexAlignemnt = GetFlexAlignmentSelf(Child);
696                 PositionType positionType = GetFlexPositionType(Child);
697                 float flexAspectRatio = GetFlexAspectRatio(Child);
698                 float flexBasis = GetFlexBasis(Child);
699                 float flexShrink = GetFlexShrink(Child);
700                 float flexGrow = GetFlexGrow(Child);
701
702                 Interop.FlexLayout.FlexLayout_SetFlexAlignmentSelf(childHandleRef, (int)flexAlignemnt);
703                 Interop.FlexLayout.FlexLayout_SetFlexPositionType(childHandleRef, (int)positionType);
704                 Interop.FlexLayout.FlexLayout_SetFlexAspectRatio(childHandleRef, flexAspectRatio);
705                 Interop.FlexLayout.FlexLayout_SetFlexBasis(childHandleRef, flexBasis);
706                 Interop.FlexLayout.FlexLayout_SetFlexShrink(childHandleRef, flexShrink);
707                 Interop.FlexLayout.FlexLayout_SetFlexGrow(childHandleRef, flexGrow);
708             }
709
710             Interop.FlexLayout.FlexLayout_CalculateLayout(swigCPtr, width, height, isLayoutRtl);
711
712             LayoutLength flexLayoutWidth = new LayoutLength(Interop.FlexLayout.FlexLayout_GetWidth(swigCPtr));
713             LayoutLength flexLayoutHeight = new LayoutLength(Interop.FlexLayout.FlexLayout_GetHeight(swigCPtr));
714
715             Debug.WriteLineIf(LayoutDebugFlex, "FlexLayout OnMeasure width:" + flexLayoutWidth.AsRoundedValue()
716                                                 + " height:" + flexLayoutHeight.AsRoundedValue());
717
718             SetMeasuredDimensions(GetDefaultSize(flexLayoutWidth, widthMeasureSpec),
719                                    GetDefaultSize(flexLayoutHeight, heightMeasureSpec));
720         }
721
722         /// <summary>
723         /// Assign a size and position to each of its children.<br />
724         /// </summary>
725         /// <param name="changed">This is a new size or position for this layout.</param>
726         /// <param name="left">Left position, relative to parent.</param>
727         /// <param name="top"> Top position, relative to parent.</param>
728         /// <param name="right">Right position, relative to parent.</param>
729         /// <param name="bottom">Bottom position, relative to parent.</param>
730         /// <since_tizen> 6 </since_tizen>
731         protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
732         {
733
734             bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL;
735             LayoutLength width = right - left;
736             LayoutLength height = bottom - top;
737
738             // Call to FlexLayout implementation to calculate layout values for later retrieval.
739             Interop.FlexLayout.FlexLayout_CalculateLayout(swigCPtr, width.AsDecimal(), height.AsDecimal(), isLayoutRtl);
740
741             int count = LayoutChildren.Count;
742             for (int childIndex = 0; childIndex < count; childIndex++)
743             {
744                 LayoutItem childLayout = LayoutChildren[childIndex];
745                 if (childLayout != null)
746                 {
747                     if (!childLayout.Owner.ExcludeLayouting)
748                     {
749                         // Get the frame for the child, start, top, end, bottom.
750                         Vector4 frame = new Vector4(Interop.FlexLayout.FlexLayout_GetNodeFrame(swigCPtr, childIndex), true);
751                         childLayout.Layout(new LayoutLength(frame.X), new LayoutLength(frame.Y), new LayoutLength(frame.Z), new LayoutLength(frame.W));
752                     }
753                 }
754             }
755             LayoutForIndependentChild();
756         }
757     } // FLexlayout
758 } // namesspace Tizen.NUI