David PHAM-VAN

Improve Table.fromTextArray()

1 # Changelog 1 # Changelog
2 2
  3 +## 1.8.0
  4 +
  5 +- Improve Table.fromTextArray()
  6 +
3 ## 1.7.1 7 ## 1.7.1
4 8
5 - Fix justified text softWrap issue 9 - Fix justified text softWrap issue
@@ -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