Skip to content
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

Remove uses of shrinkWrap in DevTools #6038

Merged
merged 4 commits into from
Jul 14, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@ import '../../shared/primitives/auto_dispose.dart';
import '../../shared/primitives/utils.dart';
import '../../shared/theme.dart';
import '../../shared/tree.dart';
import '../../shared/utils.dart';
import 'program_explorer_controller.dart';
import 'program_explorer_model.dart';

const containerIcon = Icons.folder;
const libraryIcon = Icons.insert_drive_file;

double get _programExplorerRowHeight => scaleByFontFactor(22.0);
double get _selectedNodeTopSpacing => _programExplorerRowHeight * 3;
double get _selectedNodeTopSpacing => defaultTreeViewRowHeight * 3;

class _ProgramExplorerRow extends StatelessWidget {
const _ProgramExplorerRow({
Expand Down Expand Up @@ -313,7 +311,7 @@ class _FileExplorerState extends State<_FileExplorer> with AutoDisposeMixin {
double get selectedNodeOffset => widget.controller.selectedNodeIndex.value ==
-1
? -1
: widget.controller.selectedNodeIndex.value * _programExplorerRowHeight;
: widget.controller.selectedNodeIndex.value * defaultTreeViewRowHeight;

@override
void initState() {
Expand All @@ -334,7 +332,6 @@ class _FileExplorerState extends State<_FileExplorer> with AutoDisposeMixin {
@override
Widget build(BuildContext context) {
return TreeView<VMServiceObjectNode>(
itemExtent: _programExplorerRowHeight,
dataRootsListenable: widget.controller.rootObjectNodes,
onItemSelected: widget.onItemSelected,
onItemExpanded: widget.onItemExpanded,
Expand Down Expand Up @@ -392,7 +389,6 @@ class _ProgramOutlineView extends StatelessWidget {
return const CenteredCircularProgressIndicator();
}
return TreeView<VMServiceObjectNode>(
itemExtent: _programExplorerRowHeight,
dataRootsListenable: controller.outlineNodes,
onItemSelected: onItemSelected,
onItemExpanded: onItemExpanded,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,7 @@ class _MemoryChartPaneState extends State<MemoryChartPane>
borderRadius: BorderRadius.circular(defaultBorderRadius),
),
width: _hoverWidth,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
child: ListView(
children: [
Container(
width: _hoverWidth,
Expand Down Expand Up @@ -476,37 +475,12 @@ class _MemoryChartPaneState extends State<MemoryChartPane>
}

List<Widget> _displayExtensionEventsInHover(ChartsValues chartsValues) {
final widgets = <Widget>[];

final eventsDisplayed = chartsValues.extensionEventsToDisplay;

for (var entry in eventsDisplayed.entries) {
if (entry.key.endsWith(eventsDisplayName)) {
widgets.add(
SizedBox(
height: _hoverEventsHeight,
child: ListView(
shrinkWrap: true,
primary: false,
children: [
_listItem(
allEvents: chartsValues.extensionEvents,
title: entry.key,
),
],
),
),
);
} else {
widgets.add(_hoverRow(name: entry.key, image: entry.value));

/// Pull out the event name, and custom values.
final output =
_displayEvent(null, chartsValues.extensionEvents.first).trim();
widgets.add(_hoverRow(name: output));
}
}
return widgets;
return [
if (chartsValues.hasExtensionEvents)
..._extensionEvents(
allEvents: chartsValues.extensionEvents,
),
];
}

List<Widget> _displayEventsInHover(ChartsValues chartsValues) {
Expand All @@ -523,87 +497,70 @@ class _MemoryChartPaneState extends State<MemoryChartPane>
return results;
}

Widget _listItem({
List<Widget> _extensionEvents({
required List<Map<String, Object>> allEvents,
required String title,
}) {
final theme = Theme.of(context);

final widgets = <Widget>[];
var index = 1;
for (var event in allEvents) {
final output = _displayEvent(index, event);
widgets.add(_cardWidget(output));
index++;
}
late String? name;
if (event[eventName] == devToolsEvent && event.containsKey(customEvent)) {
final custom = event[customEvent] as Map<dynamic, dynamic>;
name = custom[customEventName];
} else {
name = event[eventName] as String?;
}

final theme = Theme.of(context);
final colorScheme = theme.colorScheme;
final collapsedColor = colorScheme.defaultBackgroundColor;

return Material(
color: Colors.transparent,
child: Theme(
// TODO(kenz): why are we using a Material and a Theme widget here?
data: ThemeData(),
child: ExpansionTile(
tilePadding: EdgeInsets.zero,
childrenPadding: EdgeInsets.zero,
leading: Container(
padding: const EdgeInsets.only(left: 5, top: 4),
child: Image(
image: allEvents.length > 1
? const AssetImage(eventsLegend)
: const AssetImage(eventLegend),
),
final output = _decodeEventValues(event);
widgets.add(
Padding(
padding: const EdgeInsets.only(left: intermediateSpacing),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'$index. $name',
overflow: TextOverflow.ellipsis,
style: theme.legendTextStyle,
),
Padding(
padding: const EdgeInsets.only(left: densePadding),
child: Text(
output,
overflow: TextOverflow.ellipsis,
style: theme.legendTextStyle,
),
),
],
),
backgroundColor: collapsedColor,
collapsedBackgroundColor: collapsedColor,
title: Text(title, style: theme.legendTextStyle),
children: widgets,
),
),
);
}

Widget _cardWidget(String value) {
final theme = Theme.of(context);
final colorScheme = theme.colorScheme;
final expandedGradient = colorScheme.verticalGradient;
);
index++;
}

return Container(
margin: const EdgeInsets.only(bottom: 8),
width: _hoverWidth,
decoration: BoxDecoration(
gradient: expandedGradient,
),
child: Row(
children: [
const SizedBox(width: 10),
Text(
value,
overflow: TextOverflow.ellipsis,
style: theme.legendTextStyle,
final eventsLength = allEvents.length;
final title = Row(
children: [
Container(
padding: const EdgeInsets.only(left: 6.0),
child: Image(
image: AssetImage(eventLegendAsset(eventsLength)),
),
],
),
),
const SizedBox(width: denseSpacing),
Text(
'$eventsLength ${pluralize('Event', eventsLength)}',
style: theme.legendTextStyle,
),
],
);
}

String _displayEvent(int? index, Map<String, Object> event) {
final output = StringBuffer();

String? name;

if (event[eventName] == devToolsEvent && event.containsKey(customEvent)) {
final custom = event[customEvent] as Map<dynamic, dynamic>;
name = custom[customEventName];
} else {
name = event[eventName] as String?;
}

output.writeln(index == null ? name : '$index. $name');
output.write(_decodeEventValues(event));

return output.toString();
return [
title,
...widgets,
];
}

String _decodeEventValues(Map<String, Object> event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,12 @@ Map<String, Map<String, Object?>> eventLegendContent(bool isLight) => {
manualGCLegendName: traceRender(
image: gcManualLegend,
),
// TODO: why do we need both a singular and plural legend entry for event?
eventLegendName: traceRender(
image: eventLegend,
image: eventLegendAsset(1),
),
eventsLegendName: traceRender(
image: eventsLegend,
image: eventLegendAsset(2),
),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,22 +270,6 @@ class ChartsValues {
return eventsDisplayed;
}

Map<String, String> get extensionEventsToDisplay {
final eventsDisplayed = <String, String>{};

if (hasExtensionEvents) {
final eventLength = extensionEventsLength;
if (eventLength > 0) {
final displayKey = '$eventLength'
'${eventLength == 1 ? eventDisplayName : eventsDisplayName}';
eventsDisplayed[displayKey] =
eventLength == 1 ? eventLegend : eventsLegend;
}
}

return eventsDisplayed;
}

Map<String, Map<String, Object?>> displayVmDataToDisplay(List<Trace> traces) {
final vmDataDisplayed = <String, Map<String, Object?>>{};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import '../../../../shared/charts/chart_controller.dart';
import '../../../../shared/charts/chart_trace.dart' as trace;
import '../../../../shared/charts/chart_trace.dart' show ChartType;
import '../../../../shared/primitives/auto_dispose.dart';
import '../../../../shared/primitives/utils.dart';
import '../../../../shared/theme.dart';
import '../../../../shared/utils.dart';
import '../../framework/connected/memory_controller.dart';
Expand All @@ -24,8 +25,8 @@ const resetDarkLegend = '${_base}reset_glyph_dark.png';
const resetLightLegend = '${_base}reset_glyph_light.png';
const gcManualLegend = '${_base}gc_manual_glyph.png';
const gcVMLegend = '${_base}gc_vm_glyph.png';
const eventLegend = '${_base}event_glyph.png';
const eventsLegend = '${_base}events_glyph.png';
String eventLegendAsset(int eventCount) =>
'$_base${pluralize('event', eventCount)}_glyph.png';

/// Events trace name displayed
const manualSnapshotLegendName = 'Snapshot';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ class ExpandableVariable extends StatelessWidget {
return TreeView<DartObjectNode>(
dataRootsListenable:
FixedValueListenable<List<DartObjectNode>>([variable]),
shrinkWrap: true,
dataDisplayProvider: dataDisplayProvider ??
(variable, onPressed) => DisplayProvider(
variable: variable,
Expand Down
51 changes: 22 additions & 29 deletions packages/devtools_app/lib/src/shared/tree.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import 'collapsible_mixin.dart';
import 'primitives/auto_dispose.dart';
import 'primitives/trees.dart';
import 'theme.dart';
import 'utils.dart';

double get defaultTreeViewRowHeight => scaleByFontFactor(20.0);

class TreeView<T extends TreeNode<T>> extends StatefulWidget {
const TreeView({
Expand All @@ -19,8 +22,6 @@ class TreeView<T extends TreeNode<T>> extends StatefulWidget {
required this.dataDisplayProvider,
required this.onItemSelected,
this.onItemExpanded,
this.shrinkWrap = false,
this.itemExtent,
this.onTraverse,
this.emptyTreeViewBuilder,
this.scrollController,
Expand All @@ -29,14 +30,6 @@ class TreeView<T extends TreeNode<T>> extends StatefulWidget {

final ValueListenable<List<T>> dataRootsListenable;

/// Use [shrinkWrap] iff you need to place a TreeView inside a ListView or
/// other container with unconstrained height.
///
/// Enabling shrinkWrap impacts performance.
///
/// Defaults to false.
final bool shrinkWrap;

final Widget Function(T, VoidCallback) dataDisplayProvider;

/// Invoked when a tree node is selected. If [onItemExpanded] is not
Expand All @@ -48,8 +41,6 @@ class TreeView<T extends TreeNode<T>> extends StatefulWidget {
/// Otherwise, [onItemSelected] will be invoked, if provided.
final FutureOr<void> Function(T)? onItemExpanded;

final double? itemExtent;

/// Called on traversal of child node during [buildFlatList].
final void Function(T)? onTraverse;

Expand Down Expand Up @@ -82,23 +73,25 @@ class _TreeViewState<T extends TreeNode<T>> extends State<TreeView<T>>
@override
Widget build(BuildContext context) {
if (dataFlatList.isEmpty) return _emptyTreeViewBuilder();
final content = SelectionArea(
child: ListView.builder(
itemCount: dataFlatList.length,
itemExtent: widget.itemExtent,
shrinkWrap: widget.shrinkWrap,
physics: widget.shrinkWrap ? const ClampingScrollPhysics() : null,
controller: widget.scrollController,
itemBuilder: (context, index) {
final T item = dataFlatList[index];
return _TreeViewItem<T>(
item,
buildDisplay: (onPressed) =>
widget.dataDisplayProvider(item, onPressed),
onItemSelected: _onItemSelected,
onItemExpanded: _onItemExpanded,
);
},
final content = SizedBox(
height: dataFlatList.length * defaultTreeViewRowHeight,
child: SelectionArea(
child: ListView.builder(
itemCount: dataFlatList.length,
itemExtent: defaultTreeViewRowHeight,
physics: const ClampingScrollPhysics(),
controller: widget.scrollController,
itemBuilder: (context, index) {
final T item = dataFlatList[index];
return _TreeViewItem<T>(
item,
buildDisplay: (onPressed) =>
widget.dataDisplayProvider(item, onPressed),
onItemSelected: _onItemSelected,
onItemExpanded: _onItemExpanded,
);
},
),
),
);
if (widget.includeScrollbar) {
Expand Down
Loading
Loading