From: agnelovaz Date: Mon, 30 Sep 2019 07:39:37 +0000 (+0100) Subject: [NUI] Layouting API made public (#1026) X-Git-Tag: submit/tizen/20191001.005203~1^2~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b7bb91cfa993065ac730539415eedc7ce065b0f4;p=platform%2Fcore%2Fcsapi%2Ftizenfx.git [NUI] Layouting API made public (#1026) * [NUI] Layouting API made public View.cs Layouting API public LayoutItem Measure API made public Moving Layouting files to public folder Change-Id: I78b0a54c07d69496a666740fd6e09ade1dd6bc9b * [NUI] Removing API not needed Change-Id: Id80cd22237a92c601839b8da388923d77e9b9617 --- diff --git a/src/Tizen.NUI/src/internal/Layouting/AbsoluteLayout.cs b/src/Tizen.NUI/src/internal/Layouting/AbsoluteLayout.cs deleted file mode 100755 index 3741b3d2e..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/AbsoluteLayout.cs +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (c) 2019 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -using System; -using Tizen.NUI.BaseComponents; - -namespace Tizen.NUI -{ - /// - /// [Draft] This class implements a absolute layout, allowing explicit positioning of children. - /// Positions are from the top left of the layout and can be set using the Actor::Property::POSITION and alike. - /// - internal class AbsoluteLayout : LayoutGroup - { - /// - /// Struct to store Measured states of height and width. - /// - private struct HeightAndWidthState - { - public MeasuredSize.StateType widthState; - public MeasuredSize.StateType heightState; - - public HeightAndWidthState( MeasuredSize.StateType width, MeasuredSize.StateType height) - { - widthState = width; - heightState = height; - } - } - - /// - /// [Draft] Constructor - /// - public AbsoluteLayout() - { - } - - protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) - { - float totalHeight = 0.0f; - float totalWidth = 0.0f; - - HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK, - MeasuredSize.StateType.MeasuredSizeOK); - - float minPositionX = 0.0f; - float minPositionY = 0.0f; - float maxPositionX = 0.0f; - float maxPositionY = 0.0f; - - // measure children - foreach( LayoutItem childLayout in _children ) - { - if (childLayout != null) - { - // Get size of child - MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec ); - float childWidth = childLayout.MeasuredWidth.Size.AsDecimal(); - float childHeight = childLayout.MeasuredHeight.Size.AsDecimal(); - - // Determine the width and height needed by the children using their given position and size. - // Children could overlap so find the left most and right most child. - Position2D childPosition = childLayout.Owner.Position2D; - float childLeft = childPosition.X; - float childTop = childPosition.Y; - - minPositionX = Math.Min( minPositionX, childLeft ); - maxPositionX = Math.Max( maxPositionX, childLeft + childWidth ); - // Children could overlap so find the highest and lowest child. - minPositionY = Math.Min( minPositionY, childTop ); - maxPositionY = Math.Max( maxPositionY, childTop + childHeight ); - - // Store current width and height needed to contain all children. - totalWidth = maxPositionX - minPositionX; - totalHeight = maxPositionY - minPositionY; - - if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) - { - childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; - } - if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) - { - childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; - } - } - } - - - MeasuredSize widthSizeAndState = ResolveSizeAndState(new LayoutLength(totalWidth), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); - MeasuredSize heightSizeAndState = ResolveSizeAndState(new LayoutLength(totalHeight), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); - totalWidth = widthSizeAndState.Size.AsDecimal(); - totalHeight = heightSizeAndState.Size.AsDecimal(); - - // Ensure layout respects it's given minimum size - totalWidth = Math.Max( totalWidth, SuggestedMinimumWidth.AsDecimal() ); - totalHeight = Math.Max( totalHeight, SuggestedMinimumHeight.AsDecimal() ); - - widthSizeAndState.State = childState.widthState; - heightSizeAndState.State = childState.heightState; - - SetMeasuredDimensions( ResolveSizeAndState( new LayoutLength(totalWidth), widthMeasureSpec, childState.widthState ), - ResolveSizeAndState( new LayoutLength(totalHeight), heightMeasureSpec, childState.heightState ) ); - } - - protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) - { - // Absolute layout positions it's children at their Actor positions. - // Children could overlap or spill outside the parent, as is the nature of absolute positions. - foreach( LayoutItem childLayout in _children ) - { - if( childLayout != null ) - { - LayoutLength childWidth = childLayout.MeasuredWidth.Size; - LayoutLength childHeight = childLayout.MeasuredHeight.Size; - - Position2D childPosition = childLayout.Owner.Position2D; - - LayoutLength childLeft = new LayoutLength(childPosition.X); - LayoutLength childTop = new LayoutLength(childPosition.Y); - - childLayout.Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight ); - } - } - } - } - -} // namespace diff --git a/src/Tizen.NUI/src/internal/Layouting/FlexLayout.cs b/src/Tizen.NUI/src/internal/Layouting/FlexLayout.cs deleted file mode 100644 index c2c36898e..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/FlexLayout.cs +++ /dev/null @@ -1,460 +0,0 @@ -/* Copyright (c) 2019 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -using System; -using System.ComponentModel; -using Tizen.NUI.BaseComponents; -using System.Runtime.InteropServices; - -namespace Tizen.NUI -{ - /// - /// [Draft] This class implements a flex layout. - /// The flex layout implementation is based on open source Facebook Yoga layout engine. - /// For more information about the flex layout API and how to use it please refer to https://yogalayout.com/docs/ - /// We implement the subset of the API in the class below. - /// - internal class FlexLayout : LayoutGroup, global::System.IDisposable - { - float Flex{ get; set;} - int AlignSelf{get; set;} - - private global::System.Runtime.InteropServices.HandleRef swigCPtr; - private bool swigCMemOwn; - private bool disposed; - private bool isDisposeQueued = false; - - private IntPtr _rootFlex; // Pointer to the unmanged flex layout class. - - public struct MeasuredSize - { - public MeasuredSize(float x, float y) - { - width = x; - height = y; - } - float width; - float height; - }; - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - internal delegate MeasuredSize ChildMeasureCallback( global::System.IntPtr child, float width, int measureModeWidth, float height, int measureModeHeight ); - - event ChildMeasureCallback measureChildDelegate; // Stores a delegate to the child measure callback. Used for all children of this FlexLayout. - - internal FlexLayout(global::System.IntPtr cPtr, bool cMemoryOwn) - { - swigCMemOwn = cMemoryOwn; - swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); - _rootFlex = Interop.FlexLayout.FlexLayout_New(); - measureChildDelegate = new ChildMeasureCallback(measureChild); - } - - internal static global::System.Runtime.InteropServices.HandleRef getCPtr(FlexLayout obj) - { - return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; - } - - public void Dispose() - { - // Throw exception if Dispose() is called in separate thread. - if (!Window.IsInstalled()) - { - throw new System.InvalidOperationException("This API called from separate thread. This API must be called from MainThread."); - } - - if (isDisposeQueued) - { - Dispose(DisposeTypes.Implicit); - } - else - { - Dispose(DisposeTypes.Explicit); - System.GC.SuppressFinalize(this); - } - } - - protected virtual void Dispose(DisposeTypes type) - { - if (disposed) - { - return; - } - - if (type == DisposeTypes.Explicit) - { - // Called by User - // Release your own managed resources here. - // You should release all of your own disposable objects here. - - } - - // Release your own unmanaged resources here. - // You should not access any managed member here except static instance. - // because the execution order of Finalizes is non-deterministic. - if (swigCPtr.Handle != global::System.IntPtr.Zero) - { - if (swigCMemOwn) - { - swigCMemOwn = false; - Interop.FlexLayout.delete_FlexLayout(swigCPtr); - } - swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); - } - disposed = true; - } - - /// - /// [Draft] Creates a FlexLayout object. - /// - public FlexLayout() : this(Interop.FlexLayout.FlexLayout_New(), true) - { - if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); - } - - internal static FlexLayout DownCast(BaseHandle handle) - { - FlexLayout ret = new FlexLayout(Interop.FlexLayout.FlexLayout_DownCast(BaseHandle.getCPtr(handle)), true); - if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); - return ret; - } - - internal FlexLayout(FlexLayout other) : this(Interop.FlexLayout.new_FlexLayout__SWIG_1(FlexLayout.getCPtr(other)), true) - { - if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); - } - - internal FlexLayout Assign(FlexLayout other) - { - FlexLayout ret = new FlexLayout(Interop.FlexLayout.FlexLayout_Assign(swigCPtr, FlexLayout.getCPtr(other)), false); - if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); - return ret; - } - - internal void SetFlexDirection(FlexLayout.FlexDirection flexDirection) - { - Interop.FlexLayout.FlexLayout_SetFlexDirection(swigCPtr, (int)flexDirection); - RequestLayout(); - } - - internal FlexLayout.FlexDirection GetFlexDirection() - { - FlexLayout.FlexDirection ret = (FlexLayout.FlexDirection)Interop.FlexLayout.FlexLayout_GetFlexDirection(swigCPtr); - return ret; - - } - - internal void SetFlexJustification(FlexLayout.FlexJustification flexJustification) - { - Interop.FlexLayout.FlexLayout_SetFlexJustification(swigCPtr, (int)flexJustification); - RequestLayout(); - } - - internal FlexLayout.FlexJustification GetFlexJustification() - { - FlexLayout.FlexJustification ret = (FlexLayout.FlexJustification)Interop.FlexLayout.FlexLayout_GetFlexJustification(swigCPtr); - return ret; - } - - internal void SetFlexWrap(FlexLayout.FlexWrapType flexWrap) - { - Interop.FlexLayout.FlexLayout_SetFlexWrap(swigCPtr, (int)flexWrap); - RequestLayout(); - } - - internal FlexLayout.FlexWrapType GetFlexWrap() - { - FlexLayout.FlexWrapType ret = (FlexLayout.FlexWrapType)Interop.FlexLayout.FlexLayout_GetFlexWrap(swigCPtr); - return ret; - } - - internal void SetFlexAlignment(FlexLayout.AlignmentType flexAlignment) - { - Interop.FlexLayout.FlexLayout_SetFlexAlignment(swigCPtr, (int)flexAlignment); - RequestLayout(); - } - - internal FlexLayout.AlignmentType GetFlexAlignment() - { - FlexLayout.AlignmentType ret = (FlexLayout.AlignmentType)Interop.FlexLayout.FlexLayout_GetFlexAlignment(swigCPtr); - if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); - return ret; - } - - internal void SetFlexItemsAlignment(FlexLayout.AlignmentType flexAlignment) - { - Interop.FlexLayout.FlexLayout_SetFlexItemsAlignment(swigCPtr, (int)flexAlignment); - RequestLayout(); - } - - internal FlexLayout.AlignmentType GetFlexItemsAlignment() - { - FlexLayout.AlignmentType ret = (FlexLayout.AlignmentType)Interop.FlexLayout.FlexLayout_GetFlexItemsAlignment(swigCPtr); - if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); - return ret; - } - - /// - /// [Draft] Get/Set the flex direction in the layout. - /// The direction of the main-axis which determines the direction that flex items are laid out. - /// - public FlexDirection Direction - { - get - { - return GetFlexDirection(); - } - set - { - SetFlexDirection(value); - } - } - - /// - /// [Draft] Get/Set the justification in the layout. - /// - public FlexJustification Justification - { - get - { - return GetFlexJustification(); - } - set - { - SetFlexJustification(value); - } - } - - /// - /// [Draft] Get/Set the wrap in the layout. - /// - public FlexWrapType WrapType - { - get - { - return GetFlexWrap(); - } - set - { - SetFlexWrap(value); - } - } - - /// - /// [Draft] Get/Set the alignment of the layout content. - /// - public AlignmentType Alignment - { - get - { - return GetFlexAlignment(); - } - set - { - SetFlexAlignment(value); - } - } - - /// - /// [Draft] Get/Set the alignment of the layout items. - /// - public AlignmentType ItemsAlignment - { - get - { - return GetFlexItemsAlignment(); - } - set - { - SetFlexItemsAlignment(value); - } - } - - /// - /// [Draft] Enumeration for the direction of the main axis in the flex container. - /// This determines the direction that flex items are laid out in the flex container. - /// - public enum FlexDirection - { - /// - /// The flexible items are displayed vertically as a column - /// - Column, - /// - /// The flexible items are displayed vertically as a column, but in reverse order - /// - ColumnReverse, - /// - /// The flexible items are displayed horizontally as a row - /// - Row, - /// - /// The flexible items are displayed horizontally as a row, but in reverse order - /// - RowReverse - } - - /// - /// [Draft] Enumeration for the alignment of the flex items when the items do not use all available space on the main-axis. - /// - public enum FlexJustification - { - /// - /// Items are positioned at the beginning of the container - /// - FlexStart, - /// - /// Items are positioned at the center of the container - /// - Center, - /// - /// Items are positioned at the end of the container - /// - FlexEnd, - /// - /// Items are positioned with equal space between the lines - /// - SpaceBetween, - /// - /// Items are positioned with equal space before, between, and after the lines - /// - SpaceAround - } - - /// - /// [Draft] Enumeration for the wrap type of the flex container when there is no enough room for all the items on one flex line. - /// - public enum FlexWrapType - { - /// - /// Flex items laid out in single line (shrunk to fit the flex container along the main axis) - /// - NoWrap, - /// - /// Flex items laid out in multiple lines if needed - /// - Wrap - } - - /// - /// [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. - /// - public enum AlignmentType - { - /// - /// Inherits the same alignment from the parent - /// - Auto, - /// - /// At the beginning of the container - /// - FlexStart, - /// - /// At the center of the container - /// - Center, - /// - /// At the end of the container - /// - FlexEnd, - /// - /// Stretch to fit the container - /// - Stretch - } - - private MeasuredSize measureChild(global::System.IntPtr child, float width, int measureModeWidth, float height, int measureModeHeight) - { - View view = Registry.GetManagedBaseHandleFromNativePtr(child) as View; - Size2D viewSize = new Size2D(8,8); - if(view) - { - viewSize = view.NaturalSize2D; - } - return new MeasuredSize(viewSize.Width,viewSize.Height); - } - - void InsertChild( LayoutItem child ) - { - // Store created node for child - Interop.FlexLayout.FlexLayout_AddChild(swigCPtr, View.getCPtr(child.Owner), measureChildDelegate, _children.Count-1); - } - - protected override void OnChildAdd(LayoutItem child) - { - InsertChild(child); - } - - protected override void OnChildRemove(LayoutItem child) - { - // When child View is removed from it's parent View (that is a Layout) then remove it from the layout too. - // FlexLayout refers to the child as a View not LayoutItem. - Interop.FlexLayout.FlexLayout_RemoveChild(swigCPtr, child); - } - - protected override void OnMeasure( MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec ) - { - bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL; - Extents padding = Owner.Padding; - Extents margin = Owner.Margin; - - Interop.FlexLayout.FlexLayout_SetMargin(swigCPtr, Extents.getCPtr(margin)); - Interop.FlexLayout.FlexLayout_SetPadding(swigCPtr, Extents.getCPtr(padding)); - - float width = 0.0f; - float height = 0.0f; - - if( widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly || widthMeasureSpec.Mode == MeasureSpecification.ModeType.AtMost ) - { - width = widthMeasureSpec.Size.AsDecimal(); - } - - if ( heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly || heightMeasureSpec.Mode == MeasureSpecification.ModeType.AtMost ) - { - height = heightMeasureSpec.Size.AsDecimal(); - } - - Interop.FlexLayout.FlexLayout_CalculateLayout( swigCPtr, width, height, isLayoutRtl ); - - SetMeasuredDimensions( GetDefaultSize( new LayoutLength( (float)Interop.FlexLayout.FlexLayout_GetWidth(swigCPtr) ), widthMeasureSpec ), - GetDefaultSize( new LayoutLength( (float)Interop.FlexLayout.FlexLayout_GetHeight(swigCPtr) ), heightMeasureSpec ) ); - } - - protected override void OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom ) - { - - bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL; - LayoutLength width = right - left; - LayoutLength height = bottom - top; - - // Call to FlexLayout implementation to calculate layout values for later retrieval. - Interop.FlexLayout.FlexLayout_CalculateLayout( swigCPtr, width.AsDecimal(), height.AsDecimal(), isLayoutRtl ); - - int count = _children.Count; - for( int childIndex = 0; childIndex < count; childIndex++) - { - LayoutItem childLayout = _children[childIndex]; - if( childLayout != null ) - { - // Get the frame for the child, start, top, end, bottom. - Vector4 frame = new Vector4(Interop.FlexLayout.FlexLayout_GetNodeFrame(swigCPtr, childIndex ), true); - childLayout.Layout( new LayoutLength(frame.X), new LayoutLength(frame.Y), new LayoutLength(frame.Z), new LayoutLength(frame.W) ); - } - } - } - - } // FLexlayout -} // namesspace Tizen.NUI \ No newline at end of file diff --git a/src/Tizen.NUI/src/internal/Layouting/GridLayout.cs b/src/Tizen.NUI/src/internal/Layouting/GridLayout.cs deleted file mode 100755 index 887cb1528..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/GridLayout.cs +++ /dev/null @@ -1,248 +0,0 @@ -/* Copyright (c) 2019 Samsung Electronics Co., Ltd. -.* -.* Licensed under the Apache License, Version 2.0 (the "License"); -.* you may not use this file except in compliance with the License. -.* You may obtain a copy of the License at -.* -.* http://www.apache.org/licenses/LICENSE-2.0 -.* -.* Unless required by applicable law or agreed to in writing, software -.* distributed under the License is distributed on an "AS IS" BASIS, -.* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -.* See the License for the specific language governing permissions and -.* limitations under the License. -.* -.*/ - -using System; -using System.ComponentModel; -using System.Collections.Generic; -using Tizen.NUI.BaseComponents; - -namespace Tizen.NUI -{ - /// - /// [Draft] This class implements a grid layout - /// - internal class GridLayout : LayoutGroup - { - const int AUTO_FIT = -1; - private int _columns = 1; - private int _rows = 1; - private int _totalWidth; - private int _totalHeight; - private int _requestedColumnWidth = 1; - private int _numberOfRequestedColumns; - private GridLocations _locations; - - /// - /// [draft] GridLayout Constructor/> - /// - /// New Grid object. - public GridLayout() - { - _locations = new GridLocations(); - } - - // - // [Draft] Get/Set the number of columns in the grid - // - public int Columns - { - get - { - return GetColumns(); - } - set - { - SetColumns(value); - } - } - - - /// - /// [draft ] Sets the number of columns the GridLayout should have. /> - /// - /// The number of columns. - internal void SetColumns(int columns) - { - _numberOfRequestedColumns = columns; - if( columns != _columns) - { - _columns = Math.Max(1, _columns); - _columns = columns; - RequestLayout(); - } - } - - /// - /// [draft ] Gets the number of columns in the Grid /> - /// - /// The number of columns in the Grid. - internal int GetColumns() - { - return _columns; - } - - void DetermineNumberOfColumns( int availableSpace ) - { - if( _numberOfRequestedColumns == AUTO_FIT ) - { - if( availableSpace > 0 ) - { - // Can only calculate number of columns if a column width has been set - _columns = ( _requestedColumnWidth > 0 ) ? ( availableSpace / _requestedColumnWidth ) : 1; - } - } - } - - protected override void OnMeasure( MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec ) - { - var gridWidthMode = widthMeasureSpec.Mode; - var gridHeightMode = heightMeasureSpec.Mode; - int widthSize = (int)widthMeasureSpec.Size.AsRoundedValue(); - int heightSize = (int)heightMeasureSpec.Size.AsRoundedValue(); - - int availableContentWidth; - int availableContentHeight; - - int desiredChildHeight; - int desiredChildWidth; - - Extents gridLayoutPadding = Padding; - - var childCount = _children.Count; - - // WIDTH SPECIFICATIONS - - // measure first child and use it's dimensions for layout measurement - - if (childCount > 0) - { - LayoutItem childLayoutItem = _children[0]; - View childOwner = childLayoutItem.Owner; - - MeasureChild( childLayoutItem, widthMeasureSpec, heightMeasureSpec ); - desiredChildHeight = (int)childLayoutItem.MeasuredHeight.Size.AsRoundedValue(); - desiredChildWidth = (int)childLayoutItem.MeasuredWidth.Size.AsRoundedValue(); - - // If child has a margin then add it to desired size - Extents childMargin = childLayoutItem.Margin; - desiredChildHeight += childMargin.Top + childMargin.Bottom; - desiredChildWidth += childMargin.Start + childMargin.End; - - _totalWidth = desiredChildWidth * _columns; - - // Include padding for max and min checks - _totalWidth += gridLayoutPadding.Start + gridLayoutPadding.End; - - // Ensure width does not exceed specified at most width or less than mininum width - _totalWidth = Math.Max( _totalWidth, (int)SuggestedMinimumWidth.AsRoundedValue() ); - - // widthMode EXACTLY so grid must be the given width - if( gridWidthMode == MeasureSpecification.ModeType.Exactly || gridWidthMode == MeasureSpecification.ModeType.AtMost ) - { - // In the case of AT_MOST, widthSize is the max limit. - _totalWidth = Math.Min( _totalWidth, widthSize ); - } - - availableContentWidth = _totalWidth - gridLayoutPadding.Start - gridLayoutPadding.End; - widthSize = _totalWidth; - - // HEIGHT SPECIFICATIONS - - // heightMode EXACTLY so grid must be the given height - if( gridHeightMode == MeasureSpecification.ModeType.Exactly || gridHeightMode == MeasureSpecification.ModeType.AtMost ) - { - if( childCount > 0 ) - { - _totalHeight = gridLayoutPadding.Top + gridLayoutPadding.Bottom; - - for( int i = 0; i < childCount; i += _columns ) - { - _totalHeight += desiredChildHeight; - } - - // Ensure ourHeight does not exceed specified at most height - _totalHeight = Math.Min( _totalHeight, heightSize ); - _totalHeight = Math.Max( _totalHeight, (int)SuggestedMinimumHeight.AsRoundedValue() ); - - heightSize = _totalHeight; - } // Child exists - - // In the case of AT_MOST, availableContentHeight is the max limit. - availableContentHeight = heightSize - gridLayoutPadding.Top - gridLayoutPadding.Bottom; - } - else - { - // Grid expands to fit content - - // If number of columns AUTO_FIT then set to 1 column. - _columns = ( _columns > 0 ) ? _columns : 1; - // Calculate numbers of rows, round down result as later check for remainder. - _rows = childCount / _columns; - // If number of cells not cleanly dividable by columns, add another row to house remainder cells. - _rows += ( childCount % _columns > 0 ) ? 1 : 0; - - availableContentHeight = desiredChildHeight * _rows; - } - - // If number of columns not defined - DetermineNumberOfColumns( availableContentWidth ); - - // Locations define the start, end,top and bottom of each cell. - _locations.CalculateLocations(_columns, availableContentWidth, availableContentHeight, childCount); - - } // Children exists - - SetMeasuredDimensions( ResolveSizeAndState( new LayoutLength(widthSize), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK ), - ResolveSizeAndState( new LayoutLength(heightSize), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK ) ); - } - - protected override void OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom ) - { - List locations = _locations.GetLocations(); - - Extents gridLayoutPadding = Padding; - Extents childMargins = new Extents(); - - // Margin for all children dependant on if set on first child - if( _children.Count > 0 ) - { - childMargins = _children[0]?.Margin; - } - - int index = 0; - foreach( LayoutItem childLayout in _children ) - { - // for each child - if( childLayout != null ) - { - // Get start and end position of child x1,x2 - int x1 = locations[ index ].Start; - int x2 = locations[ index ].End; - - // Get top and bottom position of child y1,y2 - int y1 = locations[ index ].Top; - int y2 = locations[ index ].Bottom; - - // Offset children by the grids padding if present - x1 += gridLayoutPadding.Start; - x2 += gridLayoutPadding.Start; - y1 += gridLayoutPadding.Top; - y2 += gridLayoutPadding.Top; - - // Offset children by the margin of the first child ( if required ). - x1 += childMargins.Start; - x2 -= childMargins.End; - y1 += childMargins.Top; - y2 -= childMargins.Bottom; - - childLayout.Layout( new LayoutLength(x1), new LayoutLength(y1), - new LayoutLength(x2), new LayoutLength(y2) ); - index++; - } - } - } - } -} diff --git a/src/Tizen.NUI/src/internal/Layouting/ILayoutParent.cs b/src/Tizen.NUI/src/internal/Layouting/ILayoutParent.cs deleted file mode 100755 index 82fc63078..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/ILayoutParent.cs +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -namespace Tizen.NUI -{ - /// - /// [Draft] - /// Interface that defines a layout Parent. Enables a layout child to access methods on its parent, e.g. Remove (during unparenting) - /// - internal interface ILayoutParent - { - /// - /// Add this child to the parent. - /// - /// The layout child to add. - void Add(LayoutItem layoutItem); - - /// - /// Remove this child from the parent - /// - /// The layout child to add. - void Remove(LayoutItem layoutItem); - } -} diff --git a/src/Tizen.NUI/src/internal/Layouting/Interop/Interop.MeasureSpec.cs b/src/Tizen.NUI/src/internal/Layouting/Interop/Interop.MeasureSpec.cs deleted file mode 100755 index 7c3f6164b..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/Interop/Interop.MeasureSpec.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Tizen.NUI -{ - internal static partial class Interop - { - internal static partial class MeasureSpec - { - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_MeasureSpec__SWIG_0")] - public static extern global::System.IntPtr new_MeasureSpec__SWIG_0(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_MeasureSpec__SWIG_1")] - public static extern global::System.IntPtr new_MeasureSpec__SWIG_1(int jarg1); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_delete_MeasureSpec")] - public static extern void delete_MeasureSpec(global::System.Runtime.InteropServices.HandleRef jarg1); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasureSpec_Assign")] - public static extern global::System.IntPtr MeasureSpec_Assign(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasureSpec_EqualTo")] - public static extern bool MeasureSpec_EqualTo(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasureSpec_NotEqualTo")] - public static extern bool MeasureSpec_NotEqualTo(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasureSpec_GetMode")] - public static extern int MeasureSpec_GetMode(global::System.Runtime.InteropServices.HandleRef jarg1); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasureSpec_GetSize")] - public static extern int MeasureSpec_GetSize(global::System.Runtime.InteropServices.HandleRef jarg1); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasureSpec_Adjust")] - public static extern global::System.IntPtr MeasureSpec_Adjust(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasureSpec_mSize_set")] - public static extern void MeasureSpec_mSize_set(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasureSpec_mSize_get")] - public static extern int MeasureSpec_mSize_get(global::System.Runtime.InteropServices.HandleRef jarg1); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasureSpec_mMode_set")] - public static extern void MeasureSpec_mMode_set(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasureSpec_mMode_get")] - public static extern int MeasureSpec_mMode_get(global::System.Runtime.InteropServices.HandleRef jarg1); - } - } -} \ No newline at end of file diff --git a/src/Tizen.NUI/src/internal/Layouting/Interop/Interop.MeasuredSize.cs b/src/Tizen.NUI/src/internal/Layouting/Interop/Interop.MeasuredSize.cs deleted file mode 100755 index 16ae7ef94..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/Interop/Interop.MeasuredSize.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Tizen.NUI -{ - internal static partial class Interop - { - internal static partial class MeasuredSize - { - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_MeasuredSize__SWIG_0")] - public static extern global::System.IntPtr new_MeasuredSize__SWIG_0(); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_MeasuredSize__SWIG_1")] - public static extern global::System.IntPtr new_MeasuredSize__SWIG_1(global::System.Runtime.InteropServices.HandleRef jarg1); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_new_MeasuredSize__SWIG_2")] - public static extern global::System.IntPtr new_MeasuredSize__SWIG_2(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_delete_MeasuredSize")] - public static extern void delete_MeasuredSize(global::System.Runtime.InteropServices.HandleRef jarg1); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasuredSize_Assign__SWIG_0")] - public static extern global::System.IntPtr MeasuredSize_Assign__SWIG_0(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasuredSize_Assign__SWIG_1")] - public static extern global::System.IntPtr MeasuredSize_Assign__SWIG_1(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasuredSize_EqualTo")] - public static extern bool MeasuredSize_EqualTo(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasuredSize_NotEqualTo")] - public static extern bool MeasuredSize_NotEqualTo(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasuredSize_SetState")] - public static extern void MeasuredSize_SetState(global::System.Runtime.InteropServices.HandleRef jarg1, int jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasuredSize_GetState")] - public static extern int MeasuredSize_GetState(global::System.Runtime.InteropServices.HandleRef jarg1); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasuredSize_SetSize")] - public static extern void MeasuredSize_SetSize(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2); - - [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_MeasuredSize_GetSize")] - public static extern global::System.IntPtr MeasuredSize_GetSize(global::System.Runtime.InteropServices.HandleRef jarg1); - } - } -} \ No newline at end of file diff --git a/src/Tizen.NUI/src/internal/Layouting/LayoutData.cs b/src/Tizen.NUI/src/internal/Layouting/LayoutData.cs index 0ae504703..1f89f74f9 100755 --- a/src/Tizen.NUI/src/internal/Layouting/LayoutData.cs +++ b/src/Tizen.NUI/src/internal/Layouting/LayoutData.cs @@ -15,57 +15,8 @@ * */ -using System.Collections.Generic; -using System; -using System.ComponentModel; - namespace Tizen.NUI { - /// - /// The conditions for transitions. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - [FlagsAttribute] public enum TransitionCondition - { - /// - /// Default when a condition has not been set. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - Unspecified = 0, - /// - /// Animate changing layout to another layout. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - LayoutChanged = 1, - /// - /// Animate adding item. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - Add = 2, - /// - /// Animate removing item. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - Remove = 4, - /// - /// Animation when an item changes due to a sibbling being added. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - ChangeOnAdd = 8, - /// - /// Animation when an item changes due to a sibbling being removed. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - ChangeOnRemove = 16 - } - /// /// [Draft] Class to hold layout animation and position data /// diff --git a/src/Tizen.NUI/src/internal/Layouting/LayoutGroup.cs b/src/Tizen.NUI/src/internal/Layouting/LayoutGroup.cs deleted file mode 100755 index 16f62101b..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/LayoutGroup.cs +++ /dev/null @@ -1,510 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using Tizen.NUI.BaseComponents; -using System.Linq; - -namespace Tizen.NUI -{ - /// - /// [Draft] LayoutGroup class providing container functionality. - /// - internal class LayoutGroup : LayoutItem, ILayoutParent - { - protected List _children{ get;} // Children of this LayoutGroup - - /// - /// [Draft] Constructor - /// - public LayoutGroup() - { - _children = new List(); - } - - /// - /// [Draft] Constructor setting the owner of this LayoutGroup. - /// - /// Owning View of this layout, currently a View but may be extending for Windows/Layers. - public LayoutGroup(View owner) : base(owner) - { - _children = new List(); - } - - /// - /// From ILayoutParent.
- ///
- public virtual void Add(LayoutItem childLayout) - { - _children.Add(childLayout); - childLayout.SetParent(this); - // Child added to use a Add transition. - childLayout.ConditionForAnimation = ConditionForAnimation | TransitionCondition.Add; - // Child's parent sets all other children not being added to a ChangeOnAdd transition. - SetConditionsForAnimationOnLayoutGroup(TransitionCondition.ChangeOnAdd); - OnChildAdd(childLayout); - RequestLayout(); - } - - /// - /// Remove all layout children.
- ///
- public void RemoveAll() - { - foreach( LayoutItem childLayout in _children ) - { - childLayout.ConditionForAnimation = ConditionForAnimation | TransitionCondition.Remove; - childLayout.Owner = null; - } - _children.Clear(); - // todo ensure child LayoutItems are still not parented to this group. - RequestLayout(); - } - - /// - /// From ILayoutParent - /// - public virtual void Remove(LayoutItem layoutItem) - { - bool childRemoved = false; - foreach( LayoutItem childLayout in _children.ToList() ) - { - if( childLayout == layoutItem ) - { - Window.Instance.LayoutController.AddToRemovalStack(childLayout); - _children.Remove(childLayout); - childLayout.ConditionForAnimation = childLayout.ConditionForAnimation | TransitionCondition.Remove; - // Add LayoutItem to the transition stack so can animate it out. - Window.Instance.LayoutController.AddTransitionDataEntry(new LayoutData(layoutItem, ConditionForAnimation, 0,0,0,0)); - // Reset condition for animation ready for next transition when required. - // SetFrame usually would do this but this LayoutItem is being removed. - childLayout.ConditionForAnimation = TransitionCondition.Unspecified; - childRemoved = true; - } - } - if (childRemoved) - { - // If child removed then set all siblings not being added to a ChangeOnRemove transition. - SetConditionsForAnimationOnLayoutGroup(TransitionCondition.ChangeOnRemove); - } - RequestLayout(); - } - - // Attaches to View ChildAdded signal so called when a View is added to a view. - private void AddChildToLayoutGroup(View child) - { - // Only give children a layout if their parent is an explicit container or a pure View. - // Pure View meaning not derived from a View, e.g a Legacy container. - // layoutSet flag is true when the View became a layout using the set Layout API opposed to automatically due to it's parent. - // First time the set Layout API is used by any View the Window no longer has layoutingDisabled. - - // If child already has a Layout then don't change it. - if (! View.layoutingDisabled && (null == child.Layout)) - { - // Only wrap View with a Layout if a child a pure View or Layout explicitly set on this Layout - if ((true == Owner.layoutSet || GetType() == typeof(View))) - { - // If child of this layout is a pure View then assign it a LayoutGroup - // If the child is derived from a View then it may be a legacy or existing container hence will do layouting itself. - if (child.GetType() == typeof(View)) - { - child.Layout = new LayoutGroup(); - } - else - { - // Adding child as a leaf, layouting will not propagate past this child. - // Legacy containers will be a LayoutItems too and layout their children how they wish. - child.Layout = new LayoutItem(); - } - } - } - else - { - // Add child layout to this LayoutGroup (Setting parent in the process) - if(child.Layout != null) - { - Add(child.Layout); - } - } - // Parent transitions are not attached to children. - } - - /// - /// If the child has a layout then it is removed from the parent layout. - /// - /// Child View to remove. - internal void RemoveChildFromLayoutGroup(View child) - { - Debug.Assert(child.Layout !=null); - Remove(child.Layout); - } - - /// - /// Set all children in a LayoutGroup to the supplied condition. - /// Children with Add or Remove conditions should not be changed. - /// - private void SetConditionsForAnimationOnLayoutGroup( TransitionCondition conditionToSet) - { - foreach( LayoutItem childLayout in _children ) - { - switch( conditionToSet ) - { - case TransitionCondition.ChangeOnAdd : - { - // If other children also being added (TransitionCondition.Add) then do not change their - // conditions, Continue to use their Add transitions. - if (childLayout.ConditionForAnimation.HasFlag(TransitionCondition.Add)) - { - break; // Child being Added so don't update it's condition - } - else - { - // Set siblings for the child being added to use the ChangeOnAdd transition. - childLayout.ConditionForAnimation = TransitionCondition.ChangeOnAdd; - } - break; - } - case TransitionCondition.ChangeOnRemove : - { - if (childLayout.ConditionForAnimation.HasFlag(TransitionCondition.Remove)) - { - break; // Child being Removed so don't update it's condition - } - else - { - childLayout.ConditionForAnimation = TransitionCondition.ChangeOnRemove; - } - break; - } - case TransitionCondition.LayoutChanged : - { - childLayout.ConditionForAnimation = TransitionCondition.LayoutChanged; - break; - } - } - } - - } - - /// - /// Callback for View.ChildAdded event - /// - /// The object triggering the event. - /// Arguments from the event. - void OnChildAddedToOwner(object sender, View.ChildAddedEventArgs childAddedEvent) - { - AddChildToLayoutGroup(childAddedEvent.Added); - } - - /// - /// Callback for View.ChildRemoved event - /// - /// The object triggering the event. - /// Arguments from the event. - void OnChildRemovedFromOwner(object sender, View.ChildRemovedEventArgs childRemovedEvent) - { - RemoveChildFromLayoutGroup(childRemovedEvent.Removed); - } - - /// - /// Calculate the right measure spec for this child. - /// Does the hard part of MeasureChildren: figuring out the MeasureSpec to - /// pass to a particular child. This method figures out the right MeasureSpec - /// for one dimension (height or width) of one child view.
- ///
- /// The requirements for this view. MeasureSpecification. - /// The padding of this view for the current dimension and margins, if applicable. LayoutLength. - /// How big the child wants to be in the current dimension. LayoutLength. - /// a MeasureSpec for the child. - public static MeasureSpecification GetChildMeasureSpecification(MeasureSpecification parentMeasureSpec, LayoutLength padding, LayoutLength childDimension) - { - MeasureSpecification.ModeType specMode = parentMeasureSpec.Mode; - MeasureSpecification.ModeType resultMode = MeasureSpecification.ModeType.Unspecified; - LayoutLength resultSize = new LayoutLength(Math.Max( 0.0f, (parentMeasureSpec.Size.AsDecimal() - padding.AsDecimal() ) )); // reduce available size by the owners padding - - switch( specMode ) - { - // Parent has imposed an exact size on us - case MeasureSpecification.ModeType.Exactly: - { - if ((int)childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent) - { - // Child wants to be our size. So be it. - resultMode = MeasureSpecification.ModeType.Exactly; - } - else if ((int)childDimension.AsRoundedValue() == LayoutParamPolicies.WrapContent) - { - // Child wants to determine its own size. It can't be - // bigger than us. - resultMode = MeasureSpecification.ModeType.AtMost; - } - else - { - resultSize = childDimension; - resultMode = MeasureSpecification.ModeType.Exactly; - } - - break; - } - - // Parent has imposed a maximum size on us - case MeasureSpecification.ModeType.AtMost: - { - if (childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent) - { - // Child wants to be our size, but our size is not fixed. - // Constrain child to not be bigger than us. - resultMode = MeasureSpecification.ModeType.AtMost; - } - else if (childDimension.AsRoundedValue() == LayoutParamPolicies.WrapContent) - { - // Child wants to determine its own size. It can't be - // bigger than us. - resultMode = MeasureSpecification.ModeType.AtMost; - } - else - { - // Child wants a specific size... so be it - resultSize = childDimension + padding; - resultMode = MeasureSpecification.ModeType.Exactly; - } - - break; - } - - // Parent asked to see how big we want to be - case MeasureSpecification.ModeType.Unspecified: - { - - if ((childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent)) - { - // Child wants to be our size... find out how big it should be - resultMode = MeasureSpecification.ModeType.Unspecified; - } - else if (childDimension.AsRoundedValue() == (LayoutParamPolicies.WrapContent)) - { - // Child wants to determine its own size.... find out how big - // it should be - resultMode = MeasureSpecification.ModeType.Unspecified; - } - else - { - // Child wants a specific size... let him have it - resultSize = childDimension + padding; - resultMode = MeasureSpecification.ModeType.Exactly; - } - break; - } - } // switch - - return new MeasureSpecification( resultSize, resultMode ); - } - - /// - /// Measure the layout and its content to determine the measured width and the measured height.
- /// If this method is overridden, it is the subclass's responsibility to make - /// sure the measured height and width are at least the layout's minimum height - /// and width.
- ///
- /// horizontal space requirements as imposed by the parent. - /// vertical space requirements as imposed by the parent. - protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) - { - LayoutLength measuredWidth = new LayoutLength(0.0f); - LayoutLength measuredHeight = new LayoutLength(0.0f); - - // Layout takes size of largest child width and largest child height dimensions - foreach( LayoutItem childLayout in _children ) - { - if( childLayout != null ) - { - MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec ); - LayoutLength childWidth = new LayoutLength(childLayout.MeasuredWidth.Size); - LayoutLength childHeight = new LayoutLength( childLayout.MeasuredHeight.Size); - - Extents childMargin = childLayout.Margin; - measuredWidth = new LayoutLength(Math.Max( measuredWidth.AsDecimal(), childWidth.AsDecimal() + childMargin.Start + childMargin.End)); - measuredHeight = new LayoutLength(Math.Max( measuredHeight.AsDecimal(), childHeight.AsDecimal() + childMargin.Top + childMargin.Bottom)); - } - } - - if( 0 == _children.Count ) - { - // Must be a leaf as has no children - measuredWidth = GetDefaultSize( SuggestedMinimumWidth, widthMeasureSpec ); - measuredHeight = GetDefaultSize( SuggestedMinimumHeight, heightMeasureSpec ); - } - - SetMeasuredDimensions( new MeasuredSize( measuredWidth, MeasuredSize.StateType.MeasuredSizeOK ), - new MeasuredSize( measuredHeight, MeasuredSize.StateType.MeasuredSizeOK ) ); - } - - /// - /// Called from Layout() when this layout should assign a size and position to each of its children.
- /// Derived classes with children should override this method and call Layout() on each of their children.
- ///
- /// This is a new size or position for this layout. - /// Left position, relative to parent. - /// Top position, relative to parent. - /// Right position, relative to parent. - /// Bottom position, relative to parent. - protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) - { - foreach( LayoutItem childLayout in _children ) - { - if( childLayout !=null ) - { - // Use position if explicitly set to child otherwise will be top left. - var childLeft = new LayoutLength( childLayout.Owner.Position2D.X ); - var childTop = new LayoutLength( childLayout.Owner.Position2D.Y ); - - View owner = Owner; - - if ( owner ) - { - // Margin and Padding only supported when child anchor point is TOP_LEFT. - if ( owner.PivotPoint == PivotPoint.TopLeft || ( owner.PositionUsesPivotPoint == false ) ) - { - childLeft = childLeft + owner.Padding.Start + childLayout.Margin.Start; - childTop = childTop + owner.Padding.Top + childLayout.Margin.Top; - } - } - childLayout.Layout( childLeft, childTop, childLeft + childLayout.MeasuredWidth.Size, childTop + childLayout.MeasuredHeight.Size ); - } - } - } - - /// - /// Overridden method called when the layout size changes.
- ///
- /// The new size of the layout. - /// The old size of the layout. - protected override void OnSizeChanged(LayoutSize newSize, LayoutSize oldSize) - { - // Do nothing - } - - /// - /// Overridden method called when the layout is attached to an owner.
- ///
- protected override void OnAttachedToOwner() - { - // Layout takes ownership of it's owner's children. - foreach (View view in Owner.Children) - { - AddChildToLayoutGroup(view); - } - - // Connect to owner ChildAdded signal. - Owner.ChildAdded += OnChildAddedToOwner; - - // Removing Child from the owners View will directly call the LayoutGroup removal API. - } - - // Virtual Methods that can be overridden by derived classes. - - /// - /// Callback when child is added to container.
- /// Derived classes can use this to set their own child properties on the child layout's owner.
- ///
- /// The Layout child. - protected virtual void OnChildAdd(LayoutItem child) - { - } - - /// - /// Callback when child is removed from container.
- ///
- /// The Layout child. - protected virtual void OnChildRemove(LayoutItem child) - { - } - - /// - /// Ask all of the children of this view to measure themselves, taking into - /// account both the MeasureSpec requirements for this view and its padding.
- /// The heavy lifting is done in GetChildMeasureSpec.
- ///
- /// The width requirements for this view. - /// The height requirements for this view. - protected virtual void MeasureChildren(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) - { - foreach( LayoutItem childLayout in _children ) - { - MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec ); - } - } - - /// - /// Ask one of the children of this view to measure itself, taking into - /// account both the MeasureSpec requirements for this view and its padding.
- /// The heavy lifting is done in GetChildMeasureSpec.
- ///
- /// The child to measure. - /// The width requirements for this view. - /// The height requirements for this view. - protected virtual void MeasureChild(LayoutItem child, MeasureSpecification parentWidthMeasureSpec, MeasureSpecification parentHeightMeasureSpec) - { - View childOwner = child.Owner; - - Extents padding = child.Padding; // Padding of this layout's owner, not of the child being measured. - - MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification( parentWidthMeasureSpec, - new LayoutLength(padding.Start + padding.End ), - new LayoutLength(childOwner.WidthSpecification) ); - - MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification( parentHeightMeasureSpec, - new LayoutLength(padding.Top + padding.Bottom), - new LayoutLength(childOwner.HeightSpecification) ); - - child.Measure( childWidthMeasureSpec, childHeightMeasureSpec ); - } - - /// - /// Ask one of the children of this view to measure itself, taking into - /// account both the MeasureSpec requirements for this view and its padding.
- /// and margins. The child must have MarginLayoutParams The heavy lifting is - /// done in GetChildMeasureSpecification.
- ///
- /// The child to measure. - /// The width requirements for this view. - /// Extra space that has been used up by the parent horizontally (possibly by other children of the parent). - /// The height requirements for this view. - /// Extra space that has been used up by the parent vertically (possibly by other children of the parent). - protected virtual void MeasureChildWithMargins(LayoutItem child, MeasureSpecification parentWidthMeasureSpec, LayoutLength widthUsed, MeasureSpecification parentHeightMeasureSpec, LayoutLength heightUsed) - { - View childOwner = child.Owner; - int desiredWidth = childOwner.WidthSpecification; - int desiredHeight = childOwner.HeightSpecification; - - Extents padding = child.Padding; // Padding of this layout's owner, not of the child being measured. - - MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification( parentWidthMeasureSpec, - new LayoutLength( padding.Start + padding.End ) + - widthUsed, new LayoutLength(desiredWidth) ); - - - MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification( parentHeightMeasureSpec, - new LayoutLength( padding.Top + padding.Bottom )+ - heightUsed, new LayoutLength(desiredHeight) ); - - child.Measure( childWidthMeasureSpec, childHeightMeasureSpec ); - } - } -} \ No newline at end of file diff --git a/src/Tizen.NUI/src/internal/Layouting/LayoutItem.cs b/src/Tizen.NUI/src/internal/Layouting/LayoutItem.cs deleted file mode 100755 index c45dc445d..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/LayoutItem.cs +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -using System; -using System.Diagnostics; -using Tizen.NUI.BaseComponents; - -namespace Tizen.NUI -{ - - [FlagsAttribute] - enum LayoutFlags : short - { - None = 0, - ForceLayout = 1, - LayoutRequired = 2, - MeasuredDimensionSet = 4 - }; - - /// - /// [Draft] Base class for layouts. It is used to layout a View - /// It can be laid out by a LayoutGroup. - /// - internal class LayoutItem - { - static bool LayoutDebugFrameData = false; // Debug flag - private MeasureSpecification OldWidthMeasureSpec; // Store measure specification to compare against later - private MeasureSpecification OldHeightMeasureSpec;// Store measure specification to compare against later - - private LayoutFlags Flags = LayoutFlags.None; - - private ILayoutParent Parent; - - LayoutData _layoutPositionData; - - private Extents _padding; - private Extents _margin; - - public TransitionCondition ConditionForAnimation{get; set;} - - /// - /// [Draft] The View that this Layout has been assigned to. - /// - public View Owner{get; set;} // Should not keep a View alive. - - /// - /// [Draft] Is this Layout set to animate its content. - /// - public bool Animate{get; set;} - - /// - /// [Draft] Margin for this LayoutItem - /// - public Extents Margin - { - get - { - return _margin; - } - set - { - _margin = value; - RequestLayout(); - } - } - - /// - /// [Draft] Padding for this LayoutItem - /// - public Extents Padding - { - get - { - return _padding; - } - set - { - _padding = value; - RequestLayout(); - } - } - - /// - /// [Draft] Constructor - /// - public LayoutItem() - { - Initialize(); - } - - /// - /// [Draft] Constructor setting the owner of this LayoutItem. - /// - /// Owning View of this layout, currently a View but may be extending for Windows/Layers. - public LayoutItem(View owner) - { - Owner = owner; - Initialize(); - } - - /// - /// [Draft] Set parent to this layout. - /// - /// Parent to set on this Layout. - public void SetParent( ILayoutParent parent) - { - Parent = parent as LayoutGroup; - } - - /// - /// Unparent this layout from it's owner, and remove any layout children in derived types.
- ///
- public void Unparent() - { - // Enable directly derived types to first remove children - OnUnparent(); - - // Remove myself from parent - Parent?.Remove( this ); - - // Remove parent reference - Parent = null; - - // Lastly, clear layout from owning View. - Owner?.ResetLayout(); - } - - private void Initialize() - { - _layoutPositionData = new LayoutData(this,TransitionCondition.Unspecified,0,0,0,0); - _padding = new Extents(0,0,0,0); - _margin = new Extents(0,0,0,0); - } - - /// - /// Get the View owning this LayoutItem - /// - internal View GetOwner() - { - return Owner; - } - - /// - /// Initialize the layout and allow derived classes to also perform any operations - /// - /// Owner of this Layout. - internal void AttachToOwner(View owner) - { - // Assign the layout owner. - Owner = owner; - OnAttachedToOwner(); - // Add layout to parent layout if a layout container - View parent = Owner.GetParent() as View; - (parent?.Layout as LayoutGroup)?.Add( this ); - - // If Add or ChangeOnAdd then do not update condition - if (ConditionForAnimation.Equals(TransitionCondition.Unspecified)) - { - ConditionForAnimation = TransitionCondition.LayoutChanged; - } - } - - /// - /// This is called to find out how big a layout should be.
- /// The parent supplies constraint information in the width and height parameters.
- /// The actual measurement work of a layout is performed in OnMeasure called by this - /// method. Therefore, only OnMeasure can and must be overridden by subclasses.
- ///
- /// Horizontal space requirements as imposed by the parent. - /// Vertical space requirements as imposed by the parent. - internal void Measure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) - { - // Check if relayouting is required. - bool specChanged = (widthMeasureSpec.Size != OldWidthMeasureSpec.Size) || - (heightMeasureSpec.Size != OldHeightMeasureSpec.Size) || - (widthMeasureSpec.Mode != OldWidthMeasureSpec.Mode) || - (heightMeasureSpec.Mode != OldHeightMeasureSpec.Mode); - - bool isSpecExactly = (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly) && - (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly); - - bool matchesSpecSize = (MeasuredWidth.Size == widthMeasureSpec.Size) && - (MeasuredHeight.Size == heightMeasureSpec.Size); - - bool needsLayout = specChanged && ( !isSpecExactly || !matchesSpecSize); - needsLayout = needsLayout || ((Flags & LayoutFlags.ForceLayout) == LayoutFlags.ForceLayout); - - if (needsLayout) - { - OnMeasure(widthMeasureSpec, heightMeasureSpec); - Flags = Flags | LayoutFlags.LayoutRequired; - Flags &= ~LayoutFlags.ForceLayout; - } - OldWidthMeasureSpec = widthMeasureSpec; - OldHeightMeasureSpec = heightMeasureSpec; - } - - /// - /// Assign a size and position to a layout and all of its descendants.
- /// This is the second phase of the layout mechanism. (The first is measuring). In this phase, each parent - /// calls layout on all of its children to position them. This is typically done using the child
- /// measurements that were stored in the measure pass.
- ///
- /// Left position, relative to parent. - /// Top position, relative to parent. - /// Right position, relative to parent. - /// Bottom position, relative to parent. - public void Layout(LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) - { - bool changed = SetFrame(left.AsRoundedValue(), - top.AsRoundedValue(), - right.AsRoundedValue(), - bottom.AsRoundedValue()); - - // Check if Measure needed before Layouting - if (changed || ((Flags & LayoutFlags.LayoutRequired) == LayoutFlags.LayoutRequired)) - { - OnLayout(changed, left, top, right, bottom); - // Clear flag - Flags &= ~LayoutFlags.LayoutRequired; - } - } - - /// - /// Utility to return a default size.
- /// Uses the supplied size if the MeasureSpecification imposed no constraints. Will get larger if allowed by the - /// MeasureSpecification.
- ///
- /// Default size for this layout. - /// Constraints imposed by the parent. - /// The size this layout should be. - public static LayoutLength GetDefaultSize(LayoutLength size, MeasureSpecification measureSpecification) - { - LayoutLength result = size; - MeasureSpecification.ModeType specMode = measureSpecification.Mode; - LayoutLength specSize = measureSpecification.Size; - - switch (specMode) - { - case MeasureSpecification.ModeType.Unspecified: - { - result = size; - break; - } - case MeasureSpecification.ModeType.AtMost: - { - // Ensure the default size does not exceed the spec size unless the default size is 0. - // Another container could provide a default size of 0. - - // Do not set size to 0, use specSize in this case as could be a legacy container - if( ( size.AsDecimal() < specSize.AsDecimal()) && ( size.AsDecimal() > 0) ) - { - result = size; - } - else - { - result = specSize; - } - break; - } - case MeasureSpecification.ModeType.Exactly: - { - result = specSize; - break; - } - } - - return result; - } - - public ILayoutParent GetParent() - { - return Parent; - } - - /// - /// Request that this layout is re-laid out.
- /// This will make this layout and all it's parent layouts dirty.
- ///
- public void RequestLayout() - { - Flags = Flags | LayoutFlags.ForceLayout; - Window.Instance.LayoutController.RequestLayout(this); - } - - /// - /// Predicate to determine if this layout has been requested to re-layout.
- ///
- public bool LayoutRequested - { - get - { - return ( Flags & LayoutFlags.ForceLayout) == LayoutFlags.ForceLayout; - } - } - - /// - /// Get the measured width (without any measurement flags).
- /// This method should be used only during measurement and layout calculations.
- ///
- public MeasuredSize MeasuredWidth{ get; set; } = new MeasuredSize( new LayoutLength(-3), MeasuredSize.StateType.MeasuredSizeOK); - - /// - /// Get the measured height (without any measurement flags).
- /// This method should be used only during measurement and layout calculations.
- ///
- public MeasuredSize MeasuredHeight{ get; set; } = new MeasuredSize( new LayoutLength(-3), MeasuredSize.StateType.MeasuredSizeOK); - - /// - /// Get the measured width and state.
- /// This method should be used only during measurement and layout calculations.
- ///
- public MeasuredSize MeasuredWidthAndState - { - get - { - return MeasuredWidth; // Not bitmasking State unless proven to be required. - } - } - - - /// - /// Get the measured height and state.
- /// This method should be used only during measurement and layout calculations.
- ///
- public MeasuredSize MeasuredHeightAndState - { - get - { - return MeasuredHeight; // Not bitmasking State unless proven to be required. - } - } - - /// - /// Returns the suggested minimum width that the layout should use.
- /// This returns the maximum of the layout's minimum width and the owner's natural width.
- ///
- public LayoutLength SuggestedMinimumWidth - { - get - { - int naturalWidth = Owner.NaturalSize2D.Width; - return new LayoutLength(Math.Max( MinimumWidth.AsDecimal(), naturalWidth )); - } - } - - /// - /// Returns the suggested minimum height that the layout should use.
- /// This returns the maximum of the layout's minimum height and the owner's natural height.
- ///
- public LayoutLength SuggestedMinimumHeight - { - get - { - int naturalHeight = Owner.NaturalSize2D.Height; - return new LayoutLength(Math.Max( MinimumHeight.AsDecimal(), naturalHeight )); - } - } - - /// - /// Sets the minimum width of the layout.
- /// It is not guaranteed the layout will be able to achieve this minimum width (for example, if its parent - /// layout constrains it with less available width).
- /// 1. if the owner's View.WidthSpecification has exact value, then that value overrides the minimum size.
- /// 2. If the owner's View.WidthSpecification is set to View.LayoutParamPolicies.WrapContent, then the view's width is set based on the suggested minimum width. (@see GetSuggestedMinimumWidth()).
- /// 3. If the owner's View.WidthSpecification is set to View.LayoutParamPolicies.MatchParent, then the parent width takes precedence over the minimum width.
- ///
- public LayoutLength MinimumWidth {get; set;} - - /// - /// Sets the minimum height of the layout.
- /// It is not guaranteed the layout will be able to achieve this minimum height (for example, if its parent - /// layout constrains it with less available height).
- /// 1. if the owner's View.HeightSpecification has exact value, then that value overrides the minimum size.
- /// 2. If the owner's View.HeightSpecification is set to View.LayoutParamPolicies.WrapContent, then the view's height is set based on the suggested minimum height. (@see GetSuggestedMinimumHeight()).
- /// 3. If the owner's View.HeightSpecification is set to View.LayoutParamPolicies.MatchParent, then the parent height takes precedence over the minimum height.
- ///
- public LayoutLength MinimumHeight {get; set;} - - /// - /// Utility to reconcile a desired size and state, with constraints imposed by a MeasureSpecification. - /// - /// How big the layout wants to be. - /// Constraints imposed by the parent. - /// Size information bit mask for the layout's children. - /// A measured size, which may indicate that it is too small. - protected MeasuredSize ResolveSizeAndState( LayoutLength size, MeasureSpecification measureSpecification, MeasuredSize.StateType childMeasuredState ) - { - var specMode = measureSpecification.Mode; - LayoutLength specSize = measureSpecification.Size; - MeasuredSize result = new MeasuredSize( size, childMeasuredState); - - switch( specMode ) - { - case MeasureSpecification.ModeType.AtMost: - { - if (specSize.AsRoundedValue() < size.AsRoundedValue()) - { - result = new MeasuredSize( specSize, MeasuredSize.StateType.MeasuredSizeTooSmall); - } - break; - } - - case MeasureSpecification.ModeType.Exactly: - { - result.Size = specSize; - break; - } - - case MeasureSpecification.ModeType.Unspecified: - default: - { - break; - } - } - return result; - } - - /// - /// This method must be called by OnMeasure(MeasureSpec,MeasureSpec) to store the measured width and measured height. - /// - /// The measured width of this layout. - /// The measured height of this layout. - protected void SetMeasuredDimensions( MeasuredSize measuredWidth, MeasuredSize measuredHeight ) - { - MeasuredWidth = measuredWidth; - MeasuredHeight = measuredHeight; - Flags = Flags | LayoutFlags.MeasuredDimensionSet; - } - - /// - /// Measure the layout and its content to determine the measured width and the - /// measured height.
- /// The base class implementation of measure defaults to the background size, - /// unless a larger size is allowed by the MeasureSpec. Subclasses should - /// override to provide better measurements of their content.
- /// If this method is overridden, it is the subclass's responsibility to make sure the - /// measured height and width are at least the layout's minimum height and width.
- ///
- /// horizontal space requirements as imposed by the parent. - /// vertical space requirements as imposed by the parent. - protected virtual void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) - { - // GetDefaultSize will limit the MeasureSpec to the suggested minimumWidth and minimumHeight - SetMeasuredDimensions( GetDefaultSize( SuggestedMinimumWidth, widthMeasureSpec ), - GetDefaultSize( SuggestedMinimumHeight, heightMeasureSpec ) ); - } - - /// - /// Called from Layout() when this layout should assign a size and position to each of its children.
- /// Derived classes with children should override this method and call Layout() on each of their children.
- ///
- /// This is a new size or position for this layout. - /// Left position, relative to parent. - /// Top position, relative to parent. - /// Right position, relative to parent. - /// Bottom position, relative to parent. - protected virtual void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) - { - } - - /// - /// Virtual method to inform derived classes when the layout size changed.
- ///
- /// The new size of the layout. - /// The old size of the layout. - protected virtual void OnSizeChanged(LayoutSize newSize, LayoutSize oldSize) - { - } - - /// - /// Virtual method to allow derived classes to remove any children before it is removed from - /// its parent. - /// - public virtual void OnUnparent() - { - } - - /// - /// Virtual method called when this Layout is attached to it's owner. - /// Allows derived layouts to take ownership of child Views and connect to any Owner signals required. - /// - protected virtual void OnAttachedToOwner() - { - } - - private bool SetFrame(float left, float top, float right, float bottom) - { - bool changed = false; - - if ( _layoutPositionData.Left != left || - _layoutPositionData.Right != right || - _layoutPositionData.Top != top || - _layoutPositionData.Bottom != bottom ) - { - changed = true; - - float oldWidth = _layoutPositionData.Right - _layoutPositionData.Left; - float oldHeight = _layoutPositionData.Bottom - _layoutPositionData.Top; - float newWidth = right - left; - float newHeight = bottom - top; - bool sizeChanged = ( newWidth != oldWidth ) || ( newHeight != oldHeight ); - - // Set condition to layout changed as currently unspecified. Add, Remove would have specified a condition. - if (ConditionForAnimation.Equals(TransitionCondition.Unspecified)) - { - ConditionForAnimation = TransitionCondition.LayoutChanged; - } - - // Store new layout position data - _layoutPositionData = new LayoutData(this, ConditionForAnimation, left, top, right, bottom); - - Debug.WriteLineIf( LayoutDebugFrameData, "LayoutItem FramePositionData View:" + _layoutPositionData.Item.Owner.Name + - " left:" + _layoutPositionData.Left + - " top:" + _layoutPositionData.Top + - " right:" + _layoutPositionData.Right + - " bottom:" + _layoutPositionData.Bottom ); - - Window.Instance.LayoutController.AddTransitionDataEntry(_layoutPositionData); - - // Reset condition for animation ready for next transition when required. - ConditionForAnimation = TransitionCondition.Unspecified; - } - - return changed; - } - } -} diff --git a/src/Tizen.NUI/src/internal/Layouting/LayoutLength.cs b/src/Tizen.NUI/src/internal/Layouting/LayoutLength.cs deleted file mode 100755 index 7ff7c3aa1..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/LayoutLength.cs +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -using System; -using System.ComponentModel; -using Tizen.NUI.BaseComponents; - -namespace Tizen.NUI -{ - /// - /// [Draft] A type that represents a layout length. Currently, this implies pixels, but could be extended to handle device dependant sizes, etc. - /// - internal struct LayoutLength - { - private float _value; - - /// - /// [Draft] Constructor from an int - /// - /// Int to initialize with. - public LayoutLength(int value) - { - _value = value; - } - - /// - /// [Draft] Constructor from a float - /// - /// Float to initialize with. - public LayoutLength(float value) - { - _value = value; - } - - /// - /// [Draft] Constructor from a LayoutLength - /// - /// LayoutLength object to initialize with. - public LayoutLength(LayoutLength layoutLength) - { - _value = layoutLength._value; - } - - /// - /// [Draft] Return value as rounded value (whole number), best used as final output - /// - /// The layout length value as a rounded whole number. - public float AsRoundedValue() - { - return (float)Math.Round((decimal)_value, MidpointRounding.AwayFromZero); - } - - /// - /// [Draft] Return value as the raw decimal value, best used for calculations - /// - /// The layout length value as the raw decimal value. - public float AsDecimal() - { - return _value; - } - - /// - /// [Draft] The == operator. - /// - /// The first value. - /// The second value - /// true if LayoutLengths are equal - public static bool operator ==(LayoutLength arg1, LayoutLength arg2) - { - return arg1.Equals(arg2); - } - - /// - /// [Draft] The != operator. - /// - /// The first value. - /// The second value - /// true if LayoutLengths are not equal - public static bool operator !=(LayoutLength arg1, LayoutLength arg2) - { - return !arg1.Equals(arg2); - } - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The object to compare with the current object. - /// true if equal LayoutLength, else false. - public override bool Equals(object obj) - { - if (obj is LayoutLength) - { - return this.Equals((LayoutLength)obj); - } - return false; - } - - /// - /// Determines whether the specified object is equal to the current object. - /// - /// The LayoutLength to compare with the current LayoutLength. - /// true if equal LayoutLengths, else false. - public bool Equals(LayoutLength layoutLength) - { - return (Math.Abs(_value - layoutLength._value ) <= float.Epsilon); - } - - /// - /// A hash code for the current object. - /// - public override int GetHashCode() - { - return (int)Math.Ceiling(_value); - } - - /// - /// The addition operator. - /// - /// The first value. - /// The second value. - /// The LayoutLength containing the result of the addition. - public static LayoutLength operator +(LayoutLength arg1, LayoutLength arg2) - { - return new LayoutLength( arg1._value + arg2._value ); - } - - /// - /// The addition operator. - /// - /// The first value. - /// The second value. - /// The LayoutLength containing the result of the addition. - public static LayoutLength operator +(LayoutLength arg1, int arg2) - { - return new LayoutLength(arg1._value + (float)arg2); - } - - /// - /// The subtraction operator. - /// - /// The first value. - /// The second value. - /// The LayoutLength containing the result of the subtraction. - public static LayoutLength operator -(LayoutLength arg1, LayoutLength arg2) - { - return new LayoutLength(arg1._value - arg2._value); - } - - /// - /// The subtraction operator. - /// - /// The first value. - /// The second value. - /// The LayoutLength containing the result of the subtraction. - public static LayoutLength operator -(LayoutLength arg1, int arg2) - { - return new LayoutLength(arg1._value - (float)arg2); - } - - /// - /// The multiplication operator. - /// - /// The first value. - /// The second value. - /// The LayoutLength containing the result of the multiplication. - public static LayoutLength operator *(LayoutLength arg1, LayoutLength arg2) - { - return new LayoutLength(arg1._value * arg2._value); - } - - /// - /// Th multiplication operator. - /// - /// The first value. - /// The int value to scale the LayoutLength. - /// The LayoutLength containing the result of the scaling. - public static LayoutLength operator *(LayoutLength arg1, int arg2) - { - return new LayoutLength(arg1._value * arg2); - } - - /// - /// The division operator. - /// - /// The first value. - /// The second value. - /// The LayoutLength containing the result of the division. - public static LayoutLength operator /(LayoutLength arg1, LayoutLength arg2) - { - return new LayoutLength(arg1._value / arg2._value); - } - - /// - /// Th division operator. - /// - /// The first value. - /// The int value to scale the vector by. - /// The LayoutLength containing the result of the scaling. - public static LayoutLength operator /(LayoutLength arg1, int arg2) - { - return new LayoutLength(arg1._value / (float)arg2); - } - } -} diff --git a/src/Tizen.NUI/src/internal/Layouting/LayoutSize.cs b/src/Tizen.NUI/src/internal/Layouting/LayoutSize.cs deleted file mode 100755 index 4e1f7b543..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/LayoutSize.cs +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -using System.ComponentModel; -using Tizen.NUI.BaseComponents; - -namespace Tizen.NUI -{ - /// - /// [Draft] This class represents a layout size (width and height), non mutable. - /// - internal struct LayoutSize - { - /// - /// [Draft] Constructor from width and height - /// - /// Int to initialize with. - /// Int to initialize with. - public LayoutSize(int width, int height) - { - Width = width; - Height = height; - } - - /// - /// Computes a hash code for this LayoutSize for use in hash based collections. - /// - /// A non unique hash code . - public override int GetHashCode() - { - return Width ^ Height; - } - - /// - /// Whether the values of two LayoutSize objects are equals - /// - /// Object to be compared against. - /// true if obj is equal to this LayoutSize. - public override bool Equals(object obj) - { - if (obj is LayoutSize) - { - LayoutSize layoutSize = (LayoutSize)obj; - return ((layoutSize.Width == Width) && (layoutSize.Height == Height)); - } - return false; - } - - /// - /// Compares whether the two LayoutSize instances are equal. - /// - /// A LayoutSize instance. - /// A LayoutSize instance. - /// true if the two LayoutSize instances have equal values. - public static bool operator ==(LayoutSize lhs, LayoutSize rhs) - { - return ((lhs.Width == rhs.Width) && (lhs.Height == rhs.Height)); - } - - - /// - /// Compares whether the two LayoutSize instances are same or not. - /// - /// A LayoutSize instance. - /// A LayoutSize instance. - /// true if the two LayoutSize instances have do not have equal values. - public static bool operator !=(LayoutSize lhs, LayoutSize rhs) - { - return ((lhs.Width != rhs.Width) || (lhs.Height != rhs.Height)); - } - - /// - /// [Draft] Get the width value of this layout - /// - public int Width{ get; private set; } - - /// - /// [Draft] Get the height value of this layout - /// - public int Height{ get; private set; } - - } -} diff --git a/src/Tizen.NUI/src/internal/Layouting/LayoutTransition.cs b/src/Tizen.NUI/src/internal/Layouting/LayoutTransition.cs deleted file mode 100755 index 98cf30ff4..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/LayoutTransition.cs +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -using System.Collections.Generic; -using System; -using System.ComponentModel; - -namespace Tizen.NUI -{ - /// - /// Define a List of LayoutTransitions - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public class TransitionList : List {} - - /// - /// The properties that can be animated. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public enum AnimatableProperties - { - /// - /// Position property. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - Position, - /// - /// Size property. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - Size, - /// - /// Opacity property. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - Opacity - } - - /// - /// Parts of the transition that can be configured to provide a custom effect. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public class TransitionComponents - { - /// - /// TransitionComponents default constructor. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public TransitionComponents() - { - Delay = 0; - Duration = 100; - AlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.Linear); - } - - /// - /// TransitionComponents constructor. Stores delay, duration and AlphaFunction. - /// - /// The delay before the animator starts. - /// the duration fo the animator. - /// alpha function to use . - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public TransitionComponents(int delay, int duration, AlphaFunction alphaFunction) - { - Delay = delay; - Duration = duration; - AlphaFunction = alphaFunction; - } - - /// - /// Time the transition should execute. Milliseconds. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public int Duration; - /// - /// Delay before the transition executes. Milliseconds. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public int Delay; - /// - /// Function to alter the transition path over time. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public AlphaFunction AlphaFunction; - } - - /// - /// LayoutTransition stores the aninmation setting for a transition conidition. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public class LayoutTransition - { - /// - /// LayoutTransition default constructor. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public LayoutTransition() - { - Condition = TransitionCondition.Unspecified; - AnimatableProperty = AnimatableProperties.Position; - Animator = null; - TargetValue = 0; - } - /// - /// LayoutTransition constructor. - /// - /// The animatable condition. - /// the property to animate. - /// target value of the property. - /// Components to define the animator. - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public LayoutTransition( TransitionCondition condition, - AnimatableProperties animatableProperty, - object targetValue, - TransitionComponents animator) - { - Condition = condition; - AnimatableProperty = animatableProperty; - Animator = animator; - TargetValue = targetValue; - } - - /// - /// Condition for this Transition - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public TransitionCondition Condition{get; set;} - /// - /// Property to animate. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public AnimatableProperties AnimatableProperty{get; set;} - /// - /// Components of the Animator. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public TransitionComponents Animator{get; set;} - /// - /// Target value to animate to. - /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] - public object TargetValue{get; set;} - } - - - /// - /// Class to help manage the adding and updating of transitions. - /// - internal static class LayoutTransitionsHelper - { - /// - /// Adds the given transition and condition to a transition list. - /// - /// The list to add the transition to. - /// Condition for the transition. - /// The transition to add. - /// True is set explicitly, false if inherited. - static public void AddTransitionForCondition( - Dictionary targetTransitionList, - TransitionCondition condition, - LayoutTransition transition, - bool explicitlySet) - { - bool replaced = false; - bool conditionNotInDictionary = false; - TransitionList transitionListMatchingCondition; - if (targetTransitionList.TryGetValue(condition, out transitionListMatchingCondition)) - { - for (var index=0; index < transitionListMatchingCondition?.Count; index++ ) - { - if (transitionListMatchingCondition[index].AnimatableProperty == transition.AnimatableProperty) - { - if (explicitlySet) - { - transitionListMatchingCondition[index] = transition; - replaced = true; - continue; - } - } - } - } - else - { - conditionNotInDictionary = true; - } - - if (replaced == false) - { - if (transitionListMatchingCondition == null) - { - transitionListMatchingCondition = new TransitionList(); - } - transitionListMatchingCondition.Add(transition); - // Update dictionary with new or replaced entry. - if (conditionNotInDictionary) - { - targetTransitionList.Add(condition, transitionListMatchingCondition); // new entry - } - else - { - targetTransitionList[condition] = transitionListMatchingCondition; // replaced - } - } - } - - /// - /// Retreive the transition list for the given condition. - /// - /// The source collection of transition lists to retrieve. - /// Condition for the transition. - /// transition list to return as out parameter. - /// True if a transition list found for the given condition> - static public bool GetTransitionsListForCondition( - Dictionary sourceTransitionCollection, - TransitionCondition condition, - TransitionList transitionsForCondition ) - { - TransitionCondition resolvedCondition = condition; - bool matched = false; - // LayoutChanged transitions overrides ChangeOnAdd and ChangeOnRemove as siblings will - // reposition to the new layout not to the insertion/removal of a sibling. - if ((condition & TransitionCondition.LayoutChanged) == TransitionCondition.LayoutChanged) - { - resolvedCondition = TransitionCondition.LayoutChanged; - } - - if (sourceTransitionCollection.TryGetValue(resolvedCondition, out transitionsForCondition)) - { - matched = true; - } - - return matched; - } - - /// - /// Copy the transitions in the source list to the target list - /// - /// The source transition list. - /// The target transition list to copy to. - static public void CopyTransitions( TransitionList sourceTransitionList, - TransitionList targetTransitionList ) - { - targetTransitionList.Clear(); - foreach (LayoutTransition transitionToApply in sourceTransitionList) - { - // Overwite existing transitions - targetTransitionList.Add(transitionToApply); - } - - } - } - -} // namespace Tizen.NUI \ No newline at end of file diff --git a/src/Tizen.NUI/src/internal/Layouting/LinearLayout.cs b/src/Tizen.NUI/src/internal/Layouting/LinearLayout.cs deleted file mode 100755 index c92769355..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/LinearLayout.cs +++ /dev/null @@ -1,843 +0,0 @@ -/* Copyright (c) 2019 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -using System; -using Tizen.NUI.BaseComponents; -using System.Collections.Generic; - -namespace Tizen.NUI -{ - /// - /// [Draft] This class implements a linear box layout, automatically handling right to left or left to right direction change. - /// - internal class LinearLayout : LayoutGroup - { - /// - /// [Draft] Enumeration for the direction in which the content is laid out - /// - public enum Orientation - { - /// - /// Horizontal (row) - /// - Horizontal, - /// - /// Vertical (column) - /// - Vertical - } - - /// - /// [Draft] Enumeration for the alignment of the linear layout items - /// - public enum Alignment - { - /// - /// At the left/right edge of the container (maps to LTR/RTL direction for horizontal orientation) - /// - Begin = 0x1, - /// - /// At the right/left edge of the container (maps to LTR/RTL direction for horizontal orientation) - /// - End = 0x2, - /// - /// At the horizontal center of the container - /// - CenterHorizontal = 0x4, - /// - /// At the top edge of the container - /// - Top = 0x8, - /// - /// At the bottom edge of the container - /// - Bottom = 0x10, - /// - /// At the vertical center of the container - /// - CenterVertical = 0x20, - /// - /// At the vertical and horizontal center of the container - /// - Center = 0x40 - } - - struct HeightAndWidthState - { - public MeasuredSize.StateType widthState; - public MeasuredSize.StateType heightState; - - public HeightAndWidthState( MeasuredSize.StateType width, MeasuredSize.StateType height) - { - widthState = width; - heightState = height; - } - } - - /// - /// [Draft] Get/Set the orientation in the layout - /// - public LinearLayout.Orientation LinearOrientation - { - get - { - return _linearOrientation; - } - set - { - _linearOrientation = value; - RequestLayout(); - } - } - - /// - /// [Draft] Get/Set the padding between cells in the layout - /// - public Size2D CellPadding - { - get - { - return _cellPadding; - } - set - { - _cellPadding = value; - RequestLayout(); - } - } - - - /// - /// [Draft] Get/Set the alignment in the layout - /// - public LinearLayout.Alignment LinearAlignment{ get; set; } = Alignment.Top; - - private float _totalLength = 0.0f; - private Size2D _cellPadding = new Size2D(0,0); - private Orientation _linearOrientation = Orientation.Horizontal; - - /// - /// [Draft] Constructor - /// - public LinearLayout() - { - } - - protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) - { - if (_linearOrientation == Orientation.Horizontal) - { - MeasureHorizontal(widthMeasureSpec, heightMeasureSpec); - } - else - { - MeasureVertical(widthMeasureSpec, heightMeasureSpec); - } - } - - protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) - { - if (_linearOrientation == Orientation.Horizontal) - { - LayoutHorizontal(left, top, right, bottom); - } - else - { - LayoutVertical(left, top, right, bottom); - } - } - - - private void MeasureWeightedChild( LayoutItem childLayout, float remainingExcess, float remainingWeight, float childWeight, - MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec, - HeightAndWidthState childState, Orientation orientation ) - { - bool horizontal = false; - if (orientation == Orientation.Horizontal) - { - horizontal = true; - } - - float childsShare = ( childWeight * remainingExcess ) / remainingWeight; - remainingExcess -= childsShare; - remainingWeight -= childWeight; - - float desiredWidth = childLayout.Owner.WidthSpecification; - float desiredHeight = childLayout.Owner.HeightSpecification; - float childLength = 0; - - Extents layoutPadding = Padding; - - // Always lay out weighted elements with intrinsic size regardless of the parent spec. - // for consistency between specs. - if( ( horizontal && ( desiredWidth == 0 )) || ( !horizontal && ( desiredHeight == 0 )) ) - { - // This child needs to be laid out from scratch using - // only its share of excess space. - childLength = childsShare; - } - else - { - // This child had some intrinsic width to which we - // need to add its share of excess space. - if (horizontal) - { - childLength = childLayout.MeasuredWidth.Size.AsDecimal() + childsShare; - } - else - { - childLength = childLayout.MeasuredHeight.Size.AsDecimal() + childsShare; - } - } - - MeasureSpecification childWidthMeasureSpec; - MeasureSpecification childHeightMeasureSpec; - - if (horizontal) - { - childWidthMeasureSpec = new MeasureSpecification( new LayoutLength(childLength), MeasureSpecification.ModeType.Exactly ); - childHeightMeasureSpec = GetChildMeasureSpecification( heightMeasureSpec, - new LayoutLength(layoutPadding.Top + layoutPadding.Bottom), - new LayoutLength(desiredHeight) ); - } - else // vertical - { - childWidthMeasureSpec = GetChildMeasureSpecification( widthMeasureSpec, - new LayoutLength(Padding.Start + Padding.End), - new LayoutLength(desiredWidth) ); - - childHeightMeasureSpec = new MeasureSpecification( new LayoutLength(childLength), MeasureSpecification.ModeType.Exactly); - } - - childLayout.Measure( childWidthMeasureSpec, childHeightMeasureSpec ); - - // Child may now not fit in horizontal dimension. - if( childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) - { - childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; - } - - // Child may now not fit in vertical dimension. - if( childLayout.MeasuredHeightAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) - { - childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; - } - } - - private void MeasureHorizontal(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) - { - var widthMode = widthMeasureSpec.Mode; - var heightMode = heightMeasureSpec.Mode; - bool isExactly = ( widthMode == MeasureSpecification.ModeType.Exactly ); - bool matchHeight = false; - bool allFillParent = true; - float maxHeight = 0.0f; - float alternativeMaxHeight = 0.0f; - float weightedMaxHeight = 0.0f; - float totalWeight = 0.0f; - - // Reset measure variables - _totalLength = 0.0f; - float usedExcessSpace = 0.0f; - HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK, - MeasuredSize.StateType.MeasuredSizeOK); - - // 1st phase: - // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs - // to accumulate total used space in totalLength based on measured sizes and margins. - // Weighted children are not measured at this phase. - // Available space for weighted children will be calculated in the phase 2 based on totalLength value. - // Max height of children is stored. - foreach( LayoutItem childLayout in _children ) - { - int childDesiredHeight = childLayout.Owner.HeightSpecification; - float childWeight = childLayout.Owner.Weight; - Extents childMargin = childLayout.Margin; - totalWeight += childWeight; - - bool useExcessSpace = (childLayout.Owner.WidthSpecification == 0 ) && (childWeight > 0); - if( isExactly && useExcessSpace ) - { - // Children to be laid out with excess space can be measured later - _totalLength += childMargin.Start + childMargin.End; - } - else - { - if (useExcessSpace) - { - // The widthMode is either Unspecified or AtMost, and - // this child is only laid out using excess space. Measure - // using WrapContent so that we can find out the view's - // optimal width. - MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(widthMeasureSpec, - new LayoutLength(childLayout.Padding.Start + childLayout.Padding.End), - new LayoutLength(LayoutParamPolicies.WrapContent)); - - MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(heightMeasureSpec, - new LayoutLength(childLayout.Padding.Top + childLayout.Padding.Bottom), - new LayoutLength(childDesiredHeight)); - - childLayout.Measure( childWidthMeasureSpec, childHeightMeasureSpec); - usedExcessSpace += childLayout.MeasuredWidth.Size.AsDecimal(); - } - else - { - MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec); - } - - LayoutLength childWidth = childLayout.MeasuredWidth.Size; - LayoutLength length = childWidth + childMargin.Start + childMargin.End; - - if (isExactly) - { - _totalLength += length.AsDecimal(); - } - else - { - _totalLength = Math.Max(_totalLength, _totalLength + length.AsDecimal() + CellPadding.Width); - } - } - - bool matchHeightLocally = false; - if (heightMode != MeasureSpecification.ModeType.Exactly && childDesiredHeight == LayoutParamPolicies.MatchParent) - { - // A child has set to MatchParent on it's height. - // Will have to re-measure at least this child when we know exact height. - matchHeight = true; - matchHeightLocally = true; - } - - float marginHeight = childMargin.Top + childMargin.Bottom; - float childHeight = childLayout.MeasuredHeight.Size.AsDecimal() + marginHeight; - - if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) - { - childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; - } - if (childLayout.MeasuredHeightAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) - { - childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; - } - - maxHeight = Math.Max( maxHeight, childHeight); - allFillParent = ( allFillParent && childDesiredHeight == LayoutParamPolicies.MatchParent); - - if (childWeight > 0) - { - // Heights of weighted Views are invalid if we end up remeasuring, so store them separately. - weightedMaxHeight = Math.Max( weightedMaxHeight, matchHeightLocally ? marginHeight : childHeight); - } - else - { - alternativeMaxHeight = Math.Max( alternativeMaxHeight, matchHeightLocally ? marginHeight : childHeight ); - } - } // foreach - - Extents padding = Padding; - _totalLength += padding.Start + padding.End; - - float widthSize = _totalLength; - widthSize = Math.Max( widthSize, SuggestedMinimumWidth.AsDecimal()); - MeasuredSize widthSizeAndState = ResolveSizeAndState( new LayoutLength(widthSize), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); - widthSize = widthSizeAndState.Size.AsDecimal(); - - // 2nd phase: - // Expand children with weight to take up available space - // We cycle through weighted children now (children with weight > 0). - // The children are measured with exact size equal to their share of the available space based on their weights. - // _totalLength is updated to include weighted children measured sizes. - float remainingExcess = widthSize - _totalLength + usedExcessSpace; - if( remainingExcess != 0 && totalWeight > 0 ) - { - float remainingWeight = totalWeight; - maxHeight = 0; - _totalLength = 0; - - int numberOfChildren = _children.Count; - for( int i = 0; i < numberOfChildren; ++i ) - { - LayoutItem childLayout = _children[i]; - - float desiredChildHeight = childLayout.Owner.HeightSpecification; - - float childWeight = childLayout.Owner.Weight; - Extents childMargin = childLayout.Margin; - - if( childWeight > 0 ) - { - MeasureWeightedChild(childLayout, remainingExcess, remainingWeight, childWeight, - widthMeasureSpec, heightMeasureSpec, childState, - Orientation.Horizontal ); - } - - float length = childLayout.MeasuredWidth.Size.AsDecimal() + childMargin.Start + childMargin.End; - float cellPadding = i < numberOfChildren - 1 ? CellPadding.Width : 0; - if( isExactly ) - { - _totalLength += length; - } - else - { - float totalLength = _totalLength; - _totalLength = Math.Max( _totalLength, _totalLength + length + cellPadding ); - } - - bool matchHeightLocally = (heightMode != MeasureSpecification.ModeType.Exactly) && (desiredChildHeight == LayoutParamPolicies.MatchParent); - float marginHeight = childMargin.Top + childMargin.Bottom; - float childHeight = childLayout.MeasuredHeight.Size.AsDecimal() + marginHeight; - - maxHeight = Math.Max( maxHeight, childHeight ); - alternativeMaxHeight = Math.Max( alternativeMaxHeight, matchHeightLocally ? marginHeight : childHeight ); - allFillParent = (allFillParent && desiredChildHeight == LayoutParamPolicies.MatchParent); - - _totalLength += padding.Start + padding.End; - } // for loop - } - else - { - // No excess space or no weighted children - alternativeMaxHeight = Math.Max( alternativeMaxHeight, weightedMaxHeight ); - } - - if (!allFillParent && heightMode != MeasureSpecification.ModeType.Exactly) - { - maxHeight = alternativeMaxHeight; - } - - maxHeight += padding.Top + padding.Bottom; - maxHeight = Math.Max( maxHeight, SuggestedMinimumHeight.AsRoundedValue() ); - - widthSizeAndState.State = childState.widthState; - - SetMeasuredDimensions(widthSizeAndState, - ResolveSizeAndState( new LayoutLength(maxHeight), heightMeasureSpec, childState.heightState )); - - if (matchHeight) - { - ForceUniformHeight(widthMeasureSpec); - } - } // MeasureHorizontal - - private void MeasureVertical( MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec ) - { - var widthMode = widthMeasureSpec.Mode; - var heightMode = heightMeasureSpec.Mode; - bool isExactly = ( heightMode == MeasureSpecification.ModeType.Exactly); - bool matchWidth = false; - bool allFillParent = true; - float maxWidth = 0.0f; - float alternativeMaxWidth = 0.0f; - float weightedMaxWidth = 0.0f; - float totalWeight = 0.0f; - - // Reset total length - _totalLength = 0.0f; - float usedExcessSpace =0.0f; - - HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK, - MeasuredSize.StateType.MeasuredSizeTooSmall); - - - // measure children, and determine if further resolution is required - - // 1st phase: - // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs - // to accumulate total used space in _totalLength. - // Weighted children are not measured in this phase. - // Available space for weighted children will be calculated in the phase 2 based on _totalLength value. - uint index = 0; - foreach( LayoutItem childLayout in _children ) - { - int childDesiredWidth = childLayout.Owner.WidthSpecification; - int childDesiredHeight = childLayout.Owner.HeightSpecification; - float childWeight = childLayout.Owner.Weight; - Extents childMargin = childLayout.Margin; - totalWeight += childWeight; - - bool useExcessSpace = (childDesiredHeight == 0) && (childWeight > 0); - - if( isExactly && useExcessSpace ) - { - _totalLength = Math.Max( _totalLength, (_totalLength + childMargin.Top + childMargin.Bottom) ); - } - else - { - float childHeight = 0.0f; - if( useExcessSpace ) - { - // The heightMode is either Unspecified or AtMost, and - // this child is only laid out using excess space. Measure - // using WrapContent so that we can find out the view's - // optimal height. - // We'll restore the original height of 0 after measurement. - MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification( widthMeasureSpec, - new LayoutLength(childLayout.Padding.Start + childLayout.Padding.End), - new LayoutLength(childDesiredWidth) ); - MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification( heightMeasureSpec, - new LayoutLength(childLayout.Padding.Top + childLayout.Padding.Bottom), - new LayoutLength(LayoutParamPolicies.WrapContent) ); - childLayout.Measure( childWidthMeasureSpec, childHeightMeasureSpec ); - childHeight = childLayout.MeasuredHeight.Size.AsDecimal(); - usedExcessSpace += childHeight; - } - else - { - MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec ); - childHeight = childLayout.MeasuredHeight.Size.AsDecimal(); - } - - float length = childHeight + childMargin.Top + childMargin.Bottom; - float cellPadding = CellPadding.Height; - // No need to add cell padding to the end of last item. - if (index>=_children.Count-1) - { - cellPadding = 0.0f; - } - _totalLength = Math.Max( _totalLength, _totalLength + length + cellPadding ); - } - - bool matchWidthLocally = false; - if( widthMode != MeasureSpecification.ModeType.Exactly && (childDesiredWidth == LayoutParamPolicies.MatchParent) ) - { - // Will have to re-measure at least this child when we know exact height. - matchWidth = true; - matchWidthLocally = true; - } - - float marginWidth = (childLayout.Margin.Start) + (childLayout.Margin.End); - float childWidth = childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth; - - if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) - { - childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; - } - if (childLayout.MeasuredHeightAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall) - { - childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; - } - - maxWidth = Math.Max( maxWidth, childWidth); - allFillParent = (allFillParent && (childDesiredWidth == LayoutParamPolicies.MatchParent)); - - float widthforWeight = childWidth; - if (matchWidthLocally) - { - widthforWeight = marginWidth; - } - - if (childWeight > 0) - { - // Widths of weighted Views are bogus if we end up remeasuring, so keep them separate. - weightedMaxWidth = Math.Max( weightedMaxWidth, widthforWeight); - } - else - { - alternativeMaxWidth = Math.Max( alternativeMaxWidth, widthforWeight); - } - index++; - } // foreach - - - Extents padding = Padding; - _totalLength += padding.Top + padding.Bottom; - LayoutLength heightSize = new LayoutLength(_totalLength); - heightSize = new LayoutLength(Math.Max( heightSize.AsDecimal(), SuggestedMinimumHeight.AsDecimal() )); - MeasuredSize heightSizeAndState = ResolveSizeAndState( heightSize, heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); - heightSize = heightSizeAndState.Size; - - // 2nd phase: - // We cycle through weighted children now (children with weight > 0). - // The children are measured with exact size equal to their share of the available space based on their weights. - // _totalLength is updated to include weighted children measured sizes. - float remainingExcess = heightSize.AsDecimal() - _totalLength + usedExcessSpace; - - if( remainingExcess != 0 && totalWeight > 0.0f ) - { - float remainingWeight = totalWeight; - - _totalLength = 0; - - int numberOfChildren = _children.Count; - for( int i = 0; i < numberOfChildren; ++i ) - { - LayoutItem childLayout = _children[i]; - - float desiredChildWidth = childLayout.Owner.WidthSpecification; - - float childWeight = childLayout.Owner.Weight; - Extents childMargin = childLayout.Margin; - - if( childWeight > 0 ) - { - MeasureWeightedChild(childLayout, remainingExcess, remainingWeight, childWeight, - widthMeasureSpec, heightMeasureSpec, childState, - Orientation.Vertical); - } - - bool matchWidthLocally = false; - if( widthMode != MeasureSpecification.ModeType.Exactly && desiredChildWidth == LayoutParamPolicies.MatchParent) - { - // Will have to re-measure at least this child when we know exact height. - matchWidth = true; - matchWidthLocally = true; - } - - float marginWidth = childMargin.Start + childMargin.End; - float childWidth = childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth; - maxWidth = Math.Max( maxWidth, childWidth ); - allFillParent = allFillParent && desiredChildWidth == LayoutParamPolicies.MatchParent; - - float childHeight = childLayout.MeasuredHeight.Size.AsDecimal(); - float childLength = childHeight + childMargin.Top + childMargin.Bottom; - float cellPadding = i < numberOfChildren - 1 ? CellPadding.Height : 0.0f; - _totalLength = _totalLength + childLength + cellPadding; - alternativeMaxWidth = Math.Max( alternativeMaxWidth, matchWidthLocally ? marginWidth : childWidth ); - } // for loop - - // Add in our padding - _totalLength += padding.Top + padding.Bottom; - } - else - { - alternativeMaxWidth = Math.Max( alternativeMaxWidth, weightedMaxWidth ); - } - - if (!allFillParent && widthMode != MeasureSpecification.ModeType.Exactly) - { - maxWidth = alternativeMaxWidth; - } - maxWidth += padding.Start + padding.End; - maxWidth = Math.Max( maxWidth, SuggestedMinimumWidth.AsRoundedValue()); - - heightSizeAndState.State = childState.heightState; - - SetMeasuredDimensions( ResolveSizeAndState( new LayoutLength(maxWidth), widthMeasureSpec, childState.widthState ), - heightSizeAndState ); - - if (matchWidth) - { - ForceUniformWidth(heightMeasureSpec ); - } - } // MeasureVertical - - private void LayoutHorizontal(LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) - { - bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL; - - LayoutLength childTop = new LayoutLength(Padding.Top); - LayoutLength childLeft = new LayoutLength(Padding.Start); - - // Where bottom of child should go - LayoutLength height = new LayoutLength(bottom - top); - - // Space available for child - LayoutLength childSpace = new LayoutLength( height - Padding.Top - Padding.Bottom); - - int count = _children.Count; - - switch (LinearAlignment) - { - case Alignment.End: - // totalLength contains the padding already - // In case of RTL map END alignment to the left edge - if (isLayoutRtl) - { - childLeft = new LayoutLength(Padding.Start); - } - else - { - childLeft = new LayoutLength(Padding.Start + right.AsDecimal() - left.AsDecimal() - _totalLength); - } - break; - case Alignment.CenterHorizontal: // FALL THROUGH - case Alignment.Center: - // totalLength contains the padding already - childLeft = new LayoutLength(Padding.Start + (right.AsDecimal() - left.AsDecimal() - _totalLength) / 2.0f); - break; - case Alignment.Begin: // FALL THROUGH (default) - default: - // totalLength contains the padding already - // In case of RTL map BEGIN alignment to the right edge - if (isLayoutRtl) - { - childLeft = new LayoutLength(Padding.Start + right.AsDecimal() - left.AsDecimal() - _totalLength); - } - else - { - childLeft = new LayoutLength(Padding.Start); - } - break; - } - - int start = 0; - int dir = 1; - - // In case of RTL, start drawing from the last child. - if (isLayoutRtl) - { - start = count - 1; - dir = -1; - } - - for( int i = 0; i < count; i++) - { - int childIndex = start + dir * i; - // Get a reference to the childLayout at the given index - LayoutItem childLayout = _children[childIndex]; - if( childLayout != null ) - { - LayoutLength childWidth = childLayout.MeasuredWidth.Size; - LayoutLength childHeight = childLayout.MeasuredHeight.Size; - Extents childMargin = childLayout.Margin; - - switch ( LinearAlignment ) - { - case Alignment.Bottom: - childTop = new LayoutLength(height - Padding.Bottom - childHeight - childMargin.Bottom); - break; - case Alignment.CenterVertical: - case Alignment.Center: // FALLTHROUGH - childTop = new LayoutLength(Padding.Top + ( ( childSpace - childHeight ).AsDecimal() / 2.0f ) + childMargin.Top - childMargin.Bottom); - break; - case Alignment.Top: // FALLTHROUGH default - default: - childTop = new LayoutLength(Padding.Top + childMargin.Top); - break; - } - childLeft += childMargin.Start; - childLayout.Layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); - childLeft += childWidth + childMargin.End + CellPadding.Width; - } - } - } // LayoutHorizontally - - private void LayoutVertical(LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) - { - LayoutLength childTop = new LayoutLength(Padding.Top); - LayoutLength childLeft = new LayoutLength(Padding.Start); - - // Where end of child should go - LayoutLength width = new LayoutLength(right - left); - - // Space available for child - LayoutLength childSpace = new LayoutLength( width - Padding.Start - Padding.End); - - int count = _children.Count; - - switch (LinearAlignment) - { - case Alignment.Bottom: - // totalLength contains the padding already - childTop = new LayoutLength( Padding.Top + bottom.AsDecimal() - top.AsDecimal() - _totalLength); - break; - case Alignment.CenterVertical: // FALL THROUGH - case Alignment.Center: - // totalLength contains the padding already - childTop = new LayoutLength(Padding.Top + ( bottom.AsDecimal() - top.AsDecimal() - _totalLength ) / 2.0f); - break; - case Alignment.Top: // FALL THROUGH (default) - default: - // totalLength contains the padding already - childTop = new LayoutLength( Padding.Top ); - break; - } - - for( int i = 0; i < count; i++) - { - LayoutItem childLayout = _children[i]; - if( childLayout != null ) - { - LayoutLength childWidth = childLayout.MeasuredWidth.Size; - LayoutLength childHeight = childLayout.MeasuredHeight.Size; - Extents childMargin = childLayout.Margin; - - childTop += childMargin.Top; - switch ( LinearAlignment ) - { - case Alignment.Begin: - default: - { - childLeft = new LayoutLength(Padding.Start + childMargin.Start); - break; - } - case Alignment.End: - { - childLeft = new LayoutLength(width - Padding.End - childWidth - childMargin.End); - break; - } - case Alignment.CenterHorizontal: - case Alignment.Center: // FALL THROUGH - { - childLeft = new LayoutLength(Padding.Start + (( childSpace - childWidth ).AsDecimal() / 2.0f) + childMargin.Start - childMargin.End); - break; - } - } - childLayout.Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight ); - childTop += childHeight + childMargin.Bottom + CellPadding.Height; - } - } - } // LayoutVertical - - private void ForceUniformHeight(MeasureSpecification widthMeasureSpec) - { - // Pretend that the linear layout has an exact size. This is the measured height of - // ourselves. The measured height should be the max height of the children, changed - // to accommodate the heightMeasureSpec from the parent - MeasureSpecification uniformMeasureSpec = new MeasureSpecification( MeasuredHeight.Size, MeasureSpecification.ModeType.Exactly); - foreach (LayoutItem childLayout in _children) - { - int desiredChildHeight = childLayout.Owner.HeightSpecification; - int desiredChildWidth = childLayout.Owner.WidthSpecification; - - if (desiredChildHeight == LayoutParamPolicies.MatchParent) - { - // Temporarily force children to reuse their original measured width - int originalWidth = desiredChildWidth; - childLayout.Owner.WidthSpecification = (int)childLayout.MeasuredWidth.Size.AsRoundedValue(); - // Remeasure with new dimensions - MeasureChildWithMargins( childLayout, widthMeasureSpec, new LayoutLength(0), - uniformMeasureSpec, new LayoutLength(0) ); - // Restore width specification - childLayout.Owner.WidthSpecification = originalWidth; - } - } - } - - private void ForceUniformWidth(MeasureSpecification heightMeasureSpec) - { - // Pretend that the linear layout has an exact size. - MeasureSpecification uniformMeasureSpec = new MeasureSpecification( MeasuredWidth.Size, MeasureSpecification.ModeType.Exactly); - foreach (LayoutItem childLayout in _children) - { - int desiredChildWidth = childLayout.Owner.WidthSpecification; - int desiredChildHeight = childLayout.Owner.WidthSpecification; - - if (desiredChildWidth == LayoutParamPolicies.MatchParent) - { - // Temporarily force children to reuse their original measured height - int originalHeight = desiredChildHeight; - childLayout.Owner.HeightSpecification = (int)childLayout.MeasuredHeight.Size.AsRoundedValue(); - - // Remeasure with new dimensions - MeasureChildWithMargins( childLayout, uniformMeasureSpec, new LayoutLength(0), - heightMeasureSpec, new LayoutLength(0)); - // Restore height specification - childLayout.Owner.HeightSpecification = originalHeight; - } - } - } - } //LinearLayout -} // namespace diff --git a/src/Tizen.NUI/src/internal/Layouting/MeasureSpecification.cs b/src/Tizen.NUI/src/internal/Layouting/MeasureSpecification.cs deleted file mode 100755 index d12e3c85f..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/MeasureSpecification.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -using System.ComponentModel; -using Tizen.NUI.BaseComponents; - -namespace Tizen.NUI -{ - /// - /// [Draft] A MeasureSpecification is used during the Measure pass by a LayoutGroup to inform it's children how to be measured. - /// For instance, it may measure a child with an exact width and an unspecified height in order to determine height for width. - /// - internal struct MeasureSpecification - { - /// - /// MeasureSpecification Size value. - /// - public LayoutLength Size; - - /// - /// MeasureSpecification Mode. - /// - public MeasureSpecification.ModeType Mode; - - /// - /// Constructor taking size and mode type. - /// - /// size value. - /// mode vaue. - public MeasureSpecification(LayoutLength size, MeasureSpecification.ModeType mode) - { - Size = size; - Mode = mode; - } - - public enum ModeType - { - /// - /// This is used by a parent to determine the desired dimension of a child layout. - /// - Unspecified, - /// - /// This is used by a parent to impose an exact size on the child. - /// The child must use this size, and guarantee that all of its descendants will fit within this size. - /// - Exactly, - /// - /// This is used by the parent to impose a maximum size on the child. - /// The child must guarantee that it and all of it's descendants will fit within this size. - /// - AtMost - } - } -} diff --git a/src/Tizen.NUI/src/internal/Layouting/MeasuredSize.cs b/src/Tizen.NUI/src/internal/Layouting/MeasuredSize.cs deleted file mode 100755 index c978212e6..000000000 --- a/src/Tizen.NUI/src/internal/Layouting/MeasuredSize.cs +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -using System.ComponentModel; -using Tizen.NUI.BaseComponents; - -namespace Tizen.NUI -{ - /// - /// [Draft] Class that encodes a measurement and a measure state, which is set if the measured size is too small. - /// - internal struct MeasuredSize - { - /// - /// Constructor - /// - /// size parameter - /// State - public MeasuredSize(LayoutLength measuredSize, MeasuredSize.StateType state) - { - Size = measuredSize; - State = state; - } - - /// - /// Creates a MeasuredSize from a LayoutLength - /// - /// LayoutLength to create - public static implicit operator MeasuredSize(LayoutLength measuredSize) - { - return new MeasuredSize(measuredSize, StateType.MeasuredSizeOK); - } - - /// - /// LayoutLength size property - /// - public LayoutLength Size{ get; set;} - - /// - /// Measured state for this size. - /// - public StateType State{ get; set; } - - /// - /// Measured states for a Size value. - /// - public enum StateType - { - /// - /// The measured size is good - /// - MeasuredSizeOK, - /// - /// The measured size is too small - /// - MeasuredSizeTooSmall - } - } -} diff --git a/src/Tizen.NUI/src/public/BaseComponents/View.cs b/src/Tizen.NUI/src/public/BaseComponents/View.cs index 3d3f64e17..c8b64dc57 100755 --- a/src/Tizen.NUI/src/public/BaseComponents/View.cs +++ b/src/Tizen.NUI/src/public/BaseComponents/View.cs @@ -1260,6 +1260,7 @@ namespace Tizen.NUI.BaseComponents return temp; }); + /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] public static readonly BindableProperty UpdateSizeHintProperty = BindableProperty.Create("UpdateSizeHint", typeof(Vector2), typeof(View), null, propertyChanged: (bindable, oldValue, newValue) => @@ -1279,6 +1280,7 @@ namespace Tizen.NUI.BaseComponents return temp; }); + /// This will be public opened in tizen_5.0 after ACR done. Before ACR, need to be hidden as inhouse API. [EditorBrowsable(EditorBrowsableState.Never)] public static readonly BindableProperty XamlStyleProperty = BindableProperty.Create("XamlStyle", typeof(Style), typeof(View), default(Style), propertyChanged: (bindable, oldvalue, newvalue) => ((View)bindable)._mergedStyle.Style = (Style)newvalue); @@ -2439,7 +2441,7 @@ namespace Tizen.NUI.BaseComponents "Like: " + "View view = new View(); " + "view.PivotPoint = PivotPoint.Center; " + - "view.PositionUsesPivotPoint = true;" + + "view.PositionUsesPivotPoint = true;" + " Deprecated in API5: Will be removed in API8")] [EditorBrowsable(EditorBrowsableState.Never)] public bool PositionUsesAnchorPoint @@ -3337,7 +3339,7 @@ namespace Tizen.NUI.BaseComponents } /// - /// Deprecated in API5; Will be removed in API8. Please use 'Container GetParent() for derived class' instead! + /// Deprecated in API5; Will be removed in API8. Please use 'Container GetParent() for derived class' instead! /// /// 3 [Obsolete("Deprecated in API5; Will be removed in API8. Please use 'Container GetParent() for derived class' instead! " + @@ -3455,11 +3457,7 @@ namespace Tizen.NUI.BaseComponents /// /// The required policy for this dimension, LayoutParamPolicies enum or exact value. /// - /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. - /// - /// Previously named LayoutWidthSpecification - /// - [EditorBrowsable(EditorBrowsableState.Never)] + /// 6 public int WidthSpecification { get @@ -3482,10 +3480,7 @@ namespace Tizen.NUI.BaseComponents /// /// The required policy for this dimension, LayoutParamPolicies enum or exact value. /// - /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API. - /// - /// Previously named LayoutHeightSpecification - /// + /// 6 [EditorBrowsable(EditorBrowsableState.Never)] public int HeightSpecification { @@ -3509,8 +3504,7 @@ namespace Tizen.NUI.BaseComponents /// /// Gets the List of transitions for this View. /// - /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed. - [EditorBrowsable(EditorBrowsableState.Never)] + /// 6 public Dictionary LayoutTransitions { get @@ -3523,7 +3517,14 @@ namespace Tizen.NUI.BaseComponents } } - internal LayoutTransition LayoutTransition + /// + /// Set a layout transitions for this View. + /// + /// + /// Use LayoutTransitions to receive a collection of LayoutTransitions set on the View. + /// + /// 6 + public LayoutTransition LayoutTransition { set { @@ -3591,24 +3592,98 @@ namespace Tizen.NUI.BaseComponents } } + /// - /// The color mode of View. - /// This specifies whether the View uses its own color, or inherits its parent color. - /// The default is ColorMode.UseOwnMultiplyParentColor. + /// Set the layout on this View. Replaces any existing Layout. /// - internal ColorMode ColorMode + /// 6 + public LayoutItem Layout { - set + get { - SetColorMode(value); + return _layout; } - get + set { - return GetColorMode(); + // Do nothing if layout provided is already set on this View. + if (value == _layout) + { + return; + } + + Log.Info("NUI", "Setting Layout on:" + Name + "\n"); + layoutingDisabled = false; + layoutSet = true; + + // If new layout being set already has a owner then that owner receives a replacement default layout. + // First check if the layout to be set already has a owner. + if (value?.Owner != null) + { + // Previous owner of the layout gets a default layout as a replacement. + value.Owner.Layout = new LayoutGroup(); + + // Copy Margin and Padding to replacement LayoutGroup. + value.Owner.Layout.Margin = value.Margin; + value.Owner.Layout.Padding = value.Padding; + } + + // Copy Margin and Padding to new layout being set or restore padding and margin back to + // View if no replacement. Previously margin and padding values would have been moved from + // the View to the layout. + if (_layout != null ) // Existing layout + { + if (value != null) + { + // Existing layout being replaced so copy over margin and padding values. + value.Margin = _layout.Margin; + value.Padding = _layout.Padding; + } + else + { + // Layout not being replaced so restore margin and padding to View. + SetValue(MarginProperty, _layout.Margin); + SetValue(PaddingProperty, _layout.Padding); + NotifyPropertyChanged(); + } + } + else + { + // First Layout to be added to the View hence copy + + // Do not try to set Margins or Padding on a null Layout (when a layout is being removed from a View) + if (value !=null) + { + if (Margin.Top != 0 || Margin.Bottom !=0 || Margin.Start !=0 || Margin.End != 0) + { + // If View already has a margin set then store it in Layout instead. + value.Margin = Margin; + SetValue(MarginProperty, new Extents(0,0,0,0)); + NotifyPropertyChanged(); + } + + if (Padding.Top != 0 || Padding.Bottom !=0 || Padding.Start !=0 || Padding.End != 0) + { + // If View already has a padding set then store it in Layout instead. + value.Padding = Padding; + SetValue(PaddingProperty, new Extents(0,0,0,0)); + NotifyPropertyChanged(); + } + } + } + + // Remove existing layout from it's parent layout group. + _layout?.Unparent(); + + // Set layout to this view + SetLayout(value); } } - internal float Weight + /// + /// The weight of the View, used to share available space in a layout with siblings. + /// + /// 6 + public float Weight { get { @@ -3621,6 +3696,24 @@ namespace Tizen.NUI.BaseComponents } } + + /// + /// The color mode of View. + /// This specifies whether the View uses its own color, or inherits its parent color. + /// The default is ColorMode.UseOwnMultiplyParentColor. + /// + internal ColorMode ColorMode + { + set + { + SetColorMode(value); + } + get + { + return GetColorMode(); + } + } + /// /// Whether to load the BackgroundImage synchronously. /// If not specified, the default is false, i.e. the BackgroundImage is loaded asynchronously. @@ -3697,92 +3790,6 @@ namespace Tizen.NUI.BaseComponents } } - /// - /// Set the layout on this View. Replaces any existing Layout. - /// - internal LayoutItem Layout - { - get - { - return _layout; - } - set - { - // Do nothing if layout provided is already set on this View. - if (value == _layout) - { - return; - } - - Log.Info("NUI", "Setting Layout on:" + Name + "\n"); - layoutingDisabled = false; - layoutSet = true; - - // If new layout being set already has a owner then that owner receives a replacement default layout. - // First check if the layout to be set already has a owner. - if (value?.Owner != null) - { - Log.Info("NUI", "Set layout already in use by another View: " + value.Owner.Name + "will get a LayoutGroup\n"); - // Previous owner of the layout gets a default layout as a replacement. - value.Owner.Layout = new LayoutGroup(); - - // Copy Margin and Padding to replacement LayoutGroup. - value.Owner.Layout.Margin = value.Margin; - value.Owner.Layout.Padding = value.Padding; - } - - // Copy Margin and Padding to new layout being set or restore padding and margin back to - // View if no replacement. Previously margin and padding values would have been moved from - // the View to the layout. - if (_layout != null ) // Existing layout - { - if (value != null) - { - // Existing layout being replaced so copy over margin and padding values. - value.Margin = _layout.Margin; - value.Padding = _layout.Padding; - } - else - { - // Layout not being replaced so restore margin and padding to View. - SetValue(MarginProperty, _layout.Margin); - SetValue(PaddingProperty, _layout.Padding); - NotifyPropertyChanged(); - } - } - else - { - // First Layout to be added to the View hence copy - - // Do not try to set Margins or Padding on a null Layout (when a layout is being removed from a View) - if (value !=null) - { - if (Margin.Top != 0 || Margin.Bottom !=0 || Margin.Start !=0 || Margin.End != 0) - { - // If View already has a margin set then store it in Layout instead. - value.Margin = Margin; - SetValue(MarginProperty, new Extents(0,0,0,0)); - NotifyPropertyChanged(); - } - - if (Padding.Top != 0 || Padding.Bottom !=0 || Padding.Start !=0 || Padding.End != 0) - { - // If View already has a padding set then store it in Layout instead. - value.Padding = Padding; - SetValue(PaddingProperty, new Extents(0,0,0,0)); - NotifyPropertyChanged(); - } - } - } - - // Remove existing layout from it's parent layout group. - _layout?.Unparent(); - - // Set layout to this view - SetLayout(value); - } - } - internal void SetLayout(LayoutItem layout) { _layout = layout; @@ -5710,7 +5717,7 @@ namespace Tizen.NUI.BaseComponents View view = GetParent()?.FindCurrentChildById(id); //If we can't find the parent's children, find in the top layer. - if (!view) + if (!view) { Container parent = GetParent(); while ((parent is View) && (parent != null)) diff --git a/src/Tizen.NUI/src/public/Layouting/AbsoluteLayout.cs b/src/Tizen.NUI/src/public/Layouting/AbsoluteLayout.cs new file mode 100755 index 000000000..05a5dfd61 --- /dev/null +++ b/src/Tizen.NUI/src/public/Layouting/AbsoluteLayout.cs @@ -0,0 +1,154 @@ +/* Copyright (c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +using System; +using Tizen.NUI.BaseComponents; + +namespace Tizen.NUI +{ + /// + /// [Draft] This class implements a absolute layout, allowing explicit positioning of children. + /// Positions are from the top left of the layout and can be set using the Actor::Property::POSITION and alike. + /// + public class AbsoluteLayout : LayoutGroup + { + /// + /// Struct to store Measured states of height and width. + /// + private struct HeightAndWidthState + { + public MeasuredSize.StateType widthState; + public MeasuredSize.StateType heightState; + + public HeightAndWidthState( MeasuredSize.StateType width, MeasuredSize.StateType height) + { + widthState = width; + heightState = height; + } + } + + /// + /// [Draft] Constructor + /// + /// 6 + public AbsoluteLayout() + { + } + + /// + /// Measure the layout and its content to determine the measured width and the measured height.
+ ///
+ /// horizontal space requirements as imposed by the parent. + /// vertical space requirements as imposed by the parent. + /// 6 + protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) + { + float totalHeight = 0.0f; + float totalWidth = 0.0f; + + HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK, + MeasuredSize.StateType.MeasuredSizeOK); + + float minPositionX = 0.0f; + float minPositionY = 0.0f; + float maxPositionX = 0.0f; + float maxPositionY = 0.0f; + + // measure children + foreach( LayoutItem childLayout in LayoutChildren ) + { + if (childLayout != null) + { + // Get size of child + MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec ); + float childWidth = childLayout.MeasuredWidth.Size.AsDecimal(); + float childHeight = childLayout.MeasuredHeight.Size.AsDecimal(); + + // Determine the width and height needed by the children using their given position and size. + // Children could overlap so find the left most and right most child. + Position2D childPosition = childLayout.Owner.Position2D; + float childLeft = childPosition.X; + float childTop = childPosition.Y; + + minPositionX = Math.Min( minPositionX, childLeft ); + maxPositionX = Math.Max( maxPositionX, childLeft + childWidth ); + // Children could overlap so find the highest and lowest child. + minPositionY = Math.Min( minPositionY, childTop ); + maxPositionY = Math.Max( maxPositionY, childTop + childHeight ); + + // Store current width and height needed to contain all children. + totalWidth = maxPositionX - minPositionX; + totalHeight = maxPositionY - minPositionY; + + if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall) + { + childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; + } + if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall) + { + childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; + } + } + } + + + MeasuredSize widthSizeAndState = ResolveSizeAndState(new LayoutLength(totalWidth), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); + MeasuredSize heightSizeAndState = ResolveSizeAndState(new LayoutLength(totalHeight), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); + totalWidth = widthSizeAndState.Size.AsDecimal(); + totalHeight = heightSizeAndState.Size.AsDecimal(); + + // Ensure layout respects it's given minimum size + totalWidth = Math.Max( totalWidth, SuggestedMinimumWidth.AsDecimal() ); + totalHeight = Math.Max( totalHeight, SuggestedMinimumHeight.AsDecimal() ); + + widthSizeAndState.State = childState.widthState; + heightSizeAndState.State = childState.heightState; + + SetMeasuredDimensions( ResolveSizeAndState( new LayoutLength(totalWidth), widthMeasureSpec, childState.widthState ), + ResolveSizeAndState( new LayoutLength(totalHeight), heightMeasureSpec, childState.heightState ) ); + } + + /// + /// Assign a size and position to each of its children.
+ ///
+ /// This is a new size or position for this layout. + /// Left position, relative to parent. + /// Top position, relative to parent. + /// Right position, relative to parent. + /// Bottom position, relative to parent. + /// 6 + protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) + { + // Absolute layout positions it's children at their Actor positions. + // Children could overlap or spill outside the parent, as is the nature of absolute positions. + foreach( LayoutItem childLayout in LayoutChildren ) + { + if( childLayout != null ) + { + LayoutLength childWidth = childLayout.MeasuredWidth.Size; + LayoutLength childHeight = childLayout.MeasuredHeight.Size; + + Position2D childPosition = childLayout.Owner.Position2D; + + LayoutLength childLeft = new LayoutLength(childPosition.X); + LayoutLength childTop = new LayoutLength(childPosition.Y); + + childLayout.Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight ); + } + } + } + } + +} // namespace diff --git a/src/Tizen.NUI/src/public/Layouting/FlexLayout.cs b/src/Tizen.NUI/src/public/Layouting/FlexLayout.cs new file mode 100644 index 000000000..3e5ed6753 --- /dev/null +++ b/src/Tizen.NUI/src/public/Layouting/FlexLayout.cs @@ -0,0 +1,504 @@ +/* Copyright (c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +using System; +using System.ComponentModel; +using Tizen.NUI.BaseComponents; +using System.Runtime.InteropServices; + +namespace Tizen.NUI +{ + /// + /// [Draft] This class implements a flex layout. + /// The flex layout implementation is based on open source Facebook Yoga layout engine. + /// For more information about the flex layout API and how to use it please refer to https://yogalayout.com/docs/ + /// We implement the subset of the API in the class below. + /// + public class FlexLayout : LayoutGroup, global::System.IDisposable + { + float Flex{ get; set;} + int AlignSelf{get; set;} + + private global::System.Runtime.InteropServices.HandleRef swigCPtr; + private bool swigCMemOwn; + private bool disposed; + private bool isDisposeQueued = false; + + private IntPtr _rootFlex; // Pointer to the unmanged flex layout class. + + internal struct MeasuredSize + { + public MeasuredSize(float x, float y) + { + width = x; + height = y; + } + float width; + float height; + }; + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + internal delegate MeasuredSize ChildMeasureCallback( global::System.IntPtr child, float width, int measureModeWidth, float height, int measureModeHeight ); + + event ChildMeasureCallback measureChildDelegate; // Stores a delegate to the child measure callback. Used for all children of this FlexLayout. + + internal FlexLayout(global::System.IntPtr cPtr, bool cMemoryOwn) + { + swigCMemOwn = cMemoryOwn; + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(this, cPtr); + _rootFlex = Interop.FlexLayout.FlexLayout_New(); + measureChildDelegate = new ChildMeasureCallback(measureChild); + } + + internal static global::System.Runtime.InteropServices.HandleRef getCPtr(FlexLayout obj) + { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } + + /// + /// Dispose. + /// + /// 6 + public void Dispose() + { + // Throw exception if Dispose() is called in separate thread. + if (!Window.IsInstalled()) + { + throw new System.InvalidOperationException("This API called from separate thread. This API must be called from MainThread."); + } + + if (isDisposeQueued) + { + Dispose(DisposeTypes.Implicit); + } + else + { + Dispose(DisposeTypes.Explicit); + System.GC.SuppressFinalize(this); + } + } + + /// + /// Dispose. + /// + /// 6 + protected virtual void Dispose(DisposeTypes type) + { + if (disposed) + { + return; + } + + if (type == DisposeTypes.Explicit) + { + // Called by User + // Release your own managed resources here. + // You should release all of your own disposable objects here. + + } + + // Release your own unmanaged resources here. + // You should not access any managed member here except static instance. + // because the execution order of Finalizes is non-deterministic. + if (swigCPtr.Handle != global::System.IntPtr.Zero) + { + if (swigCMemOwn) + { + swigCMemOwn = false; + Interop.FlexLayout.delete_FlexLayout(swigCPtr); + } + swigCPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + disposed = true; + } + + /// + /// [Draft] Creates a FlexLayout object. + /// + /// 6 + public FlexLayout() : this(Interop.FlexLayout.FlexLayout_New(), true) + { + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + + internal static FlexLayout DownCast(BaseHandle handle) + { + FlexLayout ret = new FlexLayout(Interop.FlexLayout.FlexLayout_DownCast(BaseHandle.getCPtr(handle)), true); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + internal FlexLayout(FlexLayout other) : this(Interop.FlexLayout.new_FlexLayout__SWIG_1(FlexLayout.getCPtr(other)), true) + { + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + } + + internal FlexLayout Assign(FlexLayout other) + { + FlexLayout ret = new FlexLayout(Interop.FlexLayout.FlexLayout_Assign(swigCPtr, FlexLayout.getCPtr(other)), false); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + internal void SetFlexDirection(FlexLayout.FlexDirection flexDirection) + { + Interop.FlexLayout.FlexLayout_SetFlexDirection(swigCPtr, (int)flexDirection); + RequestLayout(); + } + + internal FlexLayout.FlexDirection GetFlexDirection() + { + FlexLayout.FlexDirection ret = (FlexLayout.FlexDirection)Interop.FlexLayout.FlexLayout_GetFlexDirection(swigCPtr); + return ret; + + } + + internal void SetFlexJustification(FlexLayout.FlexJustification flexJustification) + { + Interop.FlexLayout.FlexLayout_SetFlexJustification(swigCPtr, (int)flexJustification); + RequestLayout(); + } + + internal FlexLayout.FlexJustification GetFlexJustification() + { + FlexLayout.FlexJustification ret = (FlexLayout.FlexJustification)Interop.FlexLayout.FlexLayout_GetFlexJustification(swigCPtr); + return ret; + } + + internal void SetFlexWrap(FlexLayout.FlexWrapType flexWrap) + { + Interop.FlexLayout.FlexLayout_SetFlexWrap(swigCPtr, (int)flexWrap); + RequestLayout(); + } + + internal FlexLayout.FlexWrapType GetFlexWrap() + { + FlexLayout.FlexWrapType ret = (FlexLayout.FlexWrapType)Interop.FlexLayout.FlexLayout_GetFlexWrap(swigCPtr); + return ret; + } + + internal void SetFlexAlignment(FlexLayout.AlignmentType flexAlignment) + { + Interop.FlexLayout.FlexLayout_SetFlexAlignment(swigCPtr, (int)flexAlignment); + RequestLayout(); + } + + internal FlexLayout.AlignmentType GetFlexAlignment() + { + FlexLayout.AlignmentType ret = (FlexLayout.AlignmentType)Interop.FlexLayout.FlexLayout_GetFlexAlignment(swigCPtr); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + internal void SetFlexItemsAlignment(FlexLayout.AlignmentType flexAlignment) + { + Interop.FlexLayout.FlexLayout_SetFlexItemsAlignment(swigCPtr, (int)flexAlignment); + RequestLayout(); + } + + internal FlexLayout.AlignmentType GetFlexItemsAlignment() + { + FlexLayout.AlignmentType ret = (FlexLayout.AlignmentType)Interop.FlexLayout.FlexLayout_GetFlexItemsAlignment(swigCPtr); + if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve(); + return ret; + } + + /// + /// [Draft] Get/Set the flex direction in the layout. + /// The direction of the main-axis which determines the direction that flex items are laid out. + /// + /// 6 + public FlexDirection Direction + { + get + { + return GetFlexDirection(); + } + set + { + SetFlexDirection(value); + } + } + + /// + /// [Draft] Get/Set the justification in the layout. + /// + /// 6 + public FlexJustification Justification + { + get + { + return GetFlexJustification(); + } + set + { + SetFlexJustification(value); + } + } + + /// + /// [Draft] Get/Set the wrap in the layout. + /// + /// 6 + public FlexWrapType WrapType + { + get + { + return GetFlexWrap(); + } + set + { + SetFlexWrap(value); + } + } + + /// + /// [Draft] Get/Set the alignment of the layout content. + /// + /// 6 + public AlignmentType Alignment + { + get + { + return GetFlexAlignment(); + } + set + { + SetFlexAlignment(value); + } + } + + /// + /// [Draft] Get/Set the alignment of the layout items. + /// + /// 6 + public AlignmentType ItemsAlignment + { + get + { + return GetFlexItemsAlignment(); + } + set + { + SetFlexItemsAlignment(value); + } + } + + /// + /// [Draft] Enumeration for the direction of the main axis in the flex container. + /// This determines the direction that flex items are laid out in the flex container. + /// + /// 6 + public enum FlexDirection + { + /// + /// The flexible items are displayed vertically as a column + /// + Column, + /// + /// The flexible items are displayed vertically as a column, but in reverse order + /// + ColumnReverse, + /// + /// The flexible items are displayed horizontally as a row + /// + Row, + /// + /// The flexible items are displayed horizontally as a row, but in reverse order + /// + RowReverse + } + + /// + /// [Draft] Enumeration for the alignment of the flex items when the items do not use all available space on the main-axis. + /// + /// 6 + public enum FlexJustification + { + /// + /// Items are positioned at the beginning of the container + /// + FlexStart, + /// + /// Items are positioned at the center of the container + /// + Center, + /// + /// Items are positioned at the end of the container + /// + FlexEnd, + /// + /// Items are positioned with equal space between the lines + /// + SpaceBetween, + /// + /// Items are positioned with equal space before, between, and after the lines + /// + SpaceAround + } + + /// + /// [Draft] Enumeration for the wrap type of the flex container when there is no enough room for all the items on one flex line. + /// + /// 6 + public enum FlexWrapType + { + /// + /// Flex items laid out in single line (shrunk to fit the flex container along the main axis) + /// + NoWrap, + /// + /// Flex items laid out in multiple lines if needed + /// + Wrap + } + + /// + /// [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. + /// + /// 6 + public enum AlignmentType + { + /// + /// Inherits the same alignment from the parent + /// + Auto, + /// + /// At the beginning of the container + /// + FlexStart, + /// + /// At the center of the container + /// + Center, + /// + /// At the end of the container + /// + FlexEnd, + /// + /// Stretch to fit the container + /// + Stretch + } + + private MeasuredSize measureChild(global::System.IntPtr child, float width, int measureModeWidth, float height, int measureModeHeight) + { + View view = Registry.GetManagedBaseHandleFromNativePtr(child) as View; + Size2D viewSize = new Size2D(8,8); + if(view) + { + viewSize = view.NaturalSize2D; + } + return new MeasuredSize(viewSize.Width,viewSize.Height); + } + + void InsertChild( LayoutItem child ) + { + // Store created node for child + Interop.FlexLayout.FlexLayout_AddChild(swigCPtr, View.getCPtr(child.Owner), measureChildDelegate, LayoutChildren.Count-1); + } + + /// + /// Callback when child is added to container.
+ /// Derived classes can use this to set their own child properties on the child layout's owner.
+ ///
+ /// The Layout child. + /// 6 + protected override void OnChildAdd(LayoutItem child) + { + InsertChild(child); + } + + /// + /// Callback when child is removed from container.
+ ///
+ /// The Layout child. + /// 6 + protected override void OnChildRemove(LayoutItem child) + { + // When child View is removed from it's parent View (that is a Layout) then remove it from the layout too. + // FlexLayout refers to the child as a View not LayoutItem. + Interop.FlexLayout.FlexLayout_RemoveChild(swigCPtr, child); + } + + /// + /// Measure the layout and its content to determine the measured width and the measured height.
+ ///
+ /// horizontal space requirements as imposed by the parent. + /// vertical space requirements as imposed by the parent. + /// 6 + protected override void OnMeasure( MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec ) + { + bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL; + Extents padding = Owner.Padding; + Extents margin = Owner.Margin; + + Interop.FlexLayout.FlexLayout_SetMargin(swigCPtr, Extents.getCPtr(margin)); + Interop.FlexLayout.FlexLayout_SetPadding(swigCPtr, Extents.getCPtr(padding)); + + float width = 0.0f; + float height = 0.0f; + + if( widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly || widthMeasureSpec.Mode == MeasureSpecification.ModeType.AtMost ) + { + width = widthMeasureSpec.Size.AsDecimal(); + } + + if ( heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly || heightMeasureSpec.Mode == MeasureSpecification.ModeType.AtMost ) + { + height = heightMeasureSpec.Size.AsDecimal(); + } + + Interop.FlexLayout.FlexLayout_CalculateLayout( swigCPtr, width, height, isLayoutRtl ); + + SetMeasuredDimensions( GetDefaultSize( new LayoutLength( (float)Interop.FlexLayout.FlexLayout_GetWidth(swigCPtr) ), widthMeasureSpec ), + GetDefaultSize( new LayoutLength( (float)Interop.FlexLayout.FlexLayout_GetHeight(swigCPtr) ), heightMeasureSpec ) ); + } + + /// + /// Assign a size and position to each of its children.
+ ///
+ /// This is a new size or position for this layout. + /// Left position, relative to parent. + /// Top position, relative to parent. + /// Right position, relative to parent. + /// Bottom position, relative to parent. + /// 6 + protected override void OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom ) + { + + bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL; + LayoutLength width = right - left; + LayoutLength height = bottom - top; + + // Call to FlexLayout implementation to calculate layout values for later retrieval. + Interop.FlexLayout.FlexLayout_CalculateLayout( swigCPtr, width.AsDecimal(), height.AsDecimal(), isLayoutRtl ); + + int count = LayoutChildren.Count; + for( int childIndex = 0; childIndex < count; childIndex++) + { + LayoutItem childLayout = LayoutChildren[childIndex]; + if( childLayout != null ) + { + // Get the frame for the child, start, top, end, bottom. + Vector4 frame = new Vector4(Interop.FlexLayout.FlexLayout_GetNodeFrame(swigCPtr, childIndex ), true); + childLayout.Layout( new LayoutLength(frame.X), new LayoutLength(frame.Y), new LayoutLength(frame.Z), new LayoutLength(frame.W) ); + } + } + } + + } // FLexlayout +} // namesspace Tizen.NUI \ No newline at end of file diff --git a/src/Tizen.NUI/src/public/Layouting/GridLayout.cs b/src/Tizen.NUI/src/public/Layouting/GridLayout.cs new file mode 100755 index 000000000..8d0cd5166 --- /dev/null +++ b/src/Tizen.NUI/src/public/Layouting/GridLayout.cs @@ -0,0 +1,265 @@ +/* Copyright (c) 2019 Samsung Electronics Co., Ltd. +.* +.* Licensed under the Apache License, Version 2.0 (the "License"); +.* you may not use this file except in compliance with the License. +.* You may obtain a copy of the License at +.* +.* http://www.apache.org/licenses/LICENSE-2.0 +.* +.* Unless required by applicable law or agreed to in writing, software +.* distributed under the License is distributed on an "AS IS" BASIS, +.* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +.* See the License for the specific language governing permissions and +.* limitations under the License. +.* +.*/ + +using System; +using System.ComponentModel; +using System.Collections.Generic; +using Tizen.NUI.BaseComponents; + +namespace Tizen.NUI +{ + /// + /// [Draft] This class implements a grid layout + /// + public class GridLayout : LayoutGroup + { + const int AUTO_FIT = -1; + private int _columns = 1; + private int _rows = 1; + private int _totalWidth; + private int _totalHeight; + private int _requestedColumnWidth = 1; + private int _numberOfRequestedColumns; + private GridLocations _locations; + + /// + /// [draft] GridLayout Constructor/> + /// + /// New Grid object. + /// 6 + public GridLayout() + { + _locations = new GridLocations(); + } + + /// + /// [Draft] Get/Set the number of columns in the grid + /// + /// 6 + public int Columns + { + get + { + return GetColumns(); + } + set + { + SetColumns(value); + } + } + + + /// + /// [draft ] Sets the number of columns the GridLayout should have. /> + /// + /// The number of columns. + internal void SetColumns(int columns) + { + _numberOfRequestedColumns = columns; + if( columns != _columns) + { + _columns = Math.Max(1, _columns); + _columns = columns; + RequestLayout(); + } + } + + /// + /// [draft ] Gets the number of columns in the Grid /> + /// + /// The number of columns in the Grid. + internal int GetColumns() + { + return _columns; + } + + void DetermineNumberOfColumns( int availableSpace ) + { + if( _numberOfRequestedColumns == AUTO_FIT ) + { + if( availableSpace > 0 ) + { + // Can only calculate number of columns if a column width has been set + _columns = ( _requestedColumnWidth > 0 ) ? ( availableSpace / _requestedColumnWidth ) : 1; + } + } + } + + /// + /// Measure the layout and its content to determine the measured width and the measured height.
+ ///
+ /// horizontal space requirements as imposed by the parent. + /// vertical space requirements as imposed by the parent. + /// 6 + protected override void OnMeasure( MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec ) + { + var gridWidthMode = widthMeasureSpec.Mode; + var gridHeightMode = heightMeasureSpec.Mode; + int widthSize = (int)widthMeasureSpec.Size.AsRoundedValue(); + int heightSize = (int)heightMeasureSpec.Size.AsRoundedValue(); + + int availableContentWidth; + int availableContentHeight; + + int desiredChildHeight; + int desiredChildWidth; + + Extents gridLayoutPadding = Padding; + + var childCount = LayoutChildren.Count; + + // WIDTH SPECIFICATIONS + + // measure first child and use it's dimensions for layout measurement + + if (childCount > 0) + { + LayoutItem childLayoutItem = LayoutChildren[0]; + View childOwner = childLayoutItem.Owner; + + MeasureChild( childLayoutItem, widthMeasureSpec, heightMeasureSpec ); + desiredChildHeight = (int)childLayoutItem.MeasuredHeight.Size.AsRoundedValue(); + desiredChildWidth = (int)childLayoutItem.MeasuredWidth.Size.AsRoundedValue(); + + // If child has a margin then add it to desired size + Extents childMargin = childLayoutItem.Margin; + desiredChildHeight += childMargin.Top + childMargin.Bottom; + desiredChildWidth += childMargin.Start + childMargin.End; + + _totalWidth = desiredChildWidth * _columns; + + // Include padding for max and min checks + _totalWidth += gridLayoutPadding.Start + gridLayoutPadding.End; + + // Ensure width does not exceed specified at most width or less than mininum width + _totalWidth = Math.Max( _totalWidth, (int)SuggestedMinimumWidth.AsRoundedValue() ); + + // widthMode EXACTLY so grid must be the given width + if( gridWidthMode == MeasureSpecification.ModeType.Exactly || gridWidthMode == MeasureSpecification.ModeType.AtMost ) + { + // In the case of AT_MOST, widthSize is the max limit. + _totalWidth = Math.Min( _totalWidth, widthSize ); + } + + availableContentWidth = _totalWidth - gridLayoutPadding.Start - gridLayoutPadding.End; + widthSize = _totalWidth; + + // HEIGHT SPECIFICATIONS + + // heightMode EXACTLY so grid must be the given height + if( gridHeightMode == MeasureSpecification.ModeType.Exactly || gridHeightMode == MeasureSpecification.ModeType.AtMost ) + { + if( childCount > 0 ) + { + _totalHeight = gridLayoutPadding.Top + gridLayoutPadding.Bottom; + + for( int i = 0; i < childCount; i += _columns ) + { + _totalHeight += desiredChildHeight; + } + + // Ensure ourHeight does not exceed specified at most height + _totalHeight = Math.Min( _totalHeight, heightSize ); + _totalHeight = Math.Max( _totalHeight, (int)SuggestedMinimumHeight.AsRoundedValue() ); + + heightSize = _totalHeight; + } // Child exists + + // In the case of AT_MOST, availableContentHeight is the max limit. + availableContentHeight = heightSize - gridLayoutPadding.Top - gridLayoutPadding.Bottom; + } + else + { + // Grid expands to fit content + + // If number of columns AUTO_FIT then set to 1 column. + _columns = ( _columns > 0 ) ? _columns : 1; + // Calculate numbers of rows, round down result as later check for remainder. + _rows = childCount / _columns; + // If number of cells not cleanly dividable by columns, add another row to house remainder cells. + _rows += ( childCount % _columns > 0 ) ? 1 : 0; + + availableContentHeight = desiredChildHeight * _rows; + } + + // If number of columns not defined + DetermineNumberOfColumns( availableContentWidth ); + + // Locations define the start, end,top and bottom of each cell. + _locations.CalculateLocations(_columns, availableContentWidth, availableContentHeight, childCount); + + } // Children exists + + SetMeasuredDimensions( ResolveSizeAndState( new LayoutLength(widthSize), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK ), + ResolveSizeAndState( new LayoutLength(heightSize), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK ) ); + } + + /// + /// Assign a size and position to each of its children.
+ ///
+ /// This is a new size or position for this layout. + /// Left position, relative to parent. + /// Top position, relative to parent. + /// Right position, relative to parent. + /// Bottom position, relative to parent. + /// 6 + protected override void OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom ) + { + List locations = _locations.GetLocations(); + + Extents gridLayoutPadding = Padding; + Extents childMargins = new Extents(); + + // Margin for all children dependant on if set on first child + if( LayoutChildren.Count > 0 ) + { + childMargins = LayoutChildren[0]?.Margin; + } + + int index = 0; + foreach( LayoutItem childLayout in LayoutChildren ) + { + // for each child + if( childLayout != null ) + { + // Get start and end position of child x1,x2 + int x1 = locations[ index ].Start; + int x2 = locations[ index ].End; + + // Get top and bottom position of child y1,y2 + int y1 = locations[ index ].Top; + int y2 = locations[ index ].Bottom; + + // Offset children by the grids padding if present + x1 += gridLayoutPadding.Start; + x2 += gridLayoutPadding.Start; + y1 += gridLayoutPadding.Top; + y2 += gridLayoutPadding.Top; + + // Offset children by the margin of the first child ( if required ). + x1 += childMargins.Start; + x2 -= childMargins.End; + y1 += childMargins.Top; + y2 -= childMargins.Bottom; + + childLayout.Layout( new LayoutLength(x1), new LayoutLength(y1), + new LayoutLength(x2), new LayoutLength(y2) ); + index++; + } + } + } + } +} diff --git a/src/Tizen.NUI/src/public/Layouting/ILayoutParent.cs b/src/Tizen.NUI/src/public/Layouting/ILayoutParent.cs new file mode 100755 index 000000000..34108235c --- /dev/null +++ b/src/Tizen.NUI/src/public/Layouting/ILayoutParent.cs @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +namespace Tizen.NUI +{ + /// + /// [Draft] + /// Interface that defines a layout Parent. Enables a layout child to access methods on its parent, e.g. Remove (during unparenting) + /// + public interface ILayoutParent + { + /// + /// Add this child to the parent. + /// + /// The layout child to add. + /// 6 + void Add(LayoutItem layoutItem); + + /// + /// Remove this child from the parent + /// + /// The layout child to add. + /// 6 + void Remove(LayoutItem layoutItem); + } +} diff --git a/src/Tizen.NUI/src/public/Layouting/LayoutGroup.cs b/src/Tizen.NUI/src/public/Layouting/LayoutGroup.cs new file mode 100755 index 000000000..c66176851 --- /dev/null +++ b/src/Tizen.NUI/src/public/Layouting/LayoutGroup.cs @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using Tizen.NUI.BaseComponents; +using System.Linq; + +namespace Tizen.NUI +{ + /// + /// [Draft] LayoutGroup class providing container functionality. + /// + public class LayoutGroup : LayoutItem, ILayoutParent + { + /// + /// [Draft] List of child layouts in this container. + /// + /// 6 + protected List LayoutChildren{ get;} // Children of this LayoutGroup + + /// + /// [Draft] Constructor + /// + /// 6 + public LayoutGroup() + { + LayoutChildren = new List(); + } + + /// + /// From ILayoutParent.
+ ///
+ /// 6 + /// LayoutItem to add to the layout group. + public virtual void Add(LayoutItem childLayout) + { + LayoutChildren.Add(childLayout); + childLayout.SetParent(this); + // Child added to use a Add transition. + childLayout.ConditionForAnimation = ConditionForAnimation | TransitionCondition.Add; + // Child's parent sets all other children not being added to a ChangeOnAdd transition. + SetConditionsForAnimationOnLayoutGroup(TransitionCondition.ChangeOnAdd); + OnChildAdd(childLayout); + RequestLayout(); + } + + /// + /// Remove all layout children.
+ ///
+ /// 6 + public void RemoveAll() + { + foreach( LayoutItem childLayout in LayoutChildren ) + { + childLayout.ConditionForAnimation = ConditionForAnimation | TransitionCondition.Remove; + childLayout.Owner = null; + } + LayoutChildren.Clear(); + // todo ensure child LayoutItems are still not parented to this group. + RequestLayout(); + } + + /// + /// From ILayoutParent + /// + /// LayoutItem to remove from the layout group. + /// 6 + public virtual void Remove(LayoutItem layoutItem) + { + bool childRemoved = false; + foreach( LayoutItem childLayout in LayoutChildren.ToList() ) + { + if( childLayout == layoutItem ) + { + Window.Instance.LayoutController.AddToRemovalStack(childLayout); + LayoutChildren.Remove(childLayout); + childLayout.ConditionForAnimation = childLayout.ConditionForAnimation | TransitionCondition.Remove; + // Add LayoutItem to the transition stack so can animate it out. + Window.Instance.LayoutController.AddTransitionDataEntry(new LayoutData(layoutItem, ConditionForAnimation, 0,0,0,0)); + // Reset condition for animation ready for next transition when required. + // SetFrame usually would do this but this LayoutItem is being removed. + childLayout.ConditionForAnimation = TransitionCondition.Unspecified; + childRemoved = true; + } + } + if (childRemoved) + { + // If child removed then set all siblings not being added to a ChangeOnRemove transition. + SetConditionsForAnimationOnLayoutGroup(TransitionCondition.ChangeOnRemove); + } + RequestLayout(); + } + + // Attaches to View ChildAdded signal so called when a View is added to a view. + private void AddChildToLayoutGroup(View child) + { + // Only give children a layout if their parent is an explicit container or a pure View. + // Pure View meaning not derived from a View, e.g a Legacy container. + // layoutSet flag is true when the View became a layout using the set Layout API opposed to automatically due to it's parent. + // First time the set Layout API is used by any View the Window no longer has layoutingDisabled. + + // If child already has a Layout then don't change it. + if (! View.layoutingDisabled && (null == child.Layout)) + { + // Only wrap View with a Layout if a child a pure View or Layout explicitly set on this Layout + if ((true == Owner.layoutSet || GetType() == typeof(View))) + { + // If child of this layout is a pure View then assign it a LayoutGroup + // If the child is derived from a View then it may be a legacy or existing container hence will do layouting itself. + if (child.GetType() == typeof(View)) + { + child.Layout = new LayoutGroup(); + } + else + { + // Adding child as a leaf, layouting will not propagate past this child. + // Legacy containers will be a LayoutItems too and layout their children how they wish. + child.Layout = new LayoutItem(); + } + } + } + else + { + // Add child layout to this LayoutGroup (Setting parent in the process) + if(child.Layout != null) + { + Add(child.Layout); + } + } + // Parent transitions are not attached to children. + } + + /// + /// If the child has a layout then it is removed from the parent layout. + /// + /// Child View to remove. + internal void RemoveChildFromLayoutGroup(View child) + { + Debug.Assert(child.Layout !=null); + Remove(child.Layout); + } + + /// + /// Set all children in a LayoutGroup to the supplied condition. + /// Children with Add or Remove conditions should not be changed. + /// + private void SetConditionsForAnimationOnLayoutGroup( TransitionCondition conditionToSet) + { + foreach( LayoutItem childLayout in LayoutChildren ) + { + switch( conditionToSet ) + { + case TransitionCondition.ChangeOnAdd : + { + // If other children also being added (TransitionCondition.Add) then do not change their + // conditions, Continue to use their Add transitions. + if (childLayout.ConditionForAnimation.HasFlag(TransitionCondition.Add)) + { + break; // Child being Added so don't update it's condition + } + else + { + // Set siblings for the child being added to use the ChangeOnAdd transition. + childLayout.ConditionForAnimation = TransitionCondition.ChangeOnAdd; + } + break; + } + case TransitionCondition.ChangeOnRemove : + { + if (childLayout.ConditionForAnimation.HasFlag(TransitionCondition.Remove)) + { + break; // Child being Removed so don't update it's condition + } + else + { + childLayout.ConditionForAnimation = TransitionCondition.ChangeOnRemove; + } + break; + } + case TransitionCondition.LayoutChanged : + { + childLayout.ConditionForAnimation = TransitionCondition.LayoutChanged; + break; + } + } + } + + } + + /// + /// Callback for View.ChildAdded event + /// + /// The object triggering the event. + /// Arguments from the event. + void OnChildAddedToOwner(object sender, View.ChildAddedEventArgs childAddedEvent) + { + AddChildToLayoutGroup(childAddedEvent.Added); + } + + /// + /// Callback for View.ChildRemoved event + /// + /// The object triggering the event. + /// Arguments from the event. + void OnChildRemovedFromOwner(object sender, View.ChildRemovedEventArgs childRemovedEvent) + { + RemoveChildFromLayoutGroup(childRemovedEvent.Removed); + } + + /// + /// Calculate the right measure spec for this child. + /// Does the hard part of MeasureChildren: figuring out the MeasureSpec to + /// pass to a particular child. This method figures out the right MeasureSpec + /// for one dimension (height or width) of one child view.
+ ///
+ /// The requirements for this view. MeasureSpecification. + /// The padding of this view for the current dimension and margins, if applicable. LayoutLength. + /// How big the child wants to be in the current dimension. LayoutLength. + /// a MeasureSpec for the child. + public static MeasureSpecification GetChildMeasureSpecification(MeasureSpecification parentMeasureSpec, LayoutLength padding, LayoutLength childDimension) + { + MeasureSpecification.ModeType specMode = parentMeasureSpec.Mode; + MeasureSpecification.ModeType resultMode = MeasureSpecification.ModeType.Unspecified; + LayoutLength resultSize = new LayoutLength(Math.Max( 0.0f, (parentMeasureSpec.Size.AsDecimal() - padding.AsDecimal() ) )); // reduce available size by the owners padding + + switch( specMode ) + { + // Parent has imposed an exact size on us + case MeasureSpecification.ModeType.Exactly: + { + if ((int)childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent) + { + // Child wants to be our size. So be it. + resultMode = MeasureSpecification.ModeType.Exactly; + } + else if ((int)childDimension.AsRoundedValue() == LayoutParamPolicies.WrapContent) + { + // Child wants to determine its own size. It can't be + // bigger than us. + resultMode = MeasureSpecification.ModeType.AtMost; + } + else + { + resultSize = childDimension; + resultMode = MeasureSpecification.ModeType.Exactly; + } + + break; + } + + // Parent has imposed a maximum size on us + case MeasureSpecification.ModeType.AtMost: + { + if (childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent) + { + // Child wants to be our size, but our size is not fixed. + // Constrain child to not be bigger than us. + resultMode = MeasureSpecification.ModeType.AtMost; + } + else if (childDimension.AsRoundedValue() == LayoutParamPolicies.WrapContent) + { + // Child wants to determine its own size. It can't be + // bigger than us. + resultMode = MeasureSpecification.ModeType.AtMost; + } + else + { + // Child wants a specific size... so be it + resultSize = childDimension + padding; + resultMode = MeasureSpecification.ModeType.Exactly; + } + + break; + } + + // Parent asked to see how big we want to be + case MeasureSpecification.ModeType.Unspecified: + { + + if ((childDimension.AsRoundedValue() == LayoutParamPolicies.MatchParent)) + { + // Child wants to be our size... find out how big it should be + resultMode = MeasureSpecification.ModeType.Unspecified; + } + else if (childDimension.AsRoundedValue() == (LayoutParamPolicies.WrapContent)) + { + // Child wants to determine its own size.... find out how big + // it should be + resultMode = MeasureSpecification.ModeType.Unspecified; + } + else + { + // Child wants a specific size... let him have it + resultSize = childDimension + padding; + resultMode = MeasureSpecification.ModeType.Exactly; + } + break; + } + } // switch + + return new MeasureSpecification( resultSize, resultMode ); + } + + /// + /// Measure the layout and its content to determine the measured width and the measured height.
+ /// If this method is overridden, it is the subclass's responsibility to make + /// sure the measured height and width are at least the layout's minimum height + /// and width.
+ ///
+ /// horizontal space requirements as imposed by the parent. + /// vertical space requirements as imposed by the parent. + /// 6 + protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) + { + LayoutLength measuredWidth = new LayoutLength(0.0f); + LayoutLength measuredHeight = new LayoutLength(0.0f); + + // Layout takes size of largest child width and largest child height dimensions + foreach( LayoutItem childLayout in LayoutChildren ) + { + if( childLayout != null ) + { + MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec ); + LayoutLength childWidth = new LayoutLength(childLayout.MeasuredWidth.Size); + LayoutLength childHeight = new LayoutLength( childLayout.MeasuredHeight.Size); + + Extents childMargin = childLayout.Margin; + measuredWidth = new LayoutLength(Math.Max( measuredWidth.AsDecimal(), childWidth.AsDecimal() + childMargin.Start + childMargin.End)); + measuredHeight = new LayoutLength(Math.Max( measuredHeight.AsDecimal(), childHeight.AsDecimal() + childMargin.Top + childMargin.Bottom)); + } + } + + if( 0 == LayoutChildren.Count ) + { + // Must be a leaf as has no children + measuredWidth = GetDefaultSize( SuggestedMinimumWidth, widthMeasureSpec ); + measuredHeight = GetDefaultSize( SuggestedMinimumHeight, heightMeasureSpec ); + } + + SetMeasuredDimensions( new MeasuredSize( measuredWidth, MeasuredSize.StateType.MeasuredSizeOK ), + new MeasuredSize( measuredHeight, MeasuredSize.StateType.MeasuredSizeOK ) ); + } + + /// + /// Called from Layout() when this layout should assign a size and position to each of its children.
+ /// Derived classes with children should override this method and call Layout() on each of their children.
+ ///
+ /// This is a new size or position for this layout. + /// Left position, relative to parent. + /// Top position, relative to parent. + /// Right position, relative to parent. + /// Bottom position, relative to parent. + /// 6 + protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) + { + foreach( LayoutItem childLayout in LayoutChildren ) + { + if( childLayout !=null ) + { + // Use position if explicitly set to child otherwise will be top left. + var childLeft = new LayoutLength( childLayout.Owner.Position2D.X ); + var childTop = new LayoutLength( childLayout.Owner.Position2D.Y ); + + View owner = Owner; + + if ( owner ) + { + // Margin and Padding only supported when child anchor point is TOP_LEFT. + if ( owner.PivotPoint == PivotPoint.TopLeft || ( owner.PositionUsesPivotPoint == false ) ) + { + childLeft = childLeft + owner.Padding.Start + childLayout.Margin.Start; + childTop = childTop + owner.Padding.Top + childLayout.Margin.Top; + } + } + childLayout.Layout( childLeft, childTop, childLeft + childLayout.MeasuredWidth.Size, childTop + childLayout.MeasuredHeight.Size ); + } + } + } + + /// + /// Overridden method called when the layout is attached to an owner.
+ ///
+ /// 6 + protected override void OnAttachedToOwner() + { + // Layout takes ownership of it's owner's children. + foreach (View view in Owner.Children) + { + AddChildToLayoutGroup(view); + } + + // Connect to owner ChildAdded signal. + Owner.ChildAdded += OnChildAddedToOwner; + + // Removing Child from the owners View will directly call the LayoutGroup removal API. + } + + // Virtual Methods that can be overridden by derived classes. + + /// + /// Callback when child is added to container.
+ /// Derived classes can use this to set their own child properties on the child layout's owner.
+ ///
+ /// The Layout child. + /// 6 + protected virtual void OnChildAdd(LayoutItem child) + { + } + + /// + /// Callback when child is removed from container.
+ ///
+ /// The Layout child. + /// 6 + protected virtual void OnChildRemove(LayoutItem child) + { + } + + /// + /// Ask all of the children of this view to measure themselves, taking into + /// account both the MeasureSpec requirements for this view and its padding.
+ /// The heavy lifting is done in GetChildMeasureSpec.
+ ///
+ /// The width requirements for this view. + /// The height requirements for this view. + /// 6 + protected virtual void MeasureChildren(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) + { + foreach( LayoutItem childLayout in LayoutChildren ) + { + MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec ); + } + } + + /// + /// Ask one of the children of this view to measure itself, taking into + /// account both the MeasureSpec requirements for this view and its padding.
+ /// The heavy lifting is done in GetChildMeasureSpecification.
+ ///
+ /// The child to measure. + /// The width requirements for this view. + /// The height requirements for this view. + /// 6 + protected virtual void MeasureChild(LayoutItem child, MeasureSpecification parentWidthMeasureSpec, MeasureSpecification parentHeightMeasureSpec) + { + View childOwner = child.Owner; + + Extents padding = child.Padding; // Padding of this layout's owner, not of the child being measured. + + MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification( parentWidthMeasureSpec, + new LayoutLength(padding.Start + padding.End ), + new LayoutLength(childOwner.WidthSpecification) ); + + MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification( parentHeightMeasureSpec, + new LayoutLength(padding.Top + padding.Bottom), + new LayoutLength(childOwner.HeightSpecification) ); + + child.Measure( childWidthMeasureSpec, childHeightMeasureSpec ); + } + + /// + /// Ask one of the children of this view to measure itself, taking into + /// account both the MeasureSpec requirements for this view and its padding.
+ /// and margins. The child must have MarginLayoutParams The heavy lifting is + /// done in GetChildMeasureSpecification.
+ ///
+ /// The child to measure. + /// The width requirements for this view. + /// Extra space that has been used up by the parent horizontally (possibly by other children of the parent). + /// The height requirements for this view. + /// Extra space that has been used up by the parent vertically (possibly by other children of the parent). + /// 6 + protected virtual void MeasureChildWithMargins(LayoutItem child, MeasureSpecification parentWidthMeasureSpec, LayoutLength widthUsed, MeasureSpecification parentHeightMeasureSpec, LayoutLength heightUsed) + { + View childOwner = child.Owner; + int desiredWidth = childOwner.WidthSpecification; + int desiredHeight = childOwner.HeightSpecification; + + Extents padding = child.Padding; // Padding of this layout's owner, not of the child being measured. + + MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification( parentWidthMeasureSpec, + new LayoutLength( padding.Start + padding.End ) + + widthUsed, new LayoutLength(desiredWidth) ); + + + MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification( parentHeightMeasureSpec, + new LayoutLength( padding.Top + padding.Bottom )+ + heightUsed, new LayoutLength(desiredHeight) ); + + child.Measure( childWidthMeasureSpec, childHeightMeasureSpec ); + } + } +} \ No newline at end of file diff --git a/src/Tizen.NUI/src/public/Layouting/LayoutItem.cs b/src/Tizen.NUI/src/public/Layouting/LayoutItem.cs new file mode 100755 index 000000000..a4518fb7a --- /dev/null +++ b/src/Tizen.NUI/src/public/Layouting/LayoutItem.cs @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +using System; +using System.Diagnostics; +using Tizen.NUI.BaseComponents; + +namespace Tizen.NUI +{ + + [FlagsAttribute] + enum LayoutFlags : short + { + None = 0, + ForceLayout = 1, + LayoutRequired = 2, + MeasuredDimensionSet = 4 + }; + + /// + /// [Draft] Base class for layouts. It is used to layout a View + /// It can be laid out by a LayoutGroup. + /// + public class LayoutItem + { + static bool LayoutDebugFrameData = false; // Debug flag + private MeasureSpecification OldWidthMeasureSpec; // Store measure specification to compare against later + private MeasureSpecification OldHeightMeasureSpec;// Store measure specification to compare against later + + private LayoutFlags Flags = LayoutFlags.None; + + private ILayoutParent Parent; + + LayoutData _layoutPositionData; + + private Extents _padding; + private Extents _margin; + + /// + /// [Draft] Condition event that is causing this Layout to transition. + /// + internal TransitionCondition ConditionForAnimation{get; set;} + + /// + /// [Draft] The View that this Layout has been assigned to. + /// + /// 6 + public View Owner{get; set;} // Should not keep a View alive. + + /// + /// [Draft] Margin for this LayoutItem + /// + /// 6 + public Extents Margin + { + get + { + return _margin; + } + set + { + _margin = value; + RequestLayout(); + } + } + + /// + /// [Draft] Padding for this LayoutItem + /// + /// 6 + public Extents Padding + { + get + { + return _padding; + } + set + { + _padding = value; + RequestLayout(); + } + } + + /// + /// [Draft] Constructor + /// + /// 6 + public LayoutItem() + { + Initialize(); + } + + /// + /// [Draft] Set parent to this layout. + /// + /// Parent to set on this Layout. + internal void SetParent( ILayoutParent parent) + { + Parent = parent as LayoutGroup; + } + + /// + /// Unparent this layout from it's owner, and remove any layout children in derived types.
+ ///
+ internal void Unparent() + { + // Enable directly derived types to first remove children + OnUnparent(); + + // Remove myself from parent + Parent?.Remove( this ); + + // Remove parent reference + Parent = null; + + // Lastly, clear layout from owning View. + Owner?.ResetLayout(); + } + + private void Initialize() + { + _layoutPositionData = new LayoutData(this,TransitionCondition.Unspecified,0,0,0,0); + _padding = new Extents(0,0,0,0); + _margin = new Extents(0,0,0,0); + } + + /// + /// Initialize the layout and allow derived classes to also perform any operations + /// + /// Owner of this Layout. + internal void AttachToOwner(View owner) + { + // Assign the layout owner. + Owner = owner; + OnAttachedToOwner(); + // Add layout to parent layout if a layout container + View parent = Owner.GetParent() as View; + (parent?.Layout as LayoutGroup)?.Add( this ); + + // If Add or ChangeOnAdd then do not update condition + if (ConditionForAnimation.Equals(TransitionCondition.Unspecified)) + { + ConditionForAnimation = TransitionCondition.LayoutChanged; + } + } + + /// + /// This is called to find out how big a layout should be.
+ /// The parent supplies constraint information in the width and height parameters.
+ /// The actual measurement work of a layout is performed in OnMeasure called by this + /// method. Therefore, only OnMeasure can and must be overridden by subclasses.
+ ///
+ /// Horizontal space requirements as imposed by the parent. + /// Vertical space requirements as imposed by the parent. + /// 6 + public void Measure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) + { + // Check if relayouting is required. + bool specChanged = (widthMeasureSpec.Size != OldWidthMeasureSpec.Size) || + (heightMeasureSpec.Size != OldHeightMeasureSpec.Size) || + (widthMeasureSpec.Mode != OldWidthMeasureSpec.Mode) || + (heightMeasureSpec.Mode != OldHeightMeasureSpec.Mode); + + bool isSpecExactly = (widthMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly) && + (heightMeasureSpec.Mode == MeasureSpecification.ModeType.Exactly); + + bool matchesSpecSize = (MeasuredWidth.Size == widthMeasureSpec.Size) && + (MeasuredHeight.Size == heightMeasureSpec.Size); + + bool needsLayout = specChanged && ( !isSpecExactly || !matchesSpecSize); + needsLayout = needsLayout || ((Flags & LayoutFlags.ForceLayout) == LayoutFlags.ForceLayout); + + if (needsLayout) + { + OnMeasure(widthMeasureSpec, heightMeasureSpec); + Flags = Flags | LayoutFlags.LayoutRequired; + Flags &= ~LayoutFlags.ForceLayout; + } + OldWidthMeasureSpec = widthMeasureSpec; + OldHeightMeasureSpec = heightMeasureSpec; + } + + /// + /// Assign a size and position to a layout and all of its descendants.
+ /// This is the second phase of the layout mechanism. (The first is measuring). In this phase, each parent + /// calls layout on all of its children to position them. This is typically done using the child
+ /// measurements that were stored in the measure pass.
+ ///
+ /// Left position, relative to parent. + /// Top position, relative to parent. + /// Right position, relative to parent. + /// Bottom position, relative to parent. + /// 6 + public void Layout(LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) + { + bool changed = SetFrame(left.AsRoundedValue(), + top.AsRoundedValue(), + right.AsRoundedValue(), + bottom.AsRoundedValue()); + + // Check if Measure needed before Layouting + if (changed || ((Flags & LayoutFlags.LayoutRequired) == LayoutFlags.LayoutRequired)) + { + OnLayout(changed, left, top, right, bottom); + // Clear flag + Flags &= ~LayoutFlags.LayoutRequired; + } + } + + /// + /// Utility to return a default size.
+ /// Uses the supplied size if the MeasureSpecification imposed no constraints. Will get larger if allowed by the + /// MeasureSpecification.
+ ///
+ /// Default size for this layout. + /// Constraints imposed by the parent. + /// The size this layout should be. + /// 6 + public static LayoutLength GetDefaultSize(LayoutLength size, MeasureSpecification measureSpecification) + { + LayoutLength result = size; + MeasureSpecification.ModeType specMode = measureSpecification.Mode; + LayoutLength specSize = measureSpecification.Size; + + switch (specMode) + { + case MeasureSpecification.ModeType.Unspecified: + { + result = size; + break; + } + case MeasureSpecification.ModeType.AtMost: + { + // Ensure the default size does not exceed the spec size unless the default size is 0. + // Another container could provide a default size of 0. + + // Do not set size to 0, use specSize in this case as could be a legacy container + if( ( size.AsDecimal() < specSize.AsDecimal()) && ( size.AsDecimal() > 0) ) + { + result = size; + } + else + { + result = specSize; + } + break; + } + case MeasureSpecification.ModeType.Exactly: + { + result = specSize; + break; + } + } + + return result; + } + + /// + /// Get the Layouts parent + /// + /// Layout parent with an LayoutParent interface + /// 6 + public ILayoutParent GetParent() + { + return Parent; + } + + /// + /// Request that this layout is re-laid out.
+ /// This will make this layout and all it's parent layouts dirty.
+ ///
+ /// 6 + public void RequestLayout() + { + Flags = Flags | LayoutFlags.ForceLayout; + Window.Instance.LayoutController.RequestLayout(this); + } + + /// + /// Predicate to determine if this layout has been requested to re-layout.
+ ///
+ + internal bool LayoutRequested + { + get + { + return ( Flags & LayoutFlags.ForceLayout) == LayoutFlags.ForceLayout; + } + } + + /// + /// Get the measured width (without any measurement flags).
+ /// This method should be used only during measurement and layout calculations.
+ ///
+ /// 6 + public MeasuredSize MeasuredWidth{ get; set; } = new MeasuredSize( new LayoutLength(-3), MeasuredSize.StateType.MeasuredSizeOK); + + /// + /// Get the measured height (without any measurement flags).
+ /// This method should be used only during measurement and layout calculations.
+ ///
+ /// 6 + public MeasuredSize MeasuredHeight{ get; set; } = new MeasuredSize( new LayoutLength(-3), MeasuredSize.StateType.MeasuredSizeOK); + + /// + /// Returns the suggested minimum width that the layout should use.
+ /// This returns the maximum of the layout's minimum width and the owner's natural width.
+ ///
+ /// 6 + public LayoutLength SuggestedMinimumWidth + { + get + { + int naturalWidth = Owner.NaturalSize2D.Width; + return new LayoutLength(Math.Max( MinimumWidth.AsDecimal(), naturalWidth )); + } + } + + /// + /// Returns the suggested minimum height that the layout should use.
+ /// This returns the maximum of the layout's minimum height and the owner's natural height.
+ ///
+ /// 6 + public LayoutLength SuggestedMinimumHeight + { + get + { + int naturalHeight = Owner.NaturalSize2D.Height; + return new LayoutLength(Math.Max( MinimumHeight.AsDecimal(), naturalHeight )); + } + } + + /// + /// Sets the minimum width of the layout.
+ /// It is not guaranteed the layout will be able to achieve this minimum width (for example, if its parent + /// layout constrains it with less available width).
+ /// 1. if the owner's View.WidthSpecification has exact value, then that value overrides the minimum size.
+ /// 2. If the owner's View.WidthSpecification is set to View.LayoutParamPolicies.WrapContent, then the view's width is set based on the suggested minimum width. (@see GetSuggestedMinimumWidth()).
+ /// 3. If the owner's View.WidthSpecification is set to View.LayoutParamPolicies.MatchParent, then the parent width takes precedence over the minimum width.
+ ///
+ internal LayoutLength MinimumWidth {get; set;} + + /// + /// Sets the minimum height of the layout.
+ /// It is not guaranteed the layout will be able to achieve this minimum height (for example, if its parent + /// layout constrains it with less available height).
+ /// 1. if the owner's View.HeightSpecification has exact value, then that value overrides the minimum size.
+ /// 2. If the owner's View.HeightSpecification is set to View.LayoutParamPolicies.WrapContent, then the view's height is set based on the suggested minimum height. (@see GetSuggestedMinimumHeight()).
+ /// 3. If the owner's View.HeightSpecification is set to View.LayoutParamPolicies.MatchParent, then the parent height takes precedence over the minimum height.
+ ///
+ internal LayoutLength MinimumHeight {get; set;} + + /// + /// Utility to reconcile a desired size and state, with constraints imposed by a MeasureSpecification. + /// + /// How big the layout wants to be. + /// Constraints imposed by the parent. + /// Size information bit mask for the layout's children. + /// A measured size, which may indicate that it is too small. + /// 6 + protected MeasuredSize ResolveSizeAndState( LayoutLength size, MeasureSpecification measureSpecification, MeasuredSize.StateType childMeasuredState ) + { + var specMode = measureSpecification.Mode; + LayoutLength specSize = measureSpecification.Size; + MeasuredSize result = new MeasuredSize( size, childMeasuredState); + + switch( specMode ) + { + case MeasureSpecification.ModeType.AtMost: + { + if (specSize.AsRoundedValue() < size.AsRoundedValue()) + { + result = new MeasuredSize( specSize, MeasuredSize.StateType.MeasuredSizeTooSmall); + } + break; + } + + case MeasureSpecification.ModeType.Exactly: + { + result.Size = specSize; + break; + } + + case MeasureSpecification.ModeType.Unspecified: + default: + { + break; + } + } + return result; + } + + /// + /// This method must be called by OnMeasure(MeasureSpec,MeasureSpec) to store the measured width and measured height. + /// + /// The measured width of this layout. + /// The measured height of this layout. + /// 6 + protected void SetMeasuredDimensions( MeasuredSize measuredWidth, MeasuredSize measuredHeight ) + { + MeasuredWidth = measuredWidth; + MeasuredHeight = measuredHeight; + Flags = Flags | LayoutFlags.MeasuredDimensionSet; + } + + /// + /// Measure the layout and its content to determine the measured width and the + /// measured height.
+ /// The base class implementation of measure defaults to the background size, + /// unless a larger size is allowed by the MeasureSpec. Subclasses should + /// override to provide better measurements of their content.
+ /// If this method is overridden, it is the subclass's responsibility to make sure the + /// measured height and width are at least the layout's minimum height and width.
+ ///
+ /// horizontal space requirements as imposed by the parent. + /// vertical space requirements as imposed by the parent. + /// 6 + protected virtual void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) + { + // GetDefaultSize will limit the MeasureSpec to the suggested minimumWidth and minimumHeight + SetMeasuredDimensions( GetDefaultSize( SuggestedMinimumWidth, widthMeasureSpec ), + GetDefaultSize( SuggestedMinimumHeight, heightMeasureSpec ) ); + } + + /// + /// Called from Layout() when this layout should assign a size and position to each of its children.
+ /// Derived classes with children should override this method and call Layout() on each of their children.
+ ///
+ /// This is a new size or position for this layout. + /// Left position, relative to parent. + /// Top position, relative to parent. + /// Right position, relative to parent. + /// Bottom position, relative to parent. + /// 6 + protected virtual void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) + { + } + + /// + /// Virtual method to allow derived classes to remove any children before it is removed from + /// its parent. + /// + /// 6 + protected virtual void OnUnparent() + { + } + + /// + /// Virtual method called when this Layout is attached to it's owner. + /// Allows derived layouts to take ownership of child Views and connect to any Owner signals required. + /// + /// 6 + protected virtual void OnAttachedToOwner() + { + } + + private bool SetFrame(float left, float top, float right, float bottom) + { + bool changed = false; + + if ( _layoutPositionData.Left != left || + _layoutPositionData.Right != right || + _layoutPositionData.Top != top || + _layoutPositionData.Bottom != bottom ) + { + changed = true; + + float oldWidth = _layoutPositionData.Right - _layoutPositionData.Left; + float oldHeight = _layoutPositionData.Bottom - _layoutPositionData.Top; + float newWidth = right - left; + float newHeight = bottom - top; + bool sizeChanged = ( newWidth != oldWidth ) || ( newHeight != oldHeight ); + + // Set condition to layout changed as currently unspecified. Add, Remove would have specified a condition. + if (ConditionForAnimation.Equals(TransitionCondition.Unspecified)) + { + ConditionForAnimation = TransitionCondition.LayoutChanged; + } + + // Store new layout position data + _layoutPositionData = new LayoutData(this, ConditionForAnimation, left, top, right, bottom); + + Debug.WriteLineIf( LayoutDebugFrameData, "LayoutItem FramePositionData View:" + _layoutPositionData.Item.Owner.Name + + " left:" + _layoutPositionData.Left + + " top:" + _layoutPositionData.Top + + " right:" + _layoutPositionData.Right + + " bottom:" + _layoutPositionData.Bottom ); + + Window.Instance.LayoutController.AddTransitionDataEntry(_layoutPositionData); + + // Reset condition for animation ready for next transition when required. + ConditionForAnimation = TransitionCondition.Unspecified; + } + + return changed; + } + } +} diff --git a/src/Tizen.NUI/src/public/Layouting/LayoutLength.cs b/src/Tizen.NUI/src/public/Layouting/LayoutLength.cs new file mode 100755 index 000000000..8b3b07e09 --- /dev/null +++ b/src/Tizen.NUI/src/public/Layouting/LayoutLength.cs @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +using System; +using System.ComponentModel; +using Tizen.NUI.BaseComponents; + +namespace Tizen.NUI +{ + /// + /// [Draft] A type that represents a layout length. Currently, this implies pixels, but could be extended to handle device dependant sizes, etc. + /// + public struct LayoutLength + { + private float _value; + + /// + /// [Draft] Constructor from an int + /// + /// Int to initialize with. + /// 6 + public LayoutLength(int value) + { + _value = value; + } + + /// + /// [Draft] Constructor from a float + /// + /// Float to initialize with. + /// 6 + public LayoutLength(float value) + { + _value = value; + } + + /// + /// [Draft] Constructor from a LayoutLength + /// + /// LayoutLength object to initialize with. + /// 6 + public LayoutLength(LayoutLength layoutLength) + { + _value = layoutLength._value; + } + + /// + /// [Draft] Return value as rounded value (whole number), best used as final output + /// + /// The layout length value as a rounded whole number. + /// 6 + public float AsRoundedValue() + { + return (float)Math.Round((decimal)_value, MidpointRounding.AwayFromZero); + } + + /// + /// [Draft] Return value as the raw decimal value, best used for calculations + /// + /// The layout length value as the raw decimal value. + /// 6 + public float AsDecimal() + { + return _value; + } + + /// + /// [Draft] The == operator. + /// + /// The first value. + /// The second value + /// true if LayoutLengths are equal + /// 6 + public static bool operator ==(LayoutLength arg1, LayoutLength arg2) + { + return arg1.Equals(arg2); + } + + /// + /// [Draft] The != operator. + /// + /// The first value. + /// The second value + /// true if LayoutLengths are not equal + /// 6 + public static bool operator !=(LayoutLength arg1, LayoutLength arg2) + { + return !arg1.Equals(arg2); + } + + /// + /// Determines whether the specified object is equal to the current object. + /// + /// The object to compare with the current object. + /// true if equal LayoutLength, else false. + /// 6 + public override bool Equals(object obj) + { + if (obj is LayoutLength) + { + return this.Equals((LayoutLength)obj); + } + return false; + } + + /// + /// Determines whether the specified object is equal to the current object. + /// + /// The LayoutLength to compare with the current LayoutLength. + /// true if equal LayoutLengths, else false. + /// 6 + public bool Equals(LayoutLength layoutLength) + { + return (Math.Abs(_value - layoutLength._value ) <= float.Epsilon); + } + + /// + /// A hash code for the current object. + /// + /// Calculated hash code. + /// 6 + public override int GetHashCode() + { + return (int)Math.Ceiling(_value); + } + + /// + /// The addition operator. + /// + /// The first value. + /// The second value. + /// The LayoutLength containing the result of the addition. + /// 6 + public static LayoutLength operator +(LayoutLength arg1, LayoutLength arg2) + { + return new LayoutLength( arg1._value + arg2._value ); + } + + /// + /// The addition operator. + /// + /// The first value. + /// The second value. + /// The LayoutLength containing the result of the addition. + /// 6 + public static LayoutLength operator +(LayoutLength arg1, int arg2) + { + return new LayoutLength(arg1._value + (float)arg2); + } + + /// + /// The subtraction operator. + /// + /// The first value. + /// The second value. + /// The LayoutLength containing the result of the subtraction. + /// 6 + public static LayoutLength operator -(LayoutLength arg1, LayoutLength arg2) + { + return new LayoutLength(arg1._value - arg2._value); + } + + /// + /// The subtraction operator. + /// + /// The first value. + /// The second value. + /// The LayoutLength containing the result of the subtraction. + /// 6 + public static LayoutLength operator -(LayoutLength arg1, int arg2) + { + return new LayoutLength(arg1._value - (float)arg2); + } + + /// + /// The multiplication operator. + /// + /// The first value. + /// The second value. + /// The LayoutLength containing the result of the multiplication. + /// 6 + public static LayoutLength operator *(LayoutLength arg1, LayoutLength arg2) + { + return new LayoutLength(arg1._value * arg2._value); + } + + /// + /// Th multiplication operator. + /// + /// The first value. + /// The int value to scale the LayoutLength. + /// The LayoutLength containing the result of the scaling. + /// 6 + public static LayoutLength operator *(LayoutLength arg1, int arg2) + { + return new LayoutLength(arg1._value * arg2); + } + + /// + /// The division operator. + /// + /// The first value. + /// The second value. + /// The LayoutLength containing the result of the division. + /// 6 + public static LayoutLength operator /(LayoutLength arg1, LayoutLength arg2) + { + return new LayoutLength(arg1._value / arg2._value); + } + + /// + /// Th division operator. + /// + /// The first value. + /// The int value to scale the vector by. + /// The LayoutLength containing the result of the scaling. + /// 6 + public static LayoutLength operator /(LayoutLength arg1, int arg2) + { + return new LayoutLength(arg1._value / (float)arg2); + } + } +} diff --git a/src/Tizen.NUI/src/public/Layouting/LayoutTransition.cs b/src/Tizen.NUI/src/public/Layouting/LayoutTransition.cs new file mode 100755 index 000000000..5f23f4f0d --- /dev/null +++ b/src/Tizen.NUI/src/public/Layouting/LayoutTransition.cs @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +using System.Collections.Generic; +using System; + +namespace Tizen.NUI +{ + /// + /// Define a List of LayoutTransitions + /// + /// 6 + public class TransitionList : List {} + + /// + /// The conditions for transitions. + /// + /// 6 + [FlagsAttribute] public enum TransitionCondition + { + /// + /// Default when a condition has not been set. + /// + /// 6 + Unspecified = 0, + /// + /// Animate changing layout to another layout. + /// + /// 6 + + LayoutChanged = 1, + /// + /// Animate adding item. + /// + /// 6 + + Add = 2, + /// + /// Animate removing item. + /// + /// 6 + + Remove = 4, + /// + /// Animation when an item changes due to a being added. + /// + /// 6 + + ChangeOnAdd = 8, + /// + /// Animation when an item changes due to a being removed. + /// + /// 6 + + ChangeOnRemove = 16 + } + + /// + /// The properties that can be animated. + /// + /// 6 + public enum AnimatableProperties + { + /// + /// Position property. + /// + /// 6 + + Position, + /// + /// Size property. + /// + /// 6 + + Size, + /// + /// Opacity property. + /// + /// 6 + + Opacity + } + + /// + /// Parts of the transition that can be configured to provide a custom effect. + /// + /// 6 + public class TransitionComponents + { + /// + /// TransitionComponents default constructor. + /// + /// 6 + public TransitionComponents() + { + Delay = 0; + Duration = 100; + AlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.Linear); + } + + /// + /// TransitionComponents constructor. Stores delay, duration and AlphaFunction. + /// + /// The delay before the animator starts. + /// the duration of the animator. + /// alpha function to use . + /// 6 + + public TransitionComponents(int delay, int duration, AlphaFunction alphaFunction) + { + Delay = delay; + Duration = duration; + AlphaFunction = alphaFunction; + } + + /// + /// Get, Set the time transition should execute for . Milliseconds. + /// + /// 6 + public int Duration; + /// + /// Get, Set the delay before the transition executes. Milliseconds. + /// + /// 6 + public int Delay; + /// + /// Get, Set the function to alter the transition path over time. + /// + /// 6 + public AlphaFunction AlphaFunction; + } + + /// + /// LayoutTransition stores the animation setting for a transition conidition. + /// + public class LayoutTransition + { + /// + /// LayoutTransition default constructor. + /// + /// 6 + public LayoutTransition() + { + Condition = TransitionCondition.Unspecified; + AnimatableProperty = AnimatableProperties.Position; + Animator = null; + TargetValue = 0; + } + /// + /// LayoutTransition constructor. + /// + /// The animatable condition. + /// the property to animate. + /// target value of the property. + /// Components to define the animator. + /// 6 + public LayoutTransition( TransitionCondition condition, + AnimatableProperties animatableProperty, + object targetValue, + TransitionComponents animator) + { + Condition = condition; + AnimatableProperty = animatableProperty; + Animator = animator; + TargetValue = targetValue; + } + + /// + /// Condition for this Transition + /// + /// 6 + + public TransitionCondition Condition{get; set;} + /// + /// Property to animate. + /// + /// 6 + + public AnimatableProperties AnimatableProperty{get; set;} + /// + /// Components of the Animator. + /// + /// 6 + + public TransitionComponents Animator{get; set;} + /// + /// Target value to animate to. + /// + /// 6 + + public object TargetValue{get; set;} + } + + + /// + /// Class to help manage the adding and updating of transitions. + /// + internal static class LayoutTransitionsHelper + { + /// + /// Adds the given transition and condition to a transition list. + /// + /// The list to add the transition to. + /// Condition for the transition. + /// The transition to add. + /// True is set explicitly, false if inherited. + static public void AddTransitionForCondition( + Dictionary targetTransitionList, + TransitionCondition condition, + LayoutTransition transition, + bool explicitlySet) + { + bool replaced = false; + bool conditionNotInDictionary = false; + TransitionList transitionListMatchingCondition; + if (targetTransitionList.TryGetValue(condition, out transitionListMatchingCondition)) + { + for (var index=0; index < transitionListMatchingCondition?.Count; index++ ) + { + if (transitionListMatchingCondition[index].AnimatableProperty == transition.AnimatableProperty) + { + if (explicitlySet) + { + transitionListMatchingCondition[index] = transition; + replaced = true; + continue; + } + } + } + } + else + { + conditionNotInDictionary = true; + } + + if (replaced == false) + { + if (transitionListMatchingCondition == null) + { + transitionListMatchingCondition = new TransitionList(); + } + transitionListMatchingCondition.Add(transition); + // Update dictionary with new or replaced entry. + if (conditionNotInDictionary) + { + targetTransitionList.Add(condition, transitionListMatchingCondition); // new entry + } + else + { + targetTransitionList[condition] = transitionListMatchingCondition; // replaced + } + } + } + + /// + /// Retreive the transition list for the given condition. + /// + /// The source collection of transition lists to retrieve. + /// Condition for the transition. + /// transition list to return as out parameter. + /// True if a transition list found for the given condition> + static public bool GetTransitionsListForCondition( + Dictionary sourceTransitionCollection, + TransitionCondition condition, + TransitionList transitionsForCondition ) + { + TransitionCondition resolvedCondition = condition; + bool matched = false; + // LayoutChanged transitions overrides ChangeOnAdd and ChangeOnRemove as siblings will + // reposition to the new layout not to the insertion/removal of a sibling. + if ((condition & TransitionCondition.LayoutChanged) == TransitionCondition.LayoutChanged) + { + resolvedCondition = TransitionCondition.LayoutChanged; + } + + if (sourceTransitionCollection.TryGetValue(resolvedCondition, out transitionsForCondition)) + { + matched = true; + } + + return matched; + } + + /// + /// Copy the transitions in the source list to the target list + /// + /// The source transition list. + /// The target transition list to copy to. + static public void CopyTransitions( TransitionList sourceTransitionList, + TransitionList targetTransitionList ) + { + targetTransitionList.Clear(); + foreach (LayoutTransition transitionToApply in sourceTransitionList) + { + // Overwite existing transitions + targetTransitionList.Add(transitionToApply); + } + + } + } + +} // namespace Tizen.NUI \ No newline at end of file diff --git a/src/Tizen.NUI/src/public/Layouting/LinearLayout.cs b/src/Tizen.NUI/src/public/Layouting/LinearLayout.cs new file mode 100755 index 000000000..06ab7380b --- /dev/null +++ b/src/Tizen.NUI/src/public/Layouting/LinearLayout.cs @@ -0,0 +1,864 @@ +/* Copyright (c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +using System; +using Tizen.NUI.BaseComponents; +using System.Collections.Generic; + +namespace Tizen.NUI +{ + /// + /// [Draft] This class implements a linear box layout, automatically handling right to left or left to right direction change. + /// + public class LinearLayout : LayoutGroup + { + /// + /// [Draft] Enumeration for the direction in which the content is laid out + /// + /// 6 + public enum Orientation + { + /// + /// Horizontal (row) + /// + Horizontal, + /// + /// Vertical (column) + /// + Vertical + } + + /// + /// [Draft] Enumeration for the alignment of the linear layout items + /// + /// 6 + public enum Alignment + { + /// + /// At the left/right edge of the container (maps to LTR/RTL direction for horizontal orientation) + /// + Begin = 0x1, + /// + /// At the right/left edge of the container (maps to LTR/RTL direction for horizontal orientation) + /// + End = 0x2, + /// + /// At the horizontal center of the container + /// + CenterHorizontal = 0x4, + /// + /// At the top edge of the container + /// + Top = 0x8, + /// + /// At the bottom edge of the container + /// + Bottom = 0x10, + /// + /// At the vertical center of the container + /// + CenterVertical = 0x20, + /// + /// At the vertical and horizontal center of the container + /// + Center = 0x40 + } + + struct HeightAndWidthState + { + public MeasuredSize.StateType widthState; + public MeasuredSize.StateType heightState; + + public HeightAndWidthState( MeasuredSize.StateType width, MeasuredSize.StateType height) + { + widthState = width; + heightState = height; + } + } + + /// + /// [Draft] Get/Set the orientation in the layout + /// + /// 6 + public LinearLayout.Orientation LinearOrientation + { + get + { + return _linearOrientation; + } + set + { + _linearOrientation = value; + RequestLayout(); + } + } + + /// + /// [Draft] Get/Set the padding between cells in the layout + /// + /// 6 + public Size2D CellPadding + { + get + { + return _cellPadding; + } + set + { + _cellPadding = value; + RequestLayout(); + } + } + + + /// + /// [Draft] Get/Set the alignment in the layout + /// + /// 6 + public LinearLayout.Alignment LinearAlignment{ get; set; } = Alignment.Top; + + private float _totalLength = 0.0f; + private Size2D _cellPadding = new Size2D(0,0); + private Orientation _linearOrientation = Orientation.Horizontal; + + /// + /// [Draft] Constructor + /// + /// 6 + public LinearLayout() + { + } + + /// + /// Measure the layout and its content to determine the measured width and the measured height. + /// + /// horizontal space requirements as imposed by the parent. + /// vertical space requirements as imposed by the parent. + /// 6 + protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) + { + if (_linearOrientation == Orientation.Horizontal) + { + MeasureHorizontal(widthMeasureSpec, heightMeasureSpec); + } + else + { + MeasureVertical(widthMeasureSpec, heightMeasureSpec); + } + } + + /// + /// Layout should assign a size and position to each of its children.
+ ///
+ /// This is a new size or position for this layout. + /// Left position, relative to parent. + /// Top position, relative to parent. + /// Right position, relative to parent. + /// Bottom position, relative to parent. + /// 6 + protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) + { + if (_linearOrientation == Orientation.Horizontal) + { + LayoutHorizontal(left, top, right, bottom); + } + else + { + LayoutVertical(left, top, right, bottom); + } + } + + + private void MeasureWeightedChild( LayoutItem childLayout, float remainingExcess, float remainingWeight, float childWeight, + MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec, + HeightAndWidthState childState, Orientation orientation ) + { + bool horizontal = false; + if (orientation == Orientation.Horizontal) + { + horizontal = true; + } + + float childsShare = ( childWeight * remainingExcess ) / remainingWeight; + remainingExcess -= childsShare; + remainingWeight -= childWeight; + + float desiredWidth = childLayout.Owner.WidthSpecification; + float desiredHeight = childLayout.Owner.HeightSpecification; + float childLength = 0; + + Extents layoutPadding = Padding; + + // Always lay out weighted elements with intrinsic size regardless of the parent spec. + // for consistency between specs. + if( ( horizontal && ( desiredWidth == 0 )) || ( !horizontal && ( desiredHeight == 0 )) ) + { + // This child needs to be laid out from scratch using + // only its share of excess space. + childLength = childsShare; + } + else + { + // This child had some intrinsic width to which we + // need to add its share of excess space. + if (horizontal) + { + childLength = childLayout.MeasuredWidth.Size.AsDecimal() + childsShare; + } + else + { + childLength = childLayout.MeasuredHeight.Size.AsDecimal() + childsShare; + } + } + + MeasureSpecification childWidthMeasureSpec; + MeasureSpecification childHeightMeasureSpec; + + if (horizontal) + { + childWidthMeasureSpec = new MeasureSpecification( new LayoutLength(childLength), MeasureSpecification.ModeType.Exactly ); + childHeightMeasureSpec = GetChildMeasureSpecification( heightMeasureSpec, + new LayoutLength(layoutPadding.Top + layoutPadding.Bottom), + new LayoutLength(desiredHeight) ); + } + else // vertical + { + childWidthMeasureSpec = GetChildMeasureSpecification( widthMeasureSpec, + new LayoutLength(Padding.Start + Padding.End), + new LayoutLength(desiredWidth) ); + + childHeightMeasureSpec = new MeasureSpecification( new LayoutLength(childLength), MeasureSpecification.ModeType.Exactly); + } + + childLayout.Measure( childWidthMeasureSpec, childHeightMeasureSpec ); + + // Child may now not fit in horizontal dimension. + if( childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall) + { + childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; + } + + // Child may now not fit in vertical dimension. + if( childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall) + { + childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; + } + } + + private void MeasureHorizontal(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec) + { + var widthMode = widthMeasureSpec.Mode; + var heightMode = heightMeasureSpec.Mode; + bool isExactly = ( widthMode == MeasureSpecification.ModeType.Exactly ); + bool matchHeight = false; + bool allFillParent = true; + float maxHeight = 0.0f; + float alternativeMaxHeight = 0.0f; + float weightedMaxHeight = 0.0f; + float totalWeight = 0.0f; + + // Reset measure variables + _totalLength = 0.0f; + float usedExcessSpace = 0.0f; + HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK, + MeasuredSize.StateType.MeasuredSizeOK); + + // 1st phase: + // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs + // to accumulate total used space in totalLength based on measured sizes and margins. + // Weighted children are not measured at this phase. + // Available space for weighted children will be calculated in the phase 2 based on totalLength value. + // Max height of children is stored. + foreach( LayoutItem childLayout in LayoutChildren ) + { + int childDesiredHeight = childLayout.Owner.HeightSpecification; + float childWeight = childLayout.Owner.Weight; + Extents childMargin = childLayout.Margin; + totalWeight += childWeight; + + bool useExcessSpace = (childLayout.Owner.WidthSpecification == 0 ) && (childWeight > 0); + if( isExactly && useExcessSpace ) + { + // Children to be laid out with excess space can be measured later + _totalLength += childMargin.Start + childMargin.End; + } + else + { + if (useExcessSpace) + { + // The widthMode is either Unspecified or AtMost, and + // this child is only laid out using excess space. Measure + // using WrapContent so that we can find out the view's + // optimal width. + MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(widthMeasureSpec, + new LayoutLength(childLayout.Padding.Start + childLayout.Padding.End), + new LayoutLength(LayoutParamPolicies.WrapContent)); + + MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(heightMeasureSpec, + new LayoutLength(childLayout.Padding.Top + childLayout.Padding.Bottom), + new LayoutLength(childDesiredHeight)); + + childLayout.Measure( childWidthMeasureSpec, childHeightMeasureSpec); + usedExcessSpace += childLayout.MeasuredWidth.Size.AsDecimal(); + } + else + { + MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec); + } + + LayoutLength childWidth = childLayout.MeasuredWidth.Size; + LayoutLength length = childWidth + childMargin.Start + childMargin.End; + + if (isExactly) + { + _totalLength += length.AsDecimal(); + } + else + { + _totalLength = Math.Max(_totalLength, _totalLength + length.AsDecimal() + CellPadding.Width); + } + } + + bool matchHeightLocally = false; + if (heightMode != MeasureSpecification.ModeType.Exactly && childDesiredHeight == LayoutParamPolicies.MatchParent) + { + // A child has set to MatchParent on it's height. + // Will have to re-measure at least this child when we know exact height. + matchHeight = true; + matchHeightLocally = true; + } + + float marginHeight = childMargin.Top + childMargin.Bottom; + float childHeight = childLayout.MeasuredHeight.Size.AsDecimal() + marginHeight; + + if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall) + { + childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; + } + if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall) + { + childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; + } + + maxHeight = Math.Max( maxHeight, childHeight); + allFillParent = ( allFillParent && childDesiredHeight == LayoutParamPolicies.MatchParent); + + if (childWeight > 0) + { + // Heights of weighted Views are invalid if we end up remeasuring, so store them separately. + weightedMaxHeight = Math.Max( weightedMaxHeight, matchHeightLocally ? marginHeight : childHeight); + } + else + { + alternativeMaxHeight = Math.Max( alternativeMaxHeight, matchHeightLocally ? marginHeight : childHeight ); + } + } // foreach + + Extents padding = Padding; + _totalLength += padding.Start + padding.End; + + float widthSize = _totalLength; + widthSize = Math.Max( widthSize, SuggestedMinimumWidth.AsDecimal()); + MeasuredSize widthSizeAndState = ResolveSizeAndState( new LayoutLength(widthSize), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); + widthSize = widthSizeAndState.Size.AsDecimal(); + + // 2nd phase: + // Expand children with weight to take up available space + // We cycle through weighted children now (children with weight > 0). + // The children are measured with exact size equal to their share of the available space based on their weights. + // _totalLength is updated to include weighted children measured sizes. + float remainingExcess = widthSize - _totalLength + usedExcessSpace; + if( remainingExcess != 0 && totalWeight > 0 ) + { + float remainingWeight = totalWeight; + maxHeight = 0; + _totalLength = 0; + + int numberOfChildren = LayoutChildren.Count; + for( int i = 0; i < numberOfChildren; ++i ) + { + LayoutItem childLayout = LayoutChildren[i]; + + float desiredChildHeight = childLayout.Owner.HeightSpecification; + + float childWeight = childLayout.Owner.Weight; + Extents childMargin = childLayout.Margin; + + if( childWeight > 0 ) + { + MeasureWeightedChild(childLayout, remainingExcess, remainingWeight, childWeight, + widthMeasureSpec, heightMeasureSpec, childState, + Orientation.Horizontal ); + } + + float length = childLayout.MeasuredWidth.Size.AsDecimal() + childMargin.Start + childMargin.End; + float cellPadding = i < numberOfChildren - 1 ? CellPadding.Width : 0; + if( isExactly ) + { + _totalLength += length; + } + else + { + float totalLength = _totalLength; + _totalLength = Math.Max( _totalLength, _totalLength + length + cellPadding ); + } + + bool matchHeightLocally = (heightMode != MeasureSpecification.ModeType.Exactly) && (desiredChildHeight == LayoutParamPolicies.MatchParent); + float marginHeight = childMargin.Top + childMargin.Bottom; + float childHeight = childLayout.MeasuredHeight.Size.AsDecimal() + marginHeight; + + maxHeight = Math.Max( maxHeight, childHeight ); + alternativeMaxHeight = Math.Max( alternativeMaxHeight, matchHeightLocally ? marginHeight : childHeight ); + allFillParent = (allFillParent && desiredChildHeight == LayoutParamPolicies.MatchParent); + + _totalLength += padding.Start + padding.End; + } // for loop + } + else + { + // No excess space or no weighted children + alternativeMaxHeight = Math.Max( alternativeMaxHeight, weightedMaxHeight ); + } + + if (!allFillParent && heightMode != MeasureSpecification.ModeType.Exactly) + { + maxHeight = alternativeMaxHeight; + } + + maxHeight += padding.Top + padding.Bottom; + maxHeight = Math.Max( maxHeight, SuggestedMinimumHeight.AsRoundedValue() ); + + widthSizeAndState.State = childState.widthState; + + SetMeasuredDimensions(widthSizeAndState, + ResolveSizeAndState( new LayoutLength(maxHeight), heightMeasureSpec, childState.heightState )); + + if (matchHeight) + { + ForceUniformHeight(widthMeasureSpec); + } + } // MeasureHorizontal + + private void MeasureVertical( MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec ) + { + var widthMode = widthMeasureSpec.Mode; + var heightMode = heightMeasureSpec.Mode; + bool isExactly = ( heightMode == MeasureSpecification.ModeType.Exactly); + bool matchWidth = false; + bool allFillParent = true; + float maxWidth = 0.0f; + float alternativeMaxWidth = 0.0f; + float weightedMaxWidth = 0.0f; + float totalWeight = 0.0f; + + // Reset total length + _totalLength = 0.0f; + float usedExcessSpace =0.0f; + + HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK, + MeasuredSize.StateType.MeasuredSizeTooSmall); + + + // measure children, and determine if further resolution is required + + // 1st phase: + // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs + // to accumulate total used space in _totalLength. + // Weighted children are not measured in this phase. + // Available space for weighted children will be calculated in the phase 2 based on _totalLength value. + uint index = 0; + foreach( LayoutItem childLayout in LayoutChildren ) + { + int childDesiredWidth = childLayout.Owner.WidthSpecification; + int childDesiredHeight = childLayout.Owner.HeightSpecification; + float childWeight = childLayout.Owner.Weight; + Extents childMargin = childLayout.Margin; + totalWeight += childWeight; + + bool useExcessSpace = (childDesiredHeight == 0) && (childWeight > 0); + + if( isExactly && useExcessSpace ) + { + _totalLength = Math.Max( _totalLength, (_totalLength + childMargin.Top + childMargin.Bottom) ); + } + else + { + float childHeight = 0.0f; + if( useExcessSpace ) + { + // The heightMode is either Unspecified or AtMost, and + // this child is only laid out using excess space. Measure + // using WrapContent so that we can find out the view's + // optimal height. + // We'll restore the original height of 0 after measurement. + MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification( widthMeasureSpec, + new LayoutLength(childLayout.Padding.Start + childLayout.Padding.End), + new LayoutLength(childDesiredWidth) ); + MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification( heightMeasureSpec, + new LayoutLength(childLayout.Padding.Top + childLayout.Padding.Bottom), + new LayoutLength(LayoutParamPolicies.WrapContent) ); + childLayout.Measure( childWidthMeasureSpec, childHeightMeasureSpec ); + childHeight = childLayout.MeasuredHeight.Size.AsDecimal(); + usedExcessSpace += childHeight; + } + else + { + MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec ); + childHeight = childLayout.MeasuredHeight.Size.AsDecimal(); + } + + float length = childHeight + childMargin.Top + childMargin.Bottom; + float cellPadding = CellPadding.Height; + // No need to add cell padding to the end of last item. + if (index>=LayoutChildren.Count-1) + { + cellPadding = 0.0f; + } + _totalLength = Math.Max( _totalLength, _totalLength + length + cellPadding ); + } + + bool matchWidthLocally = false; + if( widthMode != MeasureSpecification.ModeType.Exactly && (childDesiredWidth == LayoutParamPolicies.MatchParent) ) + { + // Will have to re-measure at least this child when we know exact height. + matchWidth = true; + matchWidthLocally = true; + } + + float marginWidth = (childLayout.Margin.Start) + (childLayout.Margin.End); + float childWidth = childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth; + + if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall) + { + childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall; + } + if (childLayout.MeasuredHeight.State == MeasuredSize.StateType.MeasuredSizeTooSmall) + { + childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall; + } + + maxWidth = Math.Max( maxWidth, childWidth); + allFillParent = (allFillParent && (childDesiredWidth == LayoutParamPolicies.MatchParent)); + + float widthforWeight = childWidth; + if (matchWidthLocally) + { + widthforWeight = marginWidth; + } + + if (childWeight > 0) + { + // Widths of weighted Views are bogus if we end up remeasuring, so keep them separate. + weightedMaxWidth = Math.Max( weightedMaxWidth, widthforWeight); + } + else + { + alternativeMaxWidth = Math.Max( alternativeMaxWidth, widthforWeight); + } + index++; + } // foreach + + + Extents padding = Padding; + _totalLength += padding.Top + padding.Bottom; + LayoutLength heightSize = new LayoutLength(_totalLength); + heightSize = new LayoutLength(Math.Max( heightSize.AsDecimal(), SuggestedMinimumHeight.AsDecimal() )); + MeasuredSize heightSizeAndState = ResolveSizeAndState( heightSize, heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK); + heightSize = heightSizeAndState.Size; + + // 2nd phase: + // We cycle through weighted children now (children with weight > 0). + // The children are measured with exact size equal to their share of the available space based on their weights. + // _totalLength is updated to include weighted children measured sizes. + float remainingExcess = heightSize.AsDecimal() - _totalLength + usedExcessSpace; + + if( remainingExcess != 0 && totalWeight > 0.0f ) + { + float remainingWeight = totalWeight; + + _totalLength = 0; + + int numberOfChildren = LayoutChildren.Count; + for( int i = 0; i < numberOfChildren; ++i ) + { + LayoutItem childLayout = LayoutChildren[i]; + + float desiredChildWidth = childLayout.Owner.WidthSpecification; + + float childWeight = childLayout.Owner.Weight; + Extents childMargin = childLayout.Margin; + + if( childWeight > 0 ) + { + MeasureWeightedChild(childLayout, remainingExcess, remainingWeight, childWeight, + widthMeasureSpec, heightMeasureSpec, childState, + Orientation.Vertical); + } + + bool matchWidthLocally = false; + if( widthMode != MeasureSpecification.ModeType.Exactly && desiredChildWidth == LayoutParamPolicies.MatchParent) + { + // Will have to re-measure at least this child when we know exact height. + matchWidth = true; + matchWidthLocally = true; + } + + float marginWidth = childMargin.Start + childMargin.End; + float childWidth = childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth; + maxWidth = Math.Max( maxWidth, childWidth ); + allFillParent = allFillParent && desiredChildWidth == LayoutParamPolicies.MatchParent; + + float childHeight = childLayout.MeasuredHeight.Size.AsDecimal(); + float childLength = childHeight + childMargin.Top + childMargin.Bottom; + float cellPadding = i < numberOfChildren - 1 ? CellPadding.Height : 0.0f; + _totalLength = _totalLength + childLength + cellPadding; + alternativeMaxWidth = Math.Max( alternativeMaxWidth, matchWidthLocally ? marginWidth : childWidth ); + } // for loop + + // Add in our padding + _totalLength += padding.Top + padding.Bottom; + } + else + { + alternativeMaxWidth = Math.Max( alternativeMaxWidth, weightedMaxWidth ); + } + + if (!allFillParent && widthMode != MeasureSpecification.ModeType.Exactly) + { + maxWidth = alternativeMaxWidth; + } + maxWidth += padding.Start + padding.End; + maxWidth = Math.Max( maxWidth, SuggestedMinimumWidth.AsRoundedValue()); + + heightSizeAndState.State = childState.heightState; + + SetMeasuredDimensions( ResolveSizeAndState( new LayoutLength(maxWidth), widthMeasureSpec, childState.widthState ), + heightSizeAndState ); + + if (matchWidth) + { + ForceUniformWidth(heightMeasureSpec ); + } + } // MeasureVertical + + private void LayoutHorizontal(LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) + { + bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL; + + LayoutLength childTop = new LayoutLength(Padding.Top); + LayoutLength childLeft = new LayoutLength(Padding.Start); + + // Where bottom of child should go + LayoutLength height = new LayoutLength(bottom - top); + + // Space available for child + LayoutLength childSpace = new LayoutLength( height - Padding.Top - Padding.Bottom); + + int count = LayoutChildren.Count; + + switch (LinearAlignment) + { + case Alignment.End: + // totalLength contains the padding already + // In case of RTL map END alignment to the left edge + if (isLayoutRtl) + { + childLeft = new LayoutLength(Padding.Start); + } + else + { + childLeft = new LayoutLength(Padding.Start + right.AsDecimal() - left.AsDecimal() - _totalLength); + } + break; + case Alignment.CenterHorizontal: // FALL THROUGH + case Alignment.Center: + // totalLength contains the padding already + childLeft = new LayoutLength(Padding.Start + (right.AsDecimal() - left.AsDecimal() - _totalLength) / 2.0f); + break; + case Alignment.Begin: // FALL THROUGH (default) + default: + // totalLength contains the padding already + // In case of RTL map BEGIN alignment to the right edge + if (isLayoutRtl) + { + childLeft = new LayoutLength(Padding.Start + right.AsDecimal() - left.AsDecimal() - _totalLength); + } + else + { + childLeft = new LayoutLength(Padding.Start); + } + break; + } + + int start = 0; + int dir = 1; + + // In case of RTL, start drawing from the last child. + if (isLayoutRtl) + { + start = count - 1; + dir = -1; + } + + for( int i = 0; i < count; i++) + { + int childIndex = start + dir * i; + // Get a reference to the childLayout at the given index + LayoutItem childLayout = LayoutChildren[childIndex]; + if( childLayout != null ) + { + LayoutLength childWidth = childLayout.MeasuredWidth.Size; + LayoutLength childHeight = childLayout.MeasuredHeight.Size; + Extents childMargin = childLayout.Margin; + + switch ( LinearAlignment ) + { + case Alignment.Bottom: + childTop = new LayoutLength(height - Padding.Bottom - childHeight - childMargin.Bottom); + break; + case Alignment.CenterVertical: + case Alignment.Center: // FALLTHROUGH + childTop = new LayoutLength(Padding.Top + ( ( childSpace - childHeight ).AsDecimal() / 2.0f ) + childMargin.Top - childMargin.Bottom); + break; + case Alignment.Top: // FALLTHROUGH default + default: + childTop = new LayoutLength(Padding.Top + childMargin.Top); + break; + } + childLeft += childMargin.Start; + childLayout.Layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); + childLeft += childWidth + childMargin.End + CellPadding.Width; + } + } + } // LayoutHorizontally + + private void LayoutVertical(LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom) + { + LayoutLength childTop = new LayoutLength(Padding.Top); + LayoutLength childLeft = new LayoutLength(Padding.Start); + + // Where end of child should go + LayoutLength width = new LayoutLength(right - left); + + // Space available for child + LayoutLength childSpace = new LayoutLength( width - Padding.Start - Padding.End); + + int count = LayoutChildren.Count; + + switch (LinearAlignment) + { + case Alignment.Bottom: + // totalLength contains the padding already + childTop = new LayoutLength( Padding.Top + bottom.AsDecimal() - top.AsDecimal() - _totalLength); + break; + case Alignment.CenterVertical: // FALL THROUGH + case Alignment.Center: + // totalLength contains the padding already + childTop = new LayoutLength(Padding.Top + ( bottom.AsDecimal() - top.AsDecimal() - _totalLength ) / 2.0f); + break; + case Alignment.Top: // FALL THROUGH (default) + default: + // totalLength contains the padding already + childTop = new LayoutLength( Padding.Top ); + break; + } + + for( int i = 0; i < count; i++) + { + LayoutItem childLayout = LayoutChildren[i]; + if( childLayout != null ) + { + LayoutLength childWidth = childLayout.MeasuredWidth.Size; + LayoutLength childHeight = childLayout.MeasuredHeight.Size; + Extents childMargin = childLayout.Margin; + + childTop += childMargin.Top; + switch ( LinearAlignment ) + { + case Alignment.Begin: + default: + { + childLeft = new LayoutLength(Padding.Start + childMargin.Start); + break; + } + case Alignment.End: + { + childLeft = new LayoutLength(width - Padding.End - childWidth - childMargin.End); + break; + } + case Alignment.CenterHorizontal: + case Alignment.Center: // FALL THROUGH + { + childLeft = new LayoutLength(Padding.Start + (( childSpace - childWidth ).AsDecimal() / 2.0f) + childMargin.Start - childMargin.End); + break; + } + } + childLayout.Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight ); + childTop += childHeight + childMargin.Bottom + CellPadding.Height; + } + } + } // LayoutVertical + + private void ForceUniformHeight(MeasureSpecification widthMeasureSpec) + { + // Pretend that the linear layout has an exact size. This is the measured height of + // ourselves. The measured height should be the max height of the children, changed + // to accommodate the heightMeasureSpec from the parent + MeasureSpecification uniformMeasureSpec = new MeasureSpecification( MeasuredHeight.Size, MeasureSpecification.ModeType.Exactly); + foreach (LayoutItem childLayout in LayoutChildren) + { + int desiredChildHeight = childLayout.Owner.HeightSpecification; + int desiredChildWidth = childLayout.Owner.WidthSpecification; + + if (desiredChildHeight == LayoutParamPolicies.MatchParent) + { + // Temporarily force children to reuse their original measured width + int originalWidth = desiredChildWidth; + childLayout.Owner.WidthSpecification = (int)childLayout.MeasuredWidth.Size.AsRoundedValue(); + // Remeasure with new dimensions + MeasureChildWithMargins( childLayout, widthMeasureSpec, new LayoutLength(0), + uniformMeasureSpec, new LayoutLength(0) ); + // Restore width specification + childLayout.Owner.WidthSpecification = originalWidth; + } + } + } + + private void ForceUniformWidth(MeasureSpecification heightMeasureSpec) + { + // Pretend that the linear layout has an exact size. + MeasureSpecification uniformMeasureSpec = new MeasureSpecification( MeasuredWidth.Size, MeasureSpecification.ModeType.Exactly); + foreach (LayoutItem childLayout in LayoutChildren) + { + int desiredChildWidth = childLayout.Owner.WidthSpecification; + int desiredChildHeight = childLayout.Owner.WidthSpecification; + + if (desiredChildWidth == LayoutParamPolicies.MatchParent) + { + // Temporarily force children to reuse their original measured height + int originalHeight = desiredChildHeight; + childLayout.Owner.HeightSpecification = (int)childLayout.MeasuredHeight.Size.AsRoundedValue(); + + // Remeasure with new dimensions + MeasureChildWithMargins( childLayout, uniformMeasureSpec, new LayoutLength(0), + heightMeasureSpec, new LayoutLength(0)); + // Restore height specification + childLayout.Owner.HeightSpecification = originalHeight; + } + } + } + } //LinearLayout +} // namespace diff --git a/src/Tizen.NUI/src/public/Layouting/MeasureSpecification.cs b/src/Tizen.NUI/src/public/Layouting/MeasureSpecification.cs new file mode 100755 index 000000000..c67a17c3d --- /dev/null +++ b/src/Tizen.NUI/src/public/Layouting/MeasureSpecification.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +using System.ComponentModel; +using Tizen.NUI.BaseComponents; + +namespace Tizen.NUI +{ + /// + /// [Draft] A MeasureSpecification is used during the Measure pass by a LayoutGroup to inform it's children how to be measured. + /// For instance, it may measure a child with an exact width and an unspecified height in order to determine height for width. + /// + public struct MeasureSpecification + { + /// + /// MeasureSpecification Size value. + /// + /// 6 + public LayoutLength Size; + + /// + /// MeasureSpecification Mode. + /// + /// 6 + public MeasureSpecification.ModeType Mode; + + /// + /// Constructor taking size and mode type. + /// + /// size value. + /// mode value. + /// 6 + public MeasureSpecification(LayoutLength size, MeasureSpecification.ModeType mode) + { + Size = size; + Mode = mode; + } + + /// + /// Size mode for this MeasureSpecification + /// + /// 6 + public enum ModeType + { + /// + /// This is used by a parent to determine the desired dimension of a child layout. + /// + Unspecified, + /// + /// This is used by a parent to impose an exact size on the child. + /// The child must use this size, and guarantee that all of its descendants will fit within this size. + /// + Exactly, + /// + /// This is used by the parent to impose a maximum size on the child. + /// The child must guarantee that it and all of it's descendants will fit within this size. + /// + AtMost + } + } +} diff --git a/src/Tizen.NUI/src/public/Layouting/MeasuredSize.cs b/src/Tizen.NUI/src/public/Layouting/MeasuredSize.cs new file mode 100755 index 000000000..54ae209c8 --- /dev/null +++ b/src/Tizen.NUI/src/public/Layouting/MeasuredSize.cs @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +using System.ComponentModel; +using Tizen.NUI.BaseComponents; + +namespace Tizen.NUI +{ + /// + /// [Draft] Class that encodes a measurement and a measure state, which is set if the measured size is too small. + /// + public struct MeasuredSize + { + /// + /// Constructor + /// + /// size parameter + /// State + /// 6 + public MeasuredSize(LayoutLength measuredSize, MeasuredSize.StateType state) + { + Size = measuredSize; + State = state; + } + + /// + /// Creates a MeasuredSize from a LayoutLength + /// + /// LayoutLength to create + /// 6 + /// Returns a MeasuredSize object + public static implicit operator MeasuredSize(LayoutLength measuredSize) + { + return new MeasuredSize(measuredSize, StateType.MeasuredSizeOK); + } + + /// + /// LayoutLength size property + /// + /// 6 + public LayoutLength Size{ get; set;} + + /// + /// Measured state for this size. + /// + /// 6 + public StateType State{ get; set; } + + /// + /// Measured states for a Size value. + /// + /// 6 + public enum StateType + { + /// + /// The measured size is good + /// + MeasuredSizeOK, + /// + /// The measured size is too small + /// + MeasuredSizeTooSmall + } + } +} diff --git a/src/Tizen.NUI/src/public/Window.cs b/src/Tizen.NUI/src/public/Window.cs index bf6af72d8..9a6edd947 100755 --- a/src/Tizen.NUI/src/public/Window.cs +++ b/src/Tizen.NUI/src/public/Window.cs @@ -631,6 +631,9 @@ namespace Tizen.NUI } } + /// + /// Get the LayoutController for this Window. + /// internal LayoutController LayoutController { get diff --git a/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-root-layer-test.cs b/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-root-layer-test.cs index 1347e996b..d06a00cf3 100755 --- a/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-root-layer-test.cs +++ b/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-root-layer-test.cs @@ -71,7 +71,7 @@ namespace CustomLayoutWithoutAbsoluteLayout var center = childIncrement / 2; // Check layout direction - var view = GetOwner(); + var view = Owner; ViewLayoutDirectionType layoutDirection = view.LayoutDirection; for (uint i = 0; i < count; i++) diff --git a/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-test-2.cs b/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-test-2.cs index 1a73b1023..23f42166a 100755 --- a/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-test-2.cs +++ b/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-test-2.cs @@ -87,7 +87,7 @@ namespace CustomLayoutTest2 var center = childIncrement / 2; // Check layout direction - var view = GetOwner(); + var view = Owner; ViewLayoutDirectionType layoutDirection = view.LayoutDirection; // this is needed, otherwise the child's LayoutItem is garbage collected! @@ -180,7 +180,7 @@ namespace CustomLayoutTest2 } var center = childIncrement / 2; - var view = GetOwner(); + var view = Owner; ViewLayoutDirectionType layoutDirection = view.LayoutDirection; for (uint i = 0; i < ChildCount; ++i) diff --git a/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-test.cs b/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-test.cs index 9244a5def..dc1047672 100755 --- a/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-test.cs +++ b/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-test.cs @@ -87,7 +87,7 @@ namespace CustomLayoutByAbsoluteLayout var center = childIncrement / 2; // Check layout direction - var view = GetOwner(); + var view = Owner; ViewLayoutDirectionType layoutDirection = view.LayoutDirection; // this is needed, otherwise the child's LayoutItem is garbage collected! @@ -180,7 +180,7 @@ namespace CustomLayoutByAbsoluteLayout } var center = childIncrement / 2; - var view = GetOwner(); + var view = Owner; ViewLayoutDirectionType layoutDirection = view.LayoutDirection; for (uint i = 0; i < ChildCount; ++i) diff --git a/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-without-absoluteLayout-test.cs b/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-without-absoluteLayout-test.cs index 44a2d5cda..69cc1769f 100755 --- a/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-without-absoluteLayout-test.cs +++ b/test/NUITestSample/NUITestSample/examples/layouting/custom-layout-without-absoluteLayout-test.cs @@ -71,7 +71,7 @@ namespace SimpleLayout var center = childIncrement / 2; // Check layout direction - var view = GetOwner(); + var view = Owner; ViewLayoutDirectionType layoutDirection = view.LayoutDirection; for (uint i = 0; i < count; i++) diff --git a/test/NUITestSample/NUITestSample/examples/layouting/root-problem-fix-adding-several-layers.cs b/test/NUITestSample/NUITestSample/examples/layouting/root-problem-fix-adding-several-layers.cs index bf7a0855d..858b21fb0 100755 --- a/test/NUITestSample/NUITestSample/examples/layouting/root-problem-fix-adding-several-layers.cs +++ b/test/NUITestSample/NUITestSample/examples/layouting/root-problem-fix-adding-several-layers.cs @@ -72,7 +72,7 @@ namespace RootProblemFixAddingSeveralLayers var center = childIncrement / 2; // Check layout direction - var view = GetOwner(); + var view = Owner; ViewLayoutDirectionType layoutDirection = view.LayoutDirection; for (uint i = 0; i < count; i++)