From b8672b0af21378bcd9d3b23b397b6f598713a0f4 Mon Sep 17 00:00:00 2001 From: Ben Konyi Date: Mon, 26 Sep 2022 16:53:19 -0400 Subject: [PATCH] Enable `Objects` tab and cleanup `VM Tools` screens (#4514) This change enables the object inspector / program explorer view under the VM Tools tab. This change also updates `VMInfoCard` to not use a backing `Card` to make the UI of VM Tools views more consistent with the rest of DevTools. --- .../vm_developer/isolate_statistics_view.dart | 187 ++++++++++-------- .../vm_developer/object_inspector_view.dart | 2 +- .../vm_developer_common_widgets.dart | 29 +-- .../vm_developer_tools_controller.dart | 3 +- .../vm_developer_tools_screen.dart | 4 +- .../vm_developer/vm_statistics_view.dart | 170 ++++++++-------- .../object_inspector_view_test.dart | 6 - 7 files changed, 213 insertions(+), 188 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics_view.dart b/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics_view.dart index 963ce016318..8bebb819d53 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics_view.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/isolate_statistics_view.dart @@ -11,6 +11,7 @@ import '../../shared/common_widgets.dart'; import '../../shared/split.dart'; import '../../shared/table.dart'; import '../../shared/table_data.dart'; +import '../../shared/theme.dart'; import '../profiler/cpu_profiler.dart'; import 'isolate_statistics_view_controller.dart'; import 'vm_developer_common_widgets.dart'; @@ -44,14 +45,12 @@ class IsolateStatisticsViewBody extends StatelessWidget { valueListenable: controller.refreshing, builder: (context, refreshing, _) { return Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - RefreshButton( - onPressed: controller.refresh, - ), - ], + RefreshButton( + onPressed: controller.refresh, ), + const SizedBox(height: denseRowSpacing), Flexible( child: Column( children: [ @@ -145,15 +144,19 @@ class GeneralIsolateStatisticsWidget extends StatelessWidget { @override Widget build(BuildContext context) { final isolate = controller.isolate; - return VMInfoCard( - title: 'General', - rowKeyValues: [ - selectableTextBuilderMapEntry('Name', isolate?.name), - selectableTextBuilderMapEntry('Started at', _startTime(isolate)), - selectableTextBuilderMapEntry('Uptime', _uptime(isolate)), - selectableTextBuilderMapEntry('Root Library', isolate?.rootLib?.uri), - selectableTextBuilderMapEntry('ID', isolate?.id), - ], + return OutlineDecoration( + showRight: false, + showBottom: false, + child: VMInfoCard( + title: 'General', + rowKeyValues: [ + selectableTextBuilderMapEntry('Name', isolate?.name), + selectableTextBuilderMapEntry('Started at', _startTime(isolate)), + selectableTextBuilderMapEntry('Uptime', _uptime(isolate)), + selectableTextBuilderMapEntry('Root Library', isolate?.rootLib?.uri), + selectableTextBuilderMapEntry('ID', isolate?.id), + ], + ), ); } } @@ -177,31 +180,35 @@ class IsolateMemoryStatisticsWidget extends StatelessWidget { @override Widget build(BuildContext context) { final isolate = controller.isolate; - return VMInfoCard( - title: 'Memory', - rowKeyValues: [ - selectableTextBuilderMapEntry( - 'Dart Heap', - _buildMemoryString( - isolate?.dartHeapSize, - isolate?.dartHeapCapacity, + return OutlineDecoration( + showRight: false, + showBottom: false, + child: VMInfoCard( + title: 'Memory', + rowKeyValues: [ + selectableTextBuilderMapEntry( + 'Dart Heap', + _buildMemoryString( + isolate?.dartHeapSize, + isolate?.dartHeapCapacity, + ), ), - ), - selectableTextBuilderMapEntry( - 'New Space', - _buildMemoryString( - isolate?.newSpaceUsage, - isolate?.newSpaceUsage, + selectableTextBuilderMapEntry( + 'New Space', + _buildMemoryString( + isolate?.newSpaceUsage, + isolate?.newSpaceUsage, + ), ), - ), - selectableTextBuilderMapEntry( - 'Old Space', - _buildMemoryString( - isolate?.oldSpaceUsage, - isolate?.oldSpaceCapacity, + selectableTextBuilderMapEntry( + 'Old Space', + _buildMemoryString( + isolate?.oldSpaceUsage, + isolate?.oldSpaceCapacity, + ), ), - ), - ], + ], + ), ); } } @@ -219,21 +226,24 @@ class TagStatisticsWidget extends StatelessWidget { @override Widget build(BuildContext context) { - return VMInfoCard( - title: 'Execution Time', - table: Flexible( - child: controller.cpuProfilerController.profilerEnabled - ? FlatTable( - columns: columns, - data: controller.tags, - keyFactory: (VMTag tag) => ValueKey(tag.name), - sortColumn: percentage, - sortDirection: SortDirection.descending, - onItemSelected: (_) => null, - ) - : CpuProfilerDisabled( - controller.cpuProfilerController, - ), + return OutlineDecoration( + showBottom: false, + child: VMInfoCard( + title: 'Execution Time', + table: Flexible( + child: controller.cpuProfilerController.profilerEnabled + ? FlatTable( + columns: columns, + data: controller.tags, + keyFactory: (VMTag tag) => ValueKey(tag.name), + sortColumn: percentage, + sortDirection: SortDirection.descending, + onItemSelected: (_) => null, + ) + : CpuProfilerDisabled( + controller.cpuProfilerController, + ), + ), ), ); } @@ -356,20 +366,25 @@ class _IsolatePortsWidgetState extends State { @override Widget build(BuildContext context) { final ports = widget.controller.ports; - return Column( - children: [ - Flexible( - child: VMInfoCard( - title: 'Open Ports (${ports.length})', - table: Flexible( - child: Split( - axis: Axis.horizontal, - initialFractions: const [ - 0.3, - 0.7, - ], - children: [ - FlatTable( + return OutlineDecoration( + child: Split( + axis: Axis.horizontal, + initialFractions: const [ + 0.3, + 0.7, + ], + children: [ + OutlineDecoration.onlyRight( + child: Column( + children: [ + AreaPaneHeader( + needsTopBorder: false, + title: Text( + 'Open Ports (${ports.length})', + ), + ), + Flexible( + child: FlatTable( columns: columns, data: ports, keyFactory: (InstanceRef? port) => @@ -387,15 +402,17 @@ class _IsolatePortsWidgetState extends State { }, ), ), - StackTraceViewerWidget( - stackTrace: selectedPort.value, - ), - ], - ), + ), + ], ), ), - ), - ], + OutlineDecoration.onlyLeft( + child: StackTraceViewerWidget( + stackTrace: selectedPort.value, + ), + ), + ], + ), ); } } @@ -423,16 +440,20 @@ class ServiceExtensionsWidget extends StatelessWidget { @override Widget build(BuildContext context) { final extensions = controller.isolate?.extensionRPCs ?? []; - return VMInfoCard( - title: 'Service Extensions (${extensions.length})', - table: Flexible( - child: FlatTable( - columns: columns, - data: extensions, - keyFactory: (String extension) => ValueKey(extension), - sortColumn: name, - sortDirection: SortDirection.ascending, - onItemSelected: (_) => null, + return OutlineDecoration( + showBottom: false, + showLeft: false, + child: VMInfoCard( + title: 'Service Extensions (${extensions.length})', + table: Flexible( + child: FlatTable( + columns: columns, + data: extensions, + keyFactory: (String extension) => ValueKey(extension), + sortColumn: name, + sortDirection: SortDirection.ascending, + onItemSelected: (_) => null, + ), ), ), ); diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector_view.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector_view.dart index 5d1e47d5657..9a76c88cb30 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector_view.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector_view.dart @@ -44,7 +44,7 @@ class _ObjectInspectorViewState extends State<_ObjectInspectorView> { super.didChangeDependencies(); final vmDeveloperToolsController = Provider.of(context); - controller = vmDeveloperToolsController.objectInspectorViewController! + controller = vmDeveloperToolsController.objectInspectorViewController ..init(); } diff --git a/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_common_widgets.dart b/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_common_widgets.dart index 4b7c5fa07c0..cd15e0bd0d4 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_common_widgets.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_common_widgets.dart @@ -46,12 +46,10 @@ class VMInfoCard extends StatelessWidget implements PreferredSizeWidget { Widget build(BuildContext context) { return SizedBox.fromSize( size: preferredSize, - child: Card( - child: VMInfoList( - title: title, - rowKeyValues: rowKeyValues, - table: table, - ), + child: VMInfoList( + title: title, + rowKeyValues: rowKeyValues, + table: table, ), ); } @@ -700,16 +698,23 @@ class VmObjectDisplayBasicLayout extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Flexible( - child: VMInfoCard( - title: generalInfoTitle, - rowKeyValues: generalDataRows, + child: OutlineDecoration( + showLeft: false, + showTop: false, + showRight: sideCardDataRows != null, + child: VMInfoCard( + title: generalInfoTitle, + rowKeyValues: generalDataRows, + ), ), ), if (sideCardDataRows != null) Flexible( - child: VMInfoCard( - title: sideCardTitle, - rowKeyValues: sideCardDataRows, + child: OutlineDecoration.onlyBottom( + child: VMInfoCard( + title: sideCardTitle, + rowKeyValues: sideCardDataRows, + ), ), ), ], diff --git a/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_controller.dart b/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_controller.dart index e1e26271aed..fbeaaba6171 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_controller.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_controller.dart @@ -11,8 +11,7 @@ class VMDeveloperToolsController { ValueListenable get selectedIndex => _selectedIndex; final _selectedIndex = ValueNotifier(0); - final objectInspectorViewController = - displayObjectInspector ? ObjectInspectorViewController() : null; + final objectInspectorViewController = ObjectInspectorViewController(); void selectIndex(int index) { _selectedIndex.value = index; diff --git a/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_screen.dart b/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_screen.dart index a35851c4e46..5f7d3ee728e 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_screen.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_screen.dart @@ -14,8 +14,6 @@ import 'object_inspector_view.dart'; import 'vm_developer_tools_controller.dart'; import 'vm_statistics_view.dart'; -bool displayObjectInspector = false; - abstract class VMDeveloperView { const VMDeveloperView( this.screenId, { @@ -65,7 +63,7 @@ class VMDeveloperToolsScreenBody extends StatefulWidget { static List views = [ const VMStatisticsView(), const IsolateStatisticsView(), - if (displayObjectInspector) ObjectInspectorView(), + ObjectInspectorView(), ]; @override diff --git a/packages/devtools_app/lib/src/screens/vm_developer/vm_statistics_view.dart b/packages/devtools_app/lib/src/screens/vm_developer/vm_statistics_view.dart index 5f8655b0a22..fdcf26cc65c 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/vm_statistics_view.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/vm_statistics_view.dart @@ -9,6 +9,7 @@ import '../../primitives/utils.dart'; import '../../shared/common_widgets.dart'; import '../../shared/table.dart'; import '../../shared/table_data.dart'; +import '../../shared/theme.dart'; import 'vm_developer_common_widgets.dart'; import 'vm_developer_tools_screen.dart'; import 'vm_service_private_extensions.dart'; @@ -32,27 +33,22 @@ class VMStatisticsViewBody extends StatelessWidget { final controller = VMStatisticsViewController(); @override Widget build(BuildContext context) { - return ValueListenableBuilder( - valueListenable: controller.refreshing, - builder: (context, refreshing, child) { - return Column( - children: [ - Row( - children: [ - child!, - ], - ), - Expanded( - child: VMStatisticsWidget( + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RefreshButton(onPressed: controller.refresh), + const SizedBox(height: denseRowSpacing), + Expanded( + child: ValueListenableBuilder( + valueListenable: controller.refreshing, + builder: (context, _, __) { + return VMStatisticsWidget( controller: controller, - ), - ), - ], - ); - }, - child: RefreshButton( - onPressed: controller.refresh, - ), + ); + }, + ), + ), + ], ); } } @@ -121,29 +117,31 @@ class GeneralVMStatisticsWidget extends StatelessWidget { @override Widget build(BuildContext context) { final vm = controller.vm; - return VMInfoCard( - title: 'VM', - rowKeyValues: [ - selectableTextBuilderMapEntry('Name', vm?.name), - selectableTextBuilderMapEntry('Version', vm?.version), - selectableTextBuilderMapEntry('Embedder', vm?.embedder), - selectableTextBuilderMapEntry( - 'Started', - vm == null - ? null - : formatDateTime( - DateTime.fromMillisecondsSinceEpoch(vm.startTime!), - ), - ), - selectableTextBuilderMapEntry('Profiler Mode', vm?.profilerMode), - selectableTextBuilderMapEntry( - 'Current Memory', - prettyPrintBytes( - vm?.currentMemory, - includeUnit: true, + return OutlineDecoration( + child: VMInfoCard( + title: 'VM', + rowKeyValues: [ + selectableTextBuilderMapEntry('Name', vm?.name), + selectableTextBuilderMapEntry('Version', vm?.version), + selectableTextBuilderMapEntry('Embedder', vm?.embedder), + selectableTextBuilderMapEntry( + 'Started', + vm == null + ? null + : formatDateTime( + DateTime.fromMillisecondsSinceEpoch(vm.startTime!), + ), ), - ), - ], + selectableTextBuilderMapEntry('Profiler Mode', vm?.profilerMode), + selectableTextBuilderMapEntry( + 'Current Memory', + prettyPrintBytes( + vm?.currentMemory, + includeUnit: true, + ), + ), + ], + ), ); } } @@ -163,38 +161,44 @@ class ProcessStatisticsWidget extends StatelessWidget { @override Widget build(BuildContext context) { final vm = controller.vm; - return VMInfoCard( - title: 'Process', - rowKeyValues: [ - selectableTextBuilderMapEntry('PID', vm?.pid?.toString()), - selectableTextBuilderMapEntry( - 'Host CPU', - vm == null ? null : '${vm.hostCPU} (${vm.architectureBits}-bits)', - ), - selectableTextBuilderMapEntry('Target CPU', vm?.targetCPU), - selectableTextBuilderMapEntry('Operating System', vm?.operatingSystem), - selectableTextBuilderMapEntry( - 'Max Memory (RSS)', - prettyPrintBytes( - vm?.maxRSS, - includeUnit: true, + return OutlineDecoration( + showTop: false, + child: VMInfoCard( + title: 'Process', + rowKeyValues: [ + selectableTextBuilderMapEntry('PID', vm?.pid?.toString()), + selectableTextBuilderMapEntry( + 'Host CPU', + vm == null ? null : '${vm.hostCPU} (${vm.architectureBits}-bits)', ), - ), - selectableTextBuilderMapEntry( - 'Current Memory (RSS)', - prettyPrintBytes( - vm?.currentRSS, - includeUnit: true, + selectableTextBuilderMapEntry('Target CPU', vm?.targetCPU), + selectableTextBuilderMapEntry( + 'Operating System', + vm?.operatingSystem, ), - ), - selectableTextBuilderMapEntry( - 'Zone Memory', - prettyPrintBytes( - vm?.nativeZoneMemoryUsage, - includeUnit: true, + selectableTextBuilderMapEntry( + 'Max Memory (RSS)', + prettyPrintBytes( + vm?.maxRSS, + includeUnit: true, + ), ), - ), - ], + selectableTextBuilderMapEntry( + 'Current Memory (RSS)', + prettyPrintBytes( + vm?.currentRSS, + includeUnit: true, + ), + ), + selectableTextBuilderMapEntry( + 'Zone Memory', + prettyPrintBytes( + vm?.nativeZoneMemoryUsage, + includeUnit: true, + ), + ), + ], + ), ); } } @@ -289,16 +293,20 @@ class IsolatesPreviewWidget extends StatelessWidget { final title = systemIsolates ? 'System Isolates' : 'Isolates'; final isolates = systemIsolates ? controller.systemIsolates : controller.isolates; - return VMInfoCard( - title: '$title (${isolates.length})', - table: Flexible( - child: FlatTable( - columns: columns, - data: isolates, - keyFactory: (Isolate i) => ValueKey(i.id!), - sortColumn: name, - sortDirection: SortDirection.descending, - onItemSelected: (_) => null, + return OutlineDecoration( + showLeft: false, + showTop: !systemIsolates, + child: VMInfoCard( + title: '$title (${isolates.length})', + table: Flexible( + child: FlatTable( + columns: columns, + data: isolates, + keyFactory: (Isolate i) => ValueKey(i.id!), + sortColumn: name, + sortDirection: SortDirection.descending, + onItemSelected: (_) => null, + ), ), ), ); diff --git a/packages/devtools_app/test/vm_developer/object_inspector/object_inspector_view_test.dart b/packages/devtools_app/test/vm_developer/object_inspector/object_inspector_view_test.dart index 121e03b8076..16b9cdc466e 100644 --- a/packages/devtools_app/test/vm_developer/object_inspector/object_inspector_view_test.dart +++ b/packages/devtools_app/test/vm_developer/object_inspector/object_inspector_view_test.dart @@ -7,7 +7,6 @@ import 'package:devtools_app/src/screens/debugger/program_explorer.dart'; import 'package:devtools_app/src/screens/vm_developer/object_inspector_view.dart'; import 'package:devtools_app/src/screens/vm_developer/object_viewport.dart'; import 'package:devtools_app/src/screens/vm_developer/vm_developer_tools_controller.dart'; -import 'package:devtools_app/src/screens/vm_developer/vm_developer_tools_screen.dart'; import 'package:devtools_app/src/scripts/script_manager.dart'; import 'package:devtools_app/src/service/service_manager.dart'; import 'package:devtools_app/src/shared/globals.dart'; @@ -27,7 +26,6 @@ void main() { late MockScriptManager scriptManager; setUp(() { - displayObjectInspector = true; objectInspector = ObjectInspectorView(); fakeServiceManager = FakeServiceManager(); scriptManager = MockScriptManager(); @@ -42,10 +40,6 @@ void main() { setGlobal(NotificationService, NotificationService()); }); - tearDown(() { - displayObjectInspector = false; - }); - testWidgets('builds screen', (WidgetTester tester) async { await tester.pumpWidget( wrapWithControllers(