Beispiel #1
0
        List <CellPos> GetCells(CGSize cellSize)
        {
            int    nexpands      = 0;
            double requiredSize  = 0;
            double availableSize = cellSize.Width;

            var cellFrames = new List <CellPos> (cells.Count);

            // Get the natural size of each child
            foreach (var cell in cells)
            {
                if (!cell.Backend.Frontend.Visible)
                {
                    continue;
                }
                var cellPos = new CellPos {
                    Cell = (NSView)cell, Frame = CGRect.Empty
                };
                cellFrames.Add(cellPos);
                var size = cellPos.Cell.FittingSize;
                cellPos.Frame.Width = size.Width;
                requiredSize       += size.Width;
                if (cell.Backend.Frontend.Expands)
                {
                    nexpands++;
                }
            }

            double remaining = availableSize - requiredSize;

            if (remaining > 0)
            {
                var expandRemaining = new SizeSplitter(remaining, nexpands);
                foreach (var cellFrame in cellFrames)
                {
                    if (((ICellRenderer)cellFrame.Cell).Backend.Frontend.Expands)
                    {
                        cellFrame.Frame.Width += (nfloat)expandRemaining.NextSizePart();
                    }
                }
            }

            double x = 0;

            foreach (var cellFrame in cellFrames)
            {
                var width  = cellFrame.Frame.Width;
                var canvas = cellFrame.Cell as ICanvasCellRenderer;
                var height = (canvas != null) ? canvas.GetRequiredSize(SizeConstraint.WithSize(width)).Height : cellFrame.Cell.FittingSize.Height;
                // y-align only if the cell has a valid height, otherwise we're just recalculating the required size
                var y = cellSize.Height > 0 ? (cellSize.Height - height) / 2 : 0;
                cellFrame.Frame = new CGRect(x, y, width, height);
                x += width;
            }
            return(cellFrames);
        }
Beispiel #2
0
        IEnumerable <CellPos> GetCells(CGRect cellFrame)
        {
            int    nexpands      = 0;
            double requiredSize  = 0;
            double availableSize = cellFrame.Width;

            var visibleCells = VisibleCells.ToArray();
            var sizes        = new double [visibleCells.Length];

            // Get the natural size of each child
            for (int i = 0; i < visibleCells.Length; i++)
            {
                var v = visibleCells[i] as NSView;
                var s = v.FittingSize;
                if (s.IsEmpty && SizeToFit(v))
                {
                    s = v.Frame.Size;
                }
                sizes [i]     = s.Width;
                requiredSize += s.Width;
                if (visibleCells [i].Backend.Frontend.Expands)
                {
                    nexpands++;
                }
            }

            double remaining = availableSize - requiredSize;

            if (remaining > 0)
            {
                var expandRemaining = new SizeSplitter(remaining, nexpands);
                for (int i = 0; i < visibleCells.Length; i++)
                {
                    if (visibleCells [i].Backend.Frontend.Expands)
                    {
                        sizes [i] += (nfloat)expandRemaining.NextSizePart();
                    }
                }
            }

            double x = cellFrame.X;

            for (int i = 0; i < visibleCells.Length; i++)
            {
                var cell   = (NSView)visibleCells [i];
                var height = cell.FittingSize.Height;
                var y      = (cellFrame.Height - height) / 2;
                yield return(new CellPos {
                    Cell = cell, Frame = new CGRect(x, y, sizes [i], height)
                });

                x += sizes [i];
            }
        }
Beispiel #3
0
        /// <summary>
        /// Calculates size of each cell, taking into account their preferred size, expansion/fill requests, and the available space.
        /// Calculation is done only for the provided orientation (either height or width).
        /// </summary>
        /// <param name="mode">Mode.</param>
        /// <param name="availableSize">Total size available</param>
        /// <param name="calcOffsets"></param>
        void CalcCellSizes(CellSizeVector cellSizes, double availableSize, bool calcOffsets)
        {
            TablePlacement[] visibleChildren = cellSizes.visibleChildren;
            Dictionary<int,double> fixedSizesByCell = cellSizes.fixedSizesByCell;
            double[] sizes = cellSizes.sizes;
            double spacing = cellSizes.spacing;
            Orientation orientation = cellSizes.orientation;

            // Get the total natural size
            double naturalSize = fixedSizesByCell.Values.Sum ();

            double remaining = availableSize - naturalSize - spacing;

            if (availableSize - spacing <= 0) {
                foreach (var i in fixedSizesByCell.Keys.ToArray ())
                    fixedSizesByCell [i] = 0;
            }
            else if (remaining < 0) {
                // The box is not big enough to fit the widgets using its natural size.
                // We have to shrink the cells. We do a proportional reduction

                // List of cell indexes that we have to shrink
                var toShrink = new List<int> (fixedSizesByCell.Keys);

                // The total amount we have to shrink
                double splitSize = (availableSize - spacing) / toShrink.Count;

                // We have to reduce all cells proportionally, but if a cell is much bigger that
                // its proportionally allocated space, then we reduce this one before the others

                var smallCells = fixedSizesByCell.Where (c => c.Value < splitSize);
                var belowSplitSize = smallCells.Sum (c => splitSize - c.Value);

                var bigCells = fixedSizesByCell.Where (c => c.Value > splitSize);
                var overSplitSize = bigCells.Sum (c => c.Value - splitSize);

                ReduceProportional (fixedSizesByCell, bigCells.Select (c => c.Key), overSplitSize - belowSplitSize);

                var newNatural = fixedSizesByCell.Sum (c => c.Value);
                ReduceProportional (fixedSizesByCell, fixedSizesByCell.Keys, (availableSize - spacing) - newNatural);

                RoundSizes (fixedSizesByCell);
            }
            else {
                // Distribute remaining space among the extensible widgets
                HashSet<int> cellsWithExpand = cellSizes.cellsWithExpand;
                int nexpands = cellsWithExpand.Count;
                var expandRemaining = new SizeSplitter (remaining, nexpands);
                foreach (var c in cellsWithExpand) {
                    double ws;
                    fixedSizesByCell.TryGetValue (c, out ws);
                    ws += expandRemaining.NextSizePart ();
                    fixedSizesByCell [c] = ws;
                }
            }

            // Calculate the offset of each widget, relative to the cell (so 0 means at the left/top of the cell).

            for (int n=0; n<visibleChildren.Length; n++) {
                var bp = visibleChildren[n];
                double allocatedSize = 0;
                double cellOffset = 0;

                int start = GetStartAttach (bp, orientation);
                int end = GetEndAttach (bp, orientation);
                for (int i=start; i<end; i++) {
                    double ws;
                    fixedSizesByCell.TryGetValue (i, out ws);
                    allocatedSize += ws;
                    if (i != start)
                        allocatedSize += GetSpacing (i, orientation);
                }

                var al = bp.GetAlignmentForOrientation (orientation);
                if (!double.IsNaN (al)) {
                    double s = sizes[n];
                    if (s < allocatedSize) {
                        cellOffset = (allocatedSize - s) * al;
                        allocatedSize = s;
                    }
                }

                // cellOffset is the offset of the widget inside the cell. We store it in NextX/Y, and
                // will be used below to calculate the total offset of the widget

                if (orientation == Orientation.Vertical) {
                    bp.NextHeight = allocatedSize;
                    bp.NextY = cellOffset;
                }
                else {
                    bp.NextWidth = allocatedSize;
                    bp.NextX = cellOffset;
                }
            }

            if (calcOffsets) {
                // Calculate the final offset of each widget, relative to the table origin
                var sortedChildren = visibleChildren.OrderBy (c => GetStartAttach (c, orientation)).ToArray();
                var cells = fixedSizesByCell.OrderBy (c => c.Key);
                double offset = 0;
                int n = 0;
                foreach (var c in cells) {
                    if (c.Key > 0)
                        offset += GetSpacing (c.Key, orientation);
                    while (n < sortedChildren.Length && GetStartAttach (sortedChildren[n], orientation) == c.Key) {
                        // In the loop above we store the offset of the widget inside the cell in the NextX/Y field
                        // so now we have to add (not just assign) the offset of the cell to NextX/Y
                        if (orientation == Orientation.Vertical)
                            sortedChildren[n].NextY += offset;
                        else
                            sortedChildren[n].NextX += offset;
                        n++;
                    }
                    offset += c.Value;
                }
            }
        }
Beispiel #4
0
        IEnumerable <CellPos> GetCells(CGRect cellFrame)
        {
            if (direction == Orientation.Horizontal)
            {
                int    nexpands      = 0;
                double requiredSize  = 0;
                double availableSize = cellFrame.Width;

                var sizes = new Dictionary <ICellRenderer, double> ();

                // Get the natural size of each child
                foreach (var bp in VisibleCells)
                {
                    var s = ((NSCell)bp).CellSize;
                    sizes [bp]    = s.Width;
                    requiredSize += s.Width;
                    if (bp.Backend.Frontend.Expands)
                    {
                        nexpands++;
                    }
                }

                double remaining = availableSize - requiredSize;
                if (remaining > 0)
                {
                    var expandRemaining = new SizeSplitter(remaining, nexpands);
                    foreach (var bp in VisibleCells)
                    {
                        if (bp.Backend.Frontend.Expands)
                        {
                            sizes [bp] += (nfloat)expandRemaining.NextSizePart();
                        }
                    }
                }

                double x = cellFrame.X;
                foreach (var s in sizes)
                {
                    yield return(new CellPos()
                    {
                        Cell = (NSCell)s.Key, Frame = new CGRect(x, cellFrame.Y, s.Value, cellFrame.Height)
                    });

                    x += s.Value;
                }
            }
            else
            {
                nfloat y = cellFrame.Y;
                foreach (NSCell c in VisibleCells)
                {
                    var s = c.CellSize;
                    var f = new CGRect(cellFrame.X, y, s.Width, cellFrame.Height);
                    y += s.Height;
                    yield return(new CellPos()
                    {
                        Cell = c, Frame = f
                    });
                }
            }
        }