layout method

  1. @override
PwBox layout(
  1. Context context,
  2. BoxConstraints constraints
)
override

layout API.

Implementation

@override
PwBox layout(Context context, BoxConstraints constraints) {
  final List<(PwBox, PwOffset, Positioned?, double?, double?)> laid =
      <(PwBox, PwOffset, Positioned?, double?, double?)>[];
  var w = 0.0;
  var h = 0.0;
  final PwSize stackSizeHint = constraints.constrain(
    PwSize(
      constraints.hasBoundedWidth ? constraints.maxWidth : 0,
      constraints.hasBoundedHeight ? constraints.maxHeight : 0,
    ),
  );
  for (final Widget child in children) {
    final Positioned? pos = child is Positioned ? child : null;
    final ({double? left, double? right}) pin = pos == null
        ? (left: null, right: null)
        : pos.horizontal(context.textDirection);
    final Widget inner = pos?.child ?? child;
    BoxConstraints childCs = constraints.loosen();
    if (pos != null) {
      double? tw = pos.width;
      double? th = pos.height;
      if (tw == null && pin.left != null && pin.right != null) {
        tw = (stackSizeHint.width - pin.left! - pin.right!).clamp(
          0,
          double.infinity,
        );
      }
      if (th == null && pos.top != null && pos.bottom != null) {
        th = (stackSizeHint.height - pos.top! - pos.bottom!).clamp(
          0,
          double.infinity,
        );
      }
      if (tw != null || th != null) {
        childCs = BoxConstraints.tightFor(width: tw, height: th);
      }
    }
    final PwBox box = inner.layout(context, childCs);
    if (box.size.width > w) {
      w = box.size.width;
    }
    if (box.size.height > h) {
      h = box.size.height;
    }
    laid.add((box, PwOffset.zero, pos, pin.left, pin.right));
  }
  if (fit == StackFit.expand && constraints.hasBoundedWidth) {
    w = constraints.maxWidth;
  }
  if (fit == StackFit.expand && constraints.hasBoundedHeight) {
    h = constraints.maxHeight;
  }
  // Grow stack to fit positioned right/bottom pins.
  for (final (PwBox box, PwOffset _, Positioned? pos, double? left, double? right)
      in laid) {
    if (pos == null) {
      continue;
    }
    if (left != null) {
      final double need = left + box.size.width + (right ?? 0);
      if (need > w) {
        w = need;
      }
    }
    if (pos.top != null) {
      final double need = pos.top! + box.size.height + (pos.bottom ?? 0);
      if (need > h) {
        h = need;
      }
    }
  }
  final PwSize size = constraints.constrain(PwSize(w, h));
  final List<(PwBox, PwOffset)> placed = <(PwBox, PwOffset)>[];
  for (final (PwBox box, PwOffset _, Positioned? pos, double? left, double? right)
      in laid) {
    if (pos != null) {
      final double dx =
          left ??
          (right != null ? size.width - box.size.width - right : 0.0);
      final double dy =
          pos.top ??
          (pos.bottom != null
              ? size.height - box.size.height - pos.bottom!
              : 0.0);
      placed.add((box, PwOffset(dx, dy)));
    } else {
      placed.add((
        box,
        alignment.resolve(context.textDirection).alongOffset(size, box.size),
      ));
    }
  }
  return GroupBox(size, placed);
}