diff --git a/packages/devtools_app/lib/src/charts/chart.dart b/packages/devtools_app/lib/src/charts/chart.dart index 2a48c302ae9..4d3c32129b0 100644 --- a/packages/devtools_app/lib/src/charts/chart.dart +++ b/packages/devtools_app/lib/src/charts/chart.dart @@ -164,11 +164,6 @@ class ChartPainter extends CustomPainter { }, ); - /// Number of minor ticks between major ticks. - const tickMarkInterval = 4; - - int tickIndex = 0; - /// Key is trace index and value is x,y point. final previousTracesData = {}; @@ -188,29 +183,9 @@ class ChartPainter extends CustomPainter { int xTickIndex = chartController.timestampsLength; while (--xTickIndex >= 0) { - // Hide left-side label when its ticks scrolls out. - final leftTimestamp = chartController.leftLabelTimestamp; - if (endVisibleIndex >= 0 && - leftTimestamp != null && - leftTimestamp < chartController.timestamps[endVisibleIndex]) { - chartController.leftLabelTimestamp = null; - } - - // Make sure duration label has been computed. - chartController.computeDurationLabel(); - final currentTimestamp = chartController.timestamps[xTickIndex]; - final xLabelIndex = - chartController.getLabeledIndexByTimestamp(currentTimestamp); if (xTickIndex < endVisibleIndex) { - // Has left label has slid out of visible range? - if (xLabelIndex == leftLabelIndex) { - // Yes, slide other labels left. - chartController.slideLabelsLeft(); - chartController.rightLabelTimestamp = currentTimestamp; - } - // Once outside of visible range of data skip the rest of the collected data. break; } @@ -315,79 +290,44 @@ class ChartPainter extends CustomPainter { // Undo the clipRect at beginning of for loop. canvas.restore(); - - ///////////////////////////////////////////////////////////////////////// - // Compute the ticks to label. - ///////////////////////////////////////////////////////////////////////// - - final minorTick = tickIndex++ < tickMarkInterval; - - // Compute major tick labels - if (!minorTick) { - chartController.recomputeLabels( - timestamp: chartController.timestamps.last, - ); - } - - if (chartController.displayXAxis || chartController.displayXLabels) - // Y translation is below X-axis line. - drawTranslate( - canvas, - xTranslation, - chartController.zeroYPosition + 1, - (canvas) { - // Draw right-most tick label (first major tick). - drawXTick( - canvas, - currentTimestamp, - chartController.timestampXCanvasCoord(currentTimestamp), - axis, - shortTick: minorTick, - ); - }, - ); - - if (!minorTick) tickIndex = 0; } - if (chartController.displayXAxis || chartController.displayXLabels) + chartController.computeChartArea(); + chartController.buildLabelTimestamps(); + + if (chartController.displayXAxis || chartController.displayXLabels) { // Y translation is below X-axis line. drawTranslate( canvas, xTranslation, chartController.zeroYPosition + 1, (canvas) { - // Draw the major labels. - for (var labelIndex = 0; - labelIndex < chartController.getLabelsCount(); - labelIndex++) { - final timestamp = - chartController.getLabelTimestampByIndex(labelIndex); - if (timestamp != null) { - final xCoord = chartController.timestampXCanvasCoord(timestamp); - drawXTick(canvas, timestamp, xCoord, axis, displayTime: true); - } + // Draw the X-axis labels. + for (var timestamp in chartController.labelTimestamps) { + final xCoord = chartController.timestampXCanvasCoord(timestamp); + drawXTick(canvas, timestamp, xCoord, axis, displayTime: true); } }, ); - // X translation is left-most edge of chart widget. - drawTranslate( - canvas, - chartController.xCanvasChart, - yTranslation, - (canvas) { - // Rescale Y-axis to max visible Y range. - chartController.resetYMaxValue(visibleYMax); - - // Draw Y-axis ticks and labels. - // TODO(terry): Optimization add a listener for Y-axis range changing - // only need to redraw Y-axis if the range changed. - if (chartController.displayYLabels) { - drawYTicks(canvas, chartController, axis); - } - }, - ); + // X translation is left-most edge of chart widget. + drawTranslate( + canvas, + chartController.xCanvasChart, + yTranslation, + (canvas) { + // Rescale Y-axis to max visible Y range. + chartController.resetYMaxValue(visibleYMax); + + // Draw Y-axis ticks and labels. + // TODO(terry): Optimization add a listener for Y-axis range changing + // only need to redraw Y-axis if the range changed. + if (chartController.displayYLabels) { + drawYTicks(canvas, chartController, axis); + } + }, + ); + } drawTitle(canvas, size, chartController.title); diff --git a/packages/devtools_app/lib/src/charts/chart_controller.dart b/packages/devtools_app/lib/src/charts/chart_controller.dart index 40da17c113b..6ad8f7c6748 100644 --- a/packages/devtools_app/lib/src/charts/chart_controller.dart +++ b/packages/devtools_app/lib/src/charts/chart_controller.dart @@ -25,11 +25,6 @@ String prettyTimestamp( return intl.DateFormat.Hms().format(timestampDT); // HH:mm:ss } -/// Indexes into xAxisLabeledTimestamps. -const leftLabelIndex = 0; -const centerLabelIndex = 1; -const rightLabelIndex = 2; - ///_____________________________________________________________________ /// /// xPaddingRight @@ -61,9 +56,15 @@ class ChartController extends DisposableController this.displayXLabels = true, this.displayYLabels = true, this.name, + List sharedLabelimestamps, }) { // TODO(terry): Compute dynamically based on X-axis lables text height. bottomPadding = !displayXLabels ? 0.0 : 40.0; + + if (sharedLabelimestamps != null) { + labelTimestamps = sharedLabelimestamps; + _labelsShared = true; + } } /// Used for debugging to determine which chart. @@ -105,24 +106,6 @@ class ChartController extends DisposableController int getLabelTimestampByIndex(int index) => _xAxisLabeledTimestamps[index]; - // TODO(terry): See TODO on _xAxisLabeledTimestamps. - int get leftLabelTimestamp => _xAxisLabeledTimestamps[leftLabelIndex]; - set leftLabelTimestamp(int timestamp) { - _xAxisLabeledTimestamps[leftLabelIndex] = timestamp; - } - - // TODO(terry): See TODO on _xAxisLabeledTimestamps. - int get centerLabelTimestamp => _xAxisLabeledTimestamps[centerLabelIndex]; - set centerLabelTimestamp(int timestamp) { - _xAxisLabeledTimestamps[centerLabelIndex] = timestamp; - } - - // TODO(terry): See TODO on _xAxisLabeledTimestamps. - int get rightLabelTimestamp => _xAxisLabeledTimestamps[rightLabelIndex]; - set rightLabelTimestamp(int timestamp) { - _xAxisLabeledTimestamps[rightLabelIndex] = timestamp; - } - /// If false displays top horizontal line of chart. final bool displayTopLine; @@ -136,98 +119,6 @@ class ChartController extends DisposableController final bool displayYLabels; - Duration durationLabel; - - // TODO(terry): Duration based on x-axis zoom factor (live, 5 min, 15 min, etc). - void computeDurationLabel() { - if (durationLabel == null && rightLabelTimestamp != null) { - final midTick = (visibleTicks / 2).truncate(); - if (timestampsLength > visibleTicks) { - // Lots of collected data > visible ticks so compute the visible mid tick. - final midTimestamp = timestamps[timestampsLength - midTick]; - final lastTimestamp = rightLabelTimestamp; - final midDT = DateTime.fromMillisecondsSinceEpoch(midTimestamp); - final lastDT = DateTime.fromMillisecondsSinceEpoch(lastTimestamp); - durationLabel = lastDT.difference(midDT); - } else if (timestampsLength > midTick) { - // Still collecting data when mid tick is collected compute the duration - // of the mid tick. - final midTimestamp = timestamps[midTick]; - final lastTimestamp = rightLabelTimestamp; - final midDT = DateTime.fromMillisecondsSinceEpoch(midTimestamp); - final lastDT = DateTime.fromMillisecondsSinceEpoch(lastTimestamp); - durationLabel = midDT.difference(lastDT); - } - } - } - - /// Used to compute incoming ticks. - /// @param refresh true rebuild all labels (probably zoom changed). - /// @param timestamp current timestamp received implies building all - /// parts of the x-axis labels. - void recomputeLabels({int timestamp, bool refresh = false}) { - // Chart not realized yet. - if (size == null) return; - - if (refresh && timestamps.isNotEmpty) { - // Need the correct tickWidth based on current zoom. - computeChartArea(); - - // All labels need to be recomputed. - durationLabel = null; - _xAxisLabeledTimestamps.replaceRange( - 0, - _xAxisLabeledTimestamps.length, - [null, null, null], - ); - - final midPt = (visibleTicks / 2).truncate(); - if (timestampsLength > visibleTicks) { - leftLabelTimestamp = timestamps[timestampsLength - visibleTicks + 10]; - centerLabelTimestamp = timestamps[timestampsLength - midPt]; - rightLabelTimestamp = timestamps.last; - } else if (timestampsLength > midPt) { - centerLabelTimestamp = timestamps[timestampsLength - midPt]; - rightLabelTimestamp = timestamps.last; - } else if (timestamps.isNotEmpty) { - rightLabelTimestamp = timestamps.first; - } - return; - } - - if (durationLabel == null && rightLabelTimestamp == null) { - // No center label so start first label (right-side). - rightLabelTimestamp = timestamp; - } else if (durationLabel != null && centerLabelTimestamp == null) { - // Need a center label are we at the duration we want for the - // next tick label? - final rightDT = DateTime.fromMillisecondsSinceEpoch(rightLabelTimestamp); - final currentDT = DateTime.fromMillisecondsSinceEpoch(timestamp); - if (currentDT.difference(rightDT).inSeconds >= durationLabel.inSeconds) { - slideLabelsLeft(); - rightLabelTimestamp = timestamp; - } - } else if (durationLabel != null && leftLabelTimestamp == null) { - // Need a left label are we at the duration we want for the - // next tick label? - final rightDT = DateTime.fromMillisecondsSinceEpoch(rightLabelTimestamp); - final currentDT = DateTime.fromMillisecondsSinceEpoch(timestamp); - if (currentDT.difference(rightDT).inSeconds >= durationLabel.inSeconds) { - slideLabelsLeft(); - rightLabelTimestamp = timestamp; - } - } - } - - void slideLabelsLeft() { - // Left-side out of visible range. Slide center and right labels to - // left-most and center. Need to eventually recompute right-most when - // duration gap is met. - leftLabelTimestamp = centerLabelTimestamp; - centerLabelTimestamp = rightLabelTimestamp; - rightLabelTimestamp = null; - } - /// xCanvas coord for plotting data. double xCanvasChart; @@ -329,6 +220,19 @@ class ChartController extends DisposableController bool get isZoomAll => _zoomDuration == null; + /// Label is displayed every N seconds, default is 20 seconds + /// for live view. See computeLabelInterval method. + int labelInterval = labelsLiveSeconds; + + /// List of timestamps where a label is displayed. First in the left-most + /// label (which will eventually scroll out of view and be replaced). + var labelTimestamps = []; + + bool get isLabelsShared => _labelsShared; + + /// If true signals that labels are compute from another controller. + var _labelsShared = false; + void computeZoomRatio() { // Check if ready to start computations? if (size == null) return; @@ -387,17 +291,139 @@ class ChartController extends DisposableController computeZoomRatio(); // All tick labels need to be recompted. - recomputeLabels(refresh: true); + computeChartArea(); + computeLabelInterval(); dirty = true; } + /// Label rate unit in seconds. Default label every 20 seconds for live view. + static const labelsLiveSeconds = 20; + static const labelsFifteenSeconds = 15; + static const labelsThirtySeconds = 30; + static const labelsOneMinute = 60; + static const labelsTwoMinutes = 120; + static const labelsOneHour = 60 * 60; + static const labelsFourHours = 60 * 60 * 4; + static const labelsTwelveHours = 60 * 60 * 12; + + void computeLabelInterval() { + if (zoomDuration == null && timestamps.isNotEmpty) { + final firstDT = DateTime.fromMillisecondsSinceEpoch(timestamps.first); + final lastDT = DateTime.fromMillisecondsSinceEpoch(timestamps.last); + final totalDuration = lastDT.difference(firstDT); + final totalHours = totalDuration.inHours; + if (totalHours == 0) { + final totalMinutes = totalDuration.inMinutes; + if (totalMinutes == 0) { + labelInterval = labelsThirtySeconds; + } else if (totalMinutes < 10) { + labelInterval = labelsOneMinute; + } else { + labelInterval = labelsTwoMinutes; + } + } else if (totalHours > 0 && totalHours < 8) { + labelInterval = labelsOneHour; + } else if (totalHours < 24) { + labelInterval = labelsFourHours; + } else { + labelInterval = labelsTwelveHours; + } + } else { + final rangeInMinutes = zoomDuration?.inMinutes; + if (rangeInMinutes == null) return; + switch (rangeInMinutes) { + case 0: // Live + labelInterval = labelsLiveSeconds; + break; + case 1: // 1 minute + labelInterval = labelsFifteenSeconds; + break; + case 5: // 5 minute + labelInterval = labelsOneMinute; + break; + case 10: // 10 minute + labelInterval = labelsTwoMinutes; + break; + default: + assert(false, 'Unexpected Duration $rangeInMinutes'); + } + } + + buildLabelTimestamps(refresh: true); + } + + void buildLabelTimestamps({refresh = false}) { + if (isLabelsShared || timestamps.isEmpty) return; + + if (refresh) { + labelTimestamps.clear(); + final leftMostTimestamp = leftMostVisibleTimestampIndex; + final lastTimestamp = timestamps[leftMostTimestamp]; + labelTimestamps.add(lastTimestamp); + var lastLabelDT = DateTime.fromMillisecondsSinceEpoch(lastTimestamp); + for (var index = leftMostTimestamp; index < timestampsLength; index++) { + final currentTimestamp = timestamps[index]; + final currentDT = DateTime.fromMillisecondsSinceEpoch(currentTimestamp); + if (currentDT.difference(lastLabelDT).inSeconds >= labelInterval) { + labelTimestamps.add(currentTimestamp); + lastLabelDT = currentDT; + } + } + + return; + } + + if (labelTimestamps.isEmpty) { + labelTimestamps.add(timestamps.last); + } else { + // Check left label is it out of range? + final leftEdge = leftMostVisibleTimestampIndex; + // TODO(terry): Need to insure that more than one label may not be + // visible e.g., when panning the chart. + if (labelTimestamps.first < timestamps[leftEdge]) { + // Label is outside of visible range, remove the left label. + labelTimestamps.removeAt(0); + } + } + + if (labelTimestamps.isEmpty) return; + + final rightLabelTimestamp = labelTimestamps.last; + final rightMostLableDT = + DateTime.fromMillisecondsSinceEpoch(rightLabelTimestamp); + final rightMostTimestampDT = + DateTime.fromMillisecondsSinceEpoch(timestamps.last); + + final nSeconds = + rightMostTimestampDT.difference(rightMostLableDT).inSeconds; + + if (nSeconds >= labelInterval) { + int foundTimestamp; + if (nSeconds == labelInterval) { + foundTimestamp = timestamps.last; + } else { + // Find the interval that's closest to the next interval. + final startIndex = timestamps.indexOf(rightLabelTimestamp); + for (var index = startIndex; index < timestampsLength; index++) { + foundTimestamp = timestamps[index]; + final nextDT = DateTime.fromMillisecondsSinceEpoch(foundTimestamp); + final secsDiff = nextDT.difference(rightMostTimestampDT).inSeconds; + if (secsDiff >= labelInterval) break; + } + } + assert(foundTimestamp != null); + labelTimestamps.add(foundTimestamp); + } + } + /// Clear all data in the chart. void reset() { for (var trace in traces) { trace.clearData(); } timestampsClear(); + labelTimestamps.clear(); } /// Override to load data from another source e.g., live, offline, etc. @@ -493,15 +519,23 @@ class ChartController extends DisposableController return -1; } + /// Return timestamps index of the left most visible datum. + int get leftMostVisibleTimestampIndex { + var index = 0; + if (timestampsLength > numberOfVisibleXAxisTicks) { + index = timestampsLength - numberOfVisibleXAxisTicks; + } + + return index; + } + /// X coordinate of left most visible datum. The timestampXCanvasCoord /// returns a zero based X-coord this X-coord must be translated by the /// value of this getter. double get xCoordLeftMostVisibleTimestamp { double indexOffset = xCanvasChart; - final totalTimestamps = timestampsLength; - final visibleCount = numberOfVisibleXAxisTicks; - if (totalTimestamps < visibleCount) { - final startIndex = visibleCount - totalTimestamps; + if (timestampsLength < numberOfVisibleXAxisTicks) { + final startIndex = numberOfVisibleXAxisTicks - timestampsLength; indexOffset += startIndex * tickWidth; } diff --git a/packages/devtools_app/lib/src/memory/memory_android_chart.dart b/packages/devtools_app/lib/src/memory/memory_android_chart.dart index 78683b9c7fd..9c79b7bf702 100644 --- a/packages/devtools_app/lib/src/memory/memory_android_chart.dart +++ b/packages/devtools_app/lib/src/memory/memory_android_chart.dart @@ -16,10 +16,11 @@ import 'memory_controller.dart'; import 'memory_timeline.dart'; class AndroidChartController extends ChartController { - AndroidChartController(this._memoryController) + AndroidChartController(this._memoryController, {List sharedLabels}) : super( displayTopLine: false, name: 'Android', + sharedLabelimestamps: sharedLabels, ); final MemoryController _memoryController; diff --git a/packages/devtools_app/lib/src/memory/memory_controller.dart b/packages/devtools_app/lib/src/memory/memory_controller.dart index 82b9d2658a2..f0b0bc1a815 100644 --- a/packages/devtools_app/lib/src/memory/memory_controller.dart +++ b/packages/devtools_app/lib/src/memory/memory_controller.dart @@ -52,7 +52,7 @@ enum ChartInterval { /// Duration for each ChartInterval. const displayDurations = [ - Duration(), // ChartInterval.Default + Duration.zero, // ChartInterval.Default Duration(minutes: 1), // ChartInterval.OneMinute Duration(minutes: 5), // ChartInterval.FiveMinutes Duration(minutes: 10), // ChartInterval.TenMinutes diff --git a/packages/devtools_app/lib/src/memory/memory_screen.dart b/packages/devtools_app/lib/src/memory/memory_screen.dart index 4e7c5cf21c9..64b1e76c851 100644 --- a/packages/devtools_app/lib/src/memory/memory_screen.dart +++ b/packages/devtools_app/lib/src/memory/memory_screen.dart @@ -127,7 +127,11 @@ class MemoryBodyState extends State eventChartController = EventChartController(controller); vmChartController = VMChartController(controller); - androidChartController = AndroidChartController(controller); + // Android Chart uses the VM Chart's computed labels. + androidChartController = AndroidChartController( + controller, + sharedLabels: vmChartController.labelTimestamps, + ); // Update the chart when the memorySource changes. addAutoDisposeListener(controller.selectedSnapshotNotifier, () { diff --git a/packages/devtools_app/lib/src/memory/memory_vm_chart.dart b/packages/devtools_app/lib/src/memory/memory_vm_chart.dart index 4fdcb4f5a72..afbca38f2ce 100644 --- a/packages/devtools_app/lib/src/memory/memory_vm_chart.dart +++ b/packages/devtools_app/lib/src/memory/memory_vm_chart.dart @@ -67,6 +67,18 @@ class VMChartController extends ChartController { final rssValue = sample.rss.toDouble(); addDataToTrace(TraceName.rSS.index, trace.Data(timestamp, rssValue)); + + final rasterLayerValue = sample.rasterCache.layerBytes.toDouble(); + addDataToTrace( + TraceName.rasterLayer.index, + trace.Data(timestamp, rasterLayerValue), + ); + + final rasterPictureValue = sample.rasterCache.pictureBytes.toDouble(); + addDataToTrace( + TraceName.rasterPicture.index, + trace.Data(timestamp, rasterPictureValue), + ); } void addDataToTrace(int traceIndex, trace.Data data) { @@ -90,6 +102,8 @@ enum TraceName { used, capacity, rSS, + rasterLayer, + rasterPicture, } class MemoryVMChartState extends State with AutoDisposeMixin { @@ -149,13 +163,12 @@ class MemoryVMChartState extends State with AutoDisposeMixin { } // TODO(terry): Move colors to theme? - final capacityColor = Colors.grey[400]; - //static const usedColor = Color.fromARGB(255, 51, 181, 229); - static const usedColor = Color(0xff33b5e5); // HoloBlue + static final capacityColor = Colors.grey[400]; + static final externalColor = Colors.blue[400]; static const rasterLayerColor = Color(0xff99cc00); // HoloGreenLight - static const rssColor = Color(0xffffbb33); // HoloOrangeLight static const rasterPictureColor = Color(0xffff4444); // HoloRedLight - static const externalColor = Color(0xff42a5f5); // Color.blue[400] + static const rssColor = Color(0xffffbb33); // HoloOrangeLight + static const usedColor = Color(0xff33b5e5); // HoloBlue void setupTraces() { if (_chartController.traces.isNotEmpty) { @@ -177,6 +190,14 @@ class MemoryVMChartState extends State with AutoDisposeMixin { assert(_chartController.trace(rSSIndex).name == TraceName.values[rSSIndex].toString()); + final rasterLayerIndex = TraceName.rasterLayer.index; + assert(_chartController.trace(rasterLayerIndex).name == + TraceName.values[rasterLayerIndex].toString()); + + final rasterPictureIndex = TraceName.rasterPicture.index; + assert(_chartController.trace(rasterPictureIndex).name == + TraceName.values[rasterPictureIndex].toString()); + return; } @@ -235,7 +256,31 @@ class MemoryVMChartState extends State with AutoDisposeMixin { assert(_chartController.trace(rSSIndex).name == TraceName.values[rSSIndex].toString()); - // TODO(terry): Add Raster Cache Picture and Layers traces. + final rasterLayerIndex = _chartController.createTrace( + trace.ChartType.line, + trace.PaintCharacteristics( + color: rasterLayerColor, + symbol: trace.ChartSymbol.disc, + strokeWidth: 2, + ), + name: TraceName.rasterLayer.toString(), + ); + assert(rasterLayerIndex == TraceName.rasterLayer.index); + assert(_chartController.trace(rasterLayerIndex).name == + TraceName.values[rasterLayerIndex].toString()); + + final rasterPictureIndex = _chartController.createTrace( + trace.ChartType.line, + trace.PaintCharacteristics( + color: rasterPictureColor, + symbol: trace.ChartSymbol.disc, + strokeWidth: 2, + ), + name: TraceName.rasterPicture.toString(), + ); + assert(rasterPictureIndex == TraceName.rasterPicture.index); + assert(_chartController.trace(rasterPictureIndex).name == + TraceName.values[rasterPictureIndex].toString()); assert(_chartController.traces.length == TraceName.values.length); } diff --git a/packages/devtools_app/pubspec.lock b/packages/devtools_app/pubspec.lock index 7c605e1211b..508636a0a4c 100644 --- a/packages/devtools_app/pubspec.lock +++ b/packages/devtools_app/pubspec.lock @@ -56,7 +56,7 @@ packages: name: browser_launcher url: "https://pub.dartlang.org" source: hosted - version: "0.1.7" + version: "0.1.8" build: dependency: transitive description: diff --git a/packages/devtools_app/test/chart_test.dart b/packages/devtools_app/test/chart_test.dart index b2d0cc64b3e..630b214ab7b 100644 --- a/packages/devtools_app/test/chart_test.dart +++ b/packages/devtools_app/test/chart_test.dart @@ -281,29 +281,44 @@ void main() { validateScaledYLabels(controller); // Validate the x-axis labels. - expect(controller.leftLabelTimestamp, isNotNull); - expect(controller.centerLabelTimestamp, isNotNull); - expect(controller.rightLabelTimestamp, isNotNull); - expect(controller.leftLabelTimestamp, equals(1595682514316)); - expect(controller.centerLabelTimestamp, equals(1595682534381)); - expect(controller.rightLabelTimestamp, equals(1595682556248)); + expect(controller.labelTimestamps.length, equals(3)); + expect(controller.labelTimestamps[0], equals(1595682513450)); + expect(controller.labelTimestamps[1], equals(1595682533744)); + expect(controller.labelTimestamps[2], equals(1595682553811)); // Validate using UTC timezone. expect( - prettyTimestamp(controller.leftLabelTimestamp, isUtc: true), - equals('13:08:34'), + prettyTimestamp(controller.labelTimestamps[0], isUtc: true), + equals('13:08:33'), ); expect( - prettyTimestamp(controller.centerLabelTimestamp, isUtc: true), - equals('13:08:54'), + prettyTimestamp(controller.labelTimestamps[1], isUtc: true), + equals('13:08:53'), ); expect( - prettyTimestamp(controller.rightLabelTimestamp, isUtc: true), - equals('13:09:16'), + prettyTimestamp(controller.labelTimestamps[2], isUtc: true), + equals('13:09:13'), ); }, ); + void checkScaledXAxis2Labels(ChartController controller) { + // Validate the x-axis labels. + expect(controller.labelTimestamps.length, equals(2)); + expect(controller.labelTimestamps[0], equals(1595682492441)); + expect(controller.labelTimestamps[1], equals(1595682552535)); + + // Validate using UTC timezone. + expect( + prettyTimestamp(controller.labelTimestamps[0], isUtc: true), + equals('13:08:12'), + ); + expect( + prettyTimestamp(controller.labelTimestamps[1], isUtc: true), + equals('13:09:12'), + ); + } + testWidgetsWithWindowSize('Scaled Y-axis all', windowSize, (WidgetTester tester) async { const chartKey = Key('Chart'); @@ -340,27 +355,7 @@ void main() { validateScaledYLabels(controller); - // Validate the x-axis labels. - expect(controller.leftLabelTimestamp, isNotNull); - expect(controller.centerLabelTimestamp, isNotNull); - expect(controller.rightLabelTimestamp, isNotNull); - expect(controller.leftLabelTimestamp, equals(1595682525980)); - expect(controller.centerLabelTimestamp, equals(1595682556248)); - expect(controller.rightLabelTimestamp, equals(1595682556248)); - - // Validate to UTC timezone. - expect( - prettyTimestamp(controller.leftLabelTimestamp, isUtc: true), - equals('13:08:45'), - ); - expect( - prettyTimestamp(controller.centerLabelTimestamp, isUtc: true), - equals('13:09:16'), - ); - expect( - prettyTimestamp(controller.rightLabelTimestamp, isUtc: true), - equals('13:09:16'), - ); + checkScaledXAxis2Labels(controller); }); testWidgetsWithWindowSize('Scaled Y-axis Five Minutes', windowSize, @@ -399,17 +394,7 @@ void main() { validateScaledYLabels(controller); - // Validate the x-axis labels. - expect(controller.leftLabelTimestamp, isNull); - expect(controller.centerLabelTimestamp, isNull); - expect(controller.rightLabelTimestamp, isNotNull); - expect(controller.rightLabelTimestamp, equals(1595682492441)); - - // Validate to UTC timezone. - expect( - prettyTimestamp(controller.rightLabelTimestamp, isUtc: true), - equals('13:08:12'), - ); + checkScaledXAxis2Labels(controller); }); /////////////////////////////////////////////////////////////////////////// @@ -682,29 +667,44 @@ void main() { } // Validate the x-axis labels. - expect(controller.leftLabelTimestamp, isNotNull); - expect(controller.centerLabelTimestamp, isNotNull); - expect(controller.rightLabelTimestamp, isNotNull); - expect(controller.leftLabelTimestamp, equals(1595682514316)); - expect(controller.centerLabelTimestamp, equals(1595682534381)); - expect(controller.rightLabelTimestamp, equals(1595682556248)); - - // Validate to UTC timezone. + expect(controller.labelTimestamps.length, equals(3)); + expect(controller.labelTimestamps[0], equals(1595682513450)); + expect(controller.labelTimestamps[1], equals(1595682533744)); + expect(controller.labelTimestamps[2], equals(1595682553811)); + + // Validate using UTC timezone. expect( - prettyTimestamp(controller.leftLabelTimestamp, isUtc: true), - equals('13:08:34'), + prettyTimestamp(controller.labelTimestamps[0], isUtc: true), + equals('13:08:33'), ); expect( - prettyTimestamp(controller.centerLabelTimestamp, isUtc: true), - equals('13:08:54'), + prettyTimestamp(controller.labelTimestamps[1], isUtc: true), + equals('13:08:53'), ); expect( - prettyTimestamp(controller.rightLabelTimestamp, isUtc: true), - equals('13:09:16'), + prettyTimestamp(controller.labelTimestamps[2], isUtc: true), + equals('13:09:13'), ); }, ); + void checkFixedXAxis2Labels(ChartController controller) { + // Validate the x-axis labels. + expect(controller.labelTimestamps.length, equals(2)); + expect(controller.labelTimestamps[0], equals(1595682492441)); + expect(controller.labelTimestamps[1], equals(1595682552535)); + + // Validate using UTC timezone. + expect( + prettyTimestamp(controller.labelTimestamps[0], isUtc: true), + equals('13:08:12'), + ); + expect( + prettyTimestamp(controller.labelTimestamps[1], isUtc: true), + equals('13:09:12'), + ); + } + testWidgetsWithWindowSize('Fixed Y-axis all', windowSize, (WidgetTester tester) async { const chartKey = Key('Chart'); @@ -754,27 +754,7 @@ void main() { expect(labelName, expectedLabels[labelIndex.toInt()]); } - // Validate the x-axis labels. - expect(controller.leftLabelTimestamp, isNotNull); - expect(controller.centerLabelTimestamp, isNotNull); - expect(controller.rightLabelTimestamp, isNotNull); - expect(controller.leftLabelTimestamp, equals(1595682525980)); - expect(controller.centerLabelTimestamp, equals(1595682556248)); - expect(controller.rightLabelTimestamp, equals(1595682556248)); - - // Validate to UTC timezone. - expect( - prettyTimestamp(controller.leftLabelTimestamp, isUtc: true), - equals('13:08:45'), - ); - expect( - prettyTimestamp(controller.centerLabelTimestamp, isUtc: true), - equals('13:09:16'), - ); - expect( - prettyTimestamp(controller.rightLabelTimestamp, isUtc: true), - equals('13:09:16'), - ); + checkFixedXAxis2Labels(controller); }); testWidgetsWithWindowSize('Fixed Y-axis 5 Minutes', windowSize, @@ -826,17 +806,7 @@ void main() { expect(labelName, expectedLabels[labelIndex.toInt()]); } - // Validate the x-axis labels. - expect(controller.leftLabelTimestamp, isNull); - expect(controller.centerLabelTimestamp, isNull); - expect(controller.rightLabelTimestamp, isNotNull); - expect(controller.rightLabelTimestamp, equals(1595682492441)); - - // Validate to UTC timezone. - expect( - prettyTimestamp(controller.rightLabelTimestamp, isUtc: true), - equals('13:08:12'), - ); + checkFixedXAxis2Labels(controller); }); }, ); diff --git a/packages/devtools_app/test/goldens/memory_chart_fixed_all.png b/packages/devtools_app/test/goldens/memory_chart_fixed_all.png index 64973351047..7f16726c7f7 100644 Binary files a/packages/devtools_app/test/goldens/memory_chart_fixed_all.png and b/packages/devtools_app/test/goldens/memory_chart_fixed_all.png differ diff --git a/packages/devtools_app/test/goldens/memory_chart_fixed_five_minutes.png b/packages/devtools_app/test/goldens/memory_chart_fixed_five_minutes.png index 2663742ea49..76bb4f6784f 100644 Binary files a/packages/devtools_app/test/goldens/memory_chart_fixed_five_minutes.png and b/packages/devtools_app/test/goldens/memory_chart_fixed_five_minutes.png differ diff --git a/packages/devtools_app/test/goldens/memory_chart_fixed_live.png b/packages/devtools_app/test/goldens/memory_chart_fixed_live.png index f5069cde8bc..9be0aaae597 100644 Binary files a/packages/devtools_app/test/goldens/memory_chart_fixed_live.png and b/packages/devtools_app/test/goldens/memory_chart_fixed_live.png differ diff --git a/packages/devtools_app/test/goldens/memory_chart_scaled_all.png b/packages/devtools_app/test/goldens/memory_chart_scaled_all.png index 4a5b9a14121..e1c8223dd85 100644 Binary files a/packages/devtools_app/test/goldens/memory_chart_scaled_all.png and b/packages/devtools_app/test/goldens/memory_chart_scaled_all.png differ diff --git a/packages/devtools_app/test/goldens/memory_chart_scaled_five_minute.png b/packages/devtools_app/test/goldens/memory_chart_scaled_five_minute.png index e6d7ae92f67..963570cbef1 100644 Binary files a/packages/devtools_app/test/goldens/memory_chart_scaled_five_minute.png and b/packages/devtools_app/test/goldens/memory_chart_scaled_five_minute.png differ diff --git a/packages/devtools_app/test/goldens/memory_chart_scaled_live.png b/packages/devtools_app/test/goldens/memory_chart_scaled_live.png index 4c329d6958b..84b347b6272 100644 Binary files a/packages/devtools_app/test/goldens/memory_chart_scaled_live.png and b/packages/devtools_app/test/goldens/memory_chart_scaled_live.png differ