row method

PrintBuilder row(
  1. List<String> columns,
  2. List<int> widths, {
  3. List<ColumnAlign>? aligns,
  4. FontSize fontSize = FontSize.normal,
  5. List<bool>? wrapColumns,
  6. int lineSpacing = 0,
})

columns - List of column text content (can contain \n for multi-line) widths - List of width percentages (must sum to 100) aligns - Optional list of column alignments fontSize - Font size for the entire row lineSpacing - Additional spacing between multi-lines (default: 0) Enhanced row function with better multi-line control Allows different handling for each column's multi-line behavior

Implementation

PrintBuilder row(
    List<String> columns,
    List<int> widths, {
      List<ColumnAlign>? aligns,
      FontSize fontSize = FontSize.normal,
      List<bool>? wrapColumns, // Which columns should wrap text vs truncate
      int lineSpacing = 0,
    }) {
  // Validation checks
  if (columns.length != widths.length) {
    throw ArgumentError('Columns and widths must have the same length');
  }

  int totalWidth = widths.fold(0, (sum, width) => sum + width);
  if (totalWidth != 100) {
    throw ArgumentError('Total width must equal 100%');
  }

  List<ColumnAlign> columnAligns = aligns ?? List.filled(columns.length, ColumnAlign.left);
  List<bool> shouldWrap = wrapColumns ?? List.filled(columns.length, true);

  if (columnAligns.length != columns.length || shouldWrap.length != columns.length) {
    throw ArgumentError('All parameter lists must match columns length');
  }

  int maxChars = paperSize.getMaxChars(fontSize);

  // Process columns - wrap text if needed or split by existing newlines
  List<List<String>> columnLines = [];
  int maxLines = 0;

  for (int i = 0; i < columns.length; i++) {
    int colWidth = (maxChars * widths[i] / 100).floor();
    List<String> lines;

    if (shouldWrap[i]) {
      // Split by existing newlines first, then wrap long lines
      List<String> initialSplit = columns[i].split('\n');
      lines = [];

      for (String line in initialSplit) {
        if (line.length <= colWidth) {
          lines.add(line);
        } else {
          // Wrap long lines
          for (int start = 0; start < line.length; start += colWidth) {
            int end = (start + colWidth < line.length) ? start + colWidth : line.length;
            lines.add(line.substring(start, end));
          }
        }
      }
    } else {
      // Just split by newlines, truncate long lines
      lines = columns[i].split('\n').map((line) {
        if (line.length > colWidth && colWidth > 2) {
          return '${line.substring(0, colWidth - 2)}..';
        }
        return line.length > colWidth ? line.substring(0, colWidth) : line;
      }).toList();
    }

    columnLines.add(lines);
    maxLines = maxLines > lines.length ? maxLines : lines.length;
  }

  // Generate each line
  for (int lineIndex = 0; lineIndex < maxLines; lineIndex++) {
    String line = '';

    for (int colIndex = 0; colIndex < columns.length; colIndex++) {
      int colWidth = (maxChars * widths[colIndex] / 100).floor();

      String columnText = '';
      if (lineIndex < columnLines[colIndex].length) {
        columnText = columnLines[colIndex][lineIndex];
      }

      // Apply alignment
      String formattedColumn;
      switch (columnAligns[colIndex]) {
        case ColumnAlign.left:
          formattedColumn = columnText.padRight(colWidth);
          break;
        case ColumnAlign.center:
          int totalPadding = colWidth - columnText.length;
          int leftPadding = totalPadding ~/ 2;
          int rightPadding = totalPadding - leftPadding;
          formattedColumn = '${' ' * leftPadding}$columnText${' ' * rightPadding}';
          break;
        case ColumnAlign.right:
          formattedColumn = columnText.padLeft(colWidth);
          break;
      }

      line += formattedColumn;
    }

    _bytes.addAll(utf8.encode(line));
    _bytes.add(0x0A);

    if (lineSpacing > 0 && lineIndex < maxLines - 1) {
      for (int i = 0; i < lineSpacing; i++) {
        _bytes.add(0x0A);
      }
    }
  }

  return this;
}