[NUI] Add Horizontal Grid (#1461)
authorhuiyueun <35286162+huiyueun@users.noreply.github.com>
Thu, 19 Mar 2020 05:24:55 +0000 (14:24 +0900)
committerGitHub <noreply@github.com>
Thu, 19 Mar 2020 05:24:55 +0000 (14:24 +0900)
Signed-off-by: huiyu.eun <huiyu.eun@samsung.com>
src/Tizen.NUI/src/internal/Layouting/GridLocations.cs
src/Tizen.NUI/src/public/Layouting/GridLayout.cs

index fd987b7..f36dcee 100755 (executable)
@@ -43,7 +43,7 @@ namespace Tizen.NUI
             /// <param name="top">The top y coordinate.</param>
             /// <param name="bottom">The bottom y coordinate.</param>
 
-            public Cell( int start, int end, int top, int bottom)
+            public Cell(int start, int end, int top, int bottom)
             {
                 Start = start;
                 End = end;
@@ -73,19 +73,18 @@ namespace Tizen.NUI
         /// <summary>
         /// [Draft] Uses the given parameters to calculate the x,y coordinates of each cell and cell size.
         /// </summary>
-        public void CalculateLocations( int numberOfColumns, int availableWidth,
-                                        int availableHeight, int numberOfCells)
+        public void CalculateLocations(int numberOfColumns, int availableWidth, int availableHeight, int numberOfCells)
         {
-            numberOfColumns = Math.Max( numberOfColumns, 1 );
+            numberOfColumns = Math.Max(numberOfColumns, 1);
             _locationsVector.Clear();
 
             // Calculate width and height of columns and rows.
 
             // Calculate numbers of rows, round down result as later check for remainder.
             int remainder = 0;
-            int numberOfRows = Math.DivRem(numberOfCells,numberOfColumns, out remainder);
+            int numberOfRows = Math.DivRem(numberOfCells, numberOfColumns, out remainder);
             // If number of cells not cleanly dividable by columns, add another row to house remainder cells.
-            numberOfRows += (remainder > 0) ? 1:0;
+            numberOfRows += (remainder > 0) ? 1 : 0;
 
             // Rounding on column widths performed here,
             // if visually noticeable then can divide the space explicitly between columns.
@@ -93,28 +92,28 @@ namespace Tizen.NUI
 
             int rowHeight = availableHeight;
 
-            if( numberOfRows > 0 )
+            if (numberOfRows > 0)
             {
                 // Column height supplied so use this unless exceeds available height.
                 rowHeight = (availableHeight / numberOfRows);
             }
 
-            int  y1 = 0;
-            int  y2 = y1 + rowHeight;
+            int y1 = 0;
+            int y2 = y1 + rowHeight;
 
             // Calculate start, end, top and bottom coordinate of each cell.
 
             // Iterate rows
-            for( var i = 0u; i < numberOfRows; i++ )
+            for (var i = 0u; i < numberOfRows; i++)
             {
                 int x1 = 0;
                 int x2 = x1 + columnWidth;
 
                 // Iterate columns
-                for( var j = 0; j < numberOfColumns; j++ )
+                for (var j = 0; j < numberOfColumns; j++)
                 {
-                    Cell cell = new Cell( x1, x2, y1, y2 );
-                    _locationsVector.Add( cell );
+                    Cell cell = new Cell(x1, x2, y1, y2);
+                    _locationsVector.Add(cell);
                     // Calculate starting x and ending x position of each column
                     x1 = x2;
                     x2 = x2 + columnWidth;
@@ -125,5 +124,48 @@ namespace Tizen.NUI
                 y2 = y2 + rowHeight;
             }
         }
+
+
+        /// <summary>
+        /// [Draft] Uses the given parameters to calculate the x,y coordinates of each cell and cell size.
+        /// </summary>
+        public void CalculateLocationsRow(int numberOfRows, int availableWidth, int availableHeight, int numberOfCells)
+        {
+            numberOfRows = Math.Max(numberOfRows, 1);
+            _locationsVector.Clear();
+
+            int remainder = 0;
+            int numberOfColumns = Math.DivRem(numberOfCells, numberOfRows, out remainder);
+
+            numberOfColumns += (remainder > 0) ? 1 : 0;
+
+            int rowHeight = availableHeight / numberOfRows;
+            int columnWidth = availableHeight;
+
+            if (numberOfColumns > 0)
+            {
+                columnWidth = (availableWidth / numberOfColumns);
+            }
+
+            int x1 = 0;
+            int x2 = x1 + columnWidth;
+
+            for (var i = 0u; i < numberOfColumns; i++)
+            {
+                int y1 = 0;
+                int y2 = y1 + rowHeight;
+
+                for (var j = 0; j < numberOfRows; j++)
+                {
+                    Cell cell = new Cell(x1, x2, y1, y2);
+                    _locationsVector.Add(cell);
+                    y1 = y2;
+                    y2 = y2 + rowHeight;
+                }
+
+                x1 = x2;
+                x2 = x2 + columnWidth;
+            }
+        }
     }
 }
index 017d055..b160593 100755 (executable)
@@ -26,6 +26,24 @@ namespace Tizen.NUI
     /// </summary>
     public class GridLayout : LayoutGroup
     {
+        /// <summary>
+        /// [Draft] Enumeration for the direction in which the content is laid out
+        /// </summary>
+        // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public enum Orientation
+        {
+            /// <summary>
+            /// Horizontal (row)
+            /// </summary>
+            Horizontal,
+            /// <summary>
+            /// Vertical (column)
+            /// </summary>
+            Vertical
+        }
+
+        private Orientation _linearOrientation = Orientation.Vertical;
         const int AUTO_FIT = -1;
         private int _columns = 1;
         private int _rows = 1;
@@ -33,7 +51,28 @@ namespace Tizen.NUI
         private int _totalHeight;
         private int _requestedColumnWidth = 1;
         private int _numberOfRequestedColumns;
-        private GridLocations _locations;
+        private int _requestedRowHeight = 1;
+        private int _numberOfRequestedRows;
+        internal GridLocations _locations;
+
+
+        /// <summary>
+        /// [Draft] Get/Set the orientation in the layout
+        /// </summary>
+        // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public Orientation LinearOrientation
+        {
+            get
+            {
+                return _linearOrientation;
+            }
+            set
+            {
+                _linearOrientation = value;
+                RequestLayout();
+            }
+        }
 
         /// <summary>
         /// [draft] GridLayout Constructor/>
@@ -61,7 +100,6 @@ namespace Tizen.NUI
             }
         }
 
-
         /// <summary>
         /// [draft ] Sets the number of columns the GridLayout should have. />
         /// </summary>
@@ -69,7 +107,7 @@ namespace Tizen.NUI
         internal void SetColumns(int columns)
         {
             _numberOfRequestedColumns = columns;
-            ifcolumns != _columns)
+            if (columns != _columns)
             {
                 _columns = Math.Max(1, _columns);
                 _columns = columns;
@@ -86,14 +124,67 @@ namespace Tizen.NUI
             return _columns;
         }
 
-        void DetermineNumberOfColumns( int availableSpace )
+        /// <summary>
+        /// [draft ]Get/Set the number of rows in the grid
+        /// </summary>
+        // This will be public opened after ACR done. (Before ACR, need to be hidden as Inhouse API)
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public int Rows
         {
-            if( _numberOfRequestedColumns == AUTO_FIT )
+            get
             {
-                if( availableSpace > 0 )
+                return GetRows();
+            }
+            set
+            {
+                SetRows(value);
+            }
+        }
+
+        /// <summary>
+        /// [draft ] Sets the number of rows the GridLayout should have. />
+        /// </summary>
+        /// <param name="rows">The number of rows.</param>
+        internal void SetRows(int rows)
+        {
+            _numberOfRequestedRows = rows;
+            if (rows != _rows)
+            {
+                _rows = Math.Max(1, _rows);
+                _rows = rows;
+                RequestLayout();
+            }
+        }
+
+        /// <summary>
+        /// [draft ] Gets the number of rows in the Grid />
+        /// </summary>
+        /// <returns>The number of rows in the Grid.</returns>
+        internal int GetRows()
+        {
+            return _rows;
+        }
+
+        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;
+                    _columns = (_requestedColumnWidth > 0) ? (availableSpace / _requestedColumnWidth) : 1;
+                }
+            }
+        }
+
+        void DetermineNumberOfRows(int availableSpace)
+        {
+            if (_numberOfRequestedRows == AUTO_FIT)
+            {
+                if (availableSpace > 0)
+                {
+                    // Can only calculate number of rows if a rows height has been set
+                    _rows = (_requestedRowHeight > 0) ? (availableSpace / _requestedRowHeight) : 1;
                 }
             }
         }
@@ -104,13 +195,45 @@ namespace Tizen.NUI
         /// <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 )
+        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();
 
+            var childCount = LayoutChildren.Count;
+
+            // WIDTH SPECIFICATIONS
+            if (childCount > 0)
+            {
+                foreach (LayoutItem childLayout in LayoutChildren)
+                {
+                    if (childLayout != null)
+                    {
+                        MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec);
+                    }
+                }
+
+                if (_linearOrientation == Orientation.Horizontal)
+                    CalculateHorizontalSize(gridWidthMode, gridHeightMode, widthSize, heightSize);
+                else
+                    CalculateVerticalSize(gridWidthMode, gridHeightMode, widthSize, heightSize);
+
+            } // Children exists
+
+            LayoutLength widthLength = new LayoutLength(widthSize + Padding.Start + Padding.End);
+            LayoutLength heightLenght = new LayoutLength(heightSize + Padding.Top + Padding.Bottom);
+
+            MeasuredSize widthMeasuredSize = ResolveSizeAndState(widthLength, widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);
+            MeasuredSize heightMeasuredSize = ResolveSizeAndState(heightLenght, heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);
+
+            SetMeasuredDimensions(widthMeasuredSize, heightMeasuredSize);
+        }
+
+        private void CalculateHorizontalSize(MeasureSpecification.ModeType gridWidthMode, MeasureSpecification.ModeType gridHeightMode, int widthSize, int heightSize)
+        {
             int availableContentWidth;
             int availableContentHeight;
 
@@ -118,98 +241,147 @@ namespace Tizen.NUI
             int desiredChildWidth;
 
             Extents gridLayoutPadding = Padding;
-
             var childCount = LayoutChildren.Count;
 
-            // WIDTH SPECIFICATIONS
-            if (childCount > 0)
+            // Use first child's dimensions for layout measurement
+            View childOwner = LayoutChildren[0].Owner;
+
+            desiredChildHeight = (int)LayoutChildren[0].MeasuredHeight.Size.AsRoundedValue();
+            desiredChildWidth = (int)LayoutChildren[0].MeasuredWidth.Size.AsRoundedValue();
+
+            // If child has a margin then add it to desired size
+            Extents childMargin = LayoutChildren[0].Margin;
+            desiredChildHeight += childMargin.Top + childMargin.Bottom;
+            desiredChildWidth += childMargin.Start + childMargin.End;
+            _totalHeight = desiredChildHeight * _rows;
+            _totalHeight += gridLayoutPadding.Top + gridLayoutPadding.Bottom;
+            _totalHeight = Math.Max(_totalHeight, (int)SuggestedMinimumHeight.AsRoundedValue());
+
+            if (gridHeightMode == MeasureSpecification.ModeType.Exactly || gridHeightMode == MeasureSpecification.ModeType.AtMost)
+            {
+                _totalHeight = Math.Min(_totalHeight, heightSize);
+            }
+
+            availableContentHeight = _totalHeight - gridLayoutPadding.Top - gridLayoutPadding.Bottom;
+            heightSize = _totalHeight;
+
+            if (gridWidthMode == MeasureSpecification.ModeType.Exactly || gridWidthMode == MeasureSpecification.ModeType.AtMost)
             {
-                foreach( LayoutItem childLayout in LayoutChildren )
+                if (childCount > 0)
                 {
-                    if( childLayout != null )
+                    _totalWidth = gridLayoutPadding.Start + gridLayoutPadding.End;
+
+                    for (int i = 0; i < childCount; i += _rows)
                     {
-                        MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
+                        _totalWidth += desiredChildWidth;
                     }
-                }
 
-                // Use first child's dimensions for layout measurement
-                View childOwner = LayoutChildren[0].Owner;
+                    _totalWidth = Math.Min(_totalWidth, widthSize);
+                    _totalWidth = Math.Max(_totalWidth, (int)SuggestedMinimumWidth.AsRoundedValue());
 
-                desiredChildHeight = (int)LayoutChildren[0].MeasuredHeight.Size.AsRoundedValue();
-                desiredChildWidth = (int)LayoutChildren[0].MeasuredWidth.Size.AsRoundedValue();
+                    widthSize = _totalWidth;
+                } // Child exists
 
-                // If child has a margin then add it to desired size
-                Extents childMargin = LayoutChildren[0].Margin;
-                desiredChildHeight += childMargin.Top + childMargin.Bottom;
-                desiredChildWidth += childMargin.Start + childMargin.End;
+                // In the case of AT_MOST, availableContentHeight is the max limit.
+                availableContentWidth = widthSize - gridLayoutPadding.Start - gridLayoutPadding.End;
+            }
+            else
+            {
+                _rows = (_rows > 0) ? _rows : 1;
+                _columns = childCount / _rows;
+                _columns += (childCount % _rows > 0) ? 1 : 0;
 
-                _totalWidth = desiredChildWidth * _columns;
+                widthSize = desiredChildWidth * _columns + gridLayoutPadding.Start + gridLayoutPadding.End;
+                availableContentWidth = widthSize - gridLayoutPadding.Start - gridLayoutPadding.End;
+            }
 
-                // Include padding for max and min checks
-                _totalWidth += gridLayoutPadding.Start + gridLayoutPadding.End;
+            // If number of rows not defined
+            DetermineNumberOfRows(availableContentHeight);
 
-                // Ensure width does not exceed specified at most width or less than mininum width
-                _totalWidth = Math.Max( _totalWidth, (int)SuggestedMinimumWidth.AsRoundedValue() );
+            _locations.CalculateLocationsRow(_rows, availableContentWidth, availableContentHeight, childCount);
+        }
 
-                // 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 );
-                }
+        private void CalculateVerticalSize(MeasureSpecification.ModeType gridWidthMode, MeasureSpecification.ModeType gridHeightMode, int widthSize, int heightSize)
+        {
+            int availableContentWidth;
+            int availableContentHeight;
 
-                availableContentWidth = _totalWidth - gridLayoutPadding.Start - gridLayoutPadding.End;
-                widthSize = _totalWidth;
+            int desiredChildHeight;
+            int desiredChildWidth;
 
-                // HEIGHT SPECIFICATIONS
+            Extents gridLayoutPadding = Padding;
+            var childCount = LayoutChildren.Count;
 
-                // 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;
+            // Use first child's dimensions for layout measurement
+            View childOwner = LayoutChildren[0].Owner;
 
-                        for( int i = 0; i < childCount; i += _columns )
-                        {
-                          _totalHeight += desiredChildHeight;
-                        }
+            desiredChildHeight = (int)LayoutChildren[0].MeasuredHeight.Size.AsRoundedValue();
+            desiredChildWidth = (int)LayoutChildren[0].MeasuredWidth.Size.AsRoundedValue();
 
-                        // Ensure ourHeight does not exceed specified at most height
-                        _totalHeight = Math.Min( _totalHeight, heightSize );
-                        _totalHeight = Math.Max( _totalHeight, (int)SuggestedMinimumHeight.AsRoundedValue() );
+            // If child has a margin then add it to desired size
+            Extents childMargin = LayoutChildren[0].Margin;
+            desiredChildHeight += childMargin.Top + childMargin.Bottom;
+            desiredChildWidth += childMargin.Start + childMargin.End;
 
-                        heightSize = _totalHeight;
-                    } // Child exists
+            _totalWidth = desiredChildWidth * _columns;
 
-                    // In the case of AT_MOST, availableContentHeight is the max limit.
-                    availableContentHeight = heightSize - gridLayoutPadding.Top - gridLayoutPadding.Bottom;
-                }
-                else
-                {
-                    // Grid expands to fit content
+            // Include padding for max and min checks
+            _totalWidth += gridLayoutPadding.Start + gridLayoutPadding.End;
 
-                    // 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;
+            // Ensure width does not exceed specified at most width or less than mininum width
+            _totalWidth = Math.Max(_totalWidth, (int)SuggestedMinimumWidth.AsRoundedValue());
 
-                    heightSize = desiredChildHeight * _rows + gridLayoutPadding.Top + gridLayoutPadding.Bottom;
-                    availableContentHeight = heightSize - gridLayoutPadding.Top - gridLayoutPadding.Bottom;
-                }
+            // 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);
+            }
 
-                // If number of columns not defined
-                DetermineNumberOfColumns( availableContentWidth );
+            availableContentWidth = _totalWidth - gridLayoutPadding.Start - gridLayoutPadding.End;
+            widthSize = _totalWidth;
 
-                // Locations define the start, end,top and bottom of each cell.
-                _locations.CalculateLocations(_columns, availableContentWidth, availableContentHeight, childCount);
+            // 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;
 
-            } // Children exists
+                    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;
+
+                heightSize = desiredChildHeight * _rows + gridLayoutPadding.Top + gridLayoutPadding.Bottom;
+                availableContentHeight = heightSize - gridLayoutPadding.Top - gridLayoutPadding.Bottom;
+            }
+            // If number of columns not defined
+            DetermineNumberOfColumns(availableContentWidth);
 
-            SetMeasuredDimensions( ResolveSizeAndState( new LayoutLength(widthSize + Padding.Start + Padding.End), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK ),
-                                   ResolveSizeAndState( new LayoutLength(heightSize + Padding.Top + Padding.Bottom), heightMeasureSpec,  MeasuredSize.StateType.MeasuredSizeOK ) );
+            // Locations define the start, end,top and bottom of each cell.
+            _locations.CalculateLocations(_columns, availableContentWidth, availableContentHeight, childCount);
         }
 
         /// <summary>
@@ -221,7 +393,7 @@ namespace Tizen.NUI
         /// <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 )
+        protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
         {
             List<GridLocations.Cell> locations = _locations.GetLocations();
 
@@ -229,24 +401,24 @@ namespace Tizen.NUI
             Extents childMargins = new Extents();
 
             // Margin for all children dependant on if set on first child
-            if( LayoutChildren.Count > 0 )
+            if (LayoutChildren.Count > 0)
             {
-              childMargins = LayoutChildren[0]?.Margin;
+                childMargins = LayoutChildren[0]?.Margin;
             }
 
             int index = 0;
-            foreach( LayoutItem childLayout in LayoutChildren )
+            foreach (LayoutItem childLayout in LayoutChildren)
             {
                 // for each child
-                if( childLayout != null )
+                if (childLayout != null)
                 {
                     // Get start and end position of child x1,x2
-                    int x1 = locations[ index ].Start;
-                    int x2 = locations[ index ].End;
+                    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;
+                    int y1 = locations[index].Top;
+                    int y2 = locations[index].Bottom;
 
                     // Offset children by the grids padding if present
                     x1 += gridLayoutPadding.Start;
@@ -260,9 +432,10 @@ namespace Tizen.NUI
                     y1 += childMargins.Top;
                     y2 -= childMargins.Bottom;
 
-                    childLayout.Layout( new LayoutLength(x1), new LayoutLength(y1),
-                                        new LayoutLength(x2), new LayoutLength(y2) );
+                    childLayout.Layout(new LayoutLength(x1), new LayoutLength(y1),
+                                        new LayoutLength(x2), new LayoutLength(y2));
                     index++;
+                    //childLayout.Owner.RaiseToTop();
                 }
             }
         }