Repository navigation
Add a scrollbar for horizontal scrolling of source files in the debugger #3262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9d87187
f5c75ca
dc540cf
9586bb5
573a8b3
7cacf59
63a40ee
cd365e0
508972a
6b3390e
b0b196c
381bc72
1b81193
464d296
242f15d
a51668e
1057cd9
1147729
a055a4f
0020420
70ef6c4
787e805
51ac12e
e09de2d
32356c7
05f280a
257fd73
1d04387
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,6 +45,12 @@ class CodeView extends StatefulWidget { | |
| this.onSelected, | ||
| }) : super(key: key); | ||
|
|
||
| static const debuggerCodeViewHorizontalScrollbarKey = | ||
| Key('debuggerCodeViewHorizontalScrollbarKey'); | ||
|
|
||
| static const debuggerCodeViewVerticalScrollbarKey = | ||
| Key('debuggerCodeViewVerticalScrollbarKey'); | ||
|
|
||
| static double get rowHeight => scaleByFontFactor(20.0); | ||
| static double get assumedCharacterWidth => scaleByFontFactor(16.0); | ||
|
|
||
|
|
@@ -65,6 +71,7 @@ class _CodeViewState extends State<CodeView> | |
| LinkedScrollControllerGroup verticalController; | ||
| ScrollController gutterController; | ||
| ScrollController textController; | ||
| ScrollController horizontalController; | ||
|
|
||
| ScriptRef get scriptRef => widget.scriptRef; | ||
|
|
||
|
|
@@ -77,6 +84,7 @@ class _CodeViewState extends State<CodeView> | |
| verticalController = LinkedScrollControllerGroup(); | ||
| gutterController = verticalController.addAndGet(); | ||
| textController = verticalController.addAndGet(); | ||
| horizontalController = ScrollController(); | ||
|
|
||
| addAutoDisposeListener( | ||
| widget.controller.scriptLocation, | ||
|
|
@@ -100,6 +108,7 @@ class _CodeViewState extends State<CodeView> | |
| void dispose() { | ||
| gutterController.dispose(); | ||
| textController.dispose(); | ||
| horizontalController.dispose(); | ||
| widget.controller.scriptLocation | ||
| .removeListener(_handleScriptLocationChanged); | ||
| super.dispose(); | ||
|
|
@@ -263,7 +272,12 @@ class _CodeViewState extends State<CodeView> | |
| style: theme.fixedFontStyle, | ||
| child: Expanded( | ||
| child: Scrollbar( | ||
| key: CodeView.debuggerCodeViewVerticalScrollbarKey, | ||
| controller: textController, | ||
| // Only listen for vertical scroll notifications (ignore those | ||
|
elliette marked this conversation as resolved.
|
||
| // from the nested horizontal SingleChildScrollView): | ||
| notificationPredicate: (ScrollNotification notification) => | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should use
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, changed to use
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are we sure this notificationPredicate is needed? If it is needed, there are likely multiple other places in the UI where we need notificationPredicates. I thought it wasn't needed as we explicitly specify the scrollController.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @xu-baolin! I see you added the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok I will check that.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Piinks Hey, what are your thoughts on this?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh this may already be fixed, we noticed this recently in flutter/flutter#87697. |
||
| notification.depth == 1, | ||
| child: ValueListenableBuilder<StackFrameAndSourcePosition>( | ||
| valueListenable: widget.controller.selectedStackFrame, | ||
| builder: (context, frame, _) { | ||
|
|
@@ -298,15 +312,43 @@ class _CodeViewState extends State<CodeView> | |
| Expanded( | ||
| child: LayoutBuilder( | ||
| builder: (context, constraints) { | ||
| return Lines( | ||
| constraints: constraints, | ||
| scrollController: textController, | ||
| lines: lines, | ||
| pausedFrame: pausedFrame, | ||
| searchMatchesNotifier: | ||
| widget.controller.searchMatches, | ||
| activeSearchMatchNotifier: | ||
| widget.controller.activeSearchMatch, | ||
| // Find the longest line to measure file width: | ||
| int longestLength = 0; | ||
| TextSpan longestLine; | ||
| for (var line in lines) { | ||
| final int currentLength = | ||
| line.toPlainText().length; | ||
| if (currentLength > longestLength) { | ||
| longestLength = currentLength; | ||
| longestLine = line; | ||
| } | ||
| } | ||
| final double fileWidth = | ||
| calculateTextSpanWidth(longestLine); | ||
|
|
||
| return Scrollbar( | ||
|
elliette marked this conversation as resolved.
|
||
| key: CodeView | ||
| .debuggerCodeViewHorizontalScrollbarKey, | ||
| isAlwaysShown: true, | ||
| controller: horizontalController, | ||
| child: SingleChildScrollView( | ||
| scrollDirection: Axis.horizontal, | ||
| controller: horizontalController, | ||
| child: SizedBox( | ||
| height: constraints.maxHeight, | ||
| width: fileWidth, | ||
| child: Lines( | ||
| height: constraints.maxHeight, | ||
| scrollController: textController, | ||
| lines: lines, | ||
| pausedFrame: pausedFrame, | ||
| searchMatchesNotifier: | ||
| widget.controller.searchMatches, | ||
| activeSearchMatchNotifier: | ||
| widget.controller.activeSearchMatch, | ||
| ), | ||
| ), | ||
| ), | ||
| ); | ||
| }, | ||
| ), | ||
|
|
@@ -527,15 +569,15 @@ class GutterItem extends StatelessWidget { | |
| class Lines extends StatefulWidget { | ||
| const Lines({ | ||
| Key key, | ||
| @required this.constraints, | ||
| @required this.height, | ||
| @required this.scrollController, | ||
| @required this.lines, | ||
| @required this.pausedFrame, | ||
| @required this.searchMatchesNotifier, | ||
| @required this.activeSearchMatchNotifier, | ||
| }) : super(key: key); | ||
|
|
||
| final BoxConstraints constraints; | ||
| final double height; | ||
| final ScrollController scrollController; | ||
| final List<TextSpan> lines; | ||
| final StackFrameAndSourcePosition pausedFrame; | ||
|
|
@@ -572,17 +614,14 @@ class _LinesState extends State<Lines> with AutoDisposeMixin { | |
| if (activeSearch != null) { | ||
| final isOutOfViewTop = activeSearch.position.line * CodeView.rowHeight < | ||
| widget.scrollController.offset + CodeView.rowHeight; | ||
| final isOutOfViewBottom = | ||
| activeSearch.position.line * CodeView.rowHeight > | ||
| widget.scrollController.offset + | ||
| widget.constraints.maxHeight - | ||
| CodeView.rowHeight; | ||
| final isOutOfViewBottom = activeSearch.position.line * | ||
| CodeView.rowHeight > | ||
| widget.scrollController.offset + widget.height - CodeView.rowHeight; | ||
|
|
||
| if (isOutOfViewTop || isOutOfViewBottom) { | ||
| // Scroll this search token to the middle of the view. | ||
| final targetOffset = math.max( | ||
| activeSearch.position.line * CodeView.rowHeight - | ||
| widget.constraints.maxHeight / 2, | ||
| activeSearch.position.line * CodeView.rowHeight - widget.height / 2, | ||
| 0.0, | ||
| ); | ||
| widget.scrollController.animateTo( | ||
|
|
||

Uh oh!
There was an error while loading. Please reload this page.