build method

  1. @override
Widget build(
  1. BuildContext context
)
override

Describes the part of the UI represented by this widget.

Implementation

@override
Widget build(BuildContext context) {
  final theme = ThemeScope.of(context);
  final bColor = borderColor ?? theme.border;
  final hStyle = copyStyle(headerStyle ?? theme.titleSmall)
    ..foreground(theme.onSurface)
    ..bold();
  final cStyle = copyStyle(cellStyle ?? theme.bodyMedium)
    ..foreground(theme.onSurface);
  final bStyle = copyStyle(Style())..foreground(bColor);

  // Calculate column widths.
  final colCount = columns.length;
  final widths = List<int>.filled(colCount, 0);
  _measureCells(_headerCells, widths);
  for (final row in _cellRows) {
    _measureCells(row, widths);
  }
  _expandWidthsForSpans(_headerCells, widths);
  for (final row in _cellRows) {
    _expandWidthsForSpans(row, widths);
  }

  final chars = _borderChars();
  final hasOuterBorder = chars.topLeft != null;

  // Build a horizontal rule line.
  String buildHRule(String h, String cross, String? left, String? right) {
    final parts = <String>[];
    if (left != null) parts.add('$left$h');
    for (var i = 0; i < colCount; i++) {
      parts.add(h * widths[i]);
      if (i < colCount - 1) {
        parts.add('$h$cross$h');
      }
    }
    if (right != null) parts.add('$h$right');
    return parts.join();
  }

  // Build a content row (header or data).
  Widget buildRow(List<DataTableCell> values, Style textStyle) {
    final cells = <Widget>[];
    if (hasOuterBorder) {
      cells.add(Text('${chars.v} ', style: bStyle));
    }
    var column = 0;
    var cellIndex = 0;
    while (column < colCount) {
      final cell = cellIndex < values.length
          ? values[cellIndex]
          : const DataTableCell('');
      final span = cell.columnSpan.clamp(1, colCount - column);
      final width = _spannedWidth(widths, column, span);
      final value = _align(cell.value, width, cell.textAlign);
      cells.add(Text(value, style: cell.style ?? textStyle));
      column += span;
      cellIndex++;
      if (column < colCount) {
        cells.add(Text(' ${chars.v} ', style: bStyle));
      }
    }
    if (hasOuterBorder) {
      cells.add(Text(' ${chars.v}', style: bStyle));
    }
    return Row(gap: 0, children: cells);
  }

  final children = <Widget>[];

  // Top border (only for styles with outer borders).
  if (hasOuterBorder) {
    children.add(
      Text(
        buildHRule(chars.h, chars.topCross!, chars.topLeft, chars.topRight),
        style: bStyle,
      ),
    );
  }

  // Header row.
  children.add(buildRow(_headerCells, hStyle));

  // Header separator.
  children.add(
    Text(
      buildHRule(
        chars.h,
        chars.cross,
        hasOuterBorder ? chars.leftCross : null,
        hasOuterBorder ? chars.rightCross : null,
      ),
      style: bStyle,
    ),
  );

  // Data rows.
  for (final row in _cellRows) {
    children.add(buildRow(row, cStyle));
  }

  // Bottom border (only for styles with outer borders).
  if (hasOuterBorder) {
    children.add(
      Text(
        buildHRule(
          chars.h,
          chars.bottomCross!,
          chars.bottomLeft,
          chars.bottomRight,
        ),
        style: bStyle,
      ),
    );
  }

  return Column(gap: 0, children: children);
}