+++ /dev/null
-/* 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
-{
- /// <summary>
- /// [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.
- /// </summary>
- internal class AbsoluteLayout : LayoutGroup
- {
- /// <summary>
- /// Struct to store Measured states of height and width.
- /// </summary>
- private struct HeightAndWidthState
- {
- public MeasuredSize.StateType widthState;
- public MeasuredSize.StateType heightState;
-
- public HeightAndWidthState( MeasuredSize.StateType width, MeasuredSize.StateType height)
- {
- widthState = width;
- heightState = height;
- }
- }
-
- /// <summary>
- /// [Draft] Constructor
- /// </summary>
- 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
+++ /dev/null
-/* 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
-{
- /// <summary>
- /// [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.
- /// </summary>
- 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;
- }
-
- /// <summary>
- /// [Draft] Creates a FlexLayout object.
- /// </summary>
- 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;
- }
-
- /// <summary>
- /// [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.
- /// </summary>
- public FlexDirection Direction
- {
- get
- {
- return GetFlexDirection();
- }
- set
- {
- SetFlexDirection(value);
- }
- }
-
- /// <summary>
- /// [Draft] Get/Set the justification in the layout.
- /// </summary>
- public FlexJustification Justification
- {
- get
- {
- return GetFlexJustification();
- }
- set
- {
- SetFlexJustification(value);
- }
- }
-
- /// <summary>
- /// [Draft] Get/Set the wrap in the layout.
- /// </summary>
- public FlexWrapType WrapType
- {
- get
- {
- return GetFlexWrap();
- }
- set
- {
- SetFlexWrap(value);
- }
- }
-
- /// <summary>
- /// [Draft] Get/Set the alignment of the layout content.
- /// </summary>
- public AlignmentType Alignment
- {
- get
- {
- return GetFlexAlignment();
- }
- set
- {
- SetFlexAlignment(value);
- }
- }
-
- /// <summary>
- /// [Draft] Get/Set the alignment of the layout items.
- /// </summary>
- public AlignmentType ItemsAlignment
- {
- get
- {
- return GetFlexItemsAlignment();
- }
- set
- {
- SetFlexItemsAlignment(value);
- }
- }
-
- /// <summary>
- /// [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.
- /// </summary>
- public enum FlexDirection
- {
- /// <summary>
- /// The flexible items are displayed vertically as a column
- /// </summary>
- Column,
- /// <summary>
- /// The flexible items are displayed vertically as a column, but in reverse order
- /// </summary>
- ColumnReverse,
- /// <summary>
- /// The flexible items are displayed horizontally as a row
- /// </summary>
- Row,
- /// <summary>
- /// The flexible items are displayed horizontally as a row, but in reverse order
- /// </summary>
- RowReverse
- }
-
- /// <summary>
- /// [Draft] Enumeration for the alignment of the flex items when the items do not use all available space on the main-axis.
- /// </summary>
- public enum FlexJustification
- {
- /// <summary>
- /// Items are positioned at the beginning of the container
- /// </summary>
- FlexStart,
- /// <summary>
- /// Items are positioned at the center of the container
- /// </summary>
- Center,
- /// <summary>
- /// Items are positioned at the end of the container
- /// </summary>
- FlexEnd,
- /// <summary>
- /// Items are positioned with equal space between the lines
- /// </summary>
- SpaceBetween,
- /// <summary>
- /// Items are positioned with equal space before, between, and after the lines
- /// </summary>
- SpaceAround
- }
-
- /// <summary>
- /// [Draft] Enumeration for the wrap type of the flex container when there is no enough room for all the items on one flex line.
- /// </summary>
- public enum FlexWrapType
- {
- /// <summary>
- /// Flex items laid out in single line (shrunk to fit the flex container along the main axis)
- /// </summary>
- NoWrap,
- /// <summary>
- /// Flex items laid out in multiple lines if needed
- /// </summary>
- Wrap
- }
-
- /// <summary>
- /// [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.
- /// </summary>
- public enum AlignmentType
- {
- /// <summary>
- /// Inherits the same alignment from the parent
- /// </summary>
- Auto,
- /// <summary>
- /// At the beginning of the container
- /// </summary>
- FlexStart,
- /// <summary>
- /// At the center of the container
- /// </summary>
- Center,
- /// <summary>
- /// At the end of the container
- /// </summary>
- FlexEnd,
- /// <summary>
- /// Stretch to fit the container
- /// </summary>
- 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
+++ /dev/null
-/* 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
-{
- /// <summary>
- /// [Draft] This class implements a grid layout
- /// </summary>
- 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;
-
- /// <summary>
- /// [draft] GridLayout Constructor/>
- /// </summary>
- /// <returns> New Grid object.</returns>
- public GridLayout()
- {
- _locations = new GridLocations();
- }
-
- // <summary>
- // [Draft] Get/Set the number of columns in the grid
- // </summary>
- public int Columns
- {
- get
- {
- return GetColumns();
- }
- set
- {
- SetColumns(value);
- }
- }
-
-
- /// <summary>
- /// [draft ] Sets the number of columns the GridLayout should have. />
- /// </summary>
- /// <param name="columns">The number of columns.</param>
- internal void SetColumns(int columns)
- {
- _numberOfRequestedColumns = columns;
- if( columns != _columns)
- {
- _columns = Math.Max(1, _columns);
- _columns = columns;
- RequestLayout();
- }
- }
-
- /// <summary>
- /// [draft ] Gets the number of columns in the Grid />
- /// </summary>
- /// <returns>The number of columns in the Grid.</returns>
- 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<GridLocations.Cell> 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++;
- }
- }
- }
- }
-}
+++ /dev/null
-/*
- * 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
-{
- /// <summary>
- /// [Draft]
- /// Interface that defines a layout Parent. Enables a layout child to access methods on its parent, e.g. Remove (during unparenting)
- /// </summary>
- internal interface ILayoutParent
- {
- /// <summary>
- /// Add this child to the parent.
- /// </summary>
- /// <param name="layoutItem">The layout child to add.</param>
- void Add(LayoutItem layoutItem);
-
- /// <summary>
- /// Remove this child from the parent
- /// </summary>
- /// <param name="layoutItem">The layout child to add.</param>
- void Remove(LayoutItem layoutItem);
- }
-}
+++ /dev/null
-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
+++ /dev/null
-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
*
*/
-using System.Collections.Generic;
-using System;
-using System.ComponentModel;
-
namespace Tizen.NUI
{
- /// <summary>
- /// The conditions for transitions.
- /// </summary>
- /// 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
- {
- /// <summary>
- /// Default when a condition has not been set.
- /// </summary>
- /// 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,
- /// <summary>
- /// Animate changing layout to another layout.
- /// </summary>
- /// 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,
- /// <summary>
- /// Animate adding item.
- /// </summary>
- /// 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,
- /// <summary>
- /// Animate removing item.
- /// </summary>
- /// 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,
- /// <summary>
- /// Animation when an item changes due to a sibbling being added.
- /// </summary>
- /// 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,
- /// <summary>
- /// Animation when an item changes due to a sibbling being removed.
- /// </summary>
- /// 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
- }
-
/// <summary>
/// [Draft] Class to hold layout animation and position data
/// </summary>
+++ /dev/null
-/*
- * 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
-{
- /// <summary>
- /// [Draft] LayoutGroup class providing container functionality.
- /// </summary>
- internal class LayoutGroup : LayoutItem, ILayoutParent
- {
- protected List<LayoutItem> _children{ get;} // Children of this LayoutGroup
-
- /// <summary>
- /// [Draft] Constructor
- /// </summary>
- public LayoutGroup()
- {
- _children = new List<LayoutItem>();
- }
-
- /// <summary>
- /// [Draft] Constructor setting the owner of this LayoutGroup.
- /// </summary>
- /// <param name="owner">Owning View of this layout, currently a View but may be extending for Windows/Layers.</param>
- public LayoutGroup(View owner) : base(owner)
- {
- _children = new List<LayoutItem>();
- }
-
- /// <summary>
- /// From ILayoutParent.<br />
- /// </summary>
- 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();
- }
-
- /// <summary>
- /// Remove all layout children.<br />
- /// </summary>
- 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();
- }
-
- /// <summary>
- /// From ILayoutParent
- /// </summary>
- 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.
- }
-
- /// <summary>
- /// If the child has a layout then it is removed from the parent layout.
- /// </summary>
- /// <param name="child">Child View to remove.</param>
- internal void RemoveChildFromLayoutGroup(View child)
- {
- Debug.Assert(child.Layout !=null);
- Remove(child.Layout);
- }
-
- /// <summary>
- /// Set all children in a LayoutGroup to the supplied condition.
- /// Children with Add or Remove conditions should not be changed.
- /// </summary>
- 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;
- }
- }
- }
-
- }
-
- /// <summary>
- /// Callback for View.ChildAdded event
- /// </summary>
- /// <param name="sender">The object triggering the event.</param>
- /// <param name="childAddedEvent">Arguments from the event.</param>
- void OnChildAddedToOwner(object sender, View.ChildAddedEventArgs childAddedEvent)
- {
- AddChildToLayoutGroup(childAddedEvent.Added);
- }
-
- /// <summary>
- /// Callback for View.ChildRemoved event
- /// </summary>
- /// <param name="sender">The object triggering the event.</param>
- /// <param name="childRemovedEvent">Arguments from the event.</param>
- void OnChildRemovedFromOwner(object sender, View.ChildRemovedEventArgs childRemovedEvent)
- {
- RemoveChildFromLayoutGroup(childRemovedEvent.Removed);
- }
-
- /// <summary>
- /// 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.<br />
- /// </summary>
- /// <param name="parentMeasureSpec">The requirements for this view. MeasureSpecification.</param>
- /// <param name="padding">The padding of this view for the current dimension and margins, if applicable. LayoutLength.</param>
- /// <param name="childDimension"> How big the child wants to be in the current dimension. LayoutLength.</param>
- /// <returns>a MeasureSpec for the child.</returns>
- 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 );
- }
-
- /// <summary>
- /// Measure the layout and its content to determine the measured width and the measured height.<br />
- /// 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. <br />
- /// </summary>
- /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
- /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
- 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 ) );
- }
-
- /// <summary>
- /// Called from Layout() when this layout should assign a size and position to each of its children.<br />
- /// Derived classes with children should override this method and call Layout() on each of their children.<br />
- /// </summary>
- /// <param name="changed">This is a new size or position for this layout.</param>
- /// <param name="left">Left position, relative to parent.</param>
- /// <param name="top"> Top position, relative to parent.</param>
- /// <param name="right">Right position, relative to parent.</param>
- /// <param name="bottom">Bottom position, relative to parent.</param>
- 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 );
- }
- }
- }
-
- /// <summary>
- /// Overridden method called when the layout size changes.<br />
- /// </summary>
- /// <param name="newSize">The new size of the layout.</param>
- /// <param name="oldSize">The old size of the layout.</param>
- protected override void OnSizeChanged(LayoutSize newSize, LayoutSize oldSize)
- {
- // Do nothing
- }
-
- /// <summary>
- /// Overridden method called when the layout is attached to an owner.<br />
- /// </summary>
- 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.
-
- /// <summary>
- /// Callback when child is added to container.<br />
- /// Derived classes can use this to set their own child properties on the child layout's owner.<br />
- /// </summary>
- /// <param name="child">The Layout child.</param>
- protected virtual void OnChildAdd(LayoutItem child)
- {
- }
-
- /// <summary>
- /// Callback when child is removed from container.<br />
- /// </summary>
- /// <param name="child">The Layout child.</param>
- protected virtual void OnChildRemove(LayoutItem child)
- {
- }
-
- /// <summary>
- /// Ask all of the children of this view to measure themselves, taking into
- /// account both the MeasureSpec requirements for this view and its padding.<br />
- /// The heavy lifting is done in GetChildMeasureSpec.<br />
- /// </summary>
- /// <param name="widthMeasureSpec">The width requirements for this view.</param>
- /// <param name="heightMeasureSpec">The height requirements for this view.</param>
- protected virtual void MeasureChildren(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
- {
- foreach( LayoutItem childLayout in _children )
- {
- MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
- }
- }
-
- /// <summary>
- /// Ask one of the children of this view to measure itself, taking into
- /// account both the MeasureSpec requirements for this view and its padding.<br />
- /// The heavy lifting is done in GetChildMeasureSpec.<br />
- /// </summary>
- /// <param name="child">The child to measure.</param>
- /// <param name="parentWidthMeasureSpec">The width requirements for this view.</param>
- /// <param name="parentHeightMeasureSpec">The height requirements for this view.</param>
- 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 );
- }
-
- /// <summary>
- /// Ask one of the children of this view to measure itself, taking into
- /// account both the MeasureSpec requirements for this view and its padding.<br />
- /// and margins. The child must have MarginLayoutParams The heavy lifting is
- /// done in GetChildMeasureSpecification.<br />
- /// </summary>
- /// <param name="child">The child to measure.</param>
- /// <param name="parentWidthMeasureSpec">The width requirements for this view.</param>
- /// <param name="widthUsed">Extra space that has been used up by the parent horizontally (possibly by other children of the parent).</param>
- /// <param name="parentHeightMeasureSpec">The height requirements for this view.</param>
- /// <param name="heightUsed">Extra space that has been used up by the parent vertically (possibly by other children of the parent).</param>
- 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
+++ /dev/null
-/*
- * 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
- };
-
- /// <summary>
- /// [Draft] Base class for layouts. It is used to layout a View
- /// It can be laid out by a LayoutGroup.
- /// </summary>
- 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;}
-
- /// <summary>
- /// [Draft] The View that this Layout has been assigned to.
- /// </summary>
- public View Owner{get; set;} // Should not keep a View alive.
-
- /// <summary>
- /// [Draft] Is this Layout set to animate its content.
- /// </summary>
- public bool Animate{get; set;}
-
- /// <summary>
- /// [Draft] Margin for this LayoutItem
- /// </summary>
- public Extents Margin
- {
- get
- {
- return _margin;
- }
- set
- {
- _margin = value;
- RequestLayout();
- }
- }
-
- /// <summary>
- /// [Draft] Padding for this LayoutItem
- /// </summary>
- public Extents Padding
- {
- get
- {
- return _padding;
- }
- set
- {
- _padding = value;
- RequestLayout();
- }
- }
-
- /// <summary>
- /// [Draft] Constructor
- /// </summary>
- public LayoutItem()
- {
- Initialize();
- }
-
- /// <summary>
- /// [Draft] Constructor setting the owner of this LayoutItem.
- /// </summary>
- /// <param name="owner">Owning View of this layout, currently a View but may be extending for Windows/Layers.</param>
- public LayoutItem(View owner)
- {
- Owner = owner;
- Initialize();
- }
-
- /// <summary>
- /// [Draft] Set parent to this layout.
- /// </summary>
- /// <param name="parent">Parent to set on this Layout.</param>
- public void SetParent( ILayoutParent parent)
- {
- Parent = parent as LayoutGroup;
- }
-
- /// <summary>
- /// Unparent this layout from it's owner, and remove any layout children in derived types. <br />
- /// </summary>
- 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);
- }
-
- /// <summary>
- /// Get the View owning this LayoutItem
- /// </summary>
- internal View GetOwner()
- {
- return Owner;
- }
-
- /// <summary>
- /// Initialize the layout and allow derived classes to also perform any operations
- /// </summary>
- /// <param name="owner">Owner of this Layout.</param>
- 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;
- }
- }
-
- /// <summary>
- /// This is called to find out how big a layout should be. <br />
- /// The parent supplies constraint information in the width and height parameters. <br />
- /// 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. <br />
- /// </summary>
- /// <param name="widthMeasureSpec"> Horizontal space requirements as imposed by the parent.</param>
- /// <param name="heightMeasureSpec">Vertical space requirements as imposed by the parent.</param>
- 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;
- }
-
- /// <summary>
- /// Assign a size and position to a layout and all of its descendants. <br />
- /// 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<br />
- /// measurements that were stored in the measure pass.<br />
- /// </summary>
- /// <param name="left">Left position, relative to parent.</param>
- /// <param name="top">Top position, relative to parent.</param>
- /// <param name="right">Right position, relative to parent.</param>
- /// <param name="bottom">Bottom position, relative to parent.</param>
- 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;
- }
- }
-
- /// <summary>
- /// Utility to return a default size.<br />
- /// Uses the supplied size if the MeasureSpecification imposed no constraints. Will get larger if allowed by the
- /// MeasureSpecification.<br />
- /// </summary>
- /// <param name="size"> Default size for this layout.</param>
- /// <param name="measureSpecification"> Constraints imposed by the parent.</param>
- /// <returns>The size this layout should be.</returns>
- 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;
- }
-
- /// <summary>
- /// Request that this layout is re-laid out.<br />
- /// This will make this layout and all it's parent layouts dirty.<br />
- /// </summary>
- public void RequestLayout()
- {
- Flags = Flags | LayoutFlags.ForceLayout;
- Window.Instance.LayoutController.RequestLayout(this);
- }
-
- /// <summary>
- /// Predicate to determine if this layout has been requested to re-layout.<br />
- /// </summary>
- public bool LayoutRequested
- {
- get
- {
- return ( Flags & LayoutFlags.ForceLayout) == LayoutFlags.ForceLayout;
- }
- }
-
- /// <summary>
- /// Get the measured width (without any measurement flags).<br />
- /// This method should be used only during measurement and layout calculations.<br />
- /// </summary>
- public MeasuredSize MeasuredWidth{ get; set; } = new MeasuredSize( new LayoutLength(-3), MeasuredSize.StateType.MeasuredSizeOK);
-
- /// <summary>
- /// Get the measured height (without any measurement flags).<br />
- /// This method should be used only during measurement and layout calculations.<br />
- /// </summary>
- public MeasuredSize MeasuredHeight{ get; set; } = new MeasuredSize( new LayoutLength(-3), MeasuredSize.StateType.MeasuredSizeOK);
-
- /// <summary>
- /// Get the measured width and state.<br />
- /// This method should be used only during measurement and layout calculations.<br />
- /// </summary>
- public MeasuredSize MeasuredWidthAndState
- {
- get
- {
- return MeasuredWidth; // Not bitmasking State unless proven to be required.
- }
- }
-
-
- /// <summary>
- /// Get the measured height and state.<br />
- /// This method should be used only during measurement and layout calculations.<br />
- /// </summary>
- public MeasuredSize MeasuredHeightAndState
- {
- get
- {
- return MeasuredHeight; // Not bitmasking State unless proven to be required.
- }
- }
-
- /// <summary>
- /// Returns the suggested minimum width that the layout should use.<br />
- /// This returns the maximum of the layout's minimum width and the owner's natural width.<br />
- /// </summary>
- public LayoutLength SuggestedMinimumWidth
- {
- get
- {
- int naturalWidth = Owner.NaturalSize2D.Width;
- return new LayoutLength(Math.Max( MinimumWidth.AsDecimal(), naturalWidth ));
- }
- }
-
- /// <summary>
- /// Returns the suggested minimum height that the layout should use.<br />
- /// This returns the maximum of the layout's minimum height and the owner's natural height.<br />
- /// </summary>
- public LayoutLength SuggestedMinimumHeight
- {
- get
- {
- int naturalHeight = Owner.NaturalSize2D.Height;
- return new LayoutLength(Math.Max( MinimumHeight.AsDecimal(), naturalHeight ));
- }
- }
-
- /// <summary>
- /// Sets the minimum width of the layout.<br />
- /// 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).<br />
- /// 1. if the owner's View.WidthSpecification has exact value, then that value overrides the minimum size.<br />
- /// 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()).<br />
- /// 3. If the owner's View.WidthSpecification is set to View.LayoutParamPolicies.MatchParent, then the parent width takes precedence over the minimum width.<br />
- /// </summary>
- public LayoutLength MinimumWidth {get; set;}
-
- /// <summary>
- /// Sets the minimum height of the layout.<br />
- /// 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).<br />
- /// 1. if the owner's View.HeightSpecification has exact value, then that value overrides the minimum size.<br />
- /// 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()).<br />
- /// 3. If the owner's View.HeightSpecification is set to View.LayoutParamPolicies.MatchParent, then the parent height takes precedence over the minimum height.<br />
- /// </summary>
- public LayoutLength MinimumHeight {get; set;}
-
- ///<summary>
- /// Utility to reconcile a desired size and state, with constraints imposed by a MeasureSpecification.
- ///</summary>
- /// <param name="size"> How big the layout wants to be.</param>
- /// <param name="measureSpecification"> Constraints imposed by the parent.</param>
- /// <param name="childMeasuredState"> Size information bit mask for the layout's children.</param>
- /// <returns> A measured size, which may indicate that it is too small. </returns>
- 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;
- }
-
- /// <summary>
- /// This method must be called by OnMeasure(MeasureSpec,MeasureSpec) to store the measured width and measured height.
- /// </summary>
- /// <param name="measuredWidth">The measured width of this layout.</param>
- /// <param name="measuredHeight">The measured height of this layout.</param>
- protected void SetMeasuredDimensions( MeasuredSize measuredWidth, MeasuredSize measuredHeight )
- {
- MeasuredWidth = measuredWidth;
- MeasuredHeight = measuredHeight;
- Flags = Flags | LayoutFlags.MeasuredDimensionSet;
- }
-
- /// <summary>
- /// Measure the layout and its content to determine the measured width and the
- /// measured height.<br />
- /// 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.<br />
- /// 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.<br />
- /// </summary>
- /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
- /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
- 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 ) );
- }
-
- /// <summary>
- /// Called from Layout() when this layout should assign a size and position to each of its children. <br />
- /// Derived classes with children should override this method and call Layout() on each of their children. <br />
- /// </summary>
- /// <param name="changed">This is a new size or position for this layout.</param>
- /// <param name="left">Left position, relative to parent.</param>
- /// <param name="top">Top position, relative to parent.</param>
- /// <param name="right">Right position, relative to parent.</param>
- /// <param name="bottom">Bottom position, relative to parent.</param>
- protected virtual void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
- {
- }
-
- /// <summary>
- /// Virtual method to inform derived classes when the layout size changed. <br />
- /// </summary>
- /// <param name="newSize">The new size of the layout.</param>
- /// <param name="oldSize">The old size of the layout.</param>
- protected virtual void OnSizeChanged(LayoutSize newSize, LayoutSize oldSize)
- {
- }
-
- /// <summary>
- /// Virtual method to allow derived classes to remove any children before it is removed from
- /// its parent.
- /// </summary>
- public virtual void OnUnparent()
- {
- }
-
- /// <summary>
- /// 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.
- /// </summary>
- 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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
-{
- /// <summary>
- /// [Draft] A type that represents a layout length. Currently, this implies pixels, but could be extended to handle device dependant sizes, etc.
- /// </summary>
- internal struct LayoutLength
- {
- private float _value;
-
- /// <summary>
- /// [Draft] Constructor from an int
- /// </summary>
- /// <param name="value">Int to initialize with.</param>
- public LayoutLength(int value)
- {
- _value = value;
- }
-
- /// <summary>
- /// [Draft] Constructor from a float
- /// </summary>
- /// <param name="value">Float to initialize with.</param>
- public LayoutLength(float value)
- {
- _value = value;
- }
-
- /// <summary>
- /// [Draft] Constructor from a LayoutLength
- /// </summary>
- /// <param name="layoutLength">LayoutLength object to initialize with.</param>
- public LayoutLength(LayoutLength layoutLength)
- {
- _value = layoutLength._value;
- }
-
- /// <summary>
- /// [Draft] Return value as rounded value (whole number), best used as final output
- /// </summary>
- /// <returns>The layout length value as a rounded whole number.</returns>
- public float AsRoundedValue()
- {
- return (float)Math.Round((decimal)_value, MidpointRounding.AwayFromZero);
- }
-
- /// <summary>
- /// [Draft] Return value as the raw decimal value, best used for calculations
- /// </summary>
- /// <returns>The layout length value as the raw decimal value.</returns>
- public float AsDecimal()
- {
- return _value;
- }
-
- /// <summary>
- /// [Draft] The == operator.
- /// </summary>
- /// <param name="arg1">The first value.</param>
- /// <param name="arg2">The second value</param>
- /// <returns>true if LayoutLengths are equal</returns>
- public static bool operator ==(LayoutLength arg1, LayoutLength arg2)
- {
- return arg1.Equals(arg2);
- }
-
- /// <summary>
- /// [Draft] The != operator.
- /// </summary>
- /// <param name="arg1">The first value.</param>
- /// <param name="arg2">The second value</param>
- /// <returns>true if LayoutLengths are not equal</returns>
- public static bool operator !=(LayoutLength arg1, LayoutLength arg2)
- {
- return !arg1.Equals(arg2);
- }
-
- /// <summary>
- /// Determines whether the specified object is equal to the current object.
- /// </summary>
- /// <param name="obj">The object to compare with the current object.</param>
- /// <returns>true if equal LayoutLength, else false.</returns>
- public override bool Equals(object obj)
- {
- if (obj is LayoutLength)
- {
- return this.Equals((LayoutLength)obj);
- }
- return false;
- }
-
- /// <summary>
- /// Determines whether the specified object is equal to the current object.
- /// </summary>
- /// <param name="layoutLength">The LayoutLength to compare with the current LayoutLength.</param>
- /// <returns>true if equal LayoutLengths, else false.</returns>
- public bool Equals(LayoutLength layoutLength)
- {
- return (Math.Abs(_value - layoutLength._value ) <= float.Epsilon);
- }
-
- /// <summary>
- /// A hash code for the current object.
- /// </summary>
- public override int GetHashCode()
- {
- return (int)Math.Ceiling(_value);
- }
-
- /// <summary>
- /// The addition operator.
- /// </summary>
- /// <param name="arg1">The first value.</param>
- /// <param name="arg2">The second value.</param>
- /// <returns>The LayoutLength containing the result of the addition.</returns>
- public static LayoutLength operator +(LayoutLength arg1, LayoutLength arg2)
- {
- return new LayoutLength( arg1._value + arg2._value );
- }
-
- /// <summary>
- /// The addition operator.
- /// </summary>
- /// <param name="arg1">The first value.</param>
- /// <param name="arg2">The second value.</param>
- /// <returns>The LayoutLength containing the result of the addition.</returns>
- public static LayoutLength operator +(LayoutLength arg1, int arg2)
- {
- return new LayoutLength(arg1._value + (float)arg2);
- }
-
- /// <summary>
- /// The subtraction operator.
- /// </summary>
- /// <param name="arg1">The first value.</param>
- /// <param name="arg2">The second value.</param>
- /// <returns>The LayoutLength containing the result of the subtraction.</returns>
- public static LayoutLength operator -(LayoutLength arg1, LayoutLength arg2)
- {
- return new LayoutLength(arg1._value - arg2._value);
- }
-
- /// <summary>
- /// The subtraction operator.
- /// </summary>
- /// <param name="arg1">The first value.</param>
- /// <param name="arg2">The second value.</param>
- /// <returns>The LayoutLength containing the result of the subtraction.</returns>
- public static LayoutLength operator -(LayoutLength arg1, int arg2)
- {
- return new LayoutLength(arg1._value - (float)arg2);
- }
-
- /// <summary>
- /// The multiplication operator.
- /// </summary>
- /// <param name="arg1">The first value.</param>
- /// <param name="arg2">The second value.</param>
- /// <returns>The LayoutLength containing the result of the multiplication.</returns>
- public static LayoutLength operator *(LayoutLength arg1, LayoutLength arg2)
- {
- return new LayoutLength(arg1._value * arg2._value);
- }
-
- /// <summary>
- /// Th multiplication operator.
- /// </summary>
- /// <param name="arg1">The first value.</param>
- /// <param name="arg2">The int value to scale the LayoutLength.</param>
- /// <returns>The LayoutLength containing the result of the scaling.</returns>
- public static LayoutLength operator *(LayoutLength arg1, int arg2)
- {
- return new LayoutLength(arg1._value * arg2);
- }
-
- /// <summary>
- /// The division operator.
- /// </summary>
- /// <param name="arg1">The first value.</param>
- /// <param name="arg2">The second value.</param>
- /// <returns>The LayoutLength containing the result of the division.</returns>
- public static LayoutLength operator /(LayoutLength arg1, LayoutLength arg2)
- {
- return new LayoutLength(arg1._value / arg2._value);
- }
-
- /// <summary>
- /// Th division operator.
- /// </summary>
- /// <param name="arg1">The first value.</param>
- /// <param name="arg2">The int value to scale the vector by.</param>
- /// <returns>The LayoutLength containing the result of the scaling.</returns>
- public static LayoutLength operator /(LayoutLength arg1, int arg2)
- {
- return new LayoutLength(arg1._value / (float)arg2);
- }
- }
-}
+++ /dev/null
-/*
- * 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
-{
- /// <summary>
- /// [Draft] This class represents a layout size (width and height), non mutable.
- /// </summary>
- internal struct LayoutSize
- {
- /// <summary>
- /// [Draft] Constructor from width and height
- /// </summary>
- /// <param name="width">Int to initialize with.</param>
- /// <param name="height">Int to initialize with.</param>
- public LayoutSize(int width, int height)
- {
- Width = width;
- Height = height;
- }
-
- /// <summary>
- /// Computes a hash code for this LayoutSize for use in hash based collections.
- /// </summary>
- /// <returns>A non unique hash code .</returns>
- public override int GetHashCode()
- {
- return Width ^ Height;
- }
-
- /// <summary>
- /// Whether the values of two LayoutSize objects are equals
- /// </summary>
- /// <param name="obj">Object to be compared against.</param>
- /// <returns>true if obj is equal to this LayoutSize.</returns>
- public override bool Equals(object obj)
- {
- if (obj is LayoutSize)
- {
- LayoutSize layoutSize = (LayoutSize)obj;
- return ((layoutSize.Width == Width) && (layoutSize.Height == Height));
- }
- return false;
- }
-
- /// <summary>
- /// Compares whether the two LayoutSize instances are equal.
- /// </summary>
- /// <param name="lhs">A LayoutSize instance.</param>
- /// <param name="rhs">A LayoutSize instance.</param>
- /// <returns>true if the two LayoutSize instances have equal values.</returns>
- public static bool operator ==(LayoutSize lhs, LayoutSize rhs)
- {
- return ((lhs.Width == rhs.Width) && (lhs.Height == rhs.Height));
- }
-
-
- /// <summary>
- /// Compares whether the two LayoutSize instances are same or not.
- /// </summary>
- /// <param name="lhs">A LayoutSize instance.</param>
- /// <param name="rhs">A LayoutSize instance.</param>
- /// <returns>true if the two LayoutSize instances have do not have equal values.</returns>
- public static bool operator !=(LayoutSize lhs, LayoutSize rhs)
- {
- return ((lhs.Width != rhs.Width) || (lhs.Height != rhs.Height));
- }
-
- /// <summary>
- /// [Draft] Get the width value of this layout
- /// </summary>
- public int Width{ get; private set; }
-
- /// <summary>
- /// [Draft] Get the height value of this layout
- /// </summary>
- public int Height{ get; private set; }
-
- }
-}
+++ /dev/null
-/*
- * 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
-{
- /// <summary>
- /// Define a List of LayoutTransitions
- /// </summary>
- /// 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<LayoutTransition> {}
-
- /// <summary>
- /// The properties that can be animated.
- /// </summary>
- /// 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
- {
- /// <summary>
- /// Position property.
- /// </summary>
- /// 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,
- /// <summary>
- /// Size property.
- /// </summary>
- /// 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,
- /// <summary>
- /// Opacity property.
- /// </summary>
- /// 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
- }
-
- /// <summary>
- /// Parts of the transition that can be configured to provide a custom effect.
- /// </summary>
- /// 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
- {
- /// <summary>
- /// TransitionComponents default constructor.
- /// </summary>
- /// 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);
- }
-
- /// <summary>
- /// TransitionComponents constructor. Stores delay, duration and AlphaFunction.
- /// </summary>
- /// <param name="delay">The delay before the animator starts.</param>
- /// <param name="duration">the duration fo the animator.</param>
- /// <param name="alphaFunction">alpha function to use .</param>
- /// 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;
- }
-
- /// <summary>
- /// Time the transition should execute. Milliseconds.
- /// </summary>
- /// 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;
- /// <summary>
- /// Delay before the transition executes. Milliseconds.
- /// </summary>
- /// 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;
- /// <summary>
- /// Function to alter the transition path over time.
- /// </summary>
- /// 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;
- }
-
- /// <summary>
- /// LayoutTransition stores the aninmation setting for a transition conidition.
- /// </summary>
- /// 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
- {
- /// <summary>
- /// LayoutTransition default constructor.
- /// </summary>
- /// 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;
- }
- /// <summary>
- /// LayoutTransition constructor.
- /// </summary>
- /// <param name="condition">The animatable condition.</param>
- /// <param name="animatableProperty">the property to animate.</param>
- /// <param name="targetValue">target value of the property.</param>
- /// <param name="animator">Components to define the animator.</param>
- /// 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;
- }
-
- /// <summary>
- /// Condition for this Transition
- /// </summary>
- /// 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;}
- /// <summary>
- /// Property to animate.
- /// </summary>
- /// 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;}
- /// <summary>
- /// Components of the Animator.
- /// </summary>
- /// 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;}
- /// <summary>
- /// Target value to animate to.
- /// </summary>
- /// 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;}
- }
-
-
- /// <summary>
- /// Class to help manage the adding and updating of transitions.
- /// </summary>
- internal static class LayoutTransitionsHelper
- {
- /// <summary>
- /// Adds the given transition and condition to a transition list.
- /// </summary>
- /// <param name="targetTransitionList">The list to add the transition to.</param>
- /// <param name="condition">Condition for the transition.</param>
- /// <param name="transition">The transition to add.</param>
- /// <param name="explicitlySet">True is set explicitly, false if inherited.</param>
- static public void AddTransitionForCondition(
- Dictionary<TransitionCondition, TransitionList> 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
- }
- }
- }
-
- /// <summary>
- /// Retreive the transition list for the given condition.
- /// </summary>
- /// <param name="sourceTransitionCollection">The source collection of transition lists to retrieve.</param>
- /// <param name="condition">Condition for the transition.</param>
- /// <param name="transitionsForCondition">transition list to return as out parameter.</param>
- /// <returns>True if a transition list found for the given condition></returns>
- static public bool GetTransitionsListForCondition(
- Dictionary<TransitionCondition, TransitionList> 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;
- }
-
- /// <summary>
- /// Copy the transitions in the source list to the target list
- /// </summary>
- /// <param name="sourceTransitionList">The source transition list.</param>
- /// <param name="targetTransitionList">The target transition list to copy to.</param>
- 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
+++ /dev/null
-/* 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
-{
- /// <summary>
- /// [Draft] This class implements a linear box layout, automatically handling right to left or left to right direction change.
- /// </summary>
- internal class LinearLayout : LayoutGroup
- {
- /// <summary>
- /// [Draft] Enumeration for the direction in which the content is laid out
- /// </summary>
- public enum Orientation
- {
- /// <summary>
- /// Horizontal (row)
- /// </summary>
- Horizontal,
- /// <summary>
- /// Vertical (column)
- /// </summary>
- Vertical
- }
-
- /// <summary>
- /// [Draft] Enumeration for the alignment of the linear layout items
- /// </summary>
- public enum Alignment
- {
- /// <summary>
- /// At the left/right edge of the container (maps to LTR/RTL direction for horizontal orientation)
- /// </summary>
- Begin = 0x1,
- /// <summary>
- /// At the right/left edge of the container (maps to LTR/RTL direction for horizontal orientation)
- /// </summary>
- End = 0x2,
- /// <summary>
- /// At the horizontal center of the container
- /// </summary>
- CenterHorizontal = 0x4,
- /// <summary>
- /// At the top edge of the container
- /// </summary>
- Top = 0x8,
- /// <summary>
- /// At the bottom edge of the container
- /// </summary>
- Bottom = 0x10,
- /// <summary>
- /// At the vertical center of the container
- /// </summary>
- CenterVertical = 0x20,
- /// <summary>
- /// At the vertical and horizontal center of the container
- /// </summary>
- Center = 0x40
- }
-
- struct HeightAndWidthState
- {
- public MeasuredSize.StateType widthState;
- public MeasuredSize.StateType heightState;
-
- public HeightAndWidthState( MeasuredSize.StateType width, MeasuredSize.StateType height)
- {
- widthState = width;
- heightState = height;
- }
- }
-
- /// <summary>
- /// [Draft] Get/Set the orientation in the layout
- /// </summary>
- public LinearLayout.Orientation LinearOrientation
- {
- get
- {
- return _linearOrientation;
- }
- set
- {
- _linearOrientation = value;
- RequestLayout();
- }
- }
-
- /// <summary>
- /// [Draft] Get/Set the padding between cells in the layout
- /// </summary>
- public Size2D CellPadding
- {
- get
- {
- return _cellPadding;
- }
- set
- {
- _cellPadding = value;
- RequestLayout();
- }
- }
-
-
- /// <summary>
- /// [Draft] Get/Set the alignment in the layout
- /// </summary>
- 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;
-
- /// <summary>
- /// [Draft] Constructor
- /// </summary>
- 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
+++ /dev/null
-/*
- * 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
-{
- /// <summary>
- /// [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.
- /// </summary>
- internal struct MeasureSpecification
- {
- /// <summary>
- /// MeasureSpecification Size value.
- /// </summary>
- public LayoutLength Size;
-
- /// <summary>
- /// MeasureSpecification Mode.
- /// </summary>
- public MeasureSpecification.ModeType Mode;
-
- /// <summary>
- /// Constructor taking size and mode type.
- /// </summary>
- /// <param name="size">size value.</param>
- /// <param name="mode">mode vaue.</param>
- public MeasureSpecification(LayoutLength size, MeasureSpecification.ModeType mode)
- {
- Size = size;
- Mode = mode;
- }
-
- public enum ModeType
- {
- /// <summary>
- /// This is used by a parent to determine the desired dimension of a child layout.
- /// </summary>
- Unspecified,
- /// <summary>
- /// 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.
- /// </summary>
- Exactly,
- /// <summary>
- /// 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.
- /// </summary>
- AtMost
- }
- }
-}
+++ /dev/null
-/*
- * 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
-{
- /// <summary>
- /// [Draft] Class that encodes a measurement and a measure state, which is set if the measured size is too small.
- /// </summary>
- internal struct MeasuredSize
- {
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="measuredSize">size parameter</param>
- /// <param name="state">State</param>
- public MeasuredSize(LayoutLength measuredSize, MeasuredSize.StateType state)
- {
- Size = measuredSize;
- State = state;
- }
-
- /// <summary>
- /// Creates a MeasuredSize from a LayoutLength
- /// </summary>
- /// <param name="measuredSize">LayoutLength to create </param>
- public static implicit operator MeasuredSize(LayoutLength measuredSize)
- {
- return new MeasuredSize(measuredSize, StateType.MeasuredSizeOK);
- }
-
- /// <summary>
- /// LayoutLength size property
- /// </summary>
- public LayoutLength Size{ get; set;}
-
- /// <summary>
- /// Measured state for this size.
- /// </summary>
- public StateType State{ get; set; }
-
- /// <summary>
- /// Measured states for a Size value.
- /// </summary>
- public enum StateType
- {
- /// <summary>
- /// The measured size is good
- /// </summary>
- MeasuredSizeOK,
- /// <summary>
- /// The measured size is too small
- /// </summary>
- MeasuredSizeTooSmall
- }
- }
-}
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) =>
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);
"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
}
/// <summary>
- /// 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!
/// </summary>
/// <since_tizen> 3 </since_tizen>
[Obsolete("Deprecated in API5; Will be removed in API8. Please use 'Container GetParent() for derived class' instead! " +
///<summary>
/// The required policy for this dimension, LayoutParamPolicies enum or exact value.
///</summary>
- /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
- /// <remarks>
- /// Previously named LayoutWidthSpecification
- /// </remarks>
- [EditorBrowsable(EditorBrowsableState.Never)]
+ /// <since_tizen> 6 </since_tizen>
public int WidthSpecification
{
get
///<summary>
/// The required policy for this dimension, LayoutParamPolicies enum or exact value.
///</summary>
- /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
- /// <remarks>
- /// Previously named LayoutHeightSpecification
- /// </remarks>
+ /// <since_tizen> 6 </since_tizen>
[EditorBrowsable(EditorBrowsableState.Never)]
public int HeightSpecification
{
///<summary>
/// Gets the List of transitions for this View.
///</summary>
- /// Hidden-API which is usually used as Inhouse-API. If required to be opened as Public-API, ACR process is needed.
- [EditorBrowsable(EditorBrowsableState.Never)]
+ /// <since_tizen> 6 </since_tizen>
public Dictionary<TransitionCondition, TransitionList> LayoutTransitions
{
get
}
}
- internal LayoutTransition LayoutTransition
+ ///<summary>
+ /// Set a layout transitions for this View.
+ ///</summary>
+ /// <remarks>
+ /// Use LayoutTransitions to receive a collection of LayoutTransitions set on the View.
+ /// </remarks>
+ /// <since_tizen> 6 </since_tizen>
+ public LayoutTransition LayoutTransition
{
set
{
}
}
+
/// <summary>
- /// 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.
/// </summary>
- internal ColorMode ColorMode
+ /// <since_tizen> 6 </since_tizen>
+ 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
+ /// <summary>
+ /// The weight of the View, used to share available space in a layout with siblings.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public float Weight
{
get
{
}
}
+
+ /// <summary>
+ /// The color mode of View.
+ /// This specifies whether the View uses its own color, or inherits its parent color.
+ /// The default is ColorMode.UseOwnMultiplyParentColor.
+ /// </summary>
+ internal ColorMode ColorMode
+ {
+ set
+ {
+ SetColorMode(value);
+ }
+ get
+ {
+ return GetColorMode();
+ }
+ }
+
/// <summary>
/// Whether to load the BackgroundImage synchronously.
/// If not specified, the default is false, i.e. the BackgroundImage is loaded asynchronously.
}
}
- /// <summary>
- /// Set the layout on this View. Replaces any existing Layout.
- /// </summary>
- 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;
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))
--- /dev/null
+/* 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
+{
+ /// <summary>
+ /// [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.
+ /// </summary>
+ public class AbsoluteLayout : LayoutGroup
+ {
+ /// <summary>
+ /// Struct to store Measured states of height and width.
+ /// </summary>
+ private struct HeightAndWidthState
+ {
+ public MeasuredSize.StateType widthState;
+ public MeasuredSize.StateType heightState;
+
+ public HeightAndWidthState( MeasuredSize.StateType width, MeasuredSize.StateType height)
+ {
+ widthState = width;
+ heightState = height;
+ }
+ }
+
+ /// <summary>
+ /// [Draft] Constructor
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public AbsoluteLayout()
+ {
+ }
+
+ /// <summary>
+ /// Measure the layout and its content to determine the measured width and the measured height.<br />
+ /// </summary>
+ /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
+ /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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 ) );
+ }
+
+ /// <summary>
+ /// Assign a size and position to each of its children.<br />
+ /// </summary>
+ /// <param name="changed">This is a new size or position for this layout.</param>
+ /// <param name="left">Left position, relative to parent.</param>
+ /// <param name="top"> Top position, relative to parent.</param>
+ /// <param name="right">Right position, relative to parent.</param>
+ /// <param name="bottom">Bottom position, relative to parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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
--- /dev/null
+/* 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
+{
+ /// <summary>
+ /// [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.
+ /// </summary>
+ 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;
+ }
+
+ /// <summary>
+ /// Dispose.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ 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);
+ }
+ }
+
+ /// <summary>
+ /// Dispose.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ 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;
+ }
+
+ /// <summary>
+ /// [Draft] Creates a FlexLayout object.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ 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;
+ }
+
+ /// <summary>
+ /// [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.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public FlexDirection Direction
+ {
+ get
+ {
+ return GetFlexDirection();
+ }
+ set
+ {
+ SetFlexDirection(value);
+ }
+ }
+
+ /// <summary>
+ /// [Draft] Get/Set the justification in the layout.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public FlexJustification Justification
+ {
+ get
+ {
+ return GetFlexJustification();
+ }
+ set
+ {
+ SetFlexJustification(value);
+ }
+ }
+
+ /// <summary>
+ /// [Draft] Get/Set the wrap in the layout.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public FlexWrapType WrapType
+ {
+ get
+ {
+ return GetFlexWrap();
+ }
+ set
+ {
+ SetFlexWrap(value);
+ }
+ }
+
+ /// <summary>
+ /// [Draft] Get/Set the alignment of the layout content.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public AlignmentType Alignment
+ {
+ get
+ {
+ return GetFlexAlignment();
+ }
+ set
+ {
+ SetFlexAlignment(value);
+ }
+ }
+
+ /// <summary>
+ /// [Draft] Get/Set the alignment of the layout items.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public AlignmentType ItemsAlignment
+ {
+ get
+ {
+ return GetFlexItemsAlignment();
+ }
+ set
+ {
+ SetFlexItemsAlignment(value);
+ }
+ }
+
+ /// <summary>
+ /// [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.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public enum FlexDirection
+ {
+ /// <summary>
+ /// The flexible items are displayed vertically as a column
+ /// </summary>
+ Column,
+ /// <summary>
+ /// The flexible items are displayed vertically as a column, but in reverse order
+ /// </summary>
+ ColumnReverse,
+ /// <summary>
+ /// The flexible items are displayed horizontally as a row
+ /// </summary>
+ Row,
+ /// <summary>
+ /// The flexible items are displayed horizontally as a row, but in reverse order
+ /// </summary>
+ RowReverse
+ }
+
+ /// <summary>
+ /// [Draft] Enumeration for the alignment of the flex items when the items do not use all available space on the main-axis.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public enum FlexJustification
+ {
+ /// <summary>
+ /// Items are positioned at the beginning of the container
+ /// </summary>
+ FlexStart,
+ /// <summary>
+ /// Items are positioned at the center of the container
+ /// </summary>
+ Center,
+ /// <summary>
+ /// Items are positioned at the end of the container
+ /// </summary>
+ FlexEnd,
+ /// <summary>
+ /// Items are positioned with equal space between the lines
+ /// </summary>
+ SpaceBetween,
+ /// <summary>
+ /// Items are positioned with equal space before, between, and after the lines
+ /// </summary>
+ SpaceAround
+ }
+
+ /// <summary>
+ /// [Draft] Enumeration for the wrap type of the flex container when there is no enough room for all the items on one flex line.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public enum FlexWrapType
+ {
+ /// <summary>
+ /// Flex items laid out in single line (shrunk to fit the flex container along the main axis)
+ /// </summary>
+ NoWrap,
+ /// <summary>
+ /// Flex items laid out in multiple lines if needed
+ /// </summary>
+ Wrap
+ }
+
+ /// <summary>
+ /// [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.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public enum AlignmentType
+ {
+ /// <summary>
+ /// Inherits the same alignment from the parent
+ /// </summary>
+ Auto,
+ /// <summary>
+ /// At the beginning of the container
+ /// </summary>
+ FlexStart,
+ /// <summary>
+ /// At the center of the container
+ /// </summary>
+ Center,
+ /// <summary>
+ /// At the end of the container
+ /// </summary>
+ FlexEnd,
+ /// <summary>
+ /// Stretch to fit the container
+ /// </summary>
+ 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);
+ }
+
+ /// <summary>
+ /// Callback when child is added to container.<br />
+ /// Derived classes can use this to set their own child properties on the child layout's owner.<br />
+ /// </summary>
+ /// <param name="child">The Layout child.</param>
+ /// <since_tizen> 6 </since_tizen>
+ protected override void OnChildAdd(LayoutItem child)
+ {
+ InsertChild(child);
+ }
+
+ /// <summary>
+ /// Callback when child is removed from container.<br />
+ /// </summary>
+ /// <param name="child">The Layout child.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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);
+ }
+
+ /// <summary>
+ /// Measure the layout and its content to determine the measured width and the measured height.<br />
+ /// </summary>
+ /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
+ /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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 ) );
+ }
+
+ /// <summary>
+ /// Assign a size and position to each of its children.<br />
+ /// </summary>
+ /// <param name="changed">This is a new size or position for this layout.</param>
+ /// <param name="left">Left position, relative to parent.</param>
+ /// <param name="top"> Top position, relative to parent.</param>
+ /// <param name="right">Right position, relative to parent.</param>
+ /// <param name="bottom">Bottom position, relative to parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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
--- /dev/null
+/* 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
+{
+ /// <summary>
+ /// [Draft] This class implements a grid layout
+ /// </summary>
+ 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;
+
+ /// <summary>
+ /// [draft] GridLayout Constructor/>
+ /// </summary>
+ /// <returns> New Grid object.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public GridLayout()
+ {
+ _locations = new GridLocations();
+ }
+
+ /// <summary>
+ /// [Draft] Get/Set the number of columns in the grid
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public int Columns
+ {
+ get
+ {
+ return GetColumns();
+ }
+ set
+ {
+ SetColumns(value);
+ }
+ }
+
+
+ /// <summary>
+ /// [draft ] Sets the number of columns the GridLayout should have. />
+ /// </summary>
+ /// <param name="columns">The number of columns.</param>
+ internal void SetColumns(int columns)
+ {
+ _numberOfRequestedColumns = columns;
+ if( columns != _columns)
+ {
+ _columns = Math.Max(1, _columns);
+ _columns = columns;
+ RequestLayout();
+ }
+ }
+
+ /// <summary>
+ /// [draft ] Gets the number of columns in the Grid />
+ /// </summary>
+ /// <returns>The number of columns in the Grid.</returns>
+ 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;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Measure the layout and its content to determine the measured width and the measured height.<br />
+ /// </summary>
+ /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
+ /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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 ) );
+ }
+
+ /// <summary>
+ /// Assign a size and position to each of its children.<br />
+ /// </summary>
+ /// <param name="changed">This is a new size or position for this layout.</param>
+ /// <param name="left">Left position, relative to parent.</param>
+ /// <param name="top"> Top position, relative to parent.</param>
+ /// <param name="right">Right position, relative to parent.</param>
+ /// <param name="bottom">Bottom position, relative to parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ protected override void OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
+ {
+ List<GridLocations.Cell> 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++;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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
+{
+ /// <summary>
+ /// [Draft]
+ /// Interface that defines a layout Parent. Enables a layout child to access methods on its parent, e.g. Remove (during unparenting)
+ /// </summary>
+ public interface ILayoutParent
+ {
+ /// <summary>
+ /// Add this child to the parent.
+ /// </summary>
+ /// <param name="layoutItem">The layout child to add.</param>
+ /// <since_tizen> 6 </since_tizen>
+ void Add(LayoutItem layoutItem);
+
+ /// <summary>
+ /// Remove this child from the parent
+ /// </summary>
+ /// <param name="layoutItem">The layout child to add.</param>
+ /// <since_tizen> 6 </since_tizen>
+ void Remove(LayoutItem layoutItem);
+ }
+}
--- /dev/null
+/*
+ * 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
+{
+ /// <summary>
+ /// [Draft] LayoutGroup class providing container functionality.
+ /// </summary>
+ public class LayoutGroup : LayoutItem, ILayoutParent
+ {
+ /// <summary>
+ /// [Draft] List of child layouts in this container.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ protected List<LayoutItem> LayoutChildren{ get;} // Children of this LayoutGroup
+
+ /// <summary>
+ /// [Draft] Constructor
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public LayoutGroup()
+ {
+ LayoutChildren = new List<LayoutItem>();
+ }
+
+ /// <summary>
+ /// From ILayoutParent.<br />
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ /// <param name="childLayout">LayoutItem to add to the layout group.</param>
+ 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();
+ }
+
+ /// <summary>
+ /// Remove all layout children.<br />
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ 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();
+ }
+
+ /// <summary>
+ /// From ILayoutParent
+ /// </summary>
+ /// <param name="layoutItem">LayoutItem to remove from the layout group.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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.
+ }
+
+ /// <summary>
+ /// If the child has a layout then it is removed from the parent layout.
+ /// </summary>
+ /// <param name="child">Child View to remove.</param>
+ internal void RemoveChildFromLayoutGroup(View child)
+ {
+ Debug.Assert(child.Layout !=null);
+ Remove(child.Layout);
+ }
+
+ /// <summary>
+ /// Set all children in a LayoutGroup to the supplied condition.
+ /// Children with Add or Remove conditions should not be changed.
+ /// </summary>
+ 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;
+ }
+ }
+ }
+
+ }
+
+ /// <summary>
+ /// Callback for View.ChildAdded event
+ /// </summary>
+ /// <param name="sender">The object triggering the event.</param>
+ /// <param name="childAddedEvent">Arguments from the event.</param>
+ void OnChildAddedToOwner(object sender, View.ChildAddedEventArgs childAddedEvent)
+ {
+ AddChildToLayoutGroup(childAddedEvent.Added);
+ }
+
+ /// <summary>
+ /// Callback for View.ChildRemoved event
+ /// </summary>
+ /// <param name="sender">The object triggering the event.</param>
+ /// <param name="childRemovedEvent">Arguments from the event.</param>
+ void OnChildRemovedFromOwner(object sender, View.ChildRemovedEventArgs childRemovedEvent)
+ {
+ RemoveChildFromLayoutGroup(childRemovedEvent.Removed);
+ }
+
+ /// <summary>
+ /// 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.<br />
+ /// </summary>
+ /// <param name="parentMeasureSpec">The requirements for this view. MeasureSpecification.</param>
+ /// <param name="padding">The padding of this view for the current dimension and margins, if applicable. LayoutLength.</param>
+ /// <param name="childDimension"> How big the child wants to be in the current dimension. LayoutLength.</param>
+ /// <returns>a MeasureSpec for the child.</returns>
+ 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 );
+ }
+
+ /// <summary>
+ /// Measure the layout and its content to determine the measured width and the measured height.<br />
+ /// 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. <br />
+ /// </summary>
+ /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
+ /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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 ) );
+ }
+
+ /// <summary>
+ /// Called from Layout() when this layout should assign a size and position to each of its children.<br />
+ /// Derived classes with children should override this method and call Layout() on each of their children.<br />
+ /// </summary>
+ /// <param name="changed">This is a new size or position for this layout.</param>
+ /// <param name="left">Left position, relative to parent.</param>
+ /// <param name="top"> Top position, relative to parent.</param>
+ /// <param name="right">Right position, relative to parent.</param>
+ /// <param name="bottom">Bottom position, relative to parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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 );
+ }
+ }
+ }
+
+ /// <summary>
+ /// Overridden method called when the layout is attached to an owner.<br />
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ 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.
+
+ /// <summary>
+ /// Callback when child is added to container.<br />
+ /// Derived classes can use this to set their own child properties on the child layout's owner.<br />
+ /// </summary>
+ /// <param name="child">The Layout child.</param>
+ /// <since_tizen> 6 </since_tizen>
+ protected virtual void OnChildAdd(LayoutItem child)
+ {
+ }
+
+ /// <summary>
+ /// Callback when child is removed from container.<br />
+ /// </summary>
+ /// <param name="child">The Layout child.</param>
+ /// <since_tizen> 6 </since_tizen>
+ protected virtual void OnChildRemove(LayoutItem child)
+ {
+ }
+
+ /// <summary>
+ /// Ask all of the children of this view to measure themselves, taking into
+ /// account both the MeasureSpec requirements for this view and its padding.<br />
+ /// The heavy lifting is done in GetChildMeasureSpec.<br />
+ /// </summary>
+ /// <param name="widthMeasureSpec">The width requirements for this view.</param>
+ /// <param name="heightMeasureSpec">The height requirements for this view.</param>
+ /// <since_tizen> 6 </since_tizen>
+ protected virtual void MeasureChildren(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
+ {
+ foreach( LayoutItem childLayout in LayoutChildren )
+ {
+ MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
+ }
+ }
+
+ /// <summary>
+ /// Ask one of the children of this view to measure itself, taking into
+ /// account both the MeasureSpec requirements for this view and its padding.<br />
+ /// The heavy lifting is done in GetChildMeasureSpecification.<br />
+ /// </summary>
+ /// <param name="child">The child to measure.</param>
+ /// <param name="parentWidthMeasureSpec">The width requirements for this view.</param>
+ /// <param name="parentHeightMeasureSpec">The height requirements for this view.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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 );
+ }
+
+ /// <summary>
+ /// Ask one of the children of this view to measure itself, taking into
+ /// account both the MeasureSpec requirements for this view and its padding.<br />
+ /// and margins. The child must have MarginLayoutParams The heavy lifting is
+ /// done in GetChildMeasureSpecification.<br />
+ /// </summary>
+ /// <param name="child">The child to measure.</param>
+ /// <param name="parentWidthMeasureSpec">The width requirements for this view.</param>
+ /// <param name="widthUsed">Extra space that has been used up by the parent horizontally (possibly by other children of the parent).</param>
+ /// <param name="parentHeightMeasureSpec">The height requirements for this view.</param>
+ /// <param name="heightUsed">Extra space that has been used up by the parent vertically (possibly by other children of the parent).</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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
--- /dev/null
+/*
+ * 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
+ };
+
+ /// <summary>
+ /// [Draft] Base class for layouts. It is used to layout a View
+ /// It can be laid out by a LayoutGroup.
+ /// </summary>
+ 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;
+
+ /// <summary>
+ /// [Draft] Condition event that is causing this Layout to transition.
+ /// </summary>
+ internal TransitionCondition ConditionForAnimation{get; set;}
+
+ /// <summary>
+ /// [Draft] The View that this Layout has been assigned to.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public View Owner{get; set;} // Should not keep a View alive.
+
+ /// <summary>
+ /// [Draft] Margin for this LayoutItem
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public Extents Margin
+ {
+ get
+ {
+ return _margin;
+ }
+ set
+ {
+ _margin = value;
+ RequestLayout();
+ }
+ }
+
+ /// <summary>
+ /// [Draft] Padding for this LayoutItem
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public Extents Padding
+ {
+ get
+ {
+ return _padding;
+ }
+ set
+ {
+ _padding = value;
+ RequestLayout();
+ }
+ }
+
+ /// <summary>
+ /// [Draft] Constructor
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public LayoutItem()
+ {
+ Initialize();
+ }
+
+ /// <summary>
+ /// [Draft] Set parent to this layout.
+ /// </summary>
+ /// <param name="parent">Parent to set on this Layout.</param>
+ internal void SetParent( ILayoutParent parent)
+ {
+ Parent = parent as LayoutGroup;
+ }
+
+ /// <summary>
+ /// Unparent this layout from it's owner, and remove any layout children in derived types. <br />
+ /// </summary>
+ 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);
+ }
+
+ /// <summary>
+ /// Initialize the layout and allow derived classes to also perform any operations
+ /// </summary>
+ /// <param name="owner">Owner of this Layout.</param>
+ 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;
+ }
+ }
+
+ /// <summary>
+ /// This is called to find out how big a layout should be. <br />
+ /// The parent supplies constraint information in the width and height parameters. <br />
+ /// 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. <br />
+ /// </summary>
+ /// <param name="widthMeasureSpec"> Horizontal space requirements as imposed by the parent.</param>
+ /// <param name="heightMeasureSpec">Vertical space requirements as imposed by the parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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;
+ }
+
+ /// <summary>
+ /// Assign a size and position to a layout and all of its descendants. <br />
+ /// 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<br />
+ /// measurements that were stored in the measure pass.<br />
+ /// </summary>
+ /// <param name="left">Left position, relative to parent.</param>
+ /// <param name="top">Top position, relative to parent.</param>
+ /// <param name="right">Right position, relative to parent.</param>
+ /// <param name="bottom">Bottom position, relative to parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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;
+ }
+ }
+
+ /// <summary>
+ /// Utility to return a default size.<br />
+ /// Uses the supplied size if the MeasureSpecification imposed no constraints. Will get larger if allowed by the
+ /// MeasureSpecification.<br />
+ /// </summary>
+ /// <param name="size"> Default size for this layout.</param>
+ /// <param name="measureSpecification"> Constraints imposed by the parent.</param>
+ /// <returns>The size this layout should be.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ 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;
+ }
+
+ /// <summary>
+ /// Get the Layouts parent
+ /// </summary>
+ /// <returns>Layout parent with an LayoutParent interface</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public ILayoutParent GetParent()
+ {
+ return Parent;
+ }
+
+ /// <summary>
+ /// Request that this layout is re-laid out.<br />
+ /// This will make this layout and all it's parent layouts dirty.<br />
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public void RequestLayout()
+ {
+ Flags = Flags | LayoutFlags.ForceLayout;
+ Window.Instance.LayoutController.RequestLayout(this);
+ }
+
+ /// <summary>
+ /// Predicate to determine if this layout has been requested to re-layout.<br />
+ /// </summary>
+
+ internal bool LayoutRequested
+ {
+ get
+ {
+ return ( Flags & LayoutFlags.ForceLayout) == LayoutFlags.ForceLayout;
+ }
+ }
+
+ /// <summary>
+ /// Get the measured width (without any measurement flags).<br />
+ /// This method should be used only during measurement and layout calculations.<br />
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public MeasuredSize MeasuredWidth{ get; set; } = new MeasuredSize( new LayoutLength(-3), MeasuredSize.StateType.MeasuredSizeOK);
+
+ /// <summary>
+ /// Get the measured height (without any measurement flags).<br />
+ /// This method should be used only during measurement and layout calculations.<br />
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public MeasuredSize MeasuredHeight{ get; set; } = new MeasuredSize( new LayoutLength(-3), MeasuredSize.StateType.MeasuredSizeOK);
+
+ /// <summary>
+ /// Returns the suggested minimum width that the layout should use.<br />
+ /// This returns the maximum of the layout's minimum width and the owner's natural width.<br />
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public LayoutLength SuggestedMinimumWidth
+ {
+ get
+ {
+ int naturalWidth = Owner.NaturalSize2D.Width;
+ return new LayoutLength(Math.Max( MinimumWidth.AsDecimal(), naturalWidth ));
+ }
+ }
+
+ /// <summary>
+ /// Returns the suggested minimum height that the layout should use.<br />
+ /// This returns the maximum of the layout's minimum height and the owner's natural height.<br />
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public LayoutLength SuggestedMinimumHeight
+ {
+ get
+ {
+ int naturalHeight = Owner.NaturalSize2D.Height;
+ return new LayoutLength(Math.Max( MinimumHeight.AsDecimal(), naturalHeight ));
+ }
+ }
+
+ /// <summary>
+ /// Sets the minimum width of the layout.<br />
+ /// 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).<br />
+ /// 1. if the owner's View.WidthSpecification has exact value, then that value overrides the minimum size.<br />
+ /// 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()).<br />
+ /// 3. If the owner's View.WidthSpecification is set to View.LayoutParamPolicies.MatchParent, then the parent width takes precedence over the minimum width.<br />
+ /// </summary>
+ internal LayoutLength MinimumWidth {get; set;}
+
+ /// <summary>
+ /// Sets the minimum height of the layout.<br />
+ /// 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).<br />
+ /// 1. if the owner's View.HeightSpecification has exact value, then that value overrides the minimum size.<br />
+ /// 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()).<br />
+ /// 3. If the owner's View.HeightSpecification is set to View.LayoutParamPolicies.MatchParent, then the parent height takes precedence over the minimum height.<br />
+ /// </summary>
+ internal LayoutLength MinimumHeight {get; set;}
+
+ ///<summary>
+ /// Utility to reconcile a desired size and state, with constraints imposed by a MeasureSpecification.
+ ///</summary>
+ /// <param name="size"> How big the layout wants to be.</param>
+ /// <param name="measureSpecification"> Constraints imposed by the parent.</param>
+ /// <param name="childMeasuredState"> Size information bit mask for the layout's children.</param>
+ /// <returns> A measured size, which may indicate that it is too small. </returns>
+ /// <since_tizen> 6 </since_tizen>
+ 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;
+ }
+
+ /// <summary>
+ /// This method must be called by OnMeasure(MeasureSpec,MeasureSpec) to store the measured width and measured height.
+ /// </summary>
+ /// <param name="measuredWidth">The measured width of this layout.</param>
+ /// <param name="measuredHeight">The measured height of this layout.</param>
+ /// <since_tizen> 6 </since_tizen>
+ protected void SetMeasuredDimensions( MeasuredSize measuredWidth, MeasuredSize measuredHeight )
+ {
+ MeasuredWidth = measuredWidth;
+ MeasuredHeight = measuredHeight;
+ Flags = Flags | LayoutFlags.MeasuredDimensionSet;
+ }
+
+ /// <summary>
+ /// Measure the layout and its content to determine the measured width and the
+ /// measured height.<br />
+ /// 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.<br />
+ /// 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.<br />
+ /// </summary>
+ /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
+ /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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 ) );
+ }
+
+ /// <summary>
+ /// Called from Layout() when this layout should assign a size and position to each of its children. <br />
+ /// Derived classes with children should override this method and call Layout() on each of their children. <br />
+ /// </summary>
+ /// <param name="changed">This is a new size or position for this layout.</param>
+ /// <param name="left">Left position, relative to parent.</param>
+ /// <param name="top">Top position, relative to parent.</param>
+ /// <param name="right">Right position, relative to parent.</param>
+ /// <param name="bottom">Bottom position, relative to parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ protected virtual void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
+ {
+ }
+
+ /// <summary>
+ /// Virtual method to allow derived classes to remove any children before it is removed from
+ /// its parent.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ protected virtual void OnUnparent()
+ {
+ }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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
+{
+ /// <summary>
+ /// [Draft] A type that represents a layout length. Currently, this implies pixels, but could be extended to handle device dependant sizes, etc.
+ /// </summary>
+ public struct LayoutLength
+ {
+ private float _value;
+
+ /// <summary>
+ /// [Draft] Constructor from an int
+ /// </summary>
+ /// <param name="value">Int to initialize with.</param>
+ /// <since_tizen> 6 </since_tizen>
+ public LayoutLength(int value)
+ {
+ _value = value;
+ }
+
+ /// <summary>
+ /// [Draft] Constructor from a float
+ /// </summary>
+ /// <param name="value">Float to initialize with.</param>
+ /// <since_tizen> 6 </since_tizen>
+ public LayoutLength(float value)
+ {
+ _value = value;
+ }
+
+ /// <summary>
+ /// [Draft] Constructor from a LayoutLength
+ /// </summary>
+ /// <param name="layoutLength">LayoutLength object to initialize with.</param>
+ /// <since_tizen> 6 </since_tizen>
+ public LayoutLength(LayoutLength layoutLength)
+ {
+ _value = layoutLength._value;
+ }
+
+ /// <summary>
+ /// [Draft] Return value as rounded value (whole number), best used as final output
+ /// </summary>
+ /// <returns>The layout length value as a rounded whole number.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public float AsRoundedValue()
+ {
+ return (float)Math.Round((decimal)_value, MidpointRounding.AwayFromZero);
+ }
+
+ /// <summary>
+ /// [Draft] Return value as the raw decimal value, best used for calculations
+ /// </summary>
+ /// <returns>The layout length value as the raw decimal value.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public float AsDecimal()
+ {
+ return _value;
+ }
+
+ /// <summary>
+ /// [Draft] The == operator.
+ /// </summary>
+ /// <param name="arg1">The first value.</param>
+ /// <param name="arg2">The second value</param>
+ /// <returns>true if LayoutLengths are equal</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public static bool operator ==(LayoutLength arg1, LayoutLength arg2)
+ {
+ return arg1.Equals(arg2);
+ }
+
+ /// <summary>
+ /// [Draft] The != operator.
+ /// </summary>
+ /// <param name="arg1">The first value.</param>
+ /// <param name="arg2">The second value</param>
+ /// <returns>true if LayoutLengths are not equal</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public static bool operator !=(LayoutLength arg1, LayoutLength arg2)
+ {
+ return !arg1.Equals(arg2);
+ }
+
+ /// <summary>
+ /// Determines whether the specified object is equal to the current object.
+ /// </summary>
+ /// <param name="obj">The object to compare with the current object.</param>
+ /// <returns>true if equal LayoutLength, else false.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public override bool Equals(object obj)
+ {
+ if (obj is LayoutLength)
+ {
+ return this.Equals((LayoutLength)obj);
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Determines whether the specified object is equal to the current object.
+ /// </summary>
+ /// <param name="layoutLength">The LayoutLength to compare with the current LayoutLength.</param>
+ /// <returns>true if equal LayoutLengths, else false.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public bool Equals(LayoutLength layoutLength)
+ {
+ return (Math.Abs(_value - layoutLength._value ) <= float.Epsilon);
+ }
+
+ /// <summary>
+ /// A hash code for the current object.
+ /// </summary>
+ /// <returns>Calculated hash code.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public override int GetHashCode()
+ {
+ return (int)Math.Ceiling(_value);
+ }
+
+ /// <summary>
+ /// The addition operator.
+ /// </summary>
+ /// <param name="arg1">The first value.</param>
+ /// <param name="arg2">The second value.</param>
+ /// <returns>The LayoutLength containing the result of the addition.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public static LayoutLength operator +(LayoutLength arg1, LayoutLength arg2)
+ {
+ return new LayoutLength( arg1._value + arg2._value );
+ }
+
+ /// <summary>
+ /// The addition operator.
+ /// </summary>
+ /// <param name="arg1">The first value.</param>
+ /// <param name="arg2">The second value.</param>
+ /// <returns>The LayoutLength containing the result of the addition.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public static LayoutLength operator +(LayoutLength arg1, int arg2)
+ {
+ return new LayoutLength(arg1._value + (float)arg2);
+ }
+
+ /// <summary>
+ /// The subtraction operator.
+ /// </summary>
+ /// <param name="arg1">The first value.</param>
+ /// <param name="arg2">The second value.</param>
+ /// <returns>The LayoutLength containing the result of the subtraction.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public static LayoutLength operator -(LayoutLength arg1, LayoutLength arg2)
+ {
+ return new LayoutLength(arg1._value - arg2._value);
+ }
+
+ /// <summary>
+ /// The subtraction operator.
+ /// </summary>
+ /// <param name="arg1">The first value.</param>
+ /// <param name="arg2">The second value.</param>
+ /// <returns>The LayoutLength containing the result of the subtraction.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public static LayoutLength operator -(LayoutLength arg1, int arg2)
+ {
+ return new LayoutLength(arg1._value - (float)arg2);
+ }
+
+ /// <summary>
+ /// The multiplication operator.
+ /// </summary>
+ /// <param name="arg1">The first value.</param>
+ /// <param name="arg2">The second value.</param>
+ /// <returns>The LayoutLength containing the result of the multiplication.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public static LayoutLength operator *(LayoutLength arg1, LayoutLength arg2)
+ {
+ return new LayoutLength(arg1._value * arg2._value);
+ }
+
+ /// <summary>
+ /// Th multiplication operator.
+ /// </summary>
+ /// <param name="arg1">The first value.</param>
+ /// <param name="arg2">The int value to scale the LayoutLength.</param>
+ /// <returns>The LayoutLength containing the result of the scaling.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public static LayoutLength operator *(LayoutLength arg1, int arg2)
+ {
+ return new LayoutLength(arg1._value * arg2);
+ }
+
+ /// <summary>
+ /// The division operator.
+ /// </summary>
+ /// <param name="arg1">The first value.</param>
+ /// <param name="arg2">The second value.</param>
+ /// <returns>The LayoutLength containing the result of the division.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public static LayoutLength operator /(LayoutLength arg1, LayoutLength arg2)
+ {
+ return new LayoutLength(arg1._value / arg2._value);
+ }
+
+ /// <summary>
+ /// Th division operator.
+ /// </summary>
+ /// <param name="arg1">The first value.</param>
+ /// <param name="arg2">The int value to scale the vector by.</param>
+ /// <returns>The LayoutLength containing the result of the scaling.</returns>
+ /// <since_tizen> 6 </since_tizen>
+ public static LayoutLength operator /(LayoutLength arg1, int arg2)
+ {
+ return new LayoutLength(arg1._value / (float)arg2);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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
+{
+ /// <summary>
+ /// Define a List of LayoutTransitions
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public class TransitionList : List<LayoutTransition> {}
+
+ /// <summary>
+ /// The conditions for transitions.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ [FlagsAttribute] public enum TransitionCondition
+ {
+ /// <summary>
+ /// Default when a condition has not been set.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ Unspecified = 0,
+ /// <summary>
+ /// Animate changing layout to another layout.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+
+ LayoutChanged = 1,
+ /// <summary>
+ /// Animate adding item.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+
+ Add = 2,
+ /// <summary>
+ /// Animate removing item.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+
+ Remove = 4,
+ /// <summary>
+ /// Animation when an item changes due to a being added.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+
+ ChangeOnAdd = 8,
+ /// <summary>
+ /// Animation when an item changes due to a being removed.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+
+ ChangeOnRemove = 16
+ }
+
+ /// <summary>
+ /// The properties that can be animated.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public enum AnimatableProperties
+ {
+ /// <summary>
+ /// Position property.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+
+ Position,
+ /// <summary>
+ /// Size property.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+
+ Size,
+ /// <summary>
+ /// Opacity property.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+
+ Opacity
+ }
+
+ /// <summary>
+ /// Parts of the transition that can be configured to provide a custom effect.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public class TransitionComponents
+ {
+ /// <summary>
+ /// TransitionComponents default constructor.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public TransitionComponents()
+ {
+ Delay = 0;
+ Duration = 100;
+ AlphaFunction = new AlphaFunction(AlphaFunction.BuiltinFunctions.Linear);
+ }
+
+ /// <summary>
+ /// TransitionComponents constructor. Stores delay, duration and AlphaFunction.
+ /// </summary>
+ /// <param name="delay">The delay before the animator starts.</param>
+ /// <param name="duration">the duration of the animator.</param>
+ /// <param name="alphaFunction">alpha function to use .</param>
+ /// <since_tizen> 6 </since_tizen>
+
+ public TransitionComponents(int delay, int duration, AlphaFunction alphaFunction)
+ {
+ Delay = delay;
+ Duration = duration;
+ AlphaFunction = alphaFunction;
+ }
+
+ /// <summary>
+ /// Get, Set the time transition should execute for . Milliseconds.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public int Duration;
+ /// <summary>
+ /// Get, Set the delay before the transition executes. Milliseconds.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public int Delay;
+ /// <summary>
+ /// Get, Set the function to alter the transition path over time.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public AlphaFunction AlphaFunction;
+ }
+
+ /// <summary>
+ /// LayoutTransition stores the animation setting for a transition conidition.
+ /// </summary>
+ public class LayoutTransition
+ {
+ /// <summary>
+ /// LayoutTransition default constructor.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public LayoutTransition()
+ {
+ Condition = TransitionCondition.Unspecified;
+ AnimatableProperty = AnimatableProperties.Position;
+ Animator = null;
+ TargetValue = 0;
+ }
+ /// <summary>
+ /// LayoutTransition constructor.
+ /// </summary>
+ /// <param name="condition">The animatable condition.</param>
+ /// <param name="animatableProperty">the property to animate.</param>
+ /// <param name="targetValue">target value of the property.</param>
+ /// <param name="animator">Components to define the animator.</param>
+ /// <since_tizen> 6 </since_tizen>
+ public LayoutTransition( TransitionCondition condition,
+ AnimatableProperties animatableProperty,
+ object targetValue,
+ TransitionComponents animator)
+ {
+ Condition = condition;
+ AnimatableProperty = animatableProperty;
+ Animator = animator;
+ TargetValue = targetValue;
+ }
+
+ /// <summary>
+ /// Condition for this Transition
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+
+ public TransitionCondition Condition{get; set;}
+ /// <summary>
+ /// Property to animate.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+
+ public AnimatableProperties AnimatableProperty{get; set;}
+ /// <summary>
+ /// Components of the Animator.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+
+ public TransitionComponents Animator{get; set;}
+ /// <summary>
+ /// Target value to animate to.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+
+ public object TargetValue{get; set;}
+ }
+
+
+ /// <summary>
+ /// Class to help manage the adding and updating of transitions.
+ /// </summary>
+ internal static class LayoutTransitionsHelper
+ {
+ /// <summary>
+ /// Adds the given transition and condition to a transition list.
+ /// </summary>
+ /// <param name="targetTransitionList">The list to add the transition to.</param>
+ /// <param name="condition">Condition for the transition.</param>
+ /// <param name="transition">The transition to add.</param>
+ /// <param name="explicitlySet">True is set explicitly, false if inherited.</param>
+ static public void AddTransitionForCondition(
+ Dictionary<TransitionCondition, TransitionList> 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
+ }
+ }
+ }
+
+ /// <summary>
+ /// Retreive the transition list for the given condition.
+ /// </summary>
+ /// <param name="sourceTransitionCollection">The source collection of transition lists to retrieve.</param>
+ /// <param name="condition">Condition for the transition.</param>
+ /// <param name="transitionsForCondition">transition list to return as out parameter.</param>
+ /// <returns>True if a transition list found for the given condition></returns>
+ static public bool GetTransitionsListForCondition(
+ Dictionary<TransitionCondition, TransitionList> 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;
+ }
+
+ /// <summary>
+ /// Copy the transitions in the source list to the target list
+ /// </summary>
+ /// <param name="sourceTransitionList">The source transition list.</param>
+ /// <param name="targetTransitionList">The target transition list to copy to.</param>
+ 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
--- /dev/null
+/* 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
+{
+ /// <summary>
+ /// [Draft] This class implements a linear box layout, automatically handling right to left or left to right direction change.
+ /// </summary>
+ public class LinearLayout : LayoutGroup
+ {
+ /// <summary>
+ /// [Draft] Enumeration for the direction in which the content is laid out
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public enum Orientation
+ {
+ /// <summary>
+ /// Horizontal (row)
+ /// </summary>
+ Horizontal,
+ /// <summary>
+ /// Vertical (column)
+ /// </summary>
+ Vertical
+ }
+
+ /// <summary>
+ /// [Draft] Enumeration for the alignment of the linear layout items
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public enum Alignment
+ {
+ /// <summary>
+ /// At the left/right edge of the container (maps to LTR/RTL direction for horizontal orientation)
+ /// </summary>
+ Begin = 0x1,
+ /// <summary>
+ /// At the right/left edge of the container (maps to LTR/RTL direction for horizontal orientation)
+ /// </summary>
+ End = 0x2,
+ /// <summary>
+ /// At the horizontal center of the container
+ /// </summary>
+ CenterHorizontal = 0x4,
+ /// <summary>
+ /// At the top edge of the container
+ /// </summary>
+ Top = 0x8,
+ /// <summary>
+ /// At the bottom edge of the container
+ /// </summary>
+ Bottom = 0x10,
+ /// <summary>
+ /// At the vertical center of the container
+ /// </summary>
+ CenterVertical = 0x20,
+ /// <summary>
+ /// At the vertical and horizontal center of the container
+ /// </summary>
+ Center = 0x40
+ }
+
+ struct HeightAndWidthState
+ {
+ public MeasuredSize.StateType widthState;
+ public MeasuredSize.StateType heightState;
+
+ public HeightAndWidthState( MeasuredSize.StateType width, MeasuredSize.StateType height)
+ {
+ widthState = width;
+ heightState = height;
+ }
+ }
+
+ /// <summary>
+ /// [Draft] Get/Set the orientation in the layout
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public LinearLayout.Orientation LinearOrientation
+ {
+ get
+ {
+ return _linearOrientation;
+ }
+ set
+ {
+ _linearOrientation = value;
+ RequestLayout();
+ }
+ }
+
+ /// <summary>
+ /// [Draft] Get/Set the padding between cells in the layout
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public Size2D CellPadding
+ {
+ get
+ {
+ return _cellPadding;
+ }
+ set
+ {
+ _cellPadding = value;
+ RequestLayout();
+ }
+ }
+
+
+ /// <summary>
+ /// [Draft] Get/Set the alignment in the layout
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ 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;
+
+ /// <summary>
+ /// [Draft] Constructor
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public LinearLayout()
+ {
+ }
+
+ /// <summary>
+ /// Measure the layout and its content to determine the measured width and the measured height.
+ /// </summary>
+ /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
+ /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
+ {
+ if (_linearOrientation == Orientation.Horizontal)
+ {
+ MeasureHorizontal(widthMeasureSpec, heightMeasureSpec);
+ }
+ else
+ {
+ MeasureVertical(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ /// <summary>
+ /// Layout should assign a size and position to each of its children.<br />
+ /// </summary>
+ /// <param name="changed">This is a new size or position for this layout.</param>
+ /// <param name="left">Left position, relative to parent.</param>
+ /// <param name="top"> Top position, relative to parent.</param>
+ /// <param name="right">Right position, relative to parent.</param>
+ /// <param name="bottom">Bottom position, relative to parent.</param>
+ /// <since_tizen> 6 </since_tizen>
+ 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
--- /dev/null
+/*
+ * 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
+{
+ /// <summary>
+ /// [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.
+ /// </summary>
+ public struct MeasureSpecification
+ {
+ /// <summary>
+ /// MeasureSpecification Size value.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public LayoutLength Size;
+
+ /// <summary>
+ /// MeasureSpecification Mode.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public MeasureSpecification.ModeType Mode;
+
+ /// <summary>
+ /// Constructor taking size and mode type.
+ /// </summary>
+ /// <param name="size">size value.</param>
+ /// <param name="mode">mode value.</param>
+ /// <since_tizen> 6 </since_tizen>
+ public MeasureSpecification(LayoutLength size, MeasureSpecification.ModeType mode)
+ {
+ Size = size;
+ Mode = mode;
+ }
+
+ /// <summary>
+ /// Size mode for this MeasureSpecification
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public enum ModeType
+ {
+ /// <summary>
+ /// This is used by a parent to determine the desired dimension of a child layout.
+ /// </summary>
+ Unspecified,
+ /// <summary>
+ /// 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.
+ /// </summary>
+ Exactly,
+ /// <summary>
+ /// 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.
+ /// </summary>
+ AtMost
+ }
+ }
+}
--- /dev/null
+/*
+ * 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
+{
+ /// <summary>
+ /// [Draft] Class that encodes a measurement and a measure state, which is set if the measured size is too small.
+ /// </summary>
+ public struct MeasuredSize
+ {
+ /// <summary>
+ /// Constructor
+ /// </summary>
+ /// <param name="measuredSize">size parameter</param>
+ /// <param name="state">State</param>
+ /// <since_tizen> 6 </since_tizen>
+ public MeasuredSize(LayoutLength measuredSize, MeasuredSize.StateType state)
+ {
+ Size = measuredSize;
+ State = state;
+ }
+
+ /// <summary>
+ /// Creates a MeasuredSize from a LayoutLength
+ /// </summary>
+ /// <param name="measuredSize">LayoutLength to create </param>
+ /// <since_tizen> 6 </since_tizen>
+ /// <returns> Returns a MeasuredSize object</returns>
+ public static implicit operator MeasuredSize(LayoutLength measuredSize)
+ {
+ return new MeasuredSize(measuredSize, StateType.MeasuredSizeOK);
+ }
+
+ /// <summary>
+ /// LayoutLength size property
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public LayoutLength Size{ get; set;}
+
+ /// <summary>
+ /// Measured state for this size.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public StateType State{ get; set; }
+
+ /// <summary>
+ /// Measured states for a Size value.
+ /// </summary>
+ /// <since_tizen> 6 </since_tizen>
+ public enum StateType
+ {
+ /// <summary>
+ /// The measured size is good
+ /// </summary>
+ MeasuredSizeOK,
+ /// <summary>
+ /// The measured size is too small
+ /// </summary>
+ MeasuredSizeTooSmall
+ }
+ }
+}
}
}
+ /// <summary>
+ /// Get the LayoutController for this Window.
+ /// </summary>
internal LayoutController LayoutController
{
get
var center = childIncrement / 2;
// Check layout direction
- var view = GetOwner();
+ var view = Owner;
ViewLayoutDirectionType layoutDirection = view.LayoutDirection;
for (uint i = 0; i < count; i++)
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!
}
var center = childIncrement / 2;
- var view = GetOwner();
+ var view = Owner;
ViewLayoutDirectionType layoutDirection = view.LayoutDirection;
for (uint i = 0; i < ChildCount; ++i)
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!
}
var center = childIncrement / 2;
- var view = GetOwner();
+ var view = Owner;
ViewLayoutDirectionType layoutDirection = view.LayoutDirection;
for (uint i = 0; i < ChildCount; ++i)
var center = childIncrement / 2;
// Check layout direction
- var view = GetOwner();
+ var view = Owner;
ViewLayoutDirectionType layoutDirection = view.LayoutDirection;
for (uint i = 0; i < count; i++)
var center = childIncrement / 2;
// Check layout direction
- var view = GetOwner();
+ var view = Owner;
ViewLayoutDirectionType layoutDirection = view.LayoutDirection;
for (uint i = 0; i < count; i++)