• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'package:flutter/material.dart';
6import 'package:flutter/rendering.dart';
7
8import '../../gallery/demo.dart';
9
10class Dessert {
11  Dessert(this.name, this.calories, this.fat, this.carbs, this.protein, this.sodium, this.calcium, this.iron);
12  final String name;
13  final int calories;
14  final double fat;
15  final int carbs;
16  final double protein;
17  final int sodium;
18  final int calcium;
19  final int iron;
20
21  bool selected = false;
22}
23
24class DessertDataSource extends DataTableSource {
25  final List<Dessert> _desserts = <Dessert>[
26    Dessert('Frozen yogurt',                        159,  6.0,  24,  4.0,  87, 14,  1),
27    Dessert('Ice cream sandwich',                   237,  9.0,  37,  4.3, 129,  8,  1),
28    Dessert('Eclair',                               262, 16.0,  24,  6.0, 337,  6,  7),
29    Dessert('Cupcake',                              305,  3.7,  67,  4.3, 413,  3,  8),
30    Dessert('Gingerbread',                          356, 16.0,  49,  3.9, 327,  7, 16),
31    Dessert('Jelly bean',                           375,  0.0,  94,  0.0,  50,  0,  0),
32    Dessert('Lollipop',                             392,  0.2,  98,  0.0,  38,  0,  2),
33    Dessert('Honeycomb',                            408,  3.2,  87,  6.5, 562,  0, 45),
34    Dessert('Donut',                                452, 25.0,  51,  4.9, 326,  2, 22),
35    Dessert('KitKat',                               518, 26.0,  65,  7.0,  54, 12,  6),
36
37    Dessert('Frozen yogurt with sugar',             168,  6.0,  26,  4.0,  87, 14,  1),
38    Dessert('Ice cream sandwich with sugar',        246,  9.0,  39,  4.3, 129,  8,  1),
39    Dessert('Eclair with sugar',                    271, 16.0,  26,  6.0, 337,  6,  7),
40    Dessert('Cupcake with sugar',                   314,  3.7,  69,  4.3, 413,  3,  8),
41    Dessert('Gingerbread with sugar',               345, 16.0,  51,  3.9, 327,  7, 16),
42    Dessert('Jelly bean with sugar',                364,  0.0,  96,  0.0,  50,  0,  0),
43    Dessert('Lollipop with sugar',                  401,  0.2, 100,  0.0,  38,  0,  2),
44    Dessert('Honeycomb with sugar',                 417,  3.2,  89,  6.5, 562,  0, 45),
45    Dessert('Donut with sugar',                     461, 25.0,  53,  4.9, 326,  2, 22),
46    Dessert('KitKat with sugar',                    527, 26.0,  67,  7.0,  54, 12,  6),
47
48    Dessert('Frozen yogurt with honey',             223,  6.0,  36,  4.0,  87, 14,  1),
49    Dessert('Ice cream sandwich with honey',        301,  9.0,  49,  4.3, 129,  8,  1),
50    Dessert('Eclair with honey',                    326, 16.0,  36,  6.0, 337,  6,  7),
51    Dessert('Cupcake with honey',                   369,  3.7,  79,  4.3, 413,  3,  8),
52    Dessert('Gingerbread with honey',               420, 16.0,  61,  3.9, 327,  7, 16),
53    Dessert('Jelly bean with honey',                439,  0.0, 106,  0.0,  50,  0,  0),
54    Dessert('Lollipop with honey',                  456,  0.2, 110,  0.0,  38,  0,  2),
55    Dessert('Honeycomb with honey',                 472,  3.2,  99,  6.5, 562,  0, 45),
56    Dessert('Donut with honey',                     516, 25.0,  63,  4.9, 326,  2, 22),
57    Dessert('KitKat with honey',                    582, 26.0,  77,  7.0,  54, 12,  6),
58
59    Dessert('Frozen yogurt with milk',              262,  8.4,  36, 12.0, 194, 44,  1),
60    Dessert('Ice cream sandwich with milk',         339, 11.4,  49, 12.3, 236, 38,  1),
61    Dessert('Eclair with milk',                     365, 18.4,  36, 14.0, 444, 36,  7),
62    Dessert('Cupcake with milk',                    408,  6.1,  79, 12.3, 520, 33,  8),
63    Dessert('Gingerbread with milk',                459, 18.4,  61, 11.9, 434, 37, 16),
64    Dessert('Jelly bean with milk',                 478,  2.4, 106,  8.0, 157, 30,  0),
65    Dessert('Lollipop with milk',                   495,  2.6, 110,  8.0, 145, 30,  2),
66    Dessert('Honeycomb with milk',                  511,  5.6,  99, 14.5, 669, 30, 45),
67    Dessert('Donut with milk',                      555, 27.4,  63, 12.9, 433, 32, 22),
68    Dessert('KitKat with milk',                     621, 28.4,  77, 15.0, 161, 42,  6),
69
70    Dessert('Coconut slice and frozen yogurt',      318, 21.0,  31,  5.5,  96, 14,  7),
71    Dessert('Coconut slice and ice cream sandwich', 396, 24.0,  44,  5.8, 138,  8,  7),
72    Dessert('Coconut slice and eclair',             421, 31.0,  31,  7.5, 346,  6, 13),
73    Dessert('Coconut slice and cupcake',            464, 18.7,  74,  5.8, 422,  3, 14),
74    Dessert('Coconut slice and gingerbread',        515, 31.0,  56,  5.4, 316,  7, 22),
75    Dessert('Coconut slice and jelly bean',         534, 15.0, 101,  1.5,  59,  0,  6),
76    Dessert('Coconut slice and lollipop',           551, 15.2, 105,  1.5,  47,  0,  8),
77    Dessert('Coconut slice and honeycomb',          567, 18.2,  94,  8.0, 571,  0, 51),
78    Dessert('Coconut slice and donut',              611, 40.0,  58,  6.4, 335,  2, 28),
79    Dessert('Coconut slice and KitKat',             677, 41.0,  72,  8.5,  63, 12, 12),
80  ];
81
82  void _sort<T>(Comparable<T> getField(Dessert d), bool ascending) {
83    _desserts.sort((Dessert a, Dessert b) {
84      if (!ascending) {
85        final Dessert c = a;
86        a = b;
87        b = c;
88      }
89      final Comparable<T> aValue = getField(a);
90      final Comparable<T> bValue = getField(b);
91      return Comparable.compare(aValue, bValue);
92    });
93    notifyListeners();
94  }
95
96  int _selectedCount = 0;
97
98  @override
99  DataRow getRow(int index) {
100    assert(index >= 0);
101    if (index >= _desserts.length)
102      return null;
103    final Dessert dessert = _desserts[index];
104    return DataRow.byIndex(
105      index: index,
106      selected: dessert.selected,
107      onSelectChanged: (bool value) {
108        if (dessert.selected != value) {
109          _selectedCount += value ? 1 : -1;
110          assert(_selectedCount >= 0);
111          dessert.selected = value;
112          notifyListeners();
113        }
114      },
115      cells: <DataCell>[
116        DataCell(Text('${dessert.name}')),
117        DataCell(Text('${dessert.calories}')),
118        DataCell(Text('${dessert.fat.toStringAsFixed(1)}')),
119        DataCell(Text('${dessert.carbs}')),
120        DataCell(Text('${dessert.protein.toStringAsFixed(1)}')),
121        DataCell(Text('${dessert.sodium}')),
122        DataCell(Text('${dessert.calcium}%')),
123        DataCell(Text('${dessert.iron}%')),
124      ],
125    );
126  }
127
128  @override
129  int get rowCount => _desserts.length;
130
131  @override
132  bool get isRowCountApproximate => false;
133
134  @override
135  int get selectedRowCount => _selectedCount;
136
137  void _selectAll(bool checked) {
138    for (Dessert dessert in _desserts)
139      dessert.selected = checked;
140    _selectedCount = checked ? _desserts.length : 0;
141    notifyListeners();
142  }
143}
144
145class DataTableDemo extends StatefulWidget {
146  static const String routeName = '/material/data-table';
147
148  @override
149  _DataTableDemoState createState() => _DataTableDemoState();
150}
151
152class _DataTableDemoState extends State<DataTableDemo> {
153  int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;
154  int _sortColumnIndex;
155  bool _sortAscending = true;
156  final DessertDataSource _dessertsDataSource = DessertDataSource();
157
158  void _sort<T>(Comparable<T> getField(Dessert d), int columnIndex, bool ascending) {
159    _dessertsDataSource._sort<T>(getField, ascending);
160    setState(() {
161      _sortColumnIndex = columnIndex;
162      _sortAscending = ascending;
163    });
164  }
165
166  @override
167  Widget build(BuildContext context) {
168    return Scaffold(
169      appBar: AppBar(
170        title: const Text('Data tables'),
171        actions: <Widget>[
172          MaterialDemoDocumentationButton(DataTableDemo.routeName),
173        ],
174      ),
175      body: Scrollbar(
176        child: ListView(
177          padding: const EdgeInsets.all(20.0),
178          children: <Widget>[
179            PaginatedDataTable(
180              header: const Text('Nutrition'),
181              rowsPerPage: _rowsPerPage,
182              onRowsPerPageChanged: (int value) { setState(() { _rowsPerPage = value; }); },
183              sortColumnIndex: _sortColumnIndex,
184              sortAscending: _sortAscending,
185              onSelectAll: _dessertsDataSource._selectAll,
186              columns: <DataColumn>[
187                DataColumn(
188                  label: const Text('Dessert (100g serving)'),
189                  onSort: (int columnIndex, bool ascending) => _sort<String>((Dessert d) => d.name, columnIndex, ascending),
190                ),
191                DataColumn(
192                  label: const Text('Calories'),
193                  tooltip: 'The total amount of food energy in the given serving size.',
194                  numeric: true,
195                  onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.calories, columnIndex, ascending),
196                ),
197                DataColumn(
198                  label: const Text('Fat (g)'),
199                  numeric: true,
200                  onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.fat, columnIndex, ascending),
201                ),
202                DataColumn(
203                  label: const Text('Carbs (g)'),
204                  numeric: true,
205                  onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.carbs, columnIndex, ascending),
206                ),
207                DataColumn(
208                  label: const Text('Protein (g)'),
209                  numeric: true,
210                  onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.protein, columnIndex, ascending),
211                ),
212                DataColumn(
213                  label: const Text('Sodium (mg)'),
214                  numeric: true,
215                  onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.sodium, columnIndex, ascending),
216                ),
217                DataColumn(
218                  label: const Text('Calcium (%)'),
219                  tooltip: 'The amount of calcium as a percentage of the recommended daily amount.',
220                  numeric: true,
221                  onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.calcium, columnIndex, ascending),
222                ),
223                DataColumn(
224                  label: const Text('Iron (%)'),
225                  numeric: true,
226                  onSort: (int columnIndex, bool ascending) => _sort<num>((Dessert d) => d.iron, columnIndex, ascending),
227                ),
228              ],
229              source: _dessertsDataSource,
230            ),
231          ],
232        ),
233      ),
234    );
235  }
236}
237