Exemplo n.º 1
0
        public override void LayoutSubviews()
        {
            var oldSize = Frame.Size;

#if ENABLE_DEBUG_LOG
            string debugIndent = String.Concat(Enumerable.Repeat("   ", numSuperviews(this)));
            LogLine($"{debugIndent}LayoutSubviews {GetHashCode()} {this.GetType()}");
#else
            const string debugIndent = "";
#endif

            base.LayoutSubviews();

            this.UpdateLayout();

            if (CurrentLayout == null)
            {
                return;
            }

            // Allow streched cells that are in an auto sized column or row only if there is at
            // least one non-stretched cell that starts that same column/row
            foreach (var cell in this.CurrentLayout.Cells)
            {
                if (cell.Position.Horizontal == Layout.Alignment.Stretched &&
                    this.CurrentLayout.ColumnDefinitions[cell.Position.Column].SizeType == Layout.SizeType.Auto &&
                    !this.CurrentLayout.Cells.Any(c => c.Position.Column == cell.Position.Column && c.Position.Horizontal != Layout.Alignment.Stretched))
                {
                    throw new Exception($"Grid {ID}: Stretched horizontal cell alignment on row {cell.Position.Row}, col {cell.Position.Column} cannot be used in an auto sized column when there is no other cell in that column that is not stretched");
                }

                if (cell.Position.Vertical == Layout.Alignment.Stretched &&
                    this.CurrentLayout.RowDefinitions[cell.Position.Row].SizeType == Layout.SizeType.Auto &&
                    !this.CurrentLayout.Cells.Any(c => c.Position.Row == cell.Position.Row && c.Position.Vertical != Layout.Alignment.Stretched))
                {
                    throw new Exception($"Grid {ID}: Stretched vertical cell alignment on row {cell.Position.Row}, col {cell.Position.Column} cannot be used in an auto sized row when there is no other cell in that column that is not stretched");
                }
            }

#if ENABLE_DEBUG_LOG
            LogLine($"{debugIndent}Cells at start of layout:");
            foreach (var cell in this.CurrentLayout.Cells)
            {
                LogLine($"{debugIndent}   {cell}");
            }
#endif

            var horizontallyStretchedCells = this.CurrentLayout.Cells.Where(c => c.IncludeInAutoWidthSizeCalcs &&
                                                                            c.View != null && c.Position.Horizontal == Layout.Alignment.Stretched);
            if (horizontallyStretchedCells.Any())
            {
                LogLine($"{debugIndent}   Setting width of horizontally stretched cells");
                var widths1 = this.CurrentLayout.CalculateAbsoluteColumnWidth(this).Item2;
                foreach (var cell in horizontallyStretchedCells)
                {
                    nfloat w = CalcSpanWidth(cell, widths1);
                    LogLine($"{debugIndent}      Setting cell.View Width to {w}");
                    nfloat width = w - cell.Position.Margin.Width();
                    if (RoundLayout)
                    {
                        width = width.RoundToScale();
                    }
                    cell.View.SetWidth(width);
                    LogLine($"{debugIndent}      Before LayoutSubviews {cell.DebugLabel}");
                    cell.View.LayoutSubviews();
                    LogLine($"{debugIndent}      After LayoutSubviews cell.View Size={cell.View.Frame.Size} {cell.DebugLabel}");
                }
            }

            var verticallyStretchedCells = this.CurrentLayout.Cells.Where(c => c.IncludeInAutoWidthSizeCalcs &&
                                                                          c.View != null && c.Position.Vertical == Layout.Alignment.Stretched);
            if (verticallyStretchedCells.Any())
            {
                LogLine($"{debugIndent}   Setting height of vertically stretched cells");
                var heights1 = this.CurrentLayout.CalculateAbsoluteRowHeight(this).Item2;
                foreach (var cell in verticallyStretchedCells)
                {
                    nfloat h = CalcSpanHeight(cell, heights1);
                    LogLine($"{debugIndent}      Setting cell.View Height to {h}");
                    nfloat height = h - cell.Position.Margin.Height();
                    if (RoundLayout)
                    {
                        height = height.RoundToScale();
                    }
                    cell.View.SetHeight(height);
                    LogLine($"{debugIndent}      Before LayoutSubviews {cell.DebugLabel}");
                    cell.View.LayoutSubviews();
                    LogLine($"{debugIndent}      After LayoutSubviews cell.View Size={cell.View.Frame.Size} {cell.DebugLabel}");
                }
            }

            // Calculate row sizes
            var      heights           = this.CurrentLayout.CalculateAbsoluteRowHeight(this);
            nfloat   gridHeight        = heights.Item1;
            nfloat[] absoluteRowHeight = heights.Item2;
            LogLine($"{debugIndent}   AutoHeight={AutoHeight}, gridHeight={gridHeight}, Frame.Height={Frame.Height}");

            // Calculate column sizes
            var      widths              = this.CurrentLayout.CalculateAbsoluteColumnWidth(this);
            nfloat   gridWidth           = widths.Item1;
            nfloat[] absoluteColumnWidth = widths.Item2;
            LogLine($"{debugIndent}   AutoWidth={AutoWidth} gridWidth={gridWidth}, Frame.Width={Frame.Width}");

            var newGridFrame = new CGRect(Frame.Location, new CGSize(gridWidth, gridHeight));
            LogLine($"{debugIndent}   newGridFrame={newGridFrame}, old Frame={Frame}");
            Frame = newGridFrame;

            LogLine($"{debugIndent}   RowDefinitions      = [{string.Join(",", this.CurrentLayout.RowDefinitions.Select(r => r.Size))}]");
            LogLine($"{debugIndent}   absoluteRowHeight   = [{string.Join(",", absoluteRowHeight)}]");
            LogLine($"{debugIndent}   ColumnDefinitions   = [{string.Join(",", this.CurrentLayout.ColumnDefinitions.Select(r => r.Size))}]");
            LogLine($"{debugIndent}   absoluteColumnWidth = [{string.Join(",", absoluteColumnWidth)}]");

            // Calculate cell positions
            var positions = CalcCellAbsolutePositions(absoluteColumnWidth, absoluteRowHeight);

            // Layout subviews
            foreach (var cell in this.CurrentLayout.Cells)
            {
                LogLine();
                LogLine($"{debugIndent}   Laying out col {cell.Position.Column}, row {cell.Position.Row}, {cell.DebugLabel}");

                if (!cell.IncludeInAutoWidthSizeCalcs && !cell.IncludeInAutoHeightSizeCalcs)
                {
                    LogLine($"{debugIndent}      skipping: View.Hidden=true and IncludeInAutoWidthSizeCalcs,IncludeInAutoHeightSizeCalcs false");
                    continue;
                }

                if (cell.Position.Row >= this.CurrentLayout.RowDefinitions.Count())
                {
                    throw new Exception($"Grid {ID}: a cell is defined at row {cell.Position.Row}, col {cell.Position.Column} but there are only {this.CurrentLayout.RowDefinitions.Count()} rows defined in the grid");
                }

                if (cell.Position.Column >= this.CurrentLayout.ColumnDefinitions.Count())
                {
                    throw new Exception($"Grid {ID}: a cell is defined at row {cell.Position.Row}, col {cell.Position.Column} but there are only {this.CurrentLayout.ColumnDefinitions.Count()} columns defined in the grid");
                }

                cell.View?.LayoutSubviews();

                var position = positions[cell.Position.Column, cell.Position.Row];
                var cellSize = GetCellAbsoluteSize(absoluteColumnWidth, absoluteRowHeight, cell.Position);
                var viewSize = cell.AutoSizeSize;

                LogLine($"{debugIndent}      position = {position}");
                LogLine($"{debugIndent}      cellSize = {cellSize}");
                LogLine($"{debugIndent}      viewSize = {viewSize}");

                if (viewSize.Width == 0 && viewSize.Height == 0)
                {
                    viewSize = cell.InitialSize;
                    LogLine($"{debugIndent}      viewSize changed to cell.InitialSize = {viewSize}");
                }

                LogLine($"{debugIndent}      Alignment: Vertical={cell.Position.Vertical}, Horizontal={cell.Position.Horizontal}");

                switch (cell.Position.Vertical)
                {
                case Layout.Alignment.Stretched:
                    // Honor Margin.Top and Bottom
                    position.Y      += cell.Position.Margin.Top;
                    cellSize.Height -= cell.Position.Margin.Height();
                    break;

                case Layout.Alignment.Center:
                    // Honor Margin.Left and Right
                    position.Y     += (cellSize.Height / 2f) - (viewSize.Height / 2f) + cell.Position.Margin.Top / 2f - cell.Position.Margin.Bottom / 2f;
                    cellSize.Height = viewSize.Height;
                    break;

                case Layout.Alignment.Start:
                    // Honor Margin.Top
                    position.Y     += cell.Position.Margin.Top;
                    cellSize.Height = viewSize.Height;
                    break;

                case Layout.Alignment.End:
                    // Honor Margin.Bottom
                    position.Y     += cellSize.Height - viewSize.Height - cell.Position.Margin.Bottom;
                    cellSize.Height = viewSize.Height;
                    break;

                default:
                    break;
                }

                switch (cell.Position.Horizontal)
                {
                case Layout.Alignment.Stretched:
                    // Honor Margin.Left and Right
                    position.X     += cell.Position.Margin.Left;
                    cellSize.Width -= cell.Position.Margin.Width();
                    break;

                case Layout.Alignment.Center:
                    // Honor Margin.Left and Right
                    position.X    += (cellSize.Width / 2f) - (viewSize.Width / 2f) + cell.Position.Margin.Left / 2f - cell.Position.Margin.Right / 2f;
                    cellSize.Width = viewSize.Width;
                    break;

                case Layout.Alignment.Start:
                    // Honor Margin.Left
                    cellSize.Width = viewSize.Width;
                    position.X    += cell.Position.Margin.Left;
                    break;

                case Layout.Alignment.End:
                    // Honor Margin.Right
                    position.X    += cellSize.Width - viewSize.Width - cell.Position.Margin.Right;
                    cellSize.Width = viewSize.Width;
                    break;

                default:
                    break;
                }

                if (cell.Position.NoResize || cell.Position.NoPosition)
                {
                    cellSize = cell.AutoSizeSize;
                }
                if (cell.Position.NoPosition)
                {
                    position = cell.View.Frame.Location;
                }

                var newFrame = new CGRect(position, cellSize);
                Log($"{debugIndent}      newFrame={newFrame}, cell.View.Frame={cell.View?.Frame}");
                if (newFrame != cell.View?.Frame)
                {
                    Log(": UPDATE");
                    SetCellFrame(cell, newFrame);
                }
                LogLine();
                Log($"{debugIndent}      Finished {cell.DebugLabel}");
            }

            LogLine();

            OnLayoutCompleted(oldSize, Frame.Size);
        }