Unverified Commit 2f611f14 authored by Per Classon's avatar Per Classon Committed by GitHub

Make header optional in PaginatedDataTable (#69610)

parent 96a78c08
...@@ -37,8 +37,7 @@ import 'theme.dart'; ...@@ -37,8 +37,7 @@ import 'theme.dart';
class PaginatedDataTable extends StatefulWidget { class PaginatedDataTable extends StatefulWidget {
/// Creates a widget describing a paginated [DataTable] on a [Card]. /// Creates a widget describing a paginated [DataTable] on a [Card].
/// ///
/// The [header] should give the card's header, typically a [Text] widget. It /// The [header] should give the card's header, typically a [Text] widget.
/// must not be null.
/// ///
/// The [columns] argument must be a list of as many [DataColumn] objects as /// 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 table is to have columns, ignoring the leading checkbox column if any.
...@@ -64,7 +63,7 @@ class PaginatedDataTable extends StatefulWidget { ...@@ -64,7 +63,7 @@ class PaginatedDataTable extends StatefulWidget {
/// both have defaults, though, so don't have to be specified). /// both have defaults, though, so don't have to be specified).
PaginatedDataTable({ PaginatedDataTable({
Key? key, Key? key,
required this.header, this.header,
this.actions, this.actions,
required this.columns, required this.columns,
this.sortColumnIndex, this.sortColumnIndex,
...@@ -82,7 +81,7 @@ class PaginatedDataTable extends StatefulWidget { ...@@ -82,7 +81,7 @@ class PaginatedDataTable extends StatefulWidget {
this.onRowsPerPageChanged, this.onRowsPerPageChanged,
this.dragStartBehavior = DragStartBehavior.start, this.dragStartBehavior = DragStartBehavior.start,
required this.source, required this.source,
}) : assert(header != null), }) : assert(actions == null || (actions != null && header != null)),
assert(columns != null), assert(columns != null),
assert(dragStartBehavior != null), assert(dragStartBehavior != null),
assert(columns.isNotEmpty), assert(columns.isNotEmpty),
...@@ -103,17 +102,19 @@ class PaginatedDataTable extends StatefulWidget { ...@@ -103,17 +102,19 @@ class PaginatedDataTable extends StatefulWidget {
assert(source != null), assert(source != null),
super(key: key); super(key: key);
/// The table card's header. /// The table card's optional header.
/// ///
/// This is typically a [Text] widget, but can also be a [ButtonBar] with /// This is typically a [Text] widget, but can also be a [Row] of
/// [TextButton]s. Suitable defaults are automatically provided for the font, /// [TextButton]s. To show icon buttons at the top end side of the table with
/// button color, button padding, and so forth. /// a header, set the [actions] property.
/// ///
/// If items in the table are selectable, then, when the selection is not /// 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. /// empty, the header is replaced by a count of the selected items. The
final Widget header; /// [actions] are still visible when items are selected.
final Widget? header;
/// Icon buttons to show at the top right of the table. /// Icon buttons to show at the top end side of the table. The [header] must
/// not be null to show the actions.
/// ///
/// Typically, the exact actions included in this list will vary based on /// Typically, the exact actions included in this list will vary based on
/// whether any rows are selected or not. /// whether any rows are selected or not.
...@@ -337,8 +338,8 @@ class PaginatedDataTableState extends State<PaginatedDataTable> { ...@@ -337,8 +338,8 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
// HEADER // HEADER
final List<Widget> headerWidgets = <Widget>[]; final List<Widget> headerWidgets = <Widget>[];
double startPadding = 24.0; double startPadding = 24.0;
if (_selectedRowCount == 0) { if (_selectedRowCount == 0 && widget.header != null) {
headerWidgets.add(Expanded(child: widget.header)); headerWidgets.add(Expanded(child: widget.header!));
if (widget.header is ButtonBar) { if (widget.header is ButtonBar) {
// We adjust the padding when a button bar is present, because the // We adjust the padding when a button bar is present, because the
// ButtonBar introduces 2 pixels of outside padding, plus 2 pixels // ButtonBar introduces 2 pixels of outside padding, plus 2 pixels
...@@ -347,7 +348,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> { ...@@ -347,7 +348,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
// inside of the button to line up with the 24.0 left inset. // inside of the button to line up with the 24.0 left inset.
startPadding = 12.0; startPadding = 12.0;
} }
} else { } else if (widget.header != null) {
headerWidgets.add(Expanded( headerWidgets.add(Expanded(
child: Text(localizations.selectedRowCountTitle(_selectedRowCount)), child: Text(localizations.selectedRowCountTitle(_selectedRowCount)),
)); ));
...@@ -432,6 +433,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> { ...@@ -432,6 +433,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[ children: <Widget>[
if (headerWidgets.isNotEmpty)
Semantics( Semantics(
container: true, container: true,
child: DefaultTextStyle( child: DefaultTextStyle(
......
...@@ -229,6 +229,43 @@ void main() { ...@@ -229,6 +229,43 @@ void main() {
expect(tester.getTopRight(find.text('8')).dx, tester.getTopRight(find.text('Rows per page:')).dx + 40.0); // per spec expect(tester.getTopRight(find.text('8')).dx, tester.getTopRight(find.text('Rows per page:')).dx + 40.0); // per spec
}); });
testWidgets('PaginatedDataTable with and without header and actions', (WidgetTester tester) async {
await binding.setSurfaceSize(const Size(800, 800));
const String headerText = 'HEADER';
final List<Widget> actions = <Widget>[
IconButton(onPressed: () {}, icon: const Icon(Icons.add)),
];
Widget buildTable({String? header, List<Widget>? actions}) => MaterialApp(
home: PaginatedDataTable(
header: header != null ? Text(header) : null,
actions: actions,
source: TestDataSource(onSelectChanged: (bool? value) {}),
showCheckboxColumn: true,
columns: const <DataColumn>[
DataColumn(label: Text('Name')),
DataColumn(label: Text('Calories'), numeric: true),
DataColumn(label: Text('Generation')),
],
),
);
await tester.pumpWidget(buildTable(header: headerText));
expect(find.text(headerText), findsOneWidget);
expect(find.byIcon(Icons.add), findsNothing);
await tester.pumpWidget(buildTable(header: headerText, actions: actions));
expect(find.text(headerText), findsOneWidget);
expect(find.byIcon(Icons.add), findsOneWidget);
await tester.pumpWidget(buildTable());
expect(find.text(headerText), findsNothing);
expect(find.byIcon(Icons.add), findsNothing);
expect(() => buildTable(actions: actions), throwsAssertionError);
await binding.setSurfaceSize(null);
});
testWidgets('PaginatedDataTable with large text', (WidgetTester tester) async { testWidgets('PaginatedDataTable with large text', (WidgetTester tester) async {
final TestDataSource source = TestDataSource(); final TestDataSource source = TestDataSource();
await tester.pumpWidget(MaterialApp( await tester.pumpWidget(MaterialApp(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment