private static void MeasureItems(List <LayoutElement> items, Axis axis, BoxConstraint constraint)
        {
            // should return the number of items from the list that were used.
            // then that 'row' can be calculated to determine if there's room for the next row.

            var flexible   = items.Where(i => i.Child.FlexFactor > 0);
            var inflexible = items.Where(i => i.Child.FlexFactor <= 0);

            // measure each of the inflexible

            var inflexConstraint = constraint.Set(axis, 0, int.MaxValue);

            var inflexTotal = 0;

            foreach (var item in inflexible)
            {
                item.Constraint = inflexConstraint;
                item.Size       = item.Child.Measure(item.Constraint);

                var mAxis = item.Size.GetAxis(axis);
                if (mAxis == int.MaxValue)
                {
                    // TODO this should throw an error
                    // no item should ever measure as 'max' (should always return a min value)
                    // with min sizes, parent container will force sizes if necessary to fill
                    item.Child.FlexFactor = 1;
                }
                else
                {
                    inflexTotal += item.Size.GetAxis(axis);
                }
            }

            // now the flexible components using the remaining space
            // shrink that axis?
            // how to calc min/max.. hrm...
            // if we're passed unbound, we don't want to use it all
            // but we should also be able to go over the min.


            // if bound, flex size should be fixed to the max - inflextotal * flexratio

            int  remaining = 0;
            bool isBounded = constraint.IsBounded(axis);

            if (isBounded)
            {
                remaining = constraint.GetMaxSize().GetAxis(axis) - inflexTotal;
            }

            var flexTotal = (double)flexible.Sum(f => f.Child.FlexFactor);

            foreach (var item in flexible)
            {
                if (isBounded)
                {
                    // if bound, flex size should be fixed to the max - inflextotal * flexratio
                    var space = (item.Child.FlexFactor / flexTotal) * remaining;
                    item.Constraint = constraint.Set(axis, (int)Math.Floor(space));
                    item.Size       = item.Child.Measure(item.Constraint);
                }
                else
                {
                    // if bounds are unbound, flex size should be unbound, no min, no max.
                    item.Constraint = constraint.Set(axis, 0, int.MaxValue);
                    item.Size       = item.Child.Measure(item.Constraint);
                }
            }
        }
        private static void LayoutLine(MeasuredLayout layout, FlexSpacing spacing, Axis axis, BoxConstraint constraint)
        {
            int total = 0;

            try
            {
                total = layout
                        .Elements
                        .Select(l => l.Size.GetAxis(axis))
                        .Sum();
            }
            catch (ArithmeticException ex)
            {
                throw;
            }

            // if !isbounded, it's just a total + maxsize on offset

            // if isbounded, then calc the flex spacing
            // add it all together for the size

            var lineSpacing = constraint.IsBounded(axis)
                ? CalculateLineSpacing(spacing, constraint.GetMaxSize().GetAxis(axis) - total, layout.Elements.Count)
                : new FlexSpacingMeasurement()
            {
                Between = 0, End = 0, Start = 0
            };

            var used     = lineSpacing.Start;
            var crossMax = 0;

            for (var x = 0; x < layout.Elements.Count; x++)
            {
                var item = layout.Elements[x];

                item.Offset = used;

                used += item.Size.GetAxis(axis);

                if (x != layout.Elements.Count - 1)
                {
                    // add between for every item that's not 'last'
                    used += lineSpacing.Between;
                }

                var cross = item.Size.GetAxis(axis.CrossAxis());
                if (cross < int.MaxValue && cross > crossMax)
                {
                    crossMax = cross;
                }
            }

            used += lineSpacing.End;

            foreach (var i in layout.Elements)
            {
                i.Constraint = i.Constraint.Set(axis.CrossAxis(), crossMax);
            }

            layout.Size = axis == Axis.Horizontal
                ? new Size(used, crossMax)
                : new Size(crossMax, used);
        }