Showing
8 changed files
with
188 additions
and
30 deletions
@@ -187,48 +187,156 @@ class FractionColumnWidth extends TableColumnWidth { | @@ -187,48 +187,156 @@ class FractionColumnWidth extends TableColumnWidth { | ||
187 | } | 187 | } |
188 | } | 188 | } |
189 | 189 | ||
190 | +typedef OnCellFormat = String Function(int index, dynamic data); | ||
191 | + | ||
190 | /// A widget that uses the table layout algorithm for its children. | 192 | /// A widget that uses the table layout algorithm for its children. |
191 | class Table extends Widget implements SpanningWidget { | 193 | class Table extends Widget implements SpanningWidget { |
192 | - Table( | ||
193 | - {this.children = const <TableRow>[], | 194 | + Table({ |
195 | + this.children = const <TableRow>[], | ||
194 | this.border, | 196 | this.border, |
195 | this.defaultVerticalAlignment = TableCellVerticalAlignment.top, | 197 | this.defaultVerticalAlignment = TableCellVerticalAlignment.top, |
196 | this.columnWidths, | 198 | this.columnWidths, |
197 | this.defaultColumnWidth = const IntrinsicColumnWidth(), | 199 | this.defaultColumnWidth = const IntrinsicColumnWidth(), |
198 | - this.tableWidth = TableWidth.max}) | ||
199 | - : assert(children != null), | 200 | + this.tableWidth = TableWidth.max, |
201 | + }) : assert(children != null), | ||
200 | assert(defaultColumnWidth != null), | 202 | assert(defaultColumnWidth != null), |
201 | assert(defaultVerticalAlignment != null), | 203 | assert(defaultVerticalAlignment != null), |
202 | super(); | 204 | super(); |
203 | 205 | ||
204 | factory Table.fromTextArray({ | 206 | factory Table.fromTextArray({ |
205 | - @required Context context, | ||
206 | - @required List<List<String>> data, | ||
207 | - EdgeInsets margin = const EdgeInsets.all(5), | 207 | + Context context, |
208 | + @required List<List<dynamic>> data, | ||
209 | + @deprecated EdgeInsets margin, | ||
210 | + EdgeInsets cellPadding = const EdgeInsets.all(5), | ||
211 | + double cellHeight = 0, | ||
212 | + Alignment cellAlignment = Alignment.topLeft, | ||
213 | + Map<int, Alignment> cellAlignments, | ||
214 | + TextStyle cellStyle, | ||
215 | + TextStyle oddCellStyle, | ||
216 | + OnCellFormat cellFormat, | ||
217 | + int headerCount = 1, | ||
218 | + List<dynamic> headers, | ||
219 | + EdgeInsets headerPadding, | ||
220 | + double headerHeight, | ||
221 | + Alignment headerAlignment = Alignment.center, | ||
222 | + Map<int, Alignment> headerAlignments, | ||
223 | + TextStyle headerStyle, | ||
224 | + OnCellFormat headerFormat, | ||
225 | + TableBorder border = const TableBorder(), | ||
226 | + Map<int, TableColumnWidth> columnWidths, | ||
227 | + IntrinsicColumnWidth defaultColumnWidth = const IntrinsicColumnWidth(), | ||
228 | + TableWidth tableWidth = TableWidth.max, | ||
229 | + BoxDecoration headerDecoration, | ||
230 | + BoxDecoration rowDecoration, | ||
231 | + BoxDecoration oddRowDecoration, | ||
208 | }) { | 232 | }) { |
233 | + assert(data != null); | ||
234 | + assert(headerCount != null && headerCount >= 0); | ||
235 | + assert(cellHeight != null); | ||
236 | + | ||
237 | + if (margin != null) { | ||
238 | + cellPadding = margin; | ||
239 | + } | ||
240 | + | ||
241 | + if (context != null) { | ||
242 | + final ThemeData theme = Theme.of(context); | ||
243 | + headerStyle ??= theme.tableHeader; | ||
244 | + cellStyle ??= theme.tableCell; | ||
245 | + } | ||
246 | + | ||
247 | + headerPadding ??= cellPadding; | ||
248 | + headerHeight ??= cellHeight; | ||
249 | + oddRowDecoration ??= rowDecoration; | ||
250 | + oddCellStyle ??= cellStyle; | ||
251 | + cellAlignments ??= const <int, Alignment>{}; | ||
252 | + headerAlignments ??= cellAlignments; | ||
253 | + | ||
209 | final List<TableRow> rows = <TableRow>[]; | 254 | final List<TableRow> rows = <TableRow>[]; |
210 | - for (List<String> row in data) { | 255 | + |
256 | + int rowNum = 0; | ||
257 | + if (headers != null) { | ||
258 | + final List<Widget> tableRow = <Widget>[]; | ||
259 | + | ||
260 | + for (final dynamic cell in headers) { | ||
261 | + tableRow.add( | ||
262 | + Container( | ||
263 | + alignment: headerAlignments[tableRow.length] ?? headerAlignment, | ||
264 | + padding: headerPadding, | ||
265 | + constraints: BoxConstraints(minHeight: headerHeight), | ||
266 | + child: Text( | ||
267 | + headerFormat == null | ||
268 | + ? cell.toString() | ||
269 | + : headerFormat(tableRow.length, cell), | ||
270 | + style: headerStyle, | ||
271 | + ), | ||
272 | + ), | ||
273 | + ); | ||
274 | + } | ||
275 | + rows.add(TableRow( | ||
276 | + children: tableRow, | ||
277 | + repeat: true, | ||
278 | + decoration: headerDecoration, | ||
279 | + )); | ||
280 | + rowNum++; | ||
281 | + } | ||
282 | + | ||
283 | + for (final List<dynamic> row in data) { | ||
211 | final List<Widget> tableRow = <Widget>[]; | 284 | final List<Widget> tableRow = <Widget>[]; |
212 | - if (row == data.first) { | ||
213 | - for (String cell in row) { | ||
214 | - tableRow.add(Container( | ||
215 | - alignment: Alignment.center, | ||
216 | - margin: margin, | ||
217 | - child: Text(cell, style: Theme.of(context).tableHeader))); | 285 | + final bool isOdd = (rowNum - headerCount) % 2 != 0; |
286 | + | ||
287 | + if (rowNum < headerCount) { | ||
288 | + for (final dynamic cell in row) { | ||
289 | + tableRow.add( | ||
290 | + Container( | ||
291 | + alignment: headerAlignments[tableRow.length] ?? headerAlignment, | ||
292 | + padding: headerPadding, | ||
293 | + constraints: BoxConstraints(minHeight: headerHeight), | ||
294 | + child: Text( | ||
295 | + headerFormat == null | ||
296 | + ? cell.toString() | ||
297 | + : headerFormat(tableRow.length, cell), | ||
298 | + style: headerStyle, | ||
299 | + ), | ||
300 | + ), | ||
301 | + ); | ||
218 | } | 302 | } |
219 | } else { | 303 | } else { |
220 | - for (String cell in row) { | ||
221 | - tableRow.add(Container( | ||
222 | - margin: margin, | ||
223 | - child: Text(cell, style: Theme.of(context).tableCell))); | 304 | + for (final dynamic cell in row) { |
305 | + tableRow.add( | ||
306 | + Container( | ||
307 | + alignment: cellAlignments[tableRow.length] ?? cellAlignment, | ||
308 | + padding: cellPadding, | ||
309 | + constraints: BoxConstraints(minHeight: cellHeight), | ||
310 | + child: Text( | ||
311 | + cellFormat == null | ||
312 | + ? cell.toString() | ||
313 | + : cellFormat(tableRow.length, cell), | ||
314 | + style: isOdd ? oddCellStyle : cellStyle, | ||
315 | + ), | ||
316 | + ), | ||
317 | + ); | ||
224 | } | 318 | } |
225 | } | 319 | } |
226 | - rows.add(TableRow(children: tableRow, repeat: row == data.first)); | 320 | + |
321 | + BoxDecoration decoration = isOdd ? oddRowDecoration : rowDecoration; | ||
322 | + if (rowNum < headerCount) { | ||
323 | + decoration = headerDecoration; | ||
324 | + } | ||
325 | + | ||
326 | + rows.add(TableRow( | ||
327 | + children: tableRow, | ||
328 | + repeat: rowNum < headerCount, | ||
329 | + decoration: decoration, | ||
330 | + )); | ||
331 | + rowNum++; | ||
227 | } | 332 | } |
228 | return Table( | 333 | return Table( |
229 | - border: const TableBorder(), | ||
230 | - tableWidth: TableWidth.max, | ||
231 | - children: rows); | 334 | + border: border, |
335 | + tableWidth: tableWidth, | ||
336 | + children: rows, | ||
337 | + columnWidths: columnWidths, | ||
338 | + defaultColumnWidth: defaultColumnWidth, | ||
339 | + ); | ||
232 | } | 340 | } |
233 | 341 | ||
234 | @override | 342 | @override |
@@ -4,7 +4,7 @@ description: A pdf producer for Dart. It can create pdf files for both web or fl | @@ -4,7 +4,7 @@ description: A pdf producer for Dart. It can create pdf files for both web or fl | ||
4 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/pdf | 4 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/pdf |
5 | repository: https://github.com/DavBfr/dart_pdf | 5 | repository: https://github.com/DavBfr/dart_pdf |
6 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues | 6 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues |
7 | -version: 1.7.1 | 7 | +version: 1.8.0 |
8 | 8 | ||
9 | environment: | 9 | environment: |
10 | sdk: ">=2.3.0 <3.0.0" | 10 | sdk: ">=2.3.0 <3.0.0" |
@@ -186,6 +186,52 @@ void main() { | @@ -186,6 +186,52 @@ void main() { | ||
186 | ); | 186 | ); |
187 | }); | 187 | }); |
188 | 188 | ||
189 | + test('Table fromTextArray', () { | ||
190 | + pdf.addPage(Page( | ||
191 | + build: (Context context) => Table.fromTextArray( | ||
192 | + context: context, | ||
193 | + tableWidth: TableWidth.min, | ||
194 | + data: <List<dynamic>>[ | ||
195 | + <dynamic>['One', 'Two', 'Three'], | ||
196 | + <dynamic>[1, 2, 3], | ||
197 | + <dynamic>[4, 5, 6], | ||
198 | + ], | ||
199 | + ), | ||
200 | + )); | ||
201 | + }); | ||
202 | + | ||
203 | + test('Table fromTextArray with formatting', () { | ||
204 | + pdf.addPage(Page( | ||
205 | + build: (Context context) => Table.fromTextArray( | ||
206 | + border: null, | ||
207 | + cellAlignment: Alignment.center, | ||
208 | + headerDecoration: const BoxDecoration( | ||
209 | + borderRadius: 2, | ||
210 | + color: PdfColors.indigo, | ||
211 | + ), | ||
212 | + headerHeight: 25, | ||
213 | + cellHeight: 40, | ||
214 | + headerStyle: TextStyle( | ||
215 | + color: PdfColors.white, | ||
216 | + fontWeight: FontWeight.bold, | ||
217 | + ), | ||
218 | + rowDecoration: const BoxDecoration( | ||
219 | + border: BoxBorder( | ||
220 | + bottom: true, | ||
221 | + color: PdfColors.indigo, | ||
222 | + width: .5, | ||
223 | + ), | ||
224 | + ), | ||
225 | + headers: <dynamic>['One', 'Two', 'Three'], | ||
226 | + data: <List<dynamic>>[ | ||
227 | + <dynamic>[1, 2, 3], | ||
228 | + <dynamic>[4, 5, 6], | ||
229 | + <dynamic>[7, 8, 9], | ||
230 | + ], | ||
231 | + ), | ||
232 | + )); | ||
233 | + }); | ||
234 | + | ||
189 | tearDownAll(() { | 235 | tearDownAll(() { |
190 | final File file = File('widgets-table.pdf'); | 236 | final File file = File('widgets-table.pdf'); |
191 | file.writeAsBytesSync(pdf.save()); | 237 | file.writeAsBytesSync(pdf.save()); |
@@ -164,7 +164,7 @@ void main() { | @@ -164,7 +164,7 @@ void main() { | ||
164 | build: (Context context) => <Widget>[ | 164 | build: (Context context) => <Widget>[ |
165 | Table.fromTextArray( | 165 | Table.fromTextArray( |
166 | context: context, | 166 | context: context, |
167 | - margin: const EdgeInsets.all(3), | 167 | + cellPadding: const EdgeInsets.all(3), |
168 | data: <List<String>>[ | 168 | data: <List<String>>[ |
169 | <String>['Company', 'Contact', 'Country'], | 169 | <String>['Company', 'Contact', 'Country'], |
170 | <String>['Alfreds Futterkiste', 'Maria Anders', 'Germany'], | 170 | <String>['Alfreds Futterkiste', 'Maria Anders', 'Germany'], |
No preview for this file type
No preview for this file type
No preview for this file type
-
Please register or login to post a comment