-
Notifications
You must be signed in to change notification settings - Fork 340
Replace ScriptPicker
with ProgramExplorer
on DebuggerScreen
#3227
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
Conversation
@kenzieschmoll @jacob314 I think this is ready for an initial pass. PTAL when you have a chance. |
Can you add a screenshot of the new program explorer to the PR description? |
@@ -78,6 +80,13 @@ class _CodeViewState extends State<CodeView> | |||
gutterController = verticalController.addAndGet(); | |||
textController = verticalController.addAndGet(); | |||
|
|||
if (widget.initialPosition != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This likely also needs to be in didUpdateWidget so that this state object can manage the scroll position if the widget was updated with a new value for initialPosition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree we need to do something in didUpdateWidget but we will need to be very careful. You don't want to update the scrollPosition unless widget.initialPosition != oldWidget.initialPosition.
@@ -78,6 +80,13 @@ class _CodeViewState extends State<CodeView> | |||
gutterController = verticalController.addAndGet(); | |||
textController = verticalController.addAndGet(); | |||
|
|||
if (widget.initialPosition != null) { | |||
final location = widget.initialPosition.location; | |||
final lineIndex = location.line - 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a comment as to why we are subtracting 1
@@ -124,7 +124,7 @@ class _DebuggingControlsState extends State<DebuggingControls> | |||
child: Container( | |||
color: visible ? Theme.of(context).highlightColor : null, | |||
child: DebuggerButton( | |||
title: 'Libraries', | |||
title: 'Program Explorer', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not completely sold on this name. Maybe "Source Explorer"? Input here @jacob314 @devoncarew?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we leave it as Libraries for now? We are just showing more information about the libraries.
@@ -278,6 +285,9 @@ class DebuggerController extends DisposableController | |||
/// Return the sorted list of ScriptRefs active in the current isolate. | |||
ValueListenable<List<ScriptRef>> get sortedScripts => _sortedScripts; | |||
|
|||
bool get centerScrollLocation => _centerScrollLocation; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it possible that this value could get accessed for a script it is not associated with? Storing this at the controller level vs the per call level seems problematic
class SourcePosition { | ||
SourcePosition({@required this.line, @required this.column, this.tokenPos}); | ||
const SourcePosition( | ||
{@required this.line, @required this.column, this.file, this.tokenPos}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: trailing comma
@@ -79,6 +80,7 @@ class DebuggerScreenBodyState extends State<DebuggerScreenBody> | |||
static const breakpointsTitle = 'Breakpoints'; | |||
|
|||
DebuggerController controller; | |||
//ObjectTreeController objectSelectorController = ObjectTreeController(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete comment?
@@ -399,6 +399,11 @@ extension ThemeDataExtension on ThemeData { | |||
TextStyle get subtleFixedFontStyle => | |||
fixedFontStyle.copyWith(color: unselectedWidgetColor); | |||
|
|||
TextStyle get toolTipFixedFontStyle => //colorScheme.isLight ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove comment
if (onChange != null) { | ||
onChange( | ||
history.current.value, | ||
current, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not implement a peekBack
method to mirror what is done above with moveBack
and peekNext
?
At a high level, is this change something we have discussed in the past? It seems inconsistent with other discussions we've had regarding debugger UI improvements (see #3075). This is probably something that could use some UX input on (@InMatrix). @devoncarew @jacob314 for input on using a program explorer (classes, functions, fields, etc.) vs a file tree explorer in the debugger (described in linked issue #3075). My concern is making this view more complicated and thus more difficult for users to find what they are looking for. Do users expect to see a file explorer or a program explorer in a debugger? Should we make displaying low level details (classes, functions, etc.) an optional setting? |
@bkonyi Could you post some before-and-after screenshots to help me better understand this change? |
There wasn't an explicit discussion, but I did chat with @jacob314 offline. In general, we need to be able to examine details of fields, functions, and classes to reach feature parity with Observatory (that work isn't included in this PR as the explorer was already a big change) in addition to examining code objects (in VM developer mode). Inspecting code objects will require a code view in addition to an object details view, so the debugger pane seemed like the right place for this rather than creating another top-level tab. Here's some screenshots: |
@InMatrix it's not clear from the screenshots but selecting classes, functions, and fields currently jumps to their definition in the script. |
Sure, that definitely makes sense. It looked a bit "empty" to me without the second row, but it's not essential.
The icons for libraries and folders are identical to the icons in the original script picker :-)
I agree 1000%. I basically scanned through the Flutter material icons and picked ones that looked okay, so we could definitely use some design input for those. |
With regards to #3075, I don't see this in conflict with it. We won't use this view or the script picker for searching but the view will be more useful than the existing ScriptPicker for browsing. |
@@ -580,7 +603,7 @@ class _LinesState extends State<Lines> with AutoDisposeMixin { | |||
|
|||
if (isOutOfViewTop || isOutOfViewBottom) { | |||
// Scroll this search token to the middle of the view. | |||
final targetOffset = math.max( | |||
final targetOffset = math.max<double>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why was this type added? seems like it should be inferred.
final Map<String, VMServiceObjectNode> _childrenAsMap = {}; | ||
|
||
@override | ||
bool get isExpandable => super.isExpandable || object is ClassRef; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if a class has zero members?
+1 to Jacob's last comment regarding splitting this view up into two views: file explorer and structure. |
@@ -43,6 +43,8 @@ abstract class TreeNode<T extends TreeNode<T>> { | |||
|
|||
bool get isRoot => parent == null; | |||
|
|||
bool get isSelected => false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this getter be on the subclass instead of in the TreeNode base class? seems odd to have a getter return a set bool value when there aren't also methods in this TreeNode class to modify the state of isSelected
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs to be here since _TreeViewItemState
uses this to determine whether or not to highlight a given TreeNode
item.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if that is the case, then we should move the logic for managing the state of isSelected into this class as well. Subclasses can always override and call super if they need to do additional work on changing selection, in which case we'd want to annotate with @mustCallSuper
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done with review
packages/devtools_app/lib/src/debugger/program_explorer_controller.dart
Outdated
Show resolved
Hide resolved
packages/devtools_app/lib/src/debugger/program_explorer_controller.dart
Outdated
Show resolved
Hide resolved
packages/devtools_app/lib/src/debugger/program_explorer_controller.dart
Outdated
Show resolved
Hide resolved
packages/devtools_app/lib/src/debugger/program_explorer_model.dart
Outdated
Show resolved
Hide resolved
packages/devtools_app/lib/src/debugger/program_explorer_model.dart
Outdated
Show resolved
Hide resolved
packages/devtools_app/lib/src/debugger/program_explorer_model.dart
Outdated
Show resolved
Hide resolved
packages/devtools_app/lib/src/debugger/program_explorer_model.dart
Outdated
Show resolved
Hide resolved
packages/devtools_app/lib/src/performance/legacy/performance_model.dart
Outdated
Show resolved
Hide resolved
setExpanded(widget.data.isExpanded); | ||
} | ||
|
||
void _onSelected() { | ||
widget.onItemSelected(widget.data); | ||
widget?.onItemSelected(widget.data); | ||
setExpanded(widget.data.isExpanded); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we be calling onItemExpanded here as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, since onItemExpanded
corresponds to clicking the >
, whereas onItemSelected
corresponds to clicking on any other part of the list item.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a few more comments then LGTM
…een` (flutter#3227)" and associated follow-on PRs
This change replaces the current
ScriptPicker
implementation with a more fully featuredProgramExplorer
.Functionality:
Additional Changes:
CodeView
to allow for scrolling to a location aligned to the top of the viewCodeView
background was transparentTreeView
nodes are now highlighted when selectedTreeView
selection vs expansionFuture Work: