Skip to content

Commit

Permalink
Make table text selectable (#6919)
Browse files Browse the repository at this point in the history
  • Loading branch information
CoderDake committed Dec 29, 2023
1 parent e473c40 commit 9853d51
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 70 deletions.
137 changes: 70 additions & 67 deletions packages/devtools_app/lib/src/shared/table/table.dart
Expand Up @@ -1105,18 +1105,34 @@ class _TableState<T> extends State<_Table<T>> with AutoDisposeMixin {
// TODO(kenz): add horizontal scrollbar.
return LayoutBuilder(
builder: (context, constraints) {
return SizedBox(
width: max(
constraints.widthConstraints().maxWidth,
tableWidth,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (showColumnGroupHeader)
TableRow<T>.tableColumnGroupHeader(
return SelectionArea(
child: SizedBox(
width: max(
constraints.widthConstraints().maxWidth,
tableWidth,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (showColumnGroupHeader)
TableRow<T>.tableColumnGroupHeader(
linkedScrollControllerGroup:
_linkedHorizontalScrollControllerGroup,
columnGroups: columnGroups,
columnWidths: widget.columnWidths,
sortColumn: sortColumn,
sortDirection: tableUiState.sortDirection,
secondarySortColumn:
widget.tableController.secondarySortColumn,
onSortChanged: widget.tableController.sortDataAndNotify,
tall: widget.tallHeaders,
backgroundColor: widget.headerColor,
),
TableRow<T>.tableColumnHeader(
key: const Key('Table header'),
linkedScrollControllerGroup:
_linkedHorizontalScrollControllerGroup,
columns: widget.tableController.columns,
columnGroups: columnGroups,
columnWidths: widget.columnWidths,
sortColumn: sortColumn,
Expand All @@ -1127,69 +1143,56 @@ class _TableState<T> extends State<_Table<T>> with AutoDisposeMixin {
tall: widget.tallHeaders,
backgroundColor: widget.headerColor,
),
TableRow<T>.tableColumnHeader(
key: const Key('Table header'),
linkedScrollControllerGroup:
_linkedHorizontalScrollControllerGroup,
columns: widget.tableController.columns,
columnGroups: columnGroups,
columnWidths: widget.columnWidths,
sortColumn: sortColumn,
sortDirection: tableUiState.sortDirection,
secondarySortColumn: widget.tableController.secondarySortColumn,
onSortChanged: widget.tableController.sortDataAndNotify,
tall: widget.tallHeaders,
backgroundColor: widget.headerColor,
),
if (pinnedData.isNotEmpty) ...[
SizedBox(
height: _pinnedDataHeight(constraints),
child: Scrollbar(
thumbVisibility: true,
controller: pinnedScrollController,
child: ListView.builder(
if (pinnedData.isNotEmpty) ...[
SizedBox(
height: _pinnedDataHeight(constraints),
child: Scrollbar(
thumbVisibility: true,
controller: pinnedScrollController,
itemCount: pinnedData.length,
itemExtent: widget.rowItemExtent,
itemBuilder: (context, index) => _buildItem(
context,
index,
isPinned: true,
child: ListView.builder(
controller: pinnedScrollController,
itemCount: pinnedData.length,
itemExtent: widget.rowItemExtent,
itemBuilder: (context, index) => _buildItem(
context,
index,
isPinned: true,
),
),
),
),
),
const ThickDivider(),
],
Expanded(
child: Scrollbar(
thumbVisibility: true,
controller: scrollController,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTapDown: (a) => widget.focusNode?.requestFocus(),
child: Focus(
autofocus: true,
onKeyEvent: (_, event) => widget.handleKeyEvent != null
? widget.handleKeyEvent!(
event,
scrollController,
constraints,
)
: KeyEventResult.ignored,
focusNode: widget.focusNode,
child: ListView.builder(
controller: scrollController,
itemCount:
_dataRowCount(constraints, showColumnGroupHeader),
itemExtent: widget.rowItemExtent,
itemBuilder: _buildItem,
const ThickDivider(),
],
Expanded(
child: Scrollbar(
thumbVisibility: true,
controller: scrollController,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTapDown: (a) => widget.focusNode?.requestFocus(),
child: Focus(
autofocus: true,
onKeyEvent: (_, event) => widget.handleKeyEvent != null
? widget.handleKeyEvent!(
event,
scrollController,
constraints,
)
: KeyEventResult.ignored,
focusNode: widget.focusNode,
child: ListView.builder(
controller: scrollController,
itemCount:
_dataRowCount(constraints, showColumnGroupHeader),
itemExtent: widget.rowItemExtent,
itemBuilder: _buildItem,
),
),
),
),
),
),
],
],
),
),
);
},
Expand Down Expand Up @@ -1601,8 +1604,8 @@ class _TableRowState<T> extends State<TableRow<T>>
}
// If ColumnRenderer.build returns null, fall back to the default
// rendering.
content ??= RichText(
text: TextSpan(
content ??= Text.rich(
TextSpan(
text: column.getDisplayValue(node),
children: [
if (column.getCaption(node) != null)
Expand Down
1 change: 1 addition & 0 deletions packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
Expand Up @@ -12,6 +12,7 @@ To learn more about DevTools, check out the

* Added a new feature for deep link validation, supporting deep link web checks on Android. - [#6935](https://github.com/flutter/devtools/pull/6935)
* Added the basic plumbing to allow connections to a Dart Tooling Daemon. - [#7009](https://github.com/flutter/devtools/pull/7009)
* Made table text selectable [#6919](https://github.com/flutter/devtools/pull/6919)

## Inspector updates

Expand Down
4 changes: 2 additions & 2 deletions packages/devtools_app/test/app_size/app_size_screen_test.dart
Expand Up @@ -577,7 +577,7 @@ void main() {
expect(deferredMenuItemFinder, findsOneWidget);

// Select the main unit.
await tester.tap(find.text('Main').hitTestable());
await tester.tap(find.richText('Main').hitTestable());
await tester.pumpAndSettle();

// Verify the main unit is shown for entire app.
Expand Down Expand Up @@ -751,6 +751,6 @@ Finder _findDropdownButton<T>() {
Finder _findMenuItemWithText<T>(String text) {
return find.descendant(
of: find.byType(DropdownMenuItem<T>),
matching: find.text(text).first,
matching: find.richText(text).hitTestable(),
);
}
Expand Up @@ -217,7 +217,7 @@ void main() {
await tester.pumpWidget(wrap(const VMFlagsDialog()));
expect(find.richText('VM Flags'), findsOneWidget);
expect(find.richText('flag 1 name'), findsOneWidget);
final RichText commentText = tester.firstWidget<RichText>(
final Text commentText = tester.firstWidget<Text>(
findSubstring('flag 1 comment'),
);
expect(commentText, isNotNull);
Expand Down

0 comments on commit 9853d51

Please sign in to comment.