table method

void table({
  1. required List<double> columnsWidth,
  2. required List<BitmapText> texts,
  3. CellPadding cellPadding = const CellPadding(),
  4. TextStyle? defaultTableTextStyle,
  5. Color borderColor = const Color(0xFF000000),
  6. bool border = false,
})

Implementation

void table({
  required List<double> columnsWidth,
  required List<BitmapText> texts,
  CellPadding cellPadding = const CellPadding(),
  TextStyle? defaultTableTextStyle,
  Color borderColor = const Color(0xFF000000),
  bool border = false,
}) {
  assert(image == null);
  assert(texts.length % columnsWidth.length == 0);

  final maxPrintableWidth = _maxX - _minX;
  double totalColumnWidth = 0;
  int indexOfFlexibleCol = -1;
  final finalColumnWidth = List.filled(columnsWidth.length, -1.0);
  for (var i = 0; i < columnsWidth.length; i++) {
    final colWidth = columnsWidth[i];
    finalColumnWidth[i] = colWidth;

    if (indexOfFlexibleCol > -1 && colWidth == -1) {
      throw Exception("Only one column can have flexible size");
    }

    if (colWidth == -1) {
      indexOfFlexibleCol = i;
    } else {
      totalColumnWidth += colWidth;
    }
  }
  if (indexOfFlexibleCol > -1) {
    final remainingWidth = maxPrintableWidth - totalColumnWidth;
    if (remainingWidth.isNegative) {
      throw Exception("Flexible column cannot have negative size");
    }

    finalColumnWidth[indexOfFlexibleCol] = remainingWidth;
    totalColumnWidth += remainingWidth;
  }

  assert(totalColumnWidth <= maxPrintableWidth);

  final maxBorderX = totalColumnWidth + _minX;

  final horizontalPadding = cellPadding.horizontalPadding;
  final verticalPadding = cellPadding.verticalPadding;

  final colCount = columnsWidth.length;
  final rowCount = texts.length ~/ colCount;

  Paint? borderPaint = border
      ? (ui.Paint()
        ..color = borderColor
        ..strokeWidth = 1)
      : null;

  if (borderPaint != null) {
    canvas.drawLine(ui.Offset(_minX, _y), ui.Offset(maxBorderX, _y), borderPaint);
    _y += borderPaint.strokeWidth;
  }

  for (var r = 0; r < rowCount; r++) {
    double cellX = _minX;
    double paintHeight = 0;

    for (var c = 0; c < colCount; c++) {
      final colWidth = finalColumnWidth[c];

      final tableText = texts[r * colCount + c];
      final textPainter = TextPainter(
        text: TextSpan(
          text: tableText.text,
          style: tableText.style ?? defaultTableTextStyle ?? defaultTextStyle,
        ),
        textDirection: ui.TextDirection.ltr,
        textAlign: tableText.textAlign,
      );
      textPainter.layout(
        minWidth: colWidth.toDouble() - horizontalPadding,
        maxWidth: colWidth.toDouble() - horizontalPadding,
      );
      textPainter.paint(canvas, ui.Offset(cellX + cellPadding.left, _y + cellPadding.top));

      paintHeight = max(textPainter.height, paintHeight);
      cellX += colWidth;
    }

    paintHeight += verticalPadding;

    if (borderPaint != null) {
      double x = _minX;
      canvas.drawLine(ui.Offset(x, _y), ui.Offset(x, _y + paintHeight), borderPaint);
      for (final colWidth in finalColumnWidth) {
        x += colWidth;
        canvas.drawLine(ui.Offset(x, _y), ui.Offset(x, _y + paintHeight), borderPaint);
      }
    }

    _y += paintHeight;

    if (borderPaint != null) {
      canvas.drawLine(ui.Offset(_minX, _y), ui.Offset(maxBorderX, _y), borderPaint);
    }
  }
}