Skip to content

Commit

Permalink
Table widget refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
grahamsmith committed Nov 12, 2024
1 parent 58964aa commit 7c7b34c
Showing 1 changed file with 51 additions and 69 deletions.
120 changes: 51 additions & 69 deletions pdf/lib/src/widgets/table.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,13 @@ class TableBorder extends Border {
}) {
final side = BorderSide(color: color, width: width, style: style);
return TableBorder(
top: side,
right: side,
bottom: side,
left: side,
horizontalInside: side,
verticalInside: side);
top: side,
right: side,
bottom: side,
left: side,
horizontalInside: side,
verticalInside: side,
);
}

/// Creates a border for a table where all the interior sides use the same styling and all the exterior sides use the same styling.
Expand All @@ -92,8 +93,7 @@ class TableBorder extends Border {
final BorderSide horizontalInside;
final BorderSide verticalInside;

void paintTable(Context context, PdfRect box,
[List<double?>? widths, List<double>? heights]) {
void paintTable(Context context, PdfRect box, [List<double?>? widths, List<double>? heights]) {
super.paint(context, box);

if (verticalInside.style.paint) {
Expand Down Expand Up @@ -149,15 +149,14 @@ class TableContext extends WidgetContext {
class ColumnLayout {
ColumnLayout(this.width, this.flex);

final double? width;
final double? flex;
final double width;
final double flex;
}

abstract class TableColumnWidth {
const TableColumnWidth();

ColumnLayout layout(
Widget child, Context context, BoxConstraints constraints);
ColumnLayout layout(Widget child, Context context, BoxConstraints constraints);
}

class IntrinsicColumnWidth extends TableColumnWidth {
Expand All @@ -167,19 +166,19 @@ class IntrinsicColumnWidth extends TableColumnWidth {

@override
ColumnLayout layout(
Widget child, Context context, BoxConstraints constraints) {
Widget child,
Context context,
BoxConstraints constraints,
) {
if (flex != null) {
return ColumnLayout(0, flex);
return ColumnLayout(0, flex!);
}

child.layout(context, const BoxConstraints());
assert(child.box != null);
final calculatedWidth =
child.box!.width == double.infinity ? 0.0 : child.box!.width;
final childFlex = flex ??
(child is Expanded
? child.flex.toDouble()
: (child.box!.width == double.infinity ? 1 : 0));
final calculatedWidth = child.box!.width == double.infinity ? 0.0 : child.box!.width;
final childFlex =
flex ?? (child is Expanded ? child.flex.toDouble() : (child.box!.width == double.infinity ? 1 : 0));
return ColumnLayout(calculatedWidth, childFlex);
}
}
Expand All @@ -190,8 +189,7 @@ class FixedColumnWidth extends TableColumnWidth {
final double width;

@override
ColumnLayout layout(
Widget child, Context context, BoxConstraints? constraints) {
ColumnLayout layout(Widget child, Context context, BoxConstraints? constraints) {
return ColumnLayout(width, 0);
}
}
Expand All @@ -202,8 +200,7 @@ class FlexColumnWidth extends TableColumnWidth {
final double flex;

@override
ColumnLayout layout(
Widget child, Context context, BoxConstraints? constraints) {
ColumnLayout layout(Widget child, Context context, BoxConstraints? constraints) {
return ColumnLayout(0, flex);
}
}
Expand All @@ -214,15 +211,13 @@ class FractionColumnWidth extends TableColumnWidth {
final double value;

@override
ColumnLayout layout(
Widget child, Context context, BoxConstraints? constraints) {
ColumnLayout layout(Widget child, Context context, BoxConstraints? constraints) {
return ColumnLayout(constraints!.maxWidth * value, 0);
}
}

typedef OnCellFormat = String Function(int index, dynamic data);
typedef OnCellDecoration = BoxDecoration Function(
int index, dynamic data, int rowNum);
typedef OnCellDecoration = BoxDecoration Function(int index, dynamic data, int rowNum);

/// A widget that uses the table layout algorithm for its children.
class Table extends Widget with SpanningWidget {
Expand Down Expand Up @@ -315,7 +310,7 @@ class Table extends Widget with SpanningWidget {

final TableWidth tableWidth;

final List<double?> _widths = <double?>[];
final List<double> _widths = <double>[];
final List<double> _heights = <double>[];

final TableContext _context = TableContext();
Expand All @@ -335,31 +330,29 @@ class Table extends Widget with SpanningWidget {
}

@override
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
// Compute required width for all row/columns width flex
final flex = <double?>[];
final flex = <double>[];
_widths.clear();
_heights.clear();
var index = 0;

for (final row in children) {
var n = 0;
for (final child in row.children) {
final columnWidth = columnWidths != null && columnWidths![n] != null
? columnWidths![n]!
: defaultColumnWidth;
for (final entry in row.children.asMap().entries) {
final index = entry.key;
final child = entry.value;
final columnWidth = columnWidths?[index] ?? defaultColumnWidth;
final columnLayout = columnWidth.layout(child, context, constraints);
if (flex.length < n + 1) {

if (index >= flex.length) {
flex.add(columnLayout.flex);
_widths.add(columnLayout.width);
} else {
if (columnLayout.flex! > 0) {
flex[n] = math.max(flex[n]!, columnLayout.flex!);
if (columnLayout.flex > 0) {
flex[index] = math.max(flex[index], columnLayout.flex);
}
_widths[n] = math.max(_widths[n]!, columnLayout.width!);
_widths[index] = math.max(_widths[index], columnLayout.width);
}
n++;
}
}

Expand All @@ -372,31 +365,28 @@ class Table extends Widget with SpanningWidget {

// Compute column widths using flex and estimated width
if (constraints.hasBoundedWidth) {
final totalFlex = flex.reduce((double? a, double? b) => a! + b!)!;
final totalFlex = flex.reduce((double? a, double? b) => a! + b!);
var flexSpace = 0.0;
for (var n = 0; n < _widths.length; n++) {
if (flex[n] == 0.0) {
final newWidth = _widths[n]! / maxWidth! * constraints.maxWidth;
if ((tableWidth == TableWidth.max && totalFlex == 0.0) ||
newWidth < _widths[n]!) {
final newWidth = _widths[n] / maxWidth * constraints.maxWidth;
if ((tableWidth == TableWidth.max && totalFlex == 0.0) || newWidth < _widths[n]) {
_widths[n] = newWidth;
}
flexSpace += _widths[n]!;
flexSpace += _widths[n];
}
}
final spacePerFlex = totalFlex > 0.0
? ((constraints.maxWidth - flexSpace) / totalFlex)
: double.nan;
final spacePerFlex = totalFlex > 0.0 ? ((constraints.maxWidth - flexSpace) / totalFlex) : double.nan;

for (var n = 0; n < _widths.length; n++) {
if (flex[n]! > 0.0) {
final newWidth = spacePerFlex * flex[n]!;
if (flex[n] > 0.0) {
final newWidth = spacePerFlex * flex[n];
_widths[n] = newWidth;
}
}
}

final totalWidth = _widths.reduce((double? a, double? b) => a! + b!)!;
final totalWidth = _widths.reduce((double? a, double? b) => a! + b!);

// Compute final widths
var totalHeight = 0.0;
Expand All @@ -414,9 +404,8 @@ class Table extends Widget with SpanningWidget {
final childConstraints = BoxConstraints.tightFor(width: _widths[n]);
child.layout(context, childConstraints);
assert(child.box != null);
child.box =
PdfRect(x, totalHeight, child.box!.width, child.box!.height);
x += _widths[n]!;
child.box = PdfRect(x, totalHeight, child.box!.width, child.box!.height);
x += _widths[n];
lineHeight = math.max(lineHeight, child.box!.height);
n++;
}
Expand All @@ -428,13 +417,11 @@ class Table extends Widget with SpanningWidget {
n = 0;
x = 0;
for (final child in row.children) {
final childConstraints =
BoxConstraints.tightFor(width: _widths[n], height: lineHeight);
final childConstraints = BoxConstraints.tightFor(width: _widths[n], height: lineHeight);
child.layout(context, childConstraints);
assert(child.box != null);
child.box =
PdfRect(x, totalHeight, child.box!.width, child.box!.height);
x += _widths[n]!;
child.box = PdfRect(x, totalHeight, child.box!.width, child.box!.height);
x += _widths[n];
n++;
}
}
Expand Down Expand Up @@ -466,9 +453,7 @@ class Table extends Widget with SpanningWidget {
childY = totalHeight - child.box!.y - _getHeight(heightIndex);
break;
case TableCellVerticalAlignment.middle:
childY = totalHeight -
child.box!.y -
(_getHeight(heightIndex) + child.box!.height) / 2;
childY = totalHeight - child.box!.y - (_getHeight(heightIndex) + child.box!.height) / 2;
break;
case TableCellVerticalAlignment.top:
case TableCellVerticalAlignment.full:
Expand Down Expand Up @@ -530,8 +515,7 @@ class Table extends Widget with SpanningWidget {
for (final child in row.children) {
context.canvas
..saveContext()
..drawRect(
child.box!.x, child.box!.y, child.box!.width, child.box!.height)
..drawRect(child.box!.x, child.box!.y, child.box!.width, child.box!.height)
..clipPath();
child.paint(context);
context.canvas.restoreContext();
Expand Down Expand Up @@ -574,8 +558,6 @@ class Table extends Widget with SpanningWidget {
}

double _getHeight(int heightIndex) {
return (heightIndex >= 0 && heightIndex < _heights.length)
? _heights[heightIndex]
: 0.0;
return (heightIndex >= 0 && heightIndex < _heights.length) ? _heights[heightIndex] : 0.0;
}
}

0 comments on commit 7c7b34c

Please sign in to comment.