split method

List<Rect> split(
  1. Rect area
)

Implementation

List<Rect> split(Rect area) {
  final isVertical = direction == Direction.vertical;
  final total = isVertical ? area.height : area.width;

  if (total <= 0 || constraints.isEmpty) {
    return List.filled(constraints.length, const Rect.zero());
  }

  final n = constraints.length;
  final spacingTotal = spacing * (n - 1).clamp(0, n);
  final available = (total - spacingTotal).clamp(0, total);

  final sizes = List<int>.filled(n, 0);
  final mins = List<int>.filled(n, 0);
  final maxs = List<int>.filled(n, available);
  int remaining = available;

  for (int i = 0; i < n; i++) {
    switch (constraints[i]) {
      case LengthConstraint(:final value):
        sizes[i] = value.clamp(0, remaining);
        remaining -= sizes[i];
      case PercentageConstraint(:final value):
        sizes[i] = (available * value / 100).round().clamp(0, remaining);
        remaining -= sizes[i];
      case RatioConstraint(:final numerator, :final denominator):
        if (denominator == 0) {
          sizes[i] = 0;
        } else {
          sizes[i] = (available * numerator / denominator)
              .round()
              .clamp(0, remaining);
        }
        remaining -= sizes[i];
      case MinConstraint(:final value):
        mins[i] = value;
      case MaxConstraint(:final value):
        maxs[i] = value;
      case FillConstraint():
        break;
    }
  }

  final fillIndices = <int>[];
  int fillWeightTotal = 0;

  for (int i = 0; i < n; i++) {
    final c = constraints[i];
    if (c is FillConstraint) {
      fillIndices.add(i);
      fillWeightTotal += c.weight;
    } else if (c is MinConstraint || c is MaxConstraint) {
      fillIndices.add(i);
      fillWeightTotal += 1;
    }
  }

  if (fillIndices.isNotEmpty && remaining > 0) {
    if (fillWeightTotal == 0) {
      fillWeightTotal = fillIndices.length;
    }

    int fillTotal = remaining;
    for (int k = 0; k < fillIndices.length; k++) {
      final i = fillIndices[k];
      final c = constraints[i];
      final weight = c is FillConstraint ? c.weight : 1;

      int allocated;
      if (k == fillIndices.length - 1) {
        allocated = remaining;
      } else {
        allocated = (fillTotal * weight / fillWeightTotal).round();
      }

      allocated =
          allocated.clamp(mins[i], maxs[i] == 0 ? allocated : maxs[i]);
      sizes[i] = allocated;
      remaining -= allocated;
    }
  } else {
    for (var i = 0; i < n; i++) {
      if (constraints[i] is MinConstraint) {
        sizes[i] = mins[i].clamp(0, remaining + sizes[i]);
      }
    }
  }

  final rects = <Rect>[];
  int offset = isVertical ? area.y : area.x;

  for (int i = 0; i < n; i++) {
    if (isVertical) {
      rects.add(Rect(area.x, offset, area.width, sizes[i]));
    } else {
      rects.add(Rect(offset, area.y, sizes[i], area.height));
    }

    offset += sizes[i];
    if (i < n - 1) {
      offset += spacing;
    }
  }

  return rects;
}