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