retrieveCommonStackAlignment function

AlignmentModel retrieveCommonStackAlignment(
  1. BaseNode parent,
  2. List<BaseNode> nodes
)

Implementation

AlignmentModel retrieveCommonStackAlignment(
  BaseNode parent,
  List<BaseNode> nodes,
) {
  final List<AlignmentModel> alignments = [];

  if (nodes.length == 1 &&
      nodes.single is ScrollableMixin &&
      (nodes.single as ScrollableMixin).isScrollable) {
    return AlignmentModel.none;
  }

  for (final BaseNode node in nodes) {
    final AlignmentModel alignment = node.alignment;
    if (alignment.data == null) continue;
    alignments.add(alignment);
  }

  final AlignmentModel? mostCommonAlignment;

  if (alignments.isEmpty) {
    mostCommonAlignment = null;
  } else {
    mostCommonAlignment = mostCommon<AlignmentModel>(alignments);
  }

  AlignmentModel? bestAlignment = mostCommonAlignment;

  // mostCommonAlignment will be null if a tie exists. In such cases, we
  // completely disregard common alignment and use an Align widget on each child
  // as it is higher quality, more readable code. While that works most of the
  // time, if the stack is wrapping in any axis, all [Align]ed children will be
  // converted into [Positioned] widgets to prevent the Stack from expanding
  // instead of wrapping.
  //
  // With that in mind, if all of the children are Positioned in a wrapping
  // Stack, the Stack will implode on itself as it has no concrete,
  // non-Positioned children and to figure out its first-pass size. The
  // Positioned children end up in a zero-size Stack as a result.
  //
  // To fix this specific situation, we arbitrarily return one of the tied
  // alignments. The stack will use this alignment for its `stackAlignment`
  // property, which does not expand the stack, rather aligns children
  // correctly instead. Once we pass this stack alignment, the singular child
  // that this alignment matches is not going to wrap itself with an Align
  // widget because its alignment matches the stack alignment. This means that
  // the stack will have a concrete child to figure out its size and will not
  // implode. The rest of the children will be wrapped with Positioned widgets
  // in a Stack that has a concrete size.
  if (bestAlignment == null &&
      parent.isOneOrBothWrap &&
      alignments.isNotEmpty) {
    bestAlignment = getLargestNodeForWrappingStack(parent, nodes)?.alignment;
  }

  return bestAlignment ?? AlignmentModel.none;
}