diff --git a/charts_web/macos/Flutter/GeneratedPluginRegistrant.swift b/charts_web/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..cccf817 --- /dev/null +++ b/charts_web/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,10 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { +} diff --git a/charts_web/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/charts_web/macos/Flutter/ephemeral/Flutter-Generated.xcconfig new file mode 100644 index 0000000..dd433a4 --- /dev/null +++ b/charts_web/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -0,0 +1,11 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=/Users/snoopy/fvm/versions/stable +FLUTTER_APPLICATION_PATH=/Users/snoopy/Documents/infinum/flutter-charts/charts_web +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=1.0.0 +FLUTTER_BUILD_NUMBER=1 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/charts_web/macos/Flutter/ephemeral/flutter_export_environment.sh b/charts_web/macos/Flutter/ephemeral/flutter_export_environment.sh new file mode 100755 index 0000000..e02c3c1 --- /dev/null +++ b/charts_web/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=/Users/snoopy/fvm/versions/stable" +export "FLUTTER_APPLICATION_PATH=/Users/snoopy/Documents/infinum/flutter-charts/charts_web" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_BUILD_NAME=1.0.0" +export "FLUTTER_BUILD_NUMBER=1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=true" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/example/android/build.gradle b/example/android/build.gradle index 4256f91..0a2d6a1 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -26,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 94adc3a..9410ec1 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,3 +1,3 @@ -org.gradle.jvmargs=-Xmx1536M +org.gradle.jvmargs=-Xmx1536M --add-exports=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED android.useAndroidX=true android.enableJetifier=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index bc6a58a..cfe88f6 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip diff --git a/example/lib/charts/scrollable_chart_screen.dart b/example/lib/charts/scrollable_chart_screen.dart index 278b58b..3fc4e2e 100644 --- a/example/lib/charts/scrollable_chart_screen.dart +++ b/example/lib/charts/scrollable_chart_screen.dart @@ -35,7 +35,9 @@ class _ScrollableChartScreenState extends State { final Random _rand = Random(); final double _difference = _rand.nextDouble() * 15; - targetMax = 3 + ((_rand.nextDouble() * _difference * 0.75) - (_difference * 0.25)).roundToDouble(); + targetMax = 3 + + ((_rand.nextDouble() * _difference * 0.75) - (_difference * 0.25)) + .roundToDouble(); _values.addAll(List.generate(minItems, (index) { return 2 + _rand.nextDouble() * _difference; })); @@ -56,7 +58,10 @@ class _ScrollableChartScreenState extends State { final targetArea = TargetAreaDecoration( targetMax: targetMax + 2, targetMin: targetMax, - colorOverTarget: Theme.of(context).colorScheme.error.withOpacity(_showBars ? 1.0 : 0.0), + colorOverTarget: Theme.of(context) + .colorScheme + .error + .withOpacity(_showBars ? 1.0 : 0.0), targetAreaFillColor: Theme.of(context).colorScheme.error.withOpacity(0.2), targetLineColor: Theme.of(context).colorScheme.error, targetAreaRadius: BorderRadius.circular(12.0), @@ -73,7 +78,11 @@ class _ScrollableChartScreenState extends State { barItemBuilder: (data) { return BarItem( color: targetArea.getTargetItemColor( - Theme.of(context).colorScheme.primary.withOpacity(_showBars ? 1.0 : 0.0), data.item), + Theme.of(context) + .colorScheme + .primary + .withOpacity(_showBars ? 1.0 : 0.0), + data.item), radius: const BorderRadius.vertical( top: Radius.circular(24.0), ), @@ -81,7 +90,8 @@ class _ScrollableChartScreenState extends State { }, ), behaviour: ChartBehaviour( - scrollSettings: _isScrollable ? ScrollSettings() : ScrollSettings.none(), + scrollSettings: + _isScrollable ? ScrollSettings() : ScrollSettings.none(), onItemClicked: (item) { print('Clciked'); setState(() { @@ -100,13 +110,15 @@ class _ScrollableChartScreenState extends State { endWithChart: false, lineWidth: 2.0, axisStep: 2, - lineColor: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.2), + lineColor: + Theme.of(context).colorScheme.primaryContainer.withOpacity(0.2), ), VerticalAxisDecoration( endWithChart: false, lineWidth: 2.0, axisStep: 7, - lineColor: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.8), + lineColor: + Theme.of(context).colorScheme.primaryContainer.withOpacity(0.8), ), GridDecoration( showVerticalGrid: true, @@ -116,12 +128,15 @@ class _ScrollableChartScreenState extends State { verticalAxisStep: 1, horizontalAxisStep: 1, textStyle: Theme.of(context).textTheme.caption, - gridColor: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.2), + gridColor: + Theme.of(context).colorScheme.primaryContainer.withOpacity(0.2), ), targetArea, SparkLineDecoration( fill: true, - lineColor: Theme.of(context).primaryColor.withOpacity(!_showBars ? 0.2 : 0.0), + lineColor: Theme.of(context) + .primaryColor + .withOpacity(!_showBars ? 0.2 : 0.0), smoothPoints: _smoothPoints, ), ], @@ -129,12 +144,16 @@ class _ScrollableChartScreenState extends State { ValueDecoration( alignment: _showBars ? Alignment.bottomCenter : Alignment(0.0, -1.0), textStyle: Theme.of(context).textTheme.button!.copyWith( - color: (_showBars ? Theme.of(context).colorScheme.onPrimary : Theme.of(context).colorScheme.primary) + color: (_showBars + ? Theme.of(context).colorScheme.onPrimary + : Theme.of(context).colorScheme.primary) .withOpacity(_isScrollable ? 1.0 : 0.0)), ), SparkLineDecoration( lineWidth: 2.0, - lineColor: Theme.of(context).primaryColor.withOpacity(!_showBars ? 1.0 : 0.0), + lineColor: Theme.of(context) + .primaryColor + .withOpacity(!_showBars ? 1.0 : 0.0), smoothPoints: _smoothPoints, ), BorderDecoration( @@ -155,10 +174,13 @@ class _ScrollableChartScreenState extends State { border: Border.all(), shape: BoxShape.circle, ), - child: Text('${_selected != null ? _values[_selected!].toStringAsPrecision(2) : '...'}'), + child: Text( + '${_selected != null ? _values[_selected!].toStringAsPrecision(2) : '...'}'), ), ), - backgroundColor: Theme.of(context).scaffoldBackgroundColor.withOpacity(_isScrollable ? 0.5 : 0.8), + backgroundColor: Theme.of(context) + .scaffoldBackgroundColor + .withOpacity(_isScrollable ? 0.5 : 0.8), ), ], ); @@ -177,7 +199,9 @@ class _ScrollableChartScreenState extends State { children: [ Expanded( child: SingleChildScrollView( - physics: _isScrollable ? ScrollPhysics() : NeverScrollableScrollPhysics(), + physics: _isScrollable + ? ScrollPhysics() + : NeverScrollableScrollPhysics(), controller: _controller, scrollDirection: Axis.horizontal, child: AnimatedChart( @@ -191,13 +215,17 @@ class _ScrollableChartScreenState extends State { AnimatedContainer( duration: Duration(milliseconds: 350), decoration: BoxDecoration( - gradient: LinearGradient(begin: Alignment.centerRight, end: Alignment.centerLeft, colors: [ - Colors.white, - Colors.white.withOpacity(0.0), - ], stops: [ - 0.5, - 1.0 - ]), + gradient: LinearGradient( + begin: Alignment.centerRight, + end: Alignment.centerLeft, + colors: [ + Colors.white, + Colors.white.withOpacity(0.0), + ], + stops: [ + 0.5, + 1.0 + ]), ), width: _fixedAxis ? 34.0 : 0.0, height: MediaQuery.of(context).size.height * 0.4, @@ -211,10 +239,14 @@ class _ScrollableChartScreenState extends State { showValues: true, endWithChart: false, axisValue: (value) => '$value E', - legendFontStyle: Theme.of(context).textTheme.caption, + legendFontStyle: + Theme.of(context).textTheme.caption, valuesAlign: TextAlign.center, valuesPadding: const EdgeInsets.only(right: 8.0), - lineColor: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.8), + lineColor: Theme.of(context) + .colorScheme + .primaryContainer + .withOpacity(0.8), ) ] : [], diff --git a/example/lib/issue_repro.dart b/example/lib/issue_repro.dart index fbf1d9d..1b25709 100644 --- a/example/lib/issue_repro.dart +++ b/example/lib/issue_repro.dart @@ -1,54 +1,224 @@ import 'package:charts_painter/chart.dart'; import 'package:flutter/material.dart'; +const double axisWidth = 80.0; + void main() { runApp(MaterialApp( home: Scaffold( - backgroundColor: Colors.white, - body: ChartTest(), + body: LineChart(), ), )); } -class ChartTest extends StatelessWidget { - ChartTest({Key? key}) : super(key: key); +class LineChart extends StatelessWidget { + final bool useAxis; + + LineChart({Key? key, this.useAxis = true}) : super(key: key); + + final List>> _mappedValues = [ + [ + ChartItem(32.0), + ChartItem(35.0), + ChartItem(38.0), + ChartItem(33.0), + ChartItem(36.0) + ] + ]; @override Widget build(BuildContext context) { - final byCount = [5, 6, 4, 8, 6, 4, 1, 2, 3, 7, 9, 4, 2]; - - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 128.0), - child: Chart( - state: ChartState( - data: ChartData( - [ - byCount.map((e) => ChartItem(e.toDouble())).toList(), - // byCount.map((e) => BarValue(e.toDouble())).toList() - ], - ), - itemOptions: BarItemOptions(), - // itemOptions: BarItemOptions( - // padding: const EdgeInsets.symmetric(horizontal: 2), - // color: Colors.blue, - // ), - backgroundDecorations: [ - GridDecoration( - showHorizontalGrid: false, - showVerticalGrid: false, - showVerticalValues: true, - verticalLegendPosition: VerticalLegendPosition.top, - verticalAxisValueFromIndex: (idx) => '${idx + 1}', - gridWidth: 2, - textStyle: Theme.of(context).textTheme.subtitle2!.copyWith(fontSize: 8, fontWeight: FontWeight.bold), - gridColor: Theme.of(context).dividerColor, + return SizedBox( + height: MediaQuery.of(context).size.height / 2, + child: SafeArea( + child: Row( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 32), + child: AnimatedContainer( + duration: const Duration(milliseconds: 350), + width: axisWidth, + child: DecorationsRenderer( + [ + HorizontalAxisDecoration( + asFixedDecoration: true, + lineWidth: 0, + axisStep: 2, + showValues: true, + endWithChart: false, + axisValue: (value) => '$value', + legendFontStyle: Theme.of(context).textTheme.bodyMedium, + valuesAlign: TextAlign.center, + valuesPadding: + const EdgeInsets.only(left: -axisWidth, bottom: -10), + showLines: false, + showTopValue: true, + ) + ], + ChartState( + data: ChartData( + _mappedValues, + axisMin: useAxis ? 32 : null, + axisMax: useAxis ? 38 : null, + dataStrategy: + const DefaultDataStrategy(stackMultipleValues: true), + ), + itemOptions: WidgetItemOptions(widgetItemBuilder: (data) { + return const SizedBox(); + }), + backgroundDecorations: [ + GridDecoration( + showVerticalValues: true, + verticalLegendPosition: VerticalLegendPosition.bottom, + verticalValuesPadding: const EdgeInsets.only(top: 8.0), + verticalAxisStep: 2, + gridWidth: 1, + textStyle: Theme.of(context).textTheme.labelSmall, + ), + ], + ), + ), + ), ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 32), + child: AnimatedChart( + width: MediaQuery.of(context).size.width - axisWidth - 8, + duration: const Duration(milliseconds: 450), + state: ChartState( + data: ChartData( + _mappedValues, + axisMin: useAxis ? 32 : null, + axisMax: useAxis ? 38 : null, + dataStrategy: + const DefaultDataStrategy(stackMultipleValues: true), + ), + itemOptions: WidgetItemOptions(widgetItemBuilder: (data) { + return Stack( + clipBehavior: Clip.none, + children: [ + Container(color: Colors.blue.withOpacity(0.2)), + Positioned( + top: -24, + left: 0, + right: 0, + child: Column( + children: [ + Center( + child: Text(_mappedValues[data.listIndex] + [data.itemIndex] + .max + .toString())) + ], + ), + ), + Positioned( + top: -5, + left: 0, + right: 0, + child: Column( + children: [ + Center( + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: Theme.of(context) + .colorScheme + .primary, + borderRadius: const BorderRadius.all( + Radius.circular(8)), + border: Border.all( + width: 1.4, + color: Theme.of(context) + .colorScheme + .surface)), + ), + ) + ], + ), + ), + ], + ); + }), + foregroundDecorations: [], + backgroundDecorations: [ + GridDecoration( + horizontalAxisStep: 2, + showVerticalGrid: false, + showVerticalValues: true, + verticalLegendPosition: VerticalLegendPosition.bottom, + verticalValuesPadding: const EdgeInsets.only(top: 8.0), + verticalAxisStep: 1, + gridColor: Theme.of(context) + .colorScheme + .outline + .withOpacity(0.3), + dashArray: [8, 8], + gridWidth: 1, + textStyle: Theme.of(context).textTheme.labelSmall, + ), + WidgetDecoration( + widgetDecorationBuilder: (context, chartState, + itemWidth, verticalMultiplier) { + return Padding( + padding: chartState.defaultMargin, + child: Stack( + children: [ + Positioned( + right: 0, + left: 0, + bottom: verticalMultiplier * 3.6, + child: + CustomPaint(painter: DashedLinePainter()), + ), + ], + ), + ); + }, + ), + TargetAreaDecoration( + targetAreaFillColor: Theme.of(context) + .colorScheme + .error + .withOpacity(0.6), + targetLineColor: Colors.transparent, + lineWidth: 0, + targetMax: 34, + targetMin: 0, + ), + SparkLineDecoration( + lineWidth: 2, + lineColor: Theme.of(context).colorScheme.primary, + smoothPoints: true, + listIndex: 0, + ), + ], + ), + ), + ), + ) ], - // foregroundDecorations: [ - // HorizontalAxisDecoration(lineColor: Colors.brown), - // ], ), ), ); } } + +class DashedLinePainter extends CustomPainter { + @override + void paint(Canvas canvas, Size size) { + double dashWidth = 8, dashSpace = 8, startX = 0; + final paint = Paint() + ..color = Colors.blue + ..strokeWidth = 1; + while (startX < size.width) { + canvas.drawLine(Offset(startX, 0), Offset(startX + dashWidth, 0), paint); + startX += dashWidth + dashSpace; + } + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) => false; +} diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..cccf817 --- /dev/null +++ b/example/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,10 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { +} diff --git a/example/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/example/macos/Flutter/ephemeral/Flutter-Generated.xcconfig new file mode 100644 index 0000000..bcd42ee --- /dev/null +++ b/example/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -0,0 +1,11 @@ +// This is a generated file; do not edit or check into version control. +FLUTTER_ROOT=/Users/snoopy/fvm/versions/stable +FLUTTER_APPLICATION_PATH=/Users/snoopy/Documents/infinum/flutter-charts/example +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=1.0.0 +FLUTTER_BUILD_NUMBER=1 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/example/macos/Flutter/ephemeral/flutter_export_environment.sh b/example/macos/Flutter/ephemeral/flutter_export_environment.sh new file mode 100755 index 0000000..3bb4500 --- /dev/null +++ b/example/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# This is a generated file; do not edit or check into version control. +export "FLUTTER_ROOT=/Users/snoopy/fvm/versions/stable" +export "FLUTTER_APPLICATION_PATH=/Users/snoopy/Documents/infinum/flutter-charts/example" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_BUILD_DIR=build" +export "FLUTTER_BUILD_NAME=1.0.0" +export "FLUTTER_BUILD_NUMBER=1" +export "DART_OBFUSCATION=false" +export "TRACK_WIDGET_CREATION=true" +export "TREE_SHAKE_ICONS=false" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/lib/chart/model/theme/item_theme/widget/widget_item_options.dart b/lib/chart/model/theme/item_theme/widget/widget_item_options.dart index 72c7e6a..7a3e72f 100644 --- a/lib/chart/model/theme/item_theme/widget/widget_item_options.dart +++ b/lib/chart/model/theme/item_theme/widget/widget_item_options.dart @@ -1,8 +1,8 @@ part of charts_painter; // Hidden because it's only used if chart item is a widget. -GeometryPainter _emptyPainter( - ChartItem item, ChartData data, ItemOptions itemOptions, DrawDataItem drawDataItem) => +GeometryPainter _emptyPainter(ChartItem item, ChartData data, + ItemOptions itemOptions, DrawDataItem drawDataItem) => _EmptyGeometryPainter(item, data, itemOptions); typedef WidgetItemBuilder = Widget Function(ItemBuilderData); @@ -68,8 +68,12 @@ class WidgetItemOptions extends ItemOptions { @override ItemOptions animateTo(ItemOptions endValue, double t) { return WidgetItemOptions._lerp( - widgetItemBuilder: endValue is WidgetItemOptions ? endValue.widgetItemBuilder : widgetItemBuilder, - multiValuePadding: EdgeInsets.lerp(multiValuePadding, endValue.multiValuePadding, t) ?? EdgeInsets.zero, + widgetItemBuilder: endValue is WidgetItemOptions + ? endValue.widgetItemBuilder + : widgetItemBuilder, + multiValuePadding: + EdgeInsets.lerp(multiValuePadding, endValue.multiValuePadding, t) ?? + EdgeInsets.zero, ); } } diff --git a/lib/chart/render/data_renderer/chart_linear_data_renderer.dart b/lib/chart/render/data_renderer/chart_linear_data_renderer.dart index 53f762a..7d58278 100644 --- a/lib/chart/render/data_renderer/chart_linear_data_renderer.dart +++ b/lib/chart/render/data_renderer/chart_linear_data_renderer.dart @@ -201,8 +201,11 @@ class _ChartLinearItemRenderer extends ChartItemRenderer childParentData.offset = offset + // Current chart offset // Item offset in the list - Offset(itemWidth * currentValue, - size.height - ((child.item.max ?? 0.0) * _verticalMultiplier)) + + Offset( + itemWidth * currentValue, + size.height - + ((child.item.max ?? 0.0) * _verticalMultiplier) + + (chartState.data.minValue * _verticalMultiplier)) + // MultiValuePadding offset Offset(_multiValuePadding.left * _stack, 0); @@ -217,10 +220,10 @@ class _ChartLinearItemRenderer extends ChartItemRenderer } final innerConstraints = BoxConstraints.tightFor( - width: _stackWidth, - height: ((child.item.max ?? 0.0) * _verticalMultiplier) - - (bottomPaddingHeight * _verticalMultiplier), - ); + width: _stackWidth, + height: ((child.item.max ?? 0.0) * _verticalMultiplier) - + (bottomPaddingHeight * _verticalMultiplier) - + (chartState.data.minValue * _verticalMultiplier)); child.layout(innerConstraints, parentUsesSize: true); } diff --git a/lib/chart/render/decorations/renderer/chart_decoration_renderer.dart b/lib/chart/render/decorations/renderer/chart_decoration_renderer.dart index 406de5c..b4c0c10 100644 --- a/lib/chart/render/decorations/renderer/chart_decoration_renderer.dart +++ b/lib/chart/render/decorations/renderer/chart_decoration_renderer.dart @@ -1,8 +1,7 @@ part of charts_painter; class ChartDecorationRenderer extends LeafRenderObjectWidget { - ChartDecorationRenderer(this.chartState, this.decorationPainter, {Key? key}) - : super(key: key); + ChartDecorationRenderer(this.chartState, this.decorationPainter, {Key? key}) : super(key: key); final ChartState chartState; final DecorationPainter decorationPainter; @@ -13,8 +12,7 @@ class ChartDecorationRenderer extends LeafRenderObjectWidget { } @override - void updateRenderObject( - BuildContext context, _RenderChartDecoration renderObject) { + void updateRenderObject(BuildContext context, _RenderChartDecoration renderObject) { renderObject ..chartState = chartState ..item = decorationPainter; @@ -82,6 +80,8 @@ class _RenderChartDecoration extends RenderBox { void paint(PaintingContext context, Offset offset) { final canvas = context.canvas; canvas.save(); + + // Clip out of bounds decorations canvas.translate(offset.dx, offset.dy); _decoration.draw(canvas, size, _chartState); diff --git a/lib/chart/render/decorations/target_decoration.dart b/lib/chart/render/decorations/target_decoration.dart index 230d6e2..0eb587e 100644 --- a/lib/chart/render/decorations/target_decoration.dart +++ b/lib/chart/render/decorations/target_decoration.dart @@ -1,19 +1,14 @@ part of charts_painter; /// Check iv item is inside the target -bool _isInTarget(double? max, - {double? min, - double? targetMin, - double? targetMax, - bool inclusive = true}) { +bool _isInTarget(double? max, {double? min, double? targetMin, double? targetMax, bool inclusive = true}) { if (targetMin == null && targetMax == null) { return true; } final _min = min ?? max; - if ((targetMin != null && _min! <= targetMin) || - (targetMax != null && max! >= targetMax)) { + if ((targetMin != null && _min! <= targetMin) || (targetMax != null && max! >= targetMax)) { // Check if target is inclusive, don't show error color in that case if (inclusive && (_min == targetMin || max == targetMax)) { return true; @@ -25,14 +20,10 @@ bool _isInTarget(double? max, return true; } -Color _getColorForTarget(Color color, Color? colorOverTarget, - bool isTargetInclusive, double? targetMin, double? targetMax, double? max, +Color _getColorForTarget( + Color color, Color? colorOverTarget, bool isTargetInclusive, double? targetMin, double? targetMax, double? max, [double? min]) { - return _isInTarget(max, - min: min, - targetMax: targetMax, - targetMin: targetMin, - inclusive: isTargetInclusive) + return _isInTarget(max, min: min, targetMax: targetMax, targetMin: targetMin, inclusive: isTargetInclusive) ? color : (colorOverTarget ?? color); } @@ -44,8 +35,7 @@ Color _getColorForTarget(Color color, Color? colorOverTarget, /// /// In order to change the color of item when it didn't meet the target /// criteria, you will need to add [getTargetItemColor] to [ItemOptions.colorForValue] -@Deprecated( - 'You can make this decoration and much more using WidgetDecoration. Check migration guide for more info') +@Deprecated('You can make this decoration and much more using WidgetDecoration. Check migration guide for more info') class TargetLineDecoration extends DecorationPainter { /// Constructor for target line decoration /// @@ -86,31 +76,22 @@ class TargetLineDecoration extends DecorationPainter { /// Pass this to [ItemOptions.colorForValue] and chart will update item colors /// based on target line Color getTargetItemColor(Color defaultColor, ChartItem item) => - _getColorForTarget(defaultColor, colorOverTarget, isTargetInclusive, - target, null, item.max, item.min); + _getColorForTarget(defaultColor, colorOverTarget, isTargetInclusive, target, null, item.max, item.min); @override Offset applyPaintTransform(ChartState state, Size size) { - final _size = - (state.defaultPadding + state.defaultMargin).deflateSize(size); + final _size = (state.defaultPadding + state.defaultMargin).deflateSize(size); final _maxValue = state.data.maxValue - state.data.minValue; final scale = _size.height / _maxValue; final _minValue = state.data.minValue * scale; - return Offset( - state.defaultMargin.left, - (_size.height - (lineWidth / 2)) - - scale * (target ?? 0) + - _minValue + - state.defaultMargin.top); + return Offset(state.defaultMargin.left, + (_size.height - (lineWidth / 2)) - scale * (target ?? 0) + _minValue + state.defaultMargin.top); } @override Size layoutSize(BoxConstraints constraints, ChartState state) { - return Size( - (constraints.maxWidth - - (state.defaultPadding.horizontal + state.defaultMargin.horizontal)), - lineWidth); + return Size((constraints.maxWidth - (state.defaultPadding.horizontal + state.defaultMargin.horizontal)), lineWidth); } @override @@ -141,13 +122,11 @@ class TargetLineDecoration extends DecorationPainter { TargetLineDecoration animateTo(DecorationPainter endValue, double t) { if (endValue is TargetLineDecoration) { return TargetLineDecoration( - targetLineColor: - Color.lerp(targetLineColor, endValue.targetLineColor, t), + targetLineColor: Color.lerp(targetLineColor, endValue.targetLineColor, t), lineWidth: lerpDouble(lineWidth, endValue.lineWidth, t) ?? 2.0, dashArray: t < 0.5 ? dashArray : endValue.dashArray, target: lerpDouble(target, endValue.target, t), - colorOverTarget: - Color.lerp(colorOverTarget, endValue.colorOverTarget, t), + colorOverTarget: Color.lerp(colorOverTarget, endValue.colorOverTarget, t), ); } @@ -174,8 +153,7 @@ class TargetAreaDecoration extends DecorationPainter { this.areaPadding = EdgeInsets.zero, this.targetAreaRadius, this.targetAreaFillColor, - }) : assert(areaPadding.vertical == 0, - 'Vertical padding cannot be applied here!'); + }) : assert(areaPadding.vertical == 0, 'Vertical padding cannot be applied here!'); /// Dash pattern for the line, if left empty line will be solid final List? dashArray; @@ -214,38 +192,36 @@ class TargetAreaDecoration extends DecorationPainter { /// Pass this to [ItemOptions.colorForValue] and chart will update item colors /// based on target area Color getTargetItemColor(Color defaultColor, ChartItem item) => - _getColorForTarget(defaultColor, colorOverTarget, isTargetInclusive, - targetMin, targetMax, item.max, item.min); + _getColorForTarget(defaultColor, colorOverTarget, isTargetInclusive, targetMin, targetMax, item.max, item.min); @override Size layoutSize(BoxConstraints constraints, ChartState state) { - final _size = (state.defaultPadding + state.defaultMargin) - .deflateSize(constraints.biggest); + final _size = (state.defaultPadding + state.defaultMargin).deflateSize(constraints.biggest); final _maxValue = state.data.maxValue - state.data.minValue; final scale = _size.height / _maxValue; final _minValue = state.data.minValue * scale; - return Rect.fromPoints( + final rect = Rect.fromPoints( + Offset(constraints.maxWidth, -scale * (max(state.data.minValue, targetMin)) + _minValue + areaPadding.vertical), Offset(0.0, -scale * targetMax + _minValue + areaPadding.vertical), - Offset(constraints.maxWidth, -scale * targetMin + _minValue), - ).size; + ); + + return Size( + constraints.maxWidth - + (state.defaultPadding.horizontal + state.defaultMargin.horizontal - marginNeeded().horizontal), + min(rect.size.height, constraints.maxHeight), + ); } @override Offset applyPaintTransform(ChartState state, Size size) { - final _size = - (state.defaultPadding + state.defaultMargin).deflateSize(size); + final _size = (state.defaultPadding + state.defaultMargin).deflateSize(size); final _maxValue = state.data.maxValue - state.data.minValue; final scale = _size.height / _maxValue; final _minValue = state.data.minValue * scale; - return Offset( - areaPadding.left, - _size.height - - scale * targetMax + - _minValue + - state.defaultMargin.top + - state.defaultPadding.top); + return Offset(areaPadding.left, + _size.height - scale * targetMax + _minValue + state.defaultMargin.top + state.defaultPadding.top); } @override @@ -304,24 +280,15 @@ class TargetAreaDecoration extends DecorationPainter { TargetAreaDecoration animateTo(DecorationPainter endValue, double t) { if (endValue is TargetAreaDecoration) { return TargetAreaDecoration( - targetLineColor: - Color.lerp(targetLineColor, endValue.targetLineColor, t) ?? - endValue.targetLineColor, - lineWidth: - lerpDouble(lineWidth, endValue.lineWidth, t) ?? endValue.lineWidth, + targetLineColor: Color.lerp(targetLineColor, endValue.targetLineColor, t) ?? endValue.targetLineColor, + lineWidth: lerpDouble(lineWidth, endValue.lineWidth, t) ?? endValue.lineWidth, dashArray: t < 0.5 ? dashArray : endValue.dashArray, - targetAreaFillColor: - Color.lerp(targetAreaFillColor, endValue.targetAreaFillColor, t), - targetAreaRadius: - BorderRadius.lerp(targetAreaRadius, endValue.targetAreaRadius, t), + targetAreaFillColor: Color.lerp(targetAreaFillColor, endValue.targetAreaFillColor, t), + targetAreaRadius: BorderRadius.lerp(targetAreaRadius, endValue.targetAreaRadius, t), areaPadding: EdgeInsets.lerp(areaPadding, endValue.areaPadding, t)!, - targetMin: - lerpDouble(targetMin, endValue.targetMin, t) ?? endValue.targetMin, - targetMax: - lerpDouble(targetMax, endValue.targetMax, t) ?? endValue.targetMax, - colorOverTarget: - Color.lerp(colorOverTarget, endValue.colorOverTarget, t) ?? - endValue.colorOverTarget, + targetMin: lerpDouble(targetMin, endValue.targetMin, t) ?? endValue.targetMin, + targetMax: lerpDouble(targetMax, endValue.targetMax, t) ?? endValue.targetMax, + colorOverTarget: Color.lerp(colorOverTarget, endValue.colorOverTarget, t) ?? endValue.colorOverTarget, ); } diff --git a/lib/chart/render/decorations/vertical_axis_decoration.dart b/lib/chart/render/decorations/vertical_axis_decoration.dart index 412e685..910cb8a 100644 --- a/lib/chart/render/decorations/vertical_axis_decoration.dart +++ b/lib/chart/render/decorations/vertical_axis_decoration.dart @@ -127,13 +127,20 @@ class VerticalAxisDecoration extends DecorationPainter { for (var i = 0; i <= _listSize / axisStep; i++) { if (showLines) { final _showValuesTop = legendPosition == VerticalLegendPosition.top - ? -((state.defaultMargin - marginNeeded()).top * (1 - _endWithChart)) + ? -((state.defaultMargin - marginNeeded()).top * + (1 - _endWithChart)) : 0.0; final _showValuesBottom = size.height + - (legendPosition == VerticalLegendPosition.bottom ? ((marginNeeded()).bottom * (1 - _endWithChart)) : 0.0); - - gridPath.moveTo(-marginNeeded().left + lineWidth / 2 + _itemWidth * i * axisStep, _showValuesBottom); - gridPath.lineTo(-marginNeeded().left + lineWidth / 2 + _itemWidth * i * axisStep, _showValuesTop); + (legendPosition == VerticalLegendPosition.bottom + ? ((marginNeeded()).bottom * (1 - _endWithChart)) + : 0.0); + + gridPath.moveTo( + -marginNeeded().left + lineWidth / 2 + _itemWidth * i * axisStep, + _showValuesBottom); + gridPath.lineTo( + -marginNeeded().left + lineWidth / 2 + _itemWidth * i * axisStep, + _showValuesTop); } if (!showValues || i == _listSize / axisStep) { @@ -168,11 +175,14 @@ class VerticalAxisDecoration extends DecorationPainter { _textPainter.paint( canvas, Offset( - state.defaultPadding.left + _itemWidth * i * axisStep + (valuesPadding?.left ?? 0.0), + state.defaultPadding.left + + _itemWidth * i * axisStep + + (valuesPadding?.left ?? 0.0), legendPosition == VerticalLegendPosition.top ? (-(valuesPadding?.bottom ?? 0.0) - _textPainter.height) : ((marginNeeded().inflateSize(size)).height - - ((valuesPadding?.bottom ?? 0.0) + _textPainter.size.height))), + ((valuesPadding?.bottom ?? 0.0) + + _textPainter.size.height))), ); } @@ -189,7 +199,8 @@ class VerticalAxisDecoration extends DecorationPainter { return EdgeInsets.zero; } - final _value = _textHeight('0', legendFontStyle) + (valuesPadding?.vertical ?? 0.0); + final _value = + _textHeight('0', legendFontStyle) + (valuesPadding?.vertical ?? 0.0); final _isBottom = legendPosition == VerticalLegendPosition.bottom; return EdgeInsets.only( @@ -213,19 +224,26 @@ class VerticalAxisDecoration extends DecorationPainter { VerticalAxisDecoration animateTo(DecorationPainter endValue, double t) { if (endValue is VerticalAxisDecoration) { return VerticalAxisDecoration._lerp( - lineColor: Color.lerp(lineColor, endValue.lineColor, t) ?? endValue.lineColor, - lineWidth: lerpDouble(lineWidth, endValue.lineWidth, t) ?? endValue.lineWidth, - axisStep: lerpDouble(axisStep, endValue.axisStep, t) ?? endValue.axisStep, - endWithChart: lerpDouble(_endWithChart, endValue._endWithChart, t) ?? endValue._endWithChart, - valuesPadding: EdgeInsets.lerp(valuesPadding, endValue.valuesPadding, t), + lineColor: + Color.lerp(lineColor, endValue.lineColor, t) ?? endValue.lineColor, + lineWidth: + lerpDouble(lineWidth, endValue.lineWidth, t) ?? endValue.lineWidth, + axisStep: + lerpDouble(axisStep, endValue.axisStep, t) ?? endValue.axisStep, + endWithChart: lerpDouble(_endWithChart, endValue._endWithChart, t) ?? + endValue._endWithChart, + valuesPadding: + EdgeInsets.lerp(valuesPadding, endValue.valuesPadding, t), showLines: t > 0.5 ? endValue.showLines : showLines, dashArray: t < 0.5 ? dashArray : endValue.dashArray, - textScale: lerpDouble(textScale, endValue.textScale, t) ?? endValue.textScale, + textScale: + lerpDouble(textScale, endValue.textScale, t) ?? endValue.textScale, showValues: t > 0.5 ? endValue.showValues : showValues, valuesAlign: t > 0.5 ? endValue.valuesAlign : valuesAlign, valueFromIndex: t > 0.5 ? endValue.valueFromIndex : valueFromIndex, legendPosition: t > 0.5 ? endValue.legendPosition : legendPosition, - legendFontStyle: TextStyle.lerp(legendFontStyle, endValue.legendFontStyle, t), + legendFontStyle: + TextStyle.lerp(legendFontStyle, endValue.legendFontStyle, t), ); } diff --git a/lib/chart/render/geometry/painters/geometry_painter.dart b/lib/chart/render/geometry/painters/geometry_painter.dart index ad54524..abad6cb 100644 --- a/lib/chart/render/geometry/painters/geometry_painter.dart +++ b/lib/chart/render/geometry/painters/geometry_painter.dart @@ -4,7 +4,6 @@ part of charts_painter; /// Chart will slice the canvas and each item is painted has constraints (width / [itemWidth]) * height abstract class GeometryPainter { /// Default constructor for [GeometryPainter] - @mustCallSuper GeometryPainter(this.item, this.data, this.itemOptions); /// Current data of the chart diff --git a/pubspec.yaml b/pubspec.yaml index e8d2bb4..ba58f78 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,25 +1,25 @@ name: charts_painter description: Highly customizable and extendable charts library for flutter made with custom painters -version: 3.1.0 +version: 3.1.1 homepage: https://github.com/infinum/flutter-charts repository: https://github.com/infinum/flutter-charts environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=3.0.0 <4.0.0' flutter: ">=1.17.0" dependencies: flutter: sdk: flutter equatable: ^2.0.5 - collection: ^1.16.0 + collection: ^1.17.2 dev_dependencies: flutter_test: sdk: flutter pedantic: ^1.11.1 - golden_toolkit: ^0.13.0 - lints: ^2.0.1 + golden_toolkit: ^0.15.0 + lints: ^2.1.1 alchemist: git: url: https://github.com/Betterment/alchemist diff --git a/test/flutter_test_config.dart b/test/flutter_test_config.dart index d4ddcaa..e94dd9d 100644 --- a/test/flutter_test_config.dart +++ b/test/flutter_test_config.dart @@ -17,7 +17,6 @@ Future testExecutable(FutureOr Function() testMain) async { brightness: Brightness.light, background: Colors.white, ), - backgroundColor: Colors.white, brightness: Brightness.light, ), ciGoldensConfig: const CiGoldensConfig( diff --git a/test/golden/complex/goldens/ci/complex_multi_charts.png b/test/golden/complex/goldens/ci/complex_multi_charts.png index 3524369..235be4d 100644 Binary files a/test/golden/complex/goldens/ci/complex_multi_charts.png and b/test/golden/complex/goldens/ci/complex_multi_charts.png differ diff --git a/test/golden/complex/goldens/ci/showcase_charts.png b/test/golden/complex/goldens/ci/showcase_charts.png index fd549d1..f57de6c 100644 Binary files a/test/golden/complex/goldens/ci/showcase_charts.png and b/test/golden/complex/goldens/ci/showcase_charts.png differ diff --git a/test/golden/complex/goldens/macos/complex_multi_charts.png b/test/golden/complex/goldens/macos/complex_multi_charts.png index 6e7b6fa..4aaeb80 100644 Binary files a/test/golden/complex/goldens/macos/complex_multi_charts.png and b/test/golden/complex/goldens/macos/complex_multi_charts.png differ diff --git a/test/golden/complex/goldens/macos/showcase_charts.png b/test/golden/complex/goldens/macos/showcase_charts.png index 64c6154..f65478a 100644 Binary files a/test/golden/complex/goldens/macos/showcase_charts.png and b/test/golden/complex/goldens/macos/showcase_charts.png differ diff --git a/test/golden/decoration/goldens/ci/general_grid_decoration_golden.png b/test/golden/decoration/goldens/ci/general_grid_decoration_golden.png index 763cb9b..a41a8d2 100644 Binary files a/test/golden/decoration/goldens/ci/general_grid_decoration_golden.png and b/test/golden/decoration/goldens/ci/general_grid_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/ci/general_horizontal_decoration_golden.png b/test/golden/decoration/goldens/ci/general_horizontal_decoration_golden.png index d873c40..0d09535 100644 Binary files a/test/golden/decoration/goldens/ci/general_horizontal_decoration_golden.png and b/test/golden/decoration/goldens/ci/general_horizontal_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/ci/general_sparkline_decoration_golden.png b/test/golden/decoration/goldens/ci/general_sparkline_decoration_golden.png index 46b8ebc..68682d7 100644 Binary files a/test/golden/decoration/goldens/ci/general_sparkline_decoration_golden.png and b/test/golden/decoration/goldens/ci/general_sparkline_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/ci/general_target_line_text_decoration_golden.png b/test/golden/decoration/goldens/ci/general_target_line_text_decoration_golden.png index c38574f..ac6ae2d 100644 Binary files a/test/golden/decoration/goldens/ci/general_target_line_text_decoration_golden.png and b/test/golden/decoration/goldens/ci/general_target_line_text_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/ci/general_vertical_decoration_golden.png b/test/golden/decoration/goldens/ci/general_vertical_decoration_golden.png index 8c54e6f..c5bfb06 100644 Binary files a/test/golden/decoration/goldens/ci/general_vertical_decoration_golden.png and b/test/golden/decoration/goldens/ci/general_vertical_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/ci/grid_decoration_golden.png b/test/golden/decoration/goldens/ci/grid_decoration_golden.png index 901cd3c..a2b3178 100644 Binary files a/test/golden/decoration/goldens/ci/grid_decoration_golden.png and b/test/golden/decoration/goldens/ci/grid_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/ci/horizontal_decoration_golden.png b/test/golden/decoration/goldens/ci/horizontal_decoration_golden.png index 2ad057a..f445941 100644 Binary files a/test/golden/decoration/goldens/ci/horizontal_decoration_golden.png and b/test/golden/decoration/goldens/ci/horizontal_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/ci/sparkline_decoration_golden.png b/test/golden/decoration/goldens/ci/sparkline_decoration_golden.png index 5f9d7f4..db1afdd 100644 Binary files a/test/golden/decoration/goldens/ci/sparkline_decoration_golden.png and b/test/golden/decoration/goldens/ci/sparkline_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/ci/widget_decoration_golden.png b/test/golden/decoration/goldens/ci/widget_decoration_golden.png index f42e9b1..3d0160f 100644 Binary files a/test/golden/decoration/goldens/ci/widget_decoration_golden.png and b/test/golden/decoration/goldens/ci/widget_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/macos/general_grid_decoration_golden.png b/test/golden/decoration/goldens/macos/general_grid_decoration_golden.png index cda5d16..9340135 100644 Binary files a/test/golden/decoration/goldens/macos/general_grid_decoration_golden.png and b/test/golden/decoration/goldens/macos/general_grid_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/macos/general_horizontal_decoration_golden.png b/test/golden/decoration/goldens/macos/general_horizontal_decoration_golden.png index 4e76d3a..dc76c01 100644 Binary files a/test/golden/decoration/goldens/macos/general_horizontal_decoration_golden.png and b/test/golden/decoration/goldens/macos/general_horizontal_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/macos/general_sparkline_decoration_golden.png b/test/golden/decoration/goldens/macos/general_sparkline_decoration_golden.png index 82ca648..0b20e38 100644 Binary files a/test/golden/decoration/goldens/macos/general_sparkline_decoration_golden.png and b/test/golden/decoration/goldens/macos/general_sparkline_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/macos/general_vertical_decoration_golden.png b/test/golden/decoration/goldens/macos/general_vertical_decoration_golden.png index bfda038..950cc0f 100644 Binary files a/test/golden/decoration/goldens/macos/general_vertical_decoration_golden.png and b/test/golden/decoration/goldens/macos/general_vertical_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/macos/grid_decoration_golden.png b/test/golden/decoration/goldens/macos/grid_decoration_golden.png index 540f864..576d5d7 100644 Binary files a/test/golden/decoration/goldens/macos/grid_decoration_golden.png and b/test/golden/decoration/goldens/macos/grid_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/macos/horizontal_decoration_golden.png b/test/golden/decoration/goldens/macos/horizontal_decoration_golden.png index c1134be..088f89a 100644 Binary files a/test/golden/decoration/goldens/macos/horizontal_decoration_golden.png and b/test/golden/decoration/goldens/macos/horizontal_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/macos/sparkline_decoration_golden.png b/test/golden/decoration/goldens/macos/sparkline_decoration_golden.png index eafedc9..2da2d45 100644 Binary files a/test/golden/decoration/goldens/macos/sparkline_decoration_golden.png and b/test/golden/decoration/goldens/macos/sparkline_decoration_golden.png differ diff --git a/test/golden/decoration/goldens/macos/widget_decoration_golden.png b/test/golden/decoration/goldens/macos/widget_decoration_golden.png index 132e887..d4b5a06 100644 Binary files a/test/golden/decoration/goldens/macos/widget_decoration_golden.png and b/test/golden/decoration/goldens/macos/widget_decoration_golden.png differ diff --git a/test/golden/examples/goldens/ci/bar_chart.png b/test/golden/examples/goldens/ci/bar_chart.png index 43e4986..399b86c 100644 Binary files a/test/golden/examples/goldens/ci/bar_chart.png and b/test/golden/examples/goldens/ci/bar_chart.png differ diff --git a/test/golden/examples/goldens/ci/line_chart.png b/test/golden/examples/goldens/ci/line_chart.png index 4a479c6..3cc4297 100644 Binary files a/test/golden/examples/goldens/ci/line_chart.png and b/test/golden/examples/goldens/ci/line_chart.png differ diff --git a/test/golden/examples/goldens/ci/multi_line_chart.png b/test/golden/examples/goldens/ci/multi_line_chart.png index 084a51d..1159517 100644 Binary files a/test/golden/examples/goldens/ci/multi_line_chart.png and b/test/golden/examples/goldens/ci/multi_line_chart.png differ diff --git a/test/golden/examples/goldens/ci/simple_line_chart.png b/test/golden/examples/goldens/ci/simple_line_chart.png index 277e179..d067949 100644 Binary files a/test/golden/examples/goldens/ci/simple_line_chart.png and b/test/golden/examples/goldens/ci/simple_line_chart.png differ diff --git a/test/golden/examples/goldens/macos/bar_chart.png b/test/golden/examples/goldens/macos/bar_chart.png index 43e4986..399b86c 100644 Binary files a/test/golden/examples/goldens/macos/bar_chart.png and b/test/golden/examples/goldens/macos/bar_chart.png differ diff --git a/test/golden/examples/goldens/macos/line_chart.png b/test/golden/examples/goldens/macos/line_chart.png index 4a479c6..3cc4297 100644 Binary files a/test/golden/examples/goldens/macos/line_chart.png and b/test/golden/examples/goldens/macos/line_chart.png differ diff --git a/test/golden/examples/goldens/macos/multi_line_chart.png b/test/golden/examples/goldens/macos/multi_line_chart.png index 084a51d..1159517 100644 Binary files a/test/golden/examples/goldens/macos/multi_line_chart.png and b/test/golden/examples/goldens/macos/multi_line_chart.png differ diff --git a/test/golden/examples/goldens/macos/simple_line_chart.png b/test/golden/examples/goldens/macos/simple_line_chart.png index 277e179..d067949 100644 Binary files a/test/golden/examples/goldens/macos/simple_line_chart.png and b/test/golden/examples/goldens/macos/simple_line_chart.png differ diff --git a/test/golden/geometry/goldens/ci/bubble_geometry_golden.png b/test/golden/geometry/goldens/ci/bubble_geometry_golden.png index 5fe0213..203a876 100644 Binary files a/test/golden/geometry/goldens/ci/bubble_geometry_golden.png and b/test/golden/geometry/goldens/ci/bubble_geometry_golden.png differ diff --git a/test/golden/geometry/goldens/ci/widget_geometry_golden.png b/test/golden/geometry/goldens/ci/widget_geometry_golden.png index 1a7708f..ac648af 100644 Binary files a/test/golden/geometry/goldens/ci/widget_geometry_golden.png and b/test/golden/geometry/goldens/ci/widget_geometry_golden.png differ diff --git a/test/golden/geometry/goldens/macos/bubble_geometry_golden.png b/test/golden/geometry/goldens/macos/bubble_geometry_golden.png index 5fe0213..203a876 100644 Binary files a/test/golden/geometry/goldens/macos/bubble_geometry_golden.png and b/test/golden/geometry/goldens/macos/bubble_geometry_golden.png differ diff --git a/test/golden/issues/goldens/ci/issue_94.png b/test/golden/issues/goldens/ci/issue_94.png new file mode 100644 index 0000000..e2beaf6 Binary files /dev/null and b/test/golden/issues/goldens/ci/issue_94.png differ diff --git a/test/golden/issues/goldens/ci/issue_94_1.png b/test/golden/issues/goldens/ci/issue_94_1.png new file mode 100644 index 0000000..cb68f52 Binary files /dev/null and b/test/golden/issues/goldens/ci/issue_94_1.png differ diff --git a/test/golden/issues/goldens/macos/issue_94.png b/test/golden/issues/goldens/macos/issue_94.png new file mode 100644 index 0000000..dfe9e10 Binary files /dev/null and b/test/golden/issues/goldens/macos/issue_94.png differ diff --git a/test/golden/issues/goldens/macos/issue_94_1.png b/test/golden/issues/goldens/macos/issue_94_1.png new file mode 100644 index 0000000..f91b1b5 Binary files /dev/null and b/test/golden/issues/goldens/macos/issue_94_1.png differ diff --git a/test/golden/issues/issues_golden_test.dart b/test/golden/issues/issues_golden_test.dart new file mode 100644 index 0000000..26b89d0 --- /dev/null +++ b/test/golden/issues/issues_golden_test.dart @@ -0,0 +1,405 @@ +import 'package:alchemist/alchemist.dart'; +import 'package:charts_painter/chart.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:golden_toolkit/golden_toolkit.dart'; + +void main() { + setUpAll(() async { + await loadAppFonts(); + }); + + goldenTest('WidgetDecoration with axisMin', fileName: 'issue_94', + builder: () { + final List>> _mappedValues = [ + [ + ChartItem(2.0), + ChartItem(5.0), + ChartItem(8.0), + ChartItem(3.0), + ChartItem(6.0) + ] + ]; + + return Container( + height: 500, + width: 800, + child: Padding( + padding: EdgeInsets.zero, + child: SizedBox( + height: 500, + child: Row( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 32), + child: AnimatedContainer( + duration: const Duration(milliseconds: 350), + width: 80, + child: DecorationsRenderer( + [ + HorizontalAxisDecoration( + asFixedDecoration: true, + lineWidth: 0, + axisStep: 2, + showValues: true, + endWithChart: false, + axisValue: (value) => '$value', + valuesAlign: TextAlign.center, + valuesPadding: + const EdgeInsets.only(left: -80, bottom: -10), + showLines: false, + showTopValue: true, + legendFontStyle: TextStyle( + fontFamily: 'roboto', + color: Colors.black87, + ), + ) + ], + ChartState( + data: ChartData( + _mappedValues, + axisMin: 2, + axisMax: 8, + dataStrategy: const DefaultDataStrategy( + stackMultipleValues: true), + ), + itemOptions: WidgetItemOptions(widgetItemBuilder: (data) { + return const SizedBox(); + }), + backgroundDecorations: [ + GridDecoration( + showVerticalValues: true, + verticalLegendPosition: VerticalLegendPosition.bottom, + verticalValuesPadding: + const EdgeInsets.only(top: 8.0), + verticalAxisStep: 2, + gridWidth: 1, + textStyle: TextStyle( + fontFamily: 'roboto', + color: Colors.black87, + ), + ), + ], + ), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 32), + child: AnimatedChart( + width: 800 - 80 - 8, + duration: const Duration(milliseconds: 450), + state: ChartState( + data: ChartData( + _mappedValues, + axisMin: 2, + axisMax: 8, + dataStrategy: const DefaultDataStrategy( + stackMultipleValues: true), + ), + itemOptions: WidgetItemOptions(widgetItemBuilder: (data) { + return Stack( + clipBehavior: Clip.none, + children: [ + Container(color: Colors.blue.withOpacity(0.2)), + Positioned( + top: -24, + left: 0, + right: 0, + child: Column( + children: [ + Center( + child: Text(_mappedValues[data.listIndex] + [data.itemIndex] + .max + .toString())) + ], + ), + ), + Positioned( + top: -5, + left: 0, + right: 0, + child: Column( + children: [ + Center( + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: Colors.blue.withOpacity(0.4), + ), + ), + ) + ], + ), + ), + ], + ); + }), + foregroundDecorations: [], + backgroundDecorations: [ + GridDecoration( + horizontalAxisStep: 2, + showVerticalGrid: false, + showVerticalValues: true, + verticalLegendPosition: VerticalLegendPosition.bottom, + verticalValuesPadding: + const EdgeInsets.only(top: 8.0), + verticalAxisStep: 1, + dashArray: [8, 8], + gridWidth: 1, + textStyle: TextStyle( + fontFamily: 'roboto', + color: Colors.black87, + ), + ), + WidgetDecoration( + widgetDecorationBuilder: (context, chartState, + itemWidth, verticalMultiplier) { + return Padding( + padding: (chartState.defaultMargin + + chartState.defaultPadding), + child: Stack( + children: [ + Positioned( + right: 0, + left: 0, + bottom: verticalMultiplier * (3.6 - 2), + child: CustomPaint( + painter: DashedLinePainter()), + ), + ], + ), + ); + }, + ), + TargetAreaDecoration( + targetAreaFillColor: Colors.red.withOpacity(0.6), + targetLineColor: Colors.transparent, + lineWidth: 0, + targetMax: 2.0, + targetMin: 0, + ), + SparkLineDecoration( + lineWidth: 2, + lineColor: Colors.blue, + smoothPoints: true, + listIndex: 0, + ), + ], + ), + ), + ), + ) + ], + ), + ), + ), + ); + }); + goldenTest('WidgetDecoration no axisMin', fileName: 'issue_94_1', + builder: () { + final List>> _mappedValues = [ + [ + ChartItem(2.0), + ChartItem(5.0), + ChartItem(8.0), + ChartItem(3.0), + ChartItem(6.0) + ] + ]; + + return Container( + height: 500, + width: 800, + child: Padding( + padding: EdgeInsets.zero, + child: SizedBox( + height: 500, + child: Row( + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 32), + child: AnimatedContainer( + duration: const Duration(milliseconds: 350), + width: 80, + child: DecorationsRenderer( + [ + HorizontalAxisDecoration( + asFixedDecoration: true, + lineWidth: 0, + axisStep: 2, + showValues: true, + endWithChart: false, + axisValue: (value) => '$value', + valuesAlign: TextAlign.center, + valuesPadding: + const EdgeInsets.only(left: -80, bottom: -10), + showLines: false, + showTopValue: true, + legendFontStyle: TextStyle( + fontFamily: 'roboto', + color: Colors.black87, + ), + ) + ], + ChartState( + data: ChartData( + _mappedValues, + dataStrategy: const DefaultDataStrategy( + stackMultipleValues: true), + ), + itemOptions: WidgetItemOptions(widgetItemBuilder: (data) { + return const SizedBox(); + }), + backgroundDecorations: [ + GridDecoration( + showVerticalValues: true, + verticalLegendPosition: VerticalLegendPosition.bottom, + verticalValuesPadding: + const EdgeInsets.only(top: 8.0), + verticalAxisStep: 2, + gridWidth: 1, + textStyle: TextStyle( + fontFamily: 'roboto', + color: Colors.black87, + ), + ), + ], + ), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 32), + child: AnimatedChart( + width: 800 - 80 - 8, + duration: const Duration(milliseconds: 450), + state: ChartState( + data: ChartData( + _mappedValues, + dataStrategy: const DefaultDataStrategy( + stackMultipleValues: true), + ), + itemOptions: WidgetItemOptions(widgetItemBuilder: (data) { + return Stack( + clipBehavior: Clip.none, + children: [ + Container(color: Colors.blue.withOpacity(0.2)), + Positioned( + top: -24, + left: 0, + right: 0, + child: Column( + children: [ + Center( + child: Text(_mappedValues[data.listIndex] + [data.itemIndex] + .max + .toString())) + ], + ), + ), + Positioned( + top: -5, + left: 0, + right: 0, + child: Column( + children: [ + Center( + child: Container( + width: 10, + height: 10, + decoration: BoxDecoration( + color: Colors.blue.withOpacity(0.4), + ), + ), + ) + ], + ), + ), + ], + ); + }), + foregroundDecorations: [], + backgroundDecorations: [ + GridDecoration( + horizontalAxisStep: 2, + showVerticalGrid: false, + showVerticalValues: true, + verticalLegendPosition: VerticalLegendPosition.bottom, + verticalValuesPadding: + const EdgeInsets.only(top: 8.0), + verticalAxisStep: 1, + dashArray: [8, 8], + gridWidth: 1, + textStyle: TextStyle( + fontFamily: 'roboto', + color: Colors.black87, + ), + ), + WidgetDecoration( + widgetDecorationBuilder: (context, chartState, + itemWidth, verticalMultiplier) { + return Padding( + padding: (chartState.defaultMargin + + chartState.defaultPadding), + child: Stack( + children: [ + Positioned( + right: 0, + left: 0, + bottom: verticalMultiplier * 3.6, + child: CustomPaint( + painter: DashedLinePainter()), + ), + ], + ), + ); + }, + ), + TargetAreaDecoration( + targetAreaFillColor: Colors.red.withOpacity(0.6), + targetLineColor: Colors.transparent, + lineWidth: 0, + targetMax: 2.0, + targetMin: 0, + ), + SparkLineDecoration( + lineWidth: 2, + lineColor: Colors.blue, + smoothPoints: true, + listIndex: 0, + ), + ], + ), + ), + ), + ) + ], + ), + ), + ), + ); + }); +} + +class DashedLinePainter extends CustomPainter { + @override + void paint(Canvas canvas, Size size) { + double dashWidth = 8, dashSpace = 8, startX = 0; + final paint = Paint() + ..color = Colors.blue + ..strokeWidth = 1; + while (startX < size.width) { + canvas.drawLine(Offset(startX, 0), Offset(startX + dashWidth, 0), paint); + startX += dashWidth + dashSpace; + } + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) => false; +}