Showing
4 changed files
with
108 additions
and
14 deletions
| @@ -86,14 +86,91 @@ class _TableContext extends WidgetContext { | @@ -86,14 +86,91 @@ class _TableContext extends WidgetContext { | ||
| 86 | int lastLine = 0; | 86 | int lastLine = 0; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | +class _ColumnLayout { | ||
| 90 | + _ColumnLayout(this.width, this.flex); | ||
| 91 | + | ||
| 92 | + final double width; | ||
| 93 | + final double flex; | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +abstract class TableColumnWidth { | ||
| 97 | + const TableColumnWidth(); | ||
| 98 | + | ||
| 99 | + _ColumnLayout layout( | ||
| 100 | + Widget child, Context context, BoxConstraints constraints); | ||
| 101 | +} | ||
| 102 | + | ||
| 103 | +class IntrinsicColumnWidth extends TableColumnWidth { | ||
| 104 | + const IntrinsicColumnWidth({this.flex}); | ||
| 105 | + | ||
| 106 | + final double flex; | ||
| 107 | + | ||
| 108 | + @override | ||
| 109 | + _ColumnLayout layout( | ||
| 110 | + Widget child, Context context, BoxConstraints constraints) { | ||
| 111 | + if (flex != null) { | ||
| 112 | + return _ColumnLayout(0, flex); | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + child.layout(context, const BoxConstraints()); | ||
| 116 | + assert(child.box != null); | ||
| 117 | + final double calculatedWidth = | ||
| 118 | + child.box.width == double.infinity ? 0 : child.box.width; | ||
| 119 | + final double childFlex = flex ?? | ||
| 120 | + (child is Expanded | ||
| 121 | + ? child.flex.toDouble() | ||
| 122 | + : (child.box.width == double.infinity ? 1 : 0)); | ||
| 123 | + return _ColumnLayout(calculatedWidth, childFlex); | ||
| 124 | + } | ||
| 125 | +} | ||
| 126 | + | ||
| 127 | +class FixedColumnWidth extends TableColumnWidth { | ||
| 128 | + const FixedColumnWidth(this.width) : assert(width != null); | ||
| 129 | + | ||
| 130 | + final double width; | ||
| 131 | + | ||
| 132 | + @override | ||
| 133 | + _ColumnLayout layout( | ||
| 134 | + Widget child, Context context, BoxConstraints constraints) { | ||
| 135 | + return _ColumnLayout(width, 0); | ||
| 136 | + } | ||
| 137 | +} | ||
| 138 | + | ||
| 139 | +class FlexColumnWidth extends TableColumnWidth { | ||
| 140 | + const FlexColumnWidth([this.flex = 1.0]) : assert(flex != null); | ||
| 141 | + | ||
| 142 | + final double flex; | ||
| 143 | + | ||
| 144 | + @override | ||
| 145 | + _ColumnLayout layout( | ||
| 146 | + Widget child, Context context, BoxConstraints constraints) { | ||
| 147 | + return _ColumnLayout(0, flex); | ||
| 148 | + } | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +class FractionColumnWidth extends TableColumnWidth { | ||
| 152 | + const FractionColumnWidth(this.value); | ||
| 153 | + | ||
| 154 | + final double value; | ||
| 155 | + | ||
| 156 | + @override | ||
| 157 | + _ColumnLayout layout( | ||
| 158 | + Widget child, Context context, BoxConstraints constraints) { | ||
| 159 | + return _ColumnLayout(constraints.maxWidth * value, 0); | ||
| 160 | + } | ||
| 161 | +} | ||
| 162 | + | ||
| 89 | /// A widget that uses the table layout algorithm for its children. | 163 | /// A widget that uses the table layout algorithm for its children. |
| 90 | class Table extends Widget implements SpanningWidget { | 164 | class Table extends Widget implements SpanningWidget { |
| 91 | Table( | 165 | Table( |
| 92 | {this.children = const <TableRow>[], | 166 | {this.children = const <TableRow>[], |
| 93 | this.border, | 167 | this.border, |
| 94 | this.defaultVerticalAlignment = TableCellVerticalAlignment.top, | 168 | this.defaultVerticalAlignment = TableCellVerticalAlignment.top, |
| 169 | + this.columnWidths, | ||
| 170 | + this.defaultColumnWidth = const IntrinsicColumnWidth(), | ||
| 95 | this.tableWidth = TableWidth.max}) | 171 | this.tableWidth = TableWidth.max}) |
| 96 | : assert(children != null), | 172 | : assert(children != null), |
| 173 | + assert(defaultColumnWidth != null), | ||
| 97 | super(); | 174 | super(); |
| 98 | 175 | ||
| 99 | factory Table.fromTextArray( | 176 | factory Table.fromTextArray( |
| @@ -140,6 +217,9 @@ class Table extends Widget implements SpanningWidget { | @@ -140,6 +217,9 @@ class Table extends Widget implements SpanningWidget { | ||
| 140 | 217 | ||
| 141 | _TableContext _context = _TableContext(); | 218 | _TableContext _context = _TableContext(); |
| 142 | 219 | ||
| 220 | + final TableColumnWidth defaultColumnWidth; | ||
| 221 | + final Map<int, TableColumnWidth> columnWidths; | ||
| 222 | + | ||
| 143 | @override | 223 | @override |
| 144 | WidgetContext saveContext() { | 224 | WidgetContext saveContext() { |
| 145 | return _context; | 225 | return _context; |
| @@ -163,21 +243,20 @@ class Table extends Widget implements SpanningWidget { | @@ -163,21 +243,20 @@ class Table extends Widget implements SpanningWidget { | ||
| 163 | for (TableRow row in children) { | 243 | for (TableRow row in children) { |
| 164 | int n = 0; | 244 | int n = 0; |
| 165 | for (Widget child in row.children) { | 245 | for (Widget child in row.children) { |
| 166 | - child.layout(context, const BoxConstraints()); | ||
| 167 | - assert(child.box != null); | ||
| 168 | - final double calculatedWidth = | ||
| 169 | - child.box.width == double.infinity ? 0.0 : child.box.width; | ||
| 170 | - final double childFlex = child is Expanded | ||
| 171 | - ? child.flex.toDouble() | ||
| 172 | - : (child.box.width == double.infinity ? 1.0 : 0.0); | 246 | + final TableColumnWidth columnWidth = |
| 247 | + columnWidths != null && columnWidths[n] != null | ||
| 248 | + ? columnWidths[n] | ||
| 249 | + : defaultColumnWidth; | ||
| 250 | + final _ColumnLayout columnLayout = | ||
| 251 | + columnWidth.layout(child, context, constraints); | ||
| 173 | if (flex.length < n + 1) { | 252 | if (flex.length < n + 1) { |
| 174 | - flex.add(childFlex); | ||
| 175 | - _widths.add(calculatedWidth); | 253 | + flex.add(columnLayout.flex); |
| 254 | + _widths.add(columnLayout.width); | ||
| 176 | } else { | 255 | } else { |
| 177 | - if (childFlex > 0) { | ||
| 178 | - flex[n] *= childFlex; | 256 | + if (columnLayout.flex > 0) { |
| 257 | + flex[n] = math.max(flex[n], columnLayout.flex); | ||
| 179 | } | 258 | } |
| 180 | - _widths[n] = math.max(_widths[n], calculatedWidth); | 259 | + _widths[n] = math.max(_widths[n], columnLayout.width); |
| 181 | } | 260 | } |
| 182 | n++; | 261 | n++; |
| 183 | } | 262 | } |
| @@ -131,6 +131,20 @@ void main() { | @@ -131,6 +131,20 @@ void main() { | ||
| 131 | ])); | 131 | ])); |
| 132 | }); | 132 | }); |
| 133 | 133 | ||
| 134 | + test('Table Widget Widths', () { | ||
| 135 | + pdf.addPage(Page( | ||
| 136 | + build: (Context context) => Table( | ||
| 137 | + children: buildTable(context: context, count: 20), | ||
| 138 | + border: const TableBorder(), | ||
| 139 | + columnWidths: <int, TableColumnWidth>{ | ||
| 140 | + 0: const FixedColumnWidth(80), | ||
| 141 | + 1: const FlexColumnWidth(2), | ||
| 142 | + 2: const FractionColumnWidth(.2), | ||
| 143 | + }, | ||
| 144 | + ), | ||
| 145 | + )); | ||
| 146 | + }); | ||
| 147 | + | ||
| 134 | tearDownAll(() { | 148 | tearDownAll(() { |
| 135 | final File file = File('widgets-table.pdf'); | 149 | final File file = File('widgets-table.pdf'); |
| 136 | file.writeAsBytesSync(pdf.save()); | 150 | file.writeAsBytesSync(pdf.save()); |
No preview for this file type
-
Please register or login to post a comment