split static method

List<FrameArea> split(
  1. FrameArea area,
  2. List<FrameConstraint> constraints, {
  3. required FrameAxis axis,
  4. int gap = 0,
  5. FrameInsets insets = const FrameInsets(),
})

Splits area along axis.

Implementation

static List<FrameArea> split(
  FrameArea area,
  List<FrameConstraint> constraints, {
  required FrameAxis axis,
  int gap = 0,
  FrameInsets insets = const FrameInsets(),
}) {
  if (gap < 0) {
    throw ArgumentError.value(gap, 'gap', 'must not be negative');
  }
  if (constraints.isEmpty) return const <FrameArea>[];

  final inner = _inset(area, insets);
  final mainSize = axis == FrameAxis.horizontal ? inner.width : inner.height;
  final requestedGap = gap * (constraints.length - 1);
  final gapBudget = requestedGap.clamp(0, mainSize);
  final available = mainSize - gapBudget;
  final sizes = List<int>.filled(constraints.length, 0);
  var remaining = available;

  for (var i = 0; i < constraints.length; i++) {
    if (constraints[i] case FrameLength(:final cells)) {
      final allocated = ultraviolet.Fixed(cells).apply(remaining);
      sizes[i] = allocated;
      remaining -= allocated;
    }
  }

  for (var i = 0; i < constraints.length; i++) {
    if (constraints[i] case FramePercentage(:final percent)) {
      final requested = ultraviolet.Percent(percent).apply(available);
      final allocated = ultraviolet.Fixed(requested).apply(remaining);
      sizes[i] = allocated;
      remaining -= allocated;
    }
  }

  final fillIndices = <int>[];
  final fillWeights = <int>[];
  for (var i = 0; i < constraints.length; i++) {
    if (constraints[i] case FrameFill(:final flex)) {
      fillIndices.add(i);
      fillWeights.add(flex);
    }
  }
  if (fillIndices.isNotEmpty && remaining > 0) {
    final allocations = ultraviolet.splitByLargestRemainder(
      remaining,
      fillWeights,
    );
    for (var i = 0; i < fillIndices.length; i++) {
      sizes[fillIndices[i]] = allocations[i];
    }
  }

  final gapSizes = constraints.length <= 1
      ? const <int>[]
      : ultraviolet.splitByLargestRemainder(
          gapBudget,
          List<int>.filled(constraints.length - 1, 1),
        );
  var cursor = axis == FrameAxis.horizontal ? inner.x : inner.y;
  return List<FrameArea>.generate(constraints.length, (index) {
    final size = sizes[index];
    final rectangle = axis == FrameAxis.horizontal
        ? ultraviolet.rect(cursor, inner.y, size, inner.height)
        : ultraviolet.rect(inner.x, cursor, inner.width, size);
    final result = _fromUltraviolet(rectangle);
    cursor += size;
    if (index < gapSizes.length) cursor += gapSizes[index];
    final end = axis == FrameAxis.horizontal ? inner.right : inner.bottom;
    if (cursor > end) cursor = end;
    return result;
  }, growable: false);
}