Skip to content

Commit a893e72

Browse files
committed
feat: Column spans
1 parent 6be38a9 commit a893e72

File tree

1 file changed

+63
-19
lines changed

1 file changed

+63
-19
lines changed

pdf/lib/src/widgets/table.dart

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class TableRow {
3030
this.repeat = false,
3131
this.verticalAlignment,
3232
this.decoration,
33+
this.columnSpans,
3334
});
3435

3536
/// The widgets that comprise the cells in this row.
@@ -41,6 +42,8 @@ class TableRow {
4142
final BoxDecoration? decoration;
4243

4344
final TableCellVerticalAlignment? verticalAlignment;
45+
46+
final Map<int, int>? columnSpans;
4447
}
4548

4649
enum TableCellVerticalAlignment { bottom, middle, top, full }
@@ -334,69 +337,103 @@ class Table extends Widget with SpanningWidget {
334337
_context.firstLine = _context.lastLine;
335338
}
336339

340+
List<Widget> _getFilledChildrenFromColumnSpans(TableRow row) {
341+
if (row.columnSpans == null) {
342+
return row.children;
343+
}
344+
final filledChildren = <Widget>[];
345+
var n = 0;
346+
// TODO(Gustl22): Handle intrinsic column widths
347+
for (final child in row.children) {
348+
// Columns, which are currently spanned.
349+
final columnSpan = row.columnSpans![n] ?? 1;
350+
filledChildren.add(child);
351+
if (columnSpan > 1) {
352+
filledChildren
353+
.addAll(Iterable.generate(columnSpan - 1, (index) => Container()));
354+
}
355+
n += columnSpan;
356+
}
357+
return filledChildren;
358+
}
359+
360+
List<double> _getSpannedWidths(List<double?> widths, TableRow row) {
361+
final spannedWidths = <double>[];
362+
var n = 0;
363+
for (var i = 0; i < row.children.length; i++) {
364+
final columnSpan = row.columnSpans?[n] ?? 1;
365+
final indices = Iterable.generate(columnSpan, (span) => n + span);
366+
final width =
367+
indices.fold(0.0, (prev, curIndex) => prev + (widths[curIndex] ?? 0));
368+
spannedWidths.add(width);
369+
n += columnSpan;
370+
}
371+
return spannedWidths;
372+
}
373+
337374
@override
338375
void layout(Context context, BoxConstraints constraints,
339376
{bool parentUsesSize = false}) {
340377
// Compute required width for all row/columns width flex
341378
final flex = <double?>[];
342-
_widths.clear();
379+
final widths = <double?>[];
343380
_heights.clear();
344381
var index = 0;
345382

346383
for (final row in children) {
347384
var n = 0;
348-
for (final child in row.children) {
385+
for (final child in _getFilledChildrenFromColumnSpans(row)) {
349386
final columnWidth = columnWidths != null && columnWidths![n] != null
350387
? columnWidths![n]!
351388
: defaultColumnWidth;
352389
final columnLayout = columnWidth.layout(child, context, constraints);
353390
if (flex.length < n + 1) {
354391
flex.add(columnLayout.flex);
355-
_widths.add(columnLayout.width);
392+
widths.add(columnLayout.width);
356393
} else {
357394
if (columnLayout.flex! > 0) {
358395
flex[n] = math.max(flex[n]!, columnLayout.flex!);
359396
}
360-
_widths[n] = math.max(_widths[n]!, columnLayout.width!);
397+
widths[n] = math.max(widths[n]!, columnLayout.width!);
361398
}
362399
n++;
363400
}
364401
}
365402

366-
if (_widths.isEmpty) {
403+
if (widths.isEmpty) {
367404
box = PdfRect.fromPoints(PdfPoint.zero, constraints.smallest);
368405
return;
369406
}
370407

371-
final maxWidth = _widths.reduce((double? a, double? b) => a! + b!);
408+
final maxWidth = widths.reduce((double? a, double? b) => a! + b!);
372409

373410
// Compute column widths using flex and estimated width
374411
if (constraints.hasBoundedWidth) {
375412
final totalFlex = flex.reduce((double? a, double? b) => a! + b!)!;
376413
var flexSpace = 0.0;
377-
for (var n = 0; n < _widths.length; n++) {
414+
for (var n = 0; n < widths.length; n++) {
378415
if (flex[n] == 0.0) {
379-
final newWidth = _widths[n]! / maxWidth! * constraints.maxWidth;
416+
final newWidth = widths[n]! / maxWidth! * constraints.maxWidth;
380417
if ((tableWidth == TableWidth.max && totalFlex == 0.0) ||
381-
newWidth < _widths[n]!) {
382-
_widths[n] = newWidth;
418+
newWidth < widths[n]!) {
419+
widths[n] = newWidth;
383420
}
384-
flexSpace += _widths[n]!;
421+
flexSpace += widths[n]!;
385422
}
386423
}
387424
final spacePerFlex = totalFlex > 0.0
388425
? ((constraints.maxWidth - flexSpace) / totalFlex)
389426
: double.nan;
390427

391-
for (var n = 0; n < _widths.length; n++) {
428+
for (var n = 0; n < widths.length; n++) {
392429
if (flex[n]! > 0.0) {
393430
final newWidth = spacePerFlex * flex[n]!;
394-
_widths[n] = newWidth;
431+
widths[n] = newWidth;
395432
}
396433
}
397434
}
398435

399-
final totalWidth = _widths.reduce((double? a, double? b) => a! + b!)!;
436+
final totalWidth = widths.reduce((double? a, double? b) => a! + b!)!;
400437

401438
// Compute final widths
402439
var totalHeight = 0.0;
@@ -406,17 +443,21 @@ class Table extends Widget with SpanningWidget {
406443
continue;
407444
}
408445

446+
final spannedWidths = _getSpannedWidths(widths, row);
447+
409448
var n = 0;
410449
var x = 0.0;
411450

412451
var lineHeight = 0.0;
452+
413453
for (final child in row.children) {
414-
final childConstraints = BoxConstraints.tightFor(width: _widths[n]);
454+
final childConstraints =
455+
BoxConstraints.tightFor(width: spannedWidths[n]);
415456
child.layout(context, childConstraints);
416457
assert(child.box != null);
417458
child.box =
418459
PdfRect(x, totalHeight, child.box!.width, child.box!.height);
419-
x += _widths[n]!;
460+
x += spannedWidths[n];
420461
lineHeight = math.max(lineHeight, child.box!.height);
421462
n++;
422463
}
@@ -428,13 +469,13 @@ class Table extends Widget with SpanningWidget {
428469
n = 0;
429470
x = 0;
430471
for (final child in row.children) {
431-
final childConstraints =
432-
BoxConstraints.tightFor(width: _widths[n], height: lineHeight);
472+
final childConstraints = BoxConstraints.tightFor(
473+
width: spannedWidths[n], height: lineHeight);
433474
child.layout(context, childConstraints);
434475
assert(child.box != null);
435476
child.box =
436477
PdfRect(x, totalHeight, child.box!.width, child.box!.height);
437-
x += _widths[n]!;
478+
x += spannedWidths[n];
438479
n++;
439480
}
440481
}
@@ -491,6 +532,9 @@ class Table extends Widget with SpanningWidget {
491532
}
492533

493534
box = PdfRect(0, 0, totalWidth, totalHeight);
535+
536+
_widths.clear();
537+
_widths.addAll(widths);
494538
}
495539

496540
@override

0 commit comments

Comments
 (0)