Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 20 additions & 29 deletions packages/devtools_app/lib/src/shared/table/column_widths.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'dart:math';
import '../../primitives/trees.dart';
import '../../primitives/utils.dart';
import '../theme.dart';
import '../utils.dart';
import 'table_controller.dart';
import 'table_data.dart';

Expand Down Expand Up @@ -105,42 +106,32 @@ extension FlatColumnWidthExtension<T> on FlatTableController<T> {
}
}

// TODO(https://github.com/flutter/devtools/issues/2047): build flexible column
// widths into the tables so that we do not have to do in depth calculations
// like this.

extension TreeColumnWidthExtension<T extends TreeNode<T>>
on TreeTableController<T> {
/// The width to assume for columns that don't specify a width.
static const _defaultColumnWidth = 500.0;

List<double> computeColumnWidths(List<T> flattenedList) {
final firstRoot = dataRoots.first;
var deepest = firstRoot;
// This will use the width of all rows in the table, even the rows
// that are hidden by nesting.
// We may want to change this to using a flattened list of only
// the list items that should show right now.
for (var node in flattenedList) {
if (node.level > deepest.level) {
deepest = node;
}
}
final widths = <double>[];
for (var column in columns) {
var width = column.getNodeIndentPx(deepest);
assert(width >= 0.0);
double width;
if (column.fixedWidthPx != null) {
width += column.fixedWidthPx!;
width = column.fixedWidthPx!;
} else {
// TODO(djshuckerow): measure the text of the longest content
// to get an idea for how wide this column should be.
// Text measurement is a somewhat expensive algorithm, so we don't
// want to do it for every row in the table, only the row
// we are confident is the widest. A reasonable heuristic is the row
// with the longest text, but because of variable-width fonts, this is
// not always true.
width += _defaultColumnWidth;
// Note: this is assuming that we're always using a monospace font in
// our tree tables. This will almost certainly cause overflows if we
// try to use non-monospace fonts.
//
// `characterWidth` was determined through trial and error to roughly
// approximate the width of a single character.
const characterWidth = 9.0;
double longestWidth = 0;
for (var node in flattenedList) {
final width = column.getNodeIndentPx(node) +
(column.getDisplayValue(node).length *
scaleByFontFactor(characterWidth));
if (width > longestWidth) {
longestWidth = width;
}
}
width = longestWidth;
}
widths.add(width);
}
Expand Down
49 changes: 48 additions & 1 deletion packages/devtools_app/test/shared/table_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,53 @@ void main() {
expect(find.byWidget(table), findsOneWidget);
});

testWidgets('displays wide data with many columns',
(WidgetTester tester) async {
const strings = <String>[
'All work',
'and no play',
'makes Ben',
'a dull boy',
// ignore: no_adjacent_strings_in_list
'The quick brown fox jumps over the lazy dog, although the fox '
"can't jump very high and the dog is very, very small, so it really"
" isn't much of an achievement on the fox's part, so I'm not sure why "
"we're even talking about it."
];
final root = TestData('Root', 0);
var current = root;
for (int i = 0; i < 1000; ++i) {
final next = TestData(strings[i % strings.length], i);
current.addChild(next);
current = next;
}
final table = TreeTable<TestData>(
columns: [
_NumberColumn(),
_CombinedColumn(),
treeColumn,
_CombinedColumn(),
],
dataRoots: [root],
dataKey: 'test-data',
treeColumn: treeColumn,
keyFactory: (d) => Key(d.name),
defaultSortColumn: treeColumn,
defaultSortDirection: SortDirection.ascending,
);
// This test will throw an exception if the table overflows.
await tester.pumpWidget(
wrap(
SizedBox(
width: 200.0,
height: 200.0,
child: table,
),
),
);
expect(find.byWidget(table), findsOneWidget);
Comment thread
bkonyi marked this conversation as resolved.
});

testWidgets('properly collapses and expands the tree',
(WidgetTester tester) async {
final table = TreeTable<TestData>(
Expand Down Expand Up @@ -1041,7 +1088,7 @@ void main() {
await tester.pumpWidget(wrap(table));
final TreeTableState state = tester.state(find.byWidget(table));
expect(state.tableController.columnWidths[0], equals(400));
expect(state.tableController.columnWidths[1], equals(500));
expect(state.tableController.columnWidths[1], equals(63));
final tree = state.tableController.dataRoots[0];
expect(tree.children[0].name, equals('Bar'));
expect(tree.children[0].children[0].name, equals('Baz'));
Expand Down