performPaint method

  1. @override
void performPaint(
  1. Buffer buffer,
  2. Offset offset
)
override

Hook for subclasses to implement actual painting.

Implementation

@override
void performPaint(Buffer buffer, Offset offset) {
  final table = widget as Table;
  final w = size.width;
  final h = size.height;
  if (table.headers.isEmpty ||
      table.columnWidths.isEmpty ||
      h <= 2 ||
      w <= 0) {
    return;
  }

  // 1. Render Headers
  final headerSb = StringBuffer();
  for (var i = 0; i < table.headers.length; i++) {
    final width = resolvedColumnWidths[i];
    final text = table.headers[i];
    final padded = padOrTruncate(text, width);
    headerSb.write(padded);
    if (i < table.headers.length - 1) headerSb.write(' ');
  }

  final int columnsTotalWidth =
      resolvedColumnWidths.fold<int>(0, (prev, val) => prev + val) +
      (table.headers.isNotEmpty ? table.headers.length - 1 : 0);

  String headerStr;
  if (columnsTotalWidth <= w) {
    if (columnsTotalWidth < w) {
      headerSb.write(' ' * (w - columnsTotalWidth));
    }
    headerStr = headerSb.toString();
  } else {
    headerStr = padOrTruncate(headerSb.toString(), w);
  }
  buffer.writeString(offset.dx, offset.dy, headerStr, table.headerStyle);

  // 2. Render Header Divider Line
  final dividerChar = '─';
  final divider = dividerChar * w;
  buffer.writeString(offset.dx, offset.dy + 1, divider, table.borderStyle);

  // 3. Render Rows
  final usableHeight = h - 2;
  for (var r = 0; r < usableHeight; r++) {
    final rowIdx = table.scrollOffset + r;
    if (rowIdx >= table.rows.length) break;

    final rowData = table.rows[rowIdx];
    final isSelected = rowIdx == table.selectedRowIndex;
    final currentStyle = isSelected ? table.selectedRowStyle : table.rowStyle;

    int startX = 0;
    for (var c = 0; c < table.headers.length; c++) {
      final colWidth = resolvedColumnWidths[c];
      final cellData = c < rowData.length ? rowData[c] : '';
      final cellStartX = columnXOffsets[c];

      final cellRect = Rect(
        offset.dx + cellStartX,
        offset.dy + 2 + r,
        colWidth,
        1,
      );
      final vp = Viewport(buffer, cellRect);

      if (cellData is Widget) {
        vp.fillAttributes(
          char: ' ',
          fg: currentStyle.foreground?.argb ?? 0,
          bg: currentStyle.background?.argb ?? 0,
          modifiers: currentStyle.modifiers,
        );
        final cellEl = cellElements[rowIdx][c];
        if (cellEl != null) {
          cellEl.paint(vp, Offset.zero);
        }
      } else {
        final cellText = cellData.toString();
        final padded = padOrTruncate(cellText, colWidth);
        vp.writeString(0, 0, padded, currentStyle);
      }

      if (c < table.headers.length - 1) {
        final sepX = cellStartX + colWidth;
        if (sepX < w) {
          buffer.writeString(
            offset.dx + sepX,
            offset.dy + 2 + r,
            ' ',
            currentStyle,
          );
        }
      }

      startX += colWidth + 1;
    }

    if (startX < w) {
      final remainder = w - startX;
      buffer.writeString(
        offset.dx + startX,
        offset.dy + 2 + r,
        ' ' * remainder,
        currentStyle,
      );
    }
  }
}