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); }