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