Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
f75fd5c3
Commit
f75fd5c3
authored
Jun 09, 2016
by
Ian Hickson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Header for PaginatedDataTable (#4468)
Also renames ButtonTheme.footer to ButtonTheme.bar.
parent
1fe57277
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
154 additions
and
29 deletions
+154
-29
cards_demo.dart
examples/flutter_gallery/lib/demo/cards_demo.dart
+1
-1
data_table_demo.dart
examples/flutter_gallery/lib/demo/data_table_demo.dart
+23
-5
button.dart
packages/flutter/lib/src/material/button.dart
+8
-2
button_bar.dart
packages/flutter/lib/src/material/button_bar.dart
+1
-1
data_table_source.dart
packages/flutter/lib/src/material/data_table_source.dart
+5
-0
dialog.dart
packages/flutter/lib/src/material/dialog.dart
+1
-1
paginated_data_table.dart
packages/flutter/lib/src/material/paginated_data_table.dart
+100
-18
theme_data.dart
packages/flutter/lib/src/material/theme_data.dart
+15
-1
No files found.
examples/flutter_gallery/lib/demo/cards_demo.dart
View file @
f75fd5c3
...
...
@@ -96,7 +96,7 @@ class TravelDestinationItem extends StatelessWidget {
),
// share, explore buttons
// TODO(abarth): The theme and the bar should be part of card.
new
ButtonTheme
.
foote
r
(
new
ButtonTheme
.
ba
r
(
child:
new
ButtonBar
(
alignment:
MainAxisAlignment
.
start
,
children:
<
Widget
>[
...
...
examples/flutter_gallery/lib/demo/data_table_demo.dart
View file @
f75fd5c3
...
...
@@ -91,6 +91,8 @@ class DesertDataSource extends DataTableSource {
notifyListeners
();
}
int
_selectedCount
=
0
;
@override
DataRow
getRow
(
int
index
)
{
assert
(
index
>=
0
);
...
...
@@ -101,8 +103,12 @@ class DesertDataSource extends DataTableSource {
index:
index
,
selected:
desert
.
selected
,
onSelectChanged:
(
bool
value
)
{
desert
.
selected
=
value
;
notifyListeners
();
if
(
desert
.
selected
!=
value
)
{
_selectedCount
+=
value
?
1
:
-
1
;
assert
(
_selectedCount
>=
0
);
desert
.
selected
=
value
;
notifyListeners
();
}
},
cells:
<
DataCell
>[
new
DataCell
(
new
Text
(
'
${desert.name}
'
)),
...
...
@@ -122,6 +128,16 @@ class DesertDataSource extends DataTableSource {
@override
bool
get
isRowCountApproximate
=>
false
;
@override
int
get
selectedRowCount
=>
_selectedCount
;
void
_selectAll
(
bool
checked
)
{
for
(
Desert
desert
in
_deserts
)
desert
.
selected
=
checked
;
_selectedCount
=
checked
?
_deserts
.
length
:
0
;
notifyListeners
();
}
}
class
DataTableDemo
extends
StatefulWidget
{
...
...
@@ -135,10 +151,10 @@ class _DataTableDemoState extends State<DataTableDemo> {
int
_rowsPerPage
=
PaginatedDataTable
.
defaultRowsPerPage
;
int
_sortColumnIndex
;
bool
_sortAscending
=
true
;
DesertDataSource
_deserts
=
new
DesertDataSource
();
DesertDataSource
_deserts
DataSource
=
new
DesertDataSource
();
void
_sort
/*<T>*/
(
Comparable
<
dynamic
/*=T*/
>
getField
(
Desert
d
),
int
columnIndex
,
bool
ascending
)
{
_deserts
.
_sort
/*<T>*/
(
getField
,
ascending
);
_deserts
DataSource
.
_sort
/*<T>*/
(
getField
,
ascending
);
setState
(()
{
_sortColumnIndex
=
columnIndex
;
_sortAscending
=
ascending
;
...
...
@@ -153,10 +169,12 @@ class _DataTableDemoState extends State<DataTableDemo> {
padding:
const
EdgeInsets
.
all
(
20.0
),
children:
<
Widget
>[
new
PaginatedDataTable
(
header:
new
Text
(
'Nutrition'
),
rowsPerPage:
_rowsPerPage
,
onRowsPerPageChanged:
(
int
value
)
{
setState
(()
{
_rowsPerPage
=
value
;
});
},
sortColumnIndex:
_sortColumnIndex
,
sortAscending:
_sortAscending
,
onSelectAll:
_desertsDataSource
.
_selectAll
,
columns:
<
DataColumn
>[
new
DataColumn
(
label:
new
Text
(
'Dessert (100g serving)'
),
...
...
@@ -200,7 +218,7 @@ class _DataTableDemoState extends State<DataTableDemo> {
onSort:
(
int
columnIndex
,
bool
ascending
)
=>
_sort
/*<num>*/
((
Desert
d
)
=>
d
.
iron
,
columnIndex
,
ascending
)
),
],
source
:
_deserts
source
:
_deserts
DataSource
)
]
)
...
...
packages/flutter/lib/src/material/button.dart
View file @
f75fd5c3
...
...
@@ -50,15 +50,21 @@ class ButtonTheme extends InheritedWidget {
Widget
child
})
:
super
(
key:
key
,
child:
child
);
/// Creates a button theme that is appropriate for footer buttons.
/// Creates a button theme that is appropriate for button bars, as used in
/// dialog footers and in the headers of data tables.
///
/// This theme is denser, with a smaller [minWidth] and [padding], than the
/// default theme. Also, this theme uses [ButtonTextTheme.accent] rather than
/// [ButtonTextTheme.normal].
///
/// For best effect, the label of the button at the edge of the container
/// should have text that ends up wider than 64.0 pixels. This ensures that
/// the alignment of the text matches the alignment of the edge of the
/// container.
///
/// For example, buttons at the bottom of [Dialog] or [Card] widgets use this
/// button theme.
const
ButtonTheme
.
foote
r
({
const
ButtonTheme
.
ba
r
({
Key
key
,
this
.
textTheme
:
ButtonTextTheme
.
accent
,
this
.
minWidth
:
64.0
,
...
...
packages/flutter/lib/src/material/button_bar.dart
View file @
f75fd5c3
...
...
@@ -51,7 +51,7 @@ class ButtonBar extends StatelessWidget {
),
child:
new
Row
(
mainAxisAlignment:
alignment
,
children:
children
.
map
((
Widget
child
)
{
children:
children
.
map
/*<Widget>*/
((
Widget
child
)
{
return
new
Padding
(
padding:
new
EdgeInsets
.
symmetric
(
horizontal:
paddingUnit
),
child:
child
...
...
packages/flutter/lib/src/material/data_table_source.dart
View file @
f75fd5c3
...
...
@@ -54,4 +54,9 @@ abstract class DataTableSource extends ChangeNotifier {
/// then later the exact number becomes available, then call
/// [notifyListeners].
bool
get
isRowCountApproximate
;
/// Called to obtain the number of rows that are currently selected.
///
/// If the selected row count changes, call [notifyListeners].
int
get
selectedRowCount
;
}
\ No newline at end of file
packages/flutter/lib/src/material/dialog.dart
View file @
f75fd5c3
...
...
@@ -96,7 +96,7 @@ class Dialog extends StatelessWidget {
}
if
(
actions
!=
null
)
{
dialogBody
.
add
(
new
ButtonTheme
.
foote
r
(
dialogBody
.
add
(
new
ButtonTheme
.
ba
r
(
child:
new
ButtonBar
(
alignment:
MainAxisAlignment
.
end
,
children:
actions
...
...
packages/flutter/lib/src/material/paginated_data_table.dart
View file @
f75fd5c3
...
...
@@ -4,9 +4,12 @@
import
'dart:math'
as
math
;
import
'package:meta/meta.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:flutter/rendering.dart'
;
import
'button.dart'
;
import
'button_bar.dart'
;
import
'card.dart'
;
import
'data_table.dart'
;
import
'data_table_source.dart'
;
...
...
@@ -23,6 +26,9 @@ import 'theme.dart';
class
PaginatedDataTable
extends
StatefulWidget
{
/// Creates a widget describing a paginated [DataTable] on a [Card].
///
/// The [header] should give the card's header, typically a [Text] widget. It
/// must not be null.
///
/// The [columns] argument must be a list of as many [DataColumn] objects as
/// the table is to have columns, ignoring the leading checkbox column if any.
/// The [columns] argument must have a length greater than zero and cannot be
...
...
@@ -43,10 +49,12 @@ class PaginatedDataTable extends StatefulWidget {
/// widget unless the data table really is to now show entirely different
/// data from a new source.
///
/// The [rowsPerPage] and [availableRowsPerPage] must not be null (th
ough th
ey
/// both have defaults, so don't have to be specified).
/// The [rowsPerPage] and [availableRowsPerPage] must not be null (they
/// both have defaults,
though,
so don't have to be specified).
PaginatedDataTable
({
Key
key
,
@required
this
.
header
,
this
.
actions
,
this
.
columns
,
this
.
sortColumnIndex
,
this
.
sortAscending
:
true
,
...
...
@@ -56,8 +64,9 @@ class PaginatedDataTable extends StatefulWidget {
this
.
rowsPerPage
:
defaultRowsPerPage
,
this
.
availableRowsPerPage
:
const
<
int
>[
defaultRowsPerPage
,
defaultRowsPerPage
*
2
,
defaultRowsPerPage
*
5
,
defaultRowsPerPage
*
10
],
this
.
onRowsPerPageChanged
,
this
.
source
@required
this
.
source
})
:
super
(
key:
key
)
{
assert
(
header
!=
null
);
assert
(
columns
!=
null
);
assert
(
columns
.
length
>
0
);
assert
(
sortColumnIndex
==
null
||
(
sortColumnIndex
>=
0
&&
sortColumnIndex
<
columns
.
length
));
...
...
@@ -69,6 +78,24 @@ class PaginatedDataTable extends StatefulWidget {
assert
(
source
!=
null
);
}
/// The table card's header.
///
/// This is typically a [Text] widget, but can also be a [ButtonBar] with
/// [FlatButton]s. Suitable defaults are automatically provided for the font,
/// button color, button padding, and so forth.
///
/// If items in the table are selectable, then, when the selection is not
/// empty, the header is replaced by a count of the selected items.
final
Widget
header
;
/// Icon buttons to show at the top right of the table.
///
/// Typically, the exact actions included in this list will vary based on
/// whether any rows are selected or not.
///
/// These should be size 24.0 with default padding (8.0).
final
List
<
Widget
>
actions
;
/// The configuration and labels for the columns in the table.
final
List
<
DataColumn
>
columns
;
...
...
@@ -142,6 +169,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
int
_firstRowIndex
;
int
_rowCount
;
bool
_rowCountApproximate
;
int
_selectedRowCount
;
final
Map
<
int
,
DataRow
>
_rows
=
<
int
,
DataRow
>{};
@override
...
...
@@ -172,6 +200,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
setState
(()
{
_rowCount
=
config
.
source
.
rowCount
;
_rowCountApproximate
=
config
.
source
.
isRowCountApproximate
;
_selectedRowCount
=
config
.
source
.
selectedRowCount
;
_rows
.
clear
();
});
}
...
...
@@ -237,7 +266,42 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
@override
Widget
build
(
BuildContext
context
)
{
final
TextStyle
textStyle
=
Theme
.
of
(
context
).
textTheme
.
caption
;
// TODO(ianh): This whole build function doesn't handle RTL yet.
ThemeData
themeData
=
Theme
.
of
(
context
);
// HEADER
final
List
<
Widget
>
headerWidgets
=
<
Widget
>[];
double
leftPadding
=
24.0
;
if
(
_selectedRowCount
==
0
)
{
headerWidgets
.
add
(
new
Flexible
(
child:
config
.
header
));
if
(
config
.
header
is
ButtonBar
)
{
// We adjust the padding when a button bar is present, because the
// ButtonBar introduces 2 pixels of outside padding, plus 2 pixels
// around each button on each side, and the button itself will have 8
// pixels internally on each side, yet we want the left edge of the
// inside of the button to line up with the 24.0 left inset.
// TODO(ianh): Better magic. See https://github.com/flutter/flutter/issues/4460
leftPadding
=
12.0
;
}
}
else
if
(
_selectedRowCount
==
1
)
{
// TODO(ianh): Real l10n.
headerWidgets
.
add
(
new
Flexible
(
child:
new
Text
(
'1 item selected'
)));
}
else
{
headerWidgets
.
add
(
new
Flexible
(
child:
new
Text
(
'
$_selectedRowCount
items selected'
)));
}
if
(
config
.
actions
!=
null
)
{
headerWidgets
.
addAll
(
config
.
actions
.
map
/*<Widget>*/
((
Widget
widget
)
{
return
new
Padding
(
// 8.0 is the default padding of an icon button
padding:
new
EdgeInsets
.
only
(
left:
24.0
-
8.0
*
2.0
),
child:
widget
);
}).
toList
()
);
}
// FOOTER
final
TextStyle
footerTextStyle
=
themeData
.
textTheme
.
caption
;
final
List
<
Widget
>
footerWidgets
=
<
Widget
>[];
if
(
config
.
onRowsPerPageChanged
!=
null
)
{
List
<
Widget
>
availableRowsPerPage
=
config
.
availableRowsPerPage
...
...
@@ -256,7 +320,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
items:
availableRowsPerPage
,
value:
config
.
rowsPerPage
,
onChanged:
config
.
onRowsPerPageChanged
,
style:
t
extStyle
,
style:
footerT
extStyle
,
iconSize:
24.0
)
),
...
...
@@ -285,21 +349,39 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
),
new
Container
(
width:
14.0
),
]);
// CARD
return
new
Card
(
// TODO(ianh): data table card headers
/*
- title, top left
- 20px Roboto Regular, black87
- persistent actions, top left
- header when there's a selection
- accent 50?
- show number of selected items
- different actions
- actions, top right
- 24px icons, black54
*/
child:
new
BlockBody
(
children:
<
Widget
>[
new
DefaultTextStyle
(
// These typographic styles aren't quite the regular ones. We pick the closest ones from the regular
// list and then tweak them appropriately.
// See https://www.google.com/design/spec/components/data-tables.html#data-tables-tables-within-cards
style:
_selectedRowCount
>
0
?
themeData
.
textTheme
.
subhead
.
copyWith
(
color:
themeData
.
accentColor
)
:
themeData
.
textTheme
.
title
.
copyWith
(
fontWeight:
FontWeight
.
w400
),
child:
new
IconTheme
(
data:
new
IconThemeData
(
opacity:
0.54
),
child:
new
ButtonTheme
.
bar
(
child:
new
Container
(
height:
64.0
,
padding:
new
EdgeInsets
.
fromLTRB
(
leftPadding
,
0.0
,
14.0
,
0.0
),
// TODO(ianh): This decoration will prevent ink splashes from being visible.
// Instead, we should have a widget that prints the decoration on the material.
// See https://github.com/flutter/flutter/issues/3782
decoration:
_selectedRowCount
>
0
?
new
BoxDecoration
(
backgroundColor:
themeData
.
secondaryHeaderColor
)
:
null
,
child:
new
Row
(
mainAxisAlignment:
MainAxisAlignment
.
end
,
children:
headerWidgets
)
)
)
)
),
new
ScrollableViewport
(
scrollDirection:
Axis
.
horizontal
,
child:
new
DataTable
(
...
...
@@ -312,7 +394,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
)
),
new
DefaultTextStyle
(
style:
t
extStyle
,
style:
footerT
extStyle
,
child:
new
IconTheme
(
data:
new
IconThemeData
(
opacity:
0.54
...
...
packages/flutter/lib/src/material/theme_data.dart
View file @
f75fd5c3
...
...
@@ -67,6 +67,7 @@ class ThemeData {
Color
unselectedWidgetColor
,
Color
disabledColor
,
Color
buttonColor
,
Color
secondaryHeaderColor
,
Color
textSelectionColor
,
Color
textSelectionHandleColor
,
Color
backgroundColor
,
...
...
@@ -93,6 +94,7 @@ class ThemeData {
unselectedWidgetColor
??=
isDark
?
Colors
.
white70
:
Colors
.
black54
;
disabledColor
??=
isDark
?
Colors
.
white30
:
Colors
.
black26
;
buttonColor
??=
isDark
?
primarySwatch
[
600
]
:
Colors
.
grey
[
300
];
secondaryHeaderColor
??=
primarySwatch
[
50
];
// TODO(ianh): dark theme support (https://github.com/flutter/flutter/issues/3370)
textSelectionColor
??=
isDark
?
accentColor
:
primarySwatch
[
200
];
textSelectionHandleColor
??=
isDark
?
Colors
.
tealAccent
[
400
]
:
primarySwatch
[
300
];
backgroundColor
??=
isDark
?
Colors
.
grey
[
700
]
:
primarySwatch
[
200
];
...
...
@@ -117,6 +119,7 @@ class ThemeData {
unselectedWidgetColor:
unselectedWidgetColor
,
disabledColor:
disabledColor
,
buttonColor:
buttonColor
,
secondaryHeaderColor:
secondaryHeaderColor
,
textSelectionColor:
textSelectionColor
,
textSelectionHandleColor:
textSelectionHandleColor
,
backgroundColor:
backgroundColor
,
...
...
@@ -150,6 +153,7 @@ class ThemeData {
this
.
unselectedWidgetColor
,
this
.
disabledColor
,
this
.
buttonColor
,
this
.
secondaryHeaderColor
,
this
.
textSelectionColor
,
this
.
textSelectionHandleColor
,
this
.
backgroundColor
,
...
...
@@ -174,6 +178,7 @@ class ThemeData {
assert
(
unselectedWidgetColor
!=
null
);
assert
(
disabledColor
!=
null
);
assert
(
buttonColor
!=
null
);
assert
(
secondaryHeaderColor
!=
null
);
assert
(
textSelectionColor
!=
null
);
assert
(
textSelectionHandleColor
!=
null
);
assert
(
disabledColor
!=
null
);
...
...
@@ -257,6 +262,12 @@ class ThemeData {
/// The default color of the [Material] used in [RaisedButton]s.
final
Color
buttonColor
;
/// The color of the header of a [PaginatedDataTable] when there are selected rows.
// According to the spec for data tables:
// https://material.google.com/components/data-tables.html#data-tables-tables-within-cards
// ...this should be the "50-value of secondary app color".
final
Color
secondaryHeaderColor
;
/// The color of text selections in text fields, such as [Input].
final
Color
textSelectionColor
;
...
...
@@ -301,6 +312,7 @@ class ThemeData {
unselectedWidgetColor:
Color
.
lerp
(
begin
.
unselectedWidgetColor
,
end
.
unselectedWidgetColor
,
t
),
disabledColor:
Color
.
lerp
(
begin
.
disabledColor
,
end
.
disabledColor
,
t
),
buttonColor:
Color
.
lerp
(
begin
.
buttonColor
,
end
.
buttonColor
,
t
),
secondaryHeaderColor:
Color
.
lerp
(
begin
.
secondaryHeaderColor
,
end
.
secondaryHeaderColor
,
t
),
textSelectionColor:
Color
.
lerp
(
begin
.
textSelectionColor
,
end
.
textSelectionColor
,
t
),
textSelectionHandleColor:
Color
.
lerp
(
begin
.
textSelectionHandleColor
,
end
.
textSelectionHandleColor
,
t
),
backgroundColor:
Color
.
lerp
(
begin
.
backgroundColor
,
end
.
backgroundColor
,
t
),
...
...
@@ -332,6 +344,7 @@ class ThemeData {
(
otherData
.
unselectedWidgetColor
==
unselectedWidgetColor
)
&&
(
otherData
.
disabledColor
==
disabledColor
)
&&
(
otherData
.
buttonColor
==
buttonColor
)
&&
(
otherData
.
secondaryHeaderColor
==
secondaryHeaderColor
)
&&
(
otherData
.
textSelectionColor
==
textSelectionColor
)
&&
(
otherData
.
textSelectionHandleColor
==
textSelectionHandleColor
)
&&
(
otherData
.
backgroundColor
==
backgroundColor
)
&&
...
...
@@ -360,12 +373,13 @@ class ThemeData {
unselectedWidgetColor
,
disabledColor
,
buttonColor
,
secondaryHeaderColor
,
textSelectionColor
,
textSelectionHandleColor
,
backgroundColor
,
accentColor
,
accentColorBrightness
,
hashValues
(
// Too many values.
accentColorBrightness
,
indicatorColor
,
hintColor
,
errorColor
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment