1 /* Copyright (c) 2019 Samsung Electronics Co., Ltd.
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
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 using System.ComponentModel;
19 using Tizen.NUI.BaseComponents;
20 using System.Runtime.InteropServices;
25 /// [Draft] This class implements a flex layout.
26 /// The flex layout implementation is based on open source Facebook Yoga layout engine.
27 /// For more information about the flex layout API and how to use it please refer to https://yogalayout.com/docs/
28 /// We implement the subset of the API in the class below.
30 internal class FlexLayout : LayoutGroup, global::System.IDisposable
32 float Flex{ get; set;}
33 int AlignSelf{get; set;}
35 private global::System.Runtime.InteropServices.HandleRef swigCPtr;
36 private bool swigCMemOwn;
37 private bool disposed;
38 private bool isDisposeQueued = false;
40 private IntPtr _rootFlex; // Pointer to the unmanged flex layout class.
42 public struct MeasuredSize
44 public MeasuredSize(float x, float y)
53 [UnmanagedFunctionPointer(CallingConvention.StdCall)]
54 internal delegate MeasuredSize ChildMeasureCallback( global::System.IntPtr child, float width, int measureModeWidth, float height, int measureModeHeight );
56 event ChildMeasureCallback measureChildDelegate; // Stores a delegate to the child measure callback. Used for all children of this FlexLayout.
58 internal FlexLayout(global::System.IntPtr cPtr, bool cMemoryOwn)
60 swigCMemOwn = cMemoryOwn;
61 swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr);
62 _rootFlex = Interop.FlexLayout.FlexLayout_New();
63 measureChildDelegate = new ChildMeasureCallback(measureChild);
66 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(FlexLayout obj)
68 return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
73 // Throw exception if Dispose() is called in separate thread.
74 if (!Window.IsInstalled())
76 throw new System.InvalidOperationException("This API called from separate thread. This API must be called from MainThread.");
81 Dispose(DisposeTypes.Implicit);
85 Dispose(DisposeTypes.Explicit);
86 System.GC.SuppressFinalize(this);
90 protected virtual void Dispose(DisposeTypes type)
97 if (type == DisposeTypes.Explicit)
100 // Release your own managed resources here.
101 // You should release all of your own disposable objects here.
105 // Release your own unmanaged resources here.
106 // You should not access any managed member here except static instance.
107 // because the execution order of Finalizes is non-deterministic.
108 if (swigCPtr.Handle != global::System.IntPtr.Zero)
113 Interop.FlexLayout.delete_FlexLayout(swigCPtr);
115 swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
121 /// [Draft] Creates a FlexLayout object.
123 public FlexLayout() : this(Interop.FlexLayout.FlexLayout_New(), true)
125 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
128 internal static FlexLayout DownCast(BaseHandle handle)
130 FlexLayout ret = new FlexLayout(Interop.FlexLayout.FlexLayout_DownCast(BaseHandle.getCPtr(handle)), true);
131 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
135 internal FlexLayout(FlexLayout other) : this(Interop.FlexLayout.new_FlexLayout__SWIG_1(FlexLayout.getCPtr(other)), true)
137 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
140 internal FlexLayout Assign(FlexLayout other)
142 FlexLayout ret = new FlexLayout(Interop.FlexLayout.FlexLayout_Assign(swigCPtr, FlexLayout.getCPtr(other)), false);
143 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
147 internal void SetFlexDirection(FlexLayout.FlexDirection flexDirection)
149 Interop.FlexLayout.FlexLayout_SetFlexDirection(swigCPtr, (int)flexDirection);
153 internal FlexLayout.FlexDirection GetFlexDirection()
155 FlexLayout.FlexDirection ret = (FlexLayout.FlexDirection)Interop.FlexLayout.FlexLayout_GetFlexDirection(swigCPtr);
160 internal void SetFlexJustification(FlexLayout.FlexJustification flexJustification)
162 Interop.FlexLayout.FlexLayout_SetFlexJustification(swigCPtr, (int)flexJustification);
166 internal FlexLayout.FlexJustification GetFlexJustification()
168 FlexLayout.FlexJustification ret = (FlexLayout.FlexJustification)Interop.FlexLayout.FlexLayout_GetFlexJustification(swigCPtr);
172 internal void SetFlexWrap(FlexLayout.FlexWrapType flexWrap)
174 Interop.FlexLayout.FlexLayout_SetFlexWrap(swigCPtr, (int)flexWrap);
178 internal FlexLayout.FlexWrapType GetFlexWrap()
180 FlexLayout.FlexWrapType ret = (FlexLayout.FlexWrapType)Interop.FlexLayout.FlexLayout_GetFlexWrap(swigCPtr);
184 internal void SetFlexAlignment(FlexLayout.AlignmentType flexAlignment)
186 Interop.FlexLayout.FlexLayout_SetFlexAlignment(swigCPtr, (int)flexAlignment);
190 internal FlexLayout.AlignmentType GetFlexAlignment()
192 FlexLayout.AlignmentType ret = (FlexLayout.AlignmentType)Interop.FlexLayout.FlexLayout_GetFlexAlignment(swigCPtr);
193 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
197 internal void SetFlexItemsAlignment(FlexLayout.AlignmentType flexAlignment)
199 Interop.FlexLayout.FlexLayout_SetFlexItemsAlignment(swigCPtr, (int)flexAlignment);
203 internal FlexLayout.AlignmentType GetFlexItemsAlignment()
205 FlexLayout.AlignmentType ret = (FlexLayout.AlignmentType)Interop.FlexLayout.FlexLayout_GetFlexItemsAlignment(swigCPtr);
206 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
211 /// [Draft] Get/Set the flex direction in the layout.
212 /// The direction of the main-axis which determines the direction that flex items are laid out.
214 public FlexDirection Direction
218 return GetFlexDirection();
222 SetFlexDirection(value);
227 /// [Draft] Get/Set the justification in the layout.
229 public FlexJustification Justification
233 return GetFlexJustification();
237 SetFlexJustification(value);
242 /// [Draft] Get/Set the wrap in the layout.
244 public FlexWrapType WrapType
248 return GetFlexWrap();
257 /// [Draft] Get/Set the alignment of the layout content.
259 public AlignmentType Alignment
263 return GetFlexAlignment();
267 SetFlexAlignment(value);
272 /// [Draft] Get/Set the alignment of the layout items.
274 public AlignmentType ItemsAlignment
278 return GetFlexItemsAlignment();
282 SetFlexItemsAlignment(value);
287 /// [Draft] Enumeration for the direction of the main axis in the flex container.
288 /// This determines the direction that flex items are laid out in the flex container.
290 public enum FlexDirection
293 /// The flexible items are displayed vertically as a column
297 /// The flexible items are displayed vertically as a column, but in reverse order
301 /// The flexible items are displayed horizontally as a row
305 /// The flexible items are displayed horizontally as a row, but in reverse order
311 /// [Draft] Enumeration for the alignment of the flex items when the items do not use all available space on the main-axis.
313 public enum FlexJustification
316 /// Items are positioned at the beginning of the container
320 /// Items are positioned at the center of the container
324 /// Items are positioned at the end of the container
328 /// Items are positioned with equal space between the lines
332 /// Items are positioned with equal space before, between, and after the lines
338 /// [Draft] Enumeration for the wrap type of the flex container when there is no enough room for all the items on one flex line.
340 public enum FlexWrapType
343 /// Flex items laid out in single line (shrunk to fit the flex container along the main axis)
347 /// Flex items laid out in multiple lines if needed
353 /// [Draft] 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.
355 public enum AlignmentType
358 /// Inherits the same alignment from the parent
362 /// At the beginning of the container
366 /// At the center of the container
370 /// At the end of the container
374 /// Stretch to fit the container
379 private MeasuredSize measureChild(global::System.IntPtr child, float width, int measureModeWidth, float height, int measureModeHeight)
381 View view = Registry.GetManagedBaseHandleFromNativePtr(child) as View;
382 Size2D viewSize = new Size2D(8,8);
385 viewSize = view.NaturalSize2D;
387 return new MeasuredSize(viewSize.Width,viewSize.Height);
390 void InsertChild( LayoutItem child )
392 // Store created node for child
393 Interop.FlexLayout.FlexLayout_AddChild(swigCPtr, View.getCPtr(child.Owner), measureChildDelegate, _children.Count-1);
396 protected override void OnChildAdd(LayoutItem child)
401 protected override void OnChildRemove(LayoutItem child)
403 // When child View is removed from it's parent View (that is a Layout) then remove it from the layout too.
404 // FlexLayout refers to the child as a View not LayoutItem.
405 Interop.FlexLayout.FlexLayout_RemoveChild(swigCPtr, child);
408 protected override void OnMeasure( MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec )
410 bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL;
411 Extents padding = Owner.Padding;
412 Extents margin = Owner.Margin;
414 Interop.FlexLayout.FlexLayout_SetMargin(swigCPtr, Extents.getCPtr(margin));
415 Interop.FlexLayout.FlexLayout_SetPadding(swigCPtr, Extents.getCPtr(padding));
420 if( widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly || widthMeasureSpec.Mode == MeasureSpecification.ModeType.AtMost )
422 width = widthMeasureSpec.Size.AsDecimal();
425 if ( heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly || heightMeasureSpec.Mode == MeasureSpecification.ModeType.AtMost )
427 height = heightMeasureSpec.Size.AsDecimal();
430 Interop.FlexLayout.FlexLayout_CalculateLayout( swigCPtr, width, height, isLayoutRtl );
432 SetMeasuredDimensions( GetDefaultSize( new LayoutLength( (float)Interop.FlexLayout.FlexLayout_GetWidth(swigCPtr) ), widthMeasureSpec ),
433 GetDefaultSize( new LayoutLength( (float)Interop.FlexLayout.FlexLayout_GetHeight(swigCPtr) ), heightMeasureSpec ) );
436 protected override void OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
439 bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL;
440 LayoutLength width = right - left;
441 LayoutLength height = bottom - top;
443 // Call to FlexLayout implementation to calculate layout values for later retrieval.
444 Interop.FlexLayout.FlexLayout_CalculateLayout( swigCPtr, width.AsDecimal(), height.AsDecimal(), isLayoutRtl );
446 int count = _children.Count;
447 for( int childIndex = 0; childIndex < count; childIndex++)
449 LayoutItem childLayout = _children[childIndex];
450 if( childLayout != null )
452 // Get the frame for the child, start, top, end, bottom.
453 Vector4 frame = new Vector4(Interop.FlexLayout.FlexLayout_GetNodeFrame(swigCPtr, childIndex ), true);
454 childLayout.Layout( new LayoutLength(frame.X), new LayoutLength(frame.Y), new LayoutLength(frame.Z), new LayoutLength(frame.W) );
460 } // namesspace Tizen.NUI