Exemplo n.º 1
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;
                }
            }
        }
Exemplo n.º 2
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.Child.AlignmentForOrientation(orientation);
                if (al != WidgetPlacement.Fill)
                {
                    double s = sizes[n];
                    if (s < allocatedSize)
                    {
                        cellOffset    = (allocatedSize - s) * al.GetValue();
                        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;
                }
            }
        }