| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/material.dart'; |
| import 'package:flutter/rendering.dart'; |
| |
| import '../../gallery/demo.dart'; |
| |
| class Dessert { |
| Dessert(this.name, this.calories, this.fat, this.carbs, this.protein, this.sodium, this.calcium, this.iron); |
| final String name; |
| final int calories; |
| final double fat; |
| final int carbs; |
| final double protein; |
| final int sodium; |
| final int calcium; |
| final int iron; |
| |
| bool selected = false; |
| } |
| |
| class DessertDataSource extends DataTableSource { |
| final List<Dessert> _desserts = <Dessert>[ |
| Dessert('Frozen yogurt', 159, 6.0, 24, 4.0, 87, 14, 1), |
| Dessert('Ice cream sandwich', 237, 9.0, 37, 4.3, 129, 8, 1), |
| Dessert('Eclair', 262, 16.0, 24, 6.0, 337, 6, 7), |
| Dessert('Cupcake', 305, 3.7, 67, 4.3, 413, 3, 8), |
| Dessert('Gingerbread', 356, 16.0, 49, 3.9, 327, 7, 16), |
| Dessert('Jelly bean', 375, 0.0, 94, 0.0, 50, 0, 0), |
| Dessert('Lollipop', 392, 0.2, 98, 0.0, 38, 0, 2), |
| Dessert('Honeycomb', 408, 3.2, 87, 6.5, 562, 0, 45), |
| Dessert('Donut', 452, 25.0, 51, 4.9, 326, 2, 22), |
| Dessert('KitKat', 518, 26.0, 65, 7.0, 54, 12, 6), |
| |
| Dessert('Frozen yogurt with sugar', 168, 6.0, 26, 4.0, 87, 14, 1), |
| Dessert('Ice cream sandwich with sugar', 246, 9.0, 39, 4.3, 129, 8, 1), |
| Dessert('Eclair with sugar', 271, 16.0, 26, 6.0, 337, 6, 7), |
| Dessert('Cupcake with sugar', 314, 3.7, 69, 4.3, 413, 3, 8), |
| Dessert('Gingerbread with sugar', 345, 16.0, 51, 3.9, 327, 7, 16), |
| Dessert('Jelly bean with sugar', 364, 0.0, 96, 0.0, 50, 0, 0), |
| Dessert('Lollipop with sugar', 401, 0.2, 100, 0.0, 38, 0, 2), |
| Dessert('Honeycomb with sugar', 417, 3.2, 89, 6.5, 562, 0, 45), |
| Dessert('Donut with sugar', 461, 25.0, 53, 4.9, 326, 2, 22), |
| Dessert('KitKat with sugar', 527, 26.0, 67, 7.0, 54, 12, 6), |
| |
| Dessert('Frozen yogurt with honey', 223, 6.0, 36, 4.0, 87, 14, 1), |
| Dessert('Ice cream sandwich with honey', 301, 9.0, 49, 4.3, 129, 8, 1), |
| Dessert('Eclair with honey', 326, 16.0, 36, 6.0, 337, 6, 7), |
| Dessert('Cupcake with honey', 369, 3.7, 79, 4.3, 413, 3, 8), |
| Dessert('Gingerbread with honey', 420, 16.0, 61, 3.9, 327, 7, 16), |
| Dessert('Jelly bean with honey', 439, 0.0, 106, 0.0, 50, 0, 0), |
| Dessert('Lollipop with honey', 456, 0.2, 110, 0.0, 38, 0, 2), |
| Dessert('Honeycomb with honey', 472, 3.2, 99, 6.5, 562, 0, 45), |
| Dessert('Donut with honey', 516, 25.0, 63, 4.9, 326, 2, 22), |
| Dessert('KitKat with honey', 582, 26.0, 77, 7.0, 54, 12, 6), |
| |
| Dessert('Frozen yogurt with milk', 262, 8.4, 36, 12.0, 194, 44, 1), |
| Dessert('Ice cream sandwich with milk', 339, 11.4, 49, 12.3, 236, 38, 1), |
| Dessert('Eclair with milk', 365, 18.4, 36, 14.0, 444, 36, 7), |
| Dessert('Cupcake with milk', 408, 6.1, 79, 12.3, 520, 33, 8), |
| Dessert('Gingerbread with milk', 459, 18.4, 61, 11.9, 434, 37, 16), |
| Dessert('Jelly bean with milk', 478, 2.4, 106, 8.0, 157, 30, 0), |
| Dessert('Lollipop with milk', 495, 2.6, 110, 8.0, 145, 30, 2), |
| Dessert('Honeycomb with milk', 511, 5.6, 99, 14.5, 669, 30, 45), |
| Dessert('Donut with milk', 555, 27.4, 63, 12.9, 433, 32, 22), |
| Dessert('KitKat with milk', 621, 28.4, 77, 15.0, 161, 42, 6), |
| |
| Dessert('Coconut slice and frozen yogurt', 318, 21.0, 31, 5.5, 96, 14, 7), |
| Dessert('Coconut slice and ice cream sandwich', 396, 24.0, 44, 5.8, 138, 8, 7), |
| Dessert('Coconut slice and eclair', 421, 31.0, 31, 7.5, 346, 6, 13), |
| Dessert('Coconut slice and cupcake', 464, 18.7, 74, 5.8, 422, 3, 14), |
| Dessert('Coconut slice and gingerbread', 515, 31.0, 56, 5.4, 316, 7, 22), |
| Dessert('Coconut slice and jelly bean', 534, 15.0, 101, 1.5, 59, 0, 6), |
| Dessert('Coconut slice and lollipop', 551, 15.2, 105, 1.5, 47, 0, 8), |
| Dessert('Coconut slice and honeycomb', 567, 18.2, 94, 8.0, 571, 0, 51), |
| Dessert('Coconut slice and donut', 611, 40.0, 58, 6.4, 335, 2, 28), |
| Dessert('Coconut slice and KitKat', 677, 41.0, 72, 8.5, 63, 12, 12), |
| ]; |
| |
| void _sort<T>(Comparable<T> getField(Dessert d), bool ascending) { |
| _desserts.sort((Dessert a, Dessert b) { |
| if (!ascending) { |
| final Dessert c = a; |
| a = b; |
| b = c; |
| } |
| final Comparable<T> aValue = getField(a); |
| final Comparable<T> bValue = getField(b); |
| return Comparable.compare(aValue, bValue); |
| }); |
| notifyListeners(); |
| } |
| |
| int _selectedCount = 0; |
| |
| @override |
| DataRow getRow(int index) { |
| assert(index >= 0); |
| if (index >= _desserts.length) |
| return null; |
| final Dessert dessert = _desserts[index]; |
| return DataRow.byIndex( |
| index: index, |
| selected: dessert.selected, |
| onSelectChanged: (bool value) { |
| if (dessert.selected != value) { |
| _selectedCount += value ? 1 : -1; |
| assert(_selectedCount >= 0); |
| dessert.selected = value; |
| notifyListeners(); |
| } |
| }, |
| cells: <DataCell>[ |
| DataCell(Text('${dessert.name}')), |
| DataCell(Text('${dessert.calories}')), |
| DataCell(Text('${dessert.fat.toStringAsFixed(1)}')), |
| DataCell(Text('${dessert.carbs}')), |
| DataCell(Text('${dessert.protein.toStringAsFixed(1)}')), |
| DataCell(Text('${dessert.sodium}')), |
| DataCell(Text('${dessert.calcium}%')), |
| DataCell(Text('${dessert.iron}%')), |
| ], |
| ); |
| } |
| |
| @override |
| int get rowCount => _desserts.length; |
| |
| @override |
| bool get isRowCountApproximate => false; |
| |
| @override |
| int get selectedRowCount => _selectedCount; |
| |
| void _selectAll(bool checked) { |
| for (final Dessert dessert in _desserts) |
| dessert.selected = checked; |
| _selectedCount = checked ? _desserts.length : 0; |
| notifyListeners(); |
| } |
| } |
| |
| class DataTableDemo extends StatefulWidget { |
| static const String routeName = '/material/data-table'; |
| |
| @override |
| _DataTableDemoState createState() => _DataTableDemoState(); |
| } |
| |
| class _DataTableDemoState extends State<DataTableDemo> { |
| int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage; |
| int _sortColumnIndex; |
| bool _sortAscending = true; |
| final DessertDataSource _dessertsDataSource = DessertDataSource(); |
| |
| void _sort<T>(Comparable<T> getField(Dessert d), int columnIndex, bool ascending) { |
| _dessertsDataSource._sort<T>(getField, ascending); |
| setState(() { |
| _sortColumnIndex = columnIndex; |
| _sortAscending = ascending; |
| }); |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| return Scaffold( |
| appBar: AppBar( |
| title: const Text('Data tables'), |
| actions: <Widget>[ |
| MaterialDemoDocumentationButton(DataTableDemo.routeName), |
| ], |
| ), |
| body: Scrollbar( |
| child: ListView( |
| padding: const EdgeInsets.all(20.0), |
| children: <Widget>[ |
| PaginatedDataTable( |
| header: const Text('Nutrition'), |
| rowsPerPage: _rowsPerPage, |
| onRowsPerPageChanged: (int value) { setState(() { _rowsPerPage = value; }); }, |
| sortColumnIndex: _sortColumnIndex, |
| sortAscending: _sortAscending, |
| onSelectAll: _dessertsDataSource._selectAll, |
| columns: <DataColumn>[ |
| DataColumn( |
| label: const Text('Dessert (100g serving)'), |
| onSort: (int columnIndex, bool ascending) => _sort<String>((Dessert d) => d.name, columnIndex, ascending), |
| ), |
| DataColumn( |
| label: const Text('Calories'), |
| tooltip: 'The total amount of food energy in the given serving size.', |
| numeric: true, |
| onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.calories, columnIndex, ascending), |
| ), |
| DataColumn( |
| label: const Text('Fat (g)'), |
| numeric: true, |
| onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.fat, columnIndex, ascending), |
| ), |
| DataColumn( |
| label: const Text('Carbs (g)'), |
| numeric: true, |
| onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.carbs, columnIndex, ascending), |
| ), |
| DataColumn( |
| label: const Text('Protein (g)'), |
| numeric: true, |
| onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.protein, columnIndex, ascending), |
| ), |
| DataColumn( |
| label: const Text('Sodium (mg)'), |
| numeric: true, |
| onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.sodium, columnIndex, ascending), |
| ), |
| DataColumn( |
| label: const Text('Calcium (%)'), |
| tooltip: 'The amount of calcium as a percentage of the recommended daily amount.', |
| numeric: true, |
| onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.calcium, columnIndex, ascending), |
| ), |
| DataColumn( |
| label: const Text('Iron (%)'), |
| numeric: true, |
| onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.iron, columnIndex, ascending), |
| ), |
| ], |
| source: _dessertsDataSource, |
| ), |
| ], |
| ), |
| ), |
| ); |
| } |
| } |