From a18e249030be98e7c5d45b944f8bd5e8a33769df Mon Sep 17 00:00:00 2001 From: Afroz-Shaikh Date: Tue, 14 May 2024 19:31:49 +0530 Subject: [PATCH 1/7] Add:TrackLabel Formatter for Linear Gauge --- example/lib/main.dart | 56 ++++++++++++++----- .../linear_gauge_container.dart | 14 +++++ lib/src/linear_gauge/linear_gauge.dart | 16 ++++++ lib/src/linear_gauge/linear_gauge_label.dart | 10 +++- .../linear_gauge/linear_gauge_painter.dart | 10 ++++ 5 files changed, 90 insertions(+), 16 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 30e7c13b..70b4f015 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,12 +1,15 @@ import 'package:example/gauge_vertical.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:geekyants_flutter_gauges/geekyants_flutter_gauges.dart'; +// import 'package:syncfusion_flutter_gauges/gauges.dart'; +import 'package:intl/intl.dart'; void main() { runApp( const MaterialApp( debugShowCheckedModeBanner: false, - home: MyVerticalGauge(), + home: LinearGaugeExample(), ), ); } @@ -23,21 +26,41 @@ class LinearGaugeExample extends StatefulWidget { } class _LinearGaugeExampleState extends State { + NumberFormat formatter = + NumberFormat.currency(locale: 'en_US', name: 'Rupees'); + @override Widget build(BuildContext context) { return Scaffold( body: Center( - child: LinearGauge( - gaugeOrientation: GaugeOrientation.horizontal, - enableGaugeAnimation: true, - rulers: RulerStyle( - rulerPosition: RulerPosition.bottom, - ), - pointers: const [ - Pointer( - value: 50, - shape: PointerShape.circle, + child: Column( + children: [ + LinearGauge( + trackLabelFormat: (value) { + return '\$ ${value.toStringAsFixed(1)}'; + }, + // numberFormat: + // NumberFormat.currency(decimalDigits: 1, symbol: 'F'), + start: -70.33, + end: 62.4444, + gaugeOrientation: GaugeOrientation.horizontal, + enableGaugeAnimation: true, + rulers: RulerStyle( + rulerPosition: RulerPosition.bottom, + ), + pointers: const [ + Pointer( + value: 50, + shape: PointerShape.circle, + ), + ], ), + // SfLinearGauge( + // showAxisTrack: true, + // minimum: -70.333333, + // numberFormat: NumberFormat.currency(decimalDigits: 1, symbol: ''), + // maximum: 62.4, + // ) ], ), ), @@ -60,12 +83,17 @@ class RadialGaugeExample extends StatefulWidget { class _RadialGaugeExampleState extends State { @override Widget build(BuildContext context) { - return const Scaffold( + return Scaffold( backgroundColor: Colors.white, body: RadialGauge( track: RadialTrack( - start: 0, - end: 100, + // trackLabelFormater: (value) { + // return NumberFormat.currency( + // locale: 'en_US', name: 'R', decimalDigits: 3) + // .format(value); + // }, + start: -70.33, + end: 62.4444, ), needlePointer: [ NeedlePointer( diff --git a/lib/src/linear_gauge/gauge_container/linear_gauge_container.dart b/lib/src/linear_gauge/gauge_container/linear_gauge_container.dart index 15486ee9..a39010e6 100644 --- a/lib/src/linear_gauge/gauge_container/linear_gauge_container.dart +++ b/lib/src/linear_gauge/gauge_container/linear_gauge_container.dart @@ -19,6 +19,8 @@ class LinearGaugeContainer extends LeafRenderObjectWidget { return RenderLinearGaugeContainer( start: linearGauge.start!, end: linearGauge.end!, + trackLabelFormater: linearGauge.trackLabelFormat ?? + (double value) => ((value * 10).round() / 10).toString(), value: linearGauge.value!, steps: linearGauge.steps!, gaugeOrientation: linearGauge.gaugeOrientation!, @@ -59,6 +61,7 @@ class LinearGaugeContainer extends LeafRenderObjectWidget { renderObject ..setStart = linearGauge.start! ..setEnd = linearGauge.end! + ..setTrackLabelFormater = linearGauge.trackLabelFormat! ..setValue = linearGauge.value! ..setSteps = linearGauge.steps! ..setGaugeOrientation = linearGauge.gaugeOrientation! @@ -98,6 +101,7 @@ class RenderLinearGaugeContainer extends RenderBox { RenderLinearGaugeContainer({ required double start, required double end, + required final String Function(double)? trackLabelFormater, required double steps, required double value, required GaugeOrientation gaugeOrientation, @@ -130,6 +134,7 @@ class RenderLinearGaugeContainer extends RenderBox { required LinearGradient? linearGradient, }) : _start = start, _end = end, + _trackLabelFormater = trackLabelFormater, _value = value, _steps = steps, _gaugeOrientation = gaugeOrientation, @@ -195,6 +200,14 @@ class RenderLinearGaugeContainer extends RenderBox { markNeedsPaint(); } + get getTrackLabelFormater => _trackLabelFormater; + String Function(double)? _trackLabelFormater; + set setTrackLabelFormater(String Function(double)? trackLabelFormater) { + if (_trackLabelFormater == trackLabelFormater) return; + _trackLabelFormater = trackLabelFormater; + markNeedsPaint(); + } + double get getValue => _value; double _value; set setValue(double val) { @@ -700,6 +713,7 @@ class RenderLinearGaugeContainer extends RenderBox { } _linearGaugeLabel.addLabels( + trackLableFormatter: getTrackLabelFormater, distanceValueInRangeOfHundred: getSteps == 0.0 ? interval : getSteps, start: getStart, end: getEnd, diff --git a/lib/src/linear_gauge/linear_gauge.dart b/lib/src/linear_gauge/linear_gauge.dart index 0b45332b..472d1cef 100644 --- a/lib/src/linear_gauge/linear_gauge.dart +++ b/lib/src/linear_gauge/linear_gauge.dart @@ -45,6 +45,7 @@ class LinearGauge extends StatefulWidget { this.start = 0, this.end = 100, this.steps = 0, + this.trackLabelFormat, @Deprecated('Use ValueBar instead') this.value = 0, this.gaugeOrientation = GaugeOrientation.horizontal, this.showLinearGaugeContainer = true, @@ -144,6 +145,19 @@ class LinearGauge extends StatefulWidget { /// final double? end; + /// + /// `trackLabelFormat` Sets the format of the label of the [LinearGauge] labels + /// + /// ```dart + /// const LinearGauge( + /// trackLabelFormat : value) { + /// return '\$ ${value.toStringAsFixed(1)}'; + /// }, + /// ), + /// ``` + /// + final String Function(double)? trackLabelFormat; + /// /// `steps` Sets the interval between label of the [LinearGauge] Container /// @@ -712,6 +726,7 @@ class _RLinearGauge extends MultiChildRenderObjectWidget { return RenderLinearGauge( start: lGauge.start!, end: lGauge.end!, + trackLabelFormat: lGauge.trackLabelFormat, steps: lGauge.steps!, gaugeOrientation: lGauge.gaugeOrientation!, primaryRulersWidth: lGauge.rulers!.primaryRulersWidth!, @@ -741,6 +756,7 @@ class _RLinearGauge extends MultiChildRenderObjectWidget { BuildContext context, RenderLinearGauge renderObject) { renderObject ..setCustomLabels = lGauge.customLabels! + ..setTrackLabelFormat = lGauge.trackLabelFormat ..setGaugeOrientation = lGauge.gaugeOrientation! ..setPrimaryRulersHeight = lGauge.rulers!.primaryRulersHeight! ..setPrimaryRulersWidth = lGauge.rulers!.primaryRulersWidth! diff --git a/lib/src/linear_gauge/linear_gauge_label.dart b/lib/src/linear_gauge/linear_gauge_label.dart index 140d7a42..e392d298 100644 --- a/lib/src/linear_gauge/linear_gauge_label.dart +++ b/lib/src/linear_gauge/linear_gauge_label.dart @@ -1,3 +1,5 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:geekyants_flutter_gauges/geekyants_flutter_gauges.dart'; import 'package:geekyants_flutter_gauges/src/linear_gauge/gauge_container/linear_gauge_container.dart'; @@ -18,6 +20,7 @@ class LinearGaugeLabel { TextPainter(textDirection: TextDirection.ltr); void addLabels({ + required trackLableFormatter, required double distanceValueInRangeOfHundred, required double start, required double end, @@ -25,13 +28,16 @@ class LinearGaugeLabel { _linearGaugeLabel.clear(); for (double i = start; i <= end; i += distanceValueInRangeOfHundred) { - _linearGaugeLabel.add(LinearGaugeLabel(text: i.toString(), value: i)); + text = trackLableFormatter(i); + + _linearGaugeLabel.add(LinearGaugeLabel(text: text, value: i)); } final LinearGaugeLabel localLabel = _linearGaugeLabel[_linearGaugeLabel.length - 1]; if (localLabel.value != end && localLabel.value! < end) { - _linearGaugeLabel.add(LinearGaugeLabel(text: end.toString(), value: end)); + String text = ((end * 10).round() / 10).toString(); + _linearGaugeLabel.add(LinearGaugeLabel(text: text, value: end)); } } diff --git a/lib/src/linear_gauge/linear_gauge_painter.dart b/lib/src/linear_gauge/linear_gauge_painter.dart index 3058d880..5e882390 100644 --- a/lib/src/linear_gauge/linear_gauge_painter.dart +++ b/lib/src/linear_gauge/linear_gauge_painter.dart @@ -18,6 +18,7 @@ class RenderLinearGauge extends RenderBox RenderLinearGauge({ required double start, required double end, + required String Function(double)? trackLabelFormat, required double steps, required GaugeOrientation gaugeOrientation, required TextStyle textStyle, @@ -42,6 +43,7 @@ class RenderLinearGauge extends RenderBox }) : assert(start < end, "Start should be grater then end"), _start = start, _end = end, + _trackLabelFormat = trackLabelFormat, _steps = steps, _gaugeOrientation = gaugeOrientation, _textStyle = textStyle, @@ -267,6 +269,14 @@ class RenderLinearGauge extends RenderBox markNeedsLayout(); } + String Function(double)? get getTrackLabelFormat => _trackLabelFormat; + String Function(double)? _trackLabelFormat; + set setTrackLabelFormat(String Function(double)? val) { + if (_trackLabelFormat == val) return; + _trackLabelFormat = val; + markNeedsPaint(); + } + double get getLabelOffset => _labelOffset; double _labelOffset; set setLabelOffset(double val) { From f8bcca61a032d5a2404c1f64cd8113d432214346 Mon Sep 17 00:00:00 2001 From: Afroz-Shaikh Date: Tue, 14 May 2024 20:20:13 +0530 Subject: [PATCH 2/7] Fix:Double precision issue and rerender issue --- example/lib/main.dart | 74 ++++++------------- .../linear_gauge_container.dart | 6 +- lib/src/linear_gauge/linear_gauge.dart | 2 + .../linear_gauge/linear_gauge_painter.dart | 18 ++++- 4 files changed, 46 insertions(+), 54 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 70b4f015..0b023b05 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,4 +1,7 @@ +import 'dart:developer'; + import 'package:example/gauge_vertical.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:geekyants_flutter_gauges/geekyants_flutter_gauges.dart'; @@ -18,6 +21,7 @@ void main() { /// The following code is a Simple Example of [LinearGauge] Widget. /// You can customize the [LinearGauge] Widget as per your need. /// + class LinearGaugeExample extends StatefulWidget { const LinearGaugeExample({Key? key}) : super(key: key); @@ -26,8 +30,8 @@ class LinearGaugeExample extends StatefulWidget { } class _LinearGaugeExampleState extends State { - NumberFormat formatter = - NumberFormat.currency(locale: 'en_US', name: 'Rupees'); + double startVal = 0.0; + ValueNotifier value = ValueNotifier(0.0); @override Widget build(BuildContext context) { @@ -36,13 +40,8 @@ class _LinearGaugeExampleState extends State { child: Column( children: [ LinearGauge( - trackLabelFormat: (value) { - return '\$ ${value.toStringAsFixed(1)}'; - }, - // numberFormat: - // NumberFormat.currency(decimalDigits: 1, symbol: 'F'), - start: -70.33, - end: 62.4444, + start: startVal, + end: 100, gaugeOrientation: GaugeOrientation.horizontal, enableGaugeAnimation: true, rulers: RulerStyle( @@ -55,52 +54,23 @@ class _LinearGaugeExampleState extends State { ), ], ), - // SfLinearGauge( - // showAxisTrack: true, - // minimum: -70.333333, - // numberFormat: NumberFormat.currency(decimalDigits: 1, symbol: ''), - // maximum: 62.4, - // ) + TextButton( + onPressed: () { + if (startVal == 0.0) { + setState(() { + startVal = 50.0; + }); + } else { + setState(() { + startVal = 0.0; + }); + } + log(startVal.toString()); + }, + child: const Text('Toggle Start')) ], ), ), ); } } - -/// -/// The following code is a Simple Example of [RadialGauge] Widget. -/// You can customize the [RadialGauge] Widget as per your need. -/// - -class RadialGaugeExample extends StatefulWidget { - const RadialGaugeExample({super.key}); - - @override - State createState() => _RadialGaugeExampleState(); -} - -class _RadialGaugeExampleState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, - body: RadialGauge( - track: RadialTrack( - // trackLabelFormater: (value) { - // return NumberFormat.currency( - // locale: 'en_US', name: 'R', decimalDigits: 3) - // .format(value); - // }, - start: -70.33, - end: 62.4444, - ), - needlePointer: [ - NeedlePointer( - value: 30, - ), - ], - ), - ); - } -} diff --git a/lib/src/linear_gauge/gauge_container/linear_gauge_container.dart b/lib/src/linear_gauge/gauge_container/linear_gauge_container.dart index a39010e6..c8d402fa 100644 --- a/lib/src/linear_gauge/gauge_container/linear_gauge_container.dart +++ b/lib/src/linear_gauge/gauge_container/linear_gauge_container.dart @@ -61,7 +61,8 @@ class LinearGaugeContainer extends LeafRenderObjectWidget { renderObject ..setStart = linearGauge.start! ..setEnd = linearGauge.end! - ..setTrackLabelFormater = linearGauge.trackLabelFormat! + ..setTrackLabelFormater = linearGauge.trackLabelFormat ?? + ((double value) => ((value * 10).round() / 10).toString()) ..setValue = linearGauge.value! ..setSteps = linearGauge.steps! ..setGaugeOrientation = linearGauge.gaugeOrientation! @@ -187,6 +188,7 @@ class RenderLinearGaugeContainer extends RenderBox { if (_start == start) return; _start = start; markNeedsPaint(); + markNeedsLayout(); } /// @@ -198,6 +200,7 @@ class RenderLinearGaugeContainer extends RenderBox { if (_end == end) return; _end = end; markNeedsPaint(); + markNeedsLayout(); } get getTrackLabelFormater => _trackLabelFormater; @@ -690,6 +693,7 @@ class RenderLinearGaugeContainer extends RenderBox { } void _calculateRulerPoints() { + print("Called _calculateRulerPoints"); _linearGaugeLabel.calculateStartAndEndLabelSize( getTextStyle, getStart, getEnd, getCustomLabels!, getInversedRulers); if (getCustomLabels!.isEmpty) { diff --git a/lib/src/linear_gauge/linear_gauge.dart b/lib/src/linear_gauge/linear_gauge.dart index 472d1cef..384139f9 100644 --- a/lib/src/linear_gauge/linear_gauge.dart +++ b/lib/src/linear_gauge/linear_gauge.dart @@ -826,6 +826,8 @@ class RenderLinearGaugeElement extends MultiChildRenderObjectElement { renderObject.removeValueBar(child); } else if (child is RenderCurve) { renderObject.removeCurve(child); + } else if (child is RenderRulerLabel) { + renderObject.removeRulerLabel(child); } } } diff --git a/lib/src/linear_gauge/linear_gauge_painter.dart b/lib/src/linear_gauge/linear_gauge_painter.dart index 5e882390..088239f6 100644 --- a/lib/src/linear_gauge/linear_gauge_painter.dart +++ b/lib/src/linear_gauge/linear_gauge_painter.dart @@ -337,9 +337,19 @@ class RenderLinearGauge extends RenderBox } LinearGaugeLabel get getLinearGaugeLabel { + markNeedsPaint(); + markNeedsLayout(); return _linearGaugeLabel; } + LinearGaugeLabel _linearGaugeLabel = LinearGaugeLabel(); + set setLinearGaugeLabel(LinearGaugeLabel val) { + if (_linearGaugeLabel == val) return; + _linearGaugeLabel = val; + markNeedsPaint(); + markNeedsLayout(); + } + /// /// Getter and Setter for the [valueBar] parameter. /// @@ -408,7 +418,6 @@ class RenderLinearGauge extends RenderBox /// double get getPointerSpace => _pointerSpace; final double _pointerSpace = 0; - LinearGaugeLabel _linearGaugeLabel = LinearGaugeLabel(); late Size _axisActualSize; late final List _widgetPointers; @@ -455,10 +464,17 @@ class RenderLinearGauge extends RenderBox /// Adds the ruler render object to widget . void addRulerLabel(RenderRulerLabel label) { + print('Called'); _renderRulerLabel = label; markNeedsLayout(); } + /// Remove the ruler label render object from widget . + void removeRulerLabel(RenderRulerLabel label) { + _renderRulerLabel = null; + markNeedsLayout(); + } + /// Adds the valuebar render object to widget . void addValueBar(RenderValueBar ruler) { _valueBarRenderObject.add(ruler); From cda7e4f793eb221d024814fb0e11e36b206e8206 Mon Sep 17 00:00:00 2001 From: Afroz-Shaikh Date: Wed, 15 May 2024 01:35:59 +0530 Subject: [PATCH 3/7] Fix : hittest area --- example/lib/main.dart | 18 +++-- .../pointer/needle_pointer_painter.dart | 66 ++++++++++++++++++- .../pointer/radial_widget_painter.dart | 21 ++++-- 3 files changed, 93 insertions(+), 12 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 30e7c13b..3ae5190c 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -6,7 +6,7 @@ void main() { runApp( const MaterialApp( debugShowCheckedModeBanner: false, - home: MyVerticalGauge(), + home: RadialGaugeExample(), ), ); } @@ -58,18 +58,28 @@ class RadialGaugeExample extends StatefulWidget { } class _RadialGaugeExampleState extends State { + double value = 0; @override Widget build(BuildContext context) { - return const Scaffold( + return Scaffold( backgroundColor: Colors.white, body: RadialGauge( - track: RadialTrack( + track: const RadialTrack( start: 0, end: 100, ), needlePointer: [ NeedlePointer( - value: 30, + isInteractive: true, + onChanged: (v) { + setState(() { + value = v; + }); + }, + needleHeight: 1000, + color: Colors.red.withOpacity(0.4), + needleStyle: NeedleStyle.flatNeedle, + value: value, ), ], ), diff --git a/lib/src/radial_gauge/pointer/needle_pointer_painter.dart b/lib/src/radial_gauge/pointer/needle_pointer_painter.dart index d02753de..5c8f7a5a 100644 --- a/lib/src/radial_gauge/pointer/needle_pointer_painter.dart +++ b/lib/src/radial_gauge/pointer/needle_pointer_painter.dart @@ -144,6 +144,7 @@ class RenderNeedlePointer extends RenderBox { @override bool hitTestSelf(Offset position) { Offset calulatedPosition = localToGlobal(position); + if (needlePointerRect.contains(calulatedPosition)) { return true; } else if (needlePointerRect.contains(position)) { @@ -210,6 +211,14 @@ class RenderNeedlePointer extends RenderBox { ) ..strokeCap = StrokeCap.round; +//! + Path path = Path() + ..moveTo(needleStartX, needleStartY) + ..lineTo(needleEndX, needleEndY); + // ..addOval( + // Rect.fromCircle(center: Offset(needleEndX, needleEndY), radius: 10)); + canvas.drawPath(path, Paint()..color = Colors.orange); + // Needle Path Path needlePath = Path(); needlePath.moveTo(offset.dx + getTailRadius / 2 * cos(angle + pi / 2), @@ -227,17 +236,70 @@ class RenderNeedlePointer extends RenderBox { needlePath.close(); - needlePointerRect = needlePath; - // canvas.drawPath(needlePath, Paint()..color = Colors.green); + Path apath = Path() + ..moveTo(needleStartX, needleStartY) + ..lineTo(needleEndX, needleEndY) + ..close(); + final pathMetrics = apath.computeMetrics(); + final hitTestWidth = + _needleWidth; // adjust this to change the hit test area width + + final dx = needleEndX - needleStartX; + final dy = needleEndY - needleStartY; + + final norm = sqrt(dx * dx + dy * dy); + final perpX = -dy / norm * hitTestWidth / 2; + final perpY = dx / norm * hitTestWidth / 2; + + final hitTestPath = Path() + ..moveTo(needleStartX + perpX, needleStartY + perpY) + ..lineTo(needleEndX + perpX, needleEndY + perpY) + ..lineTo(needleEndX - perpX, needleEndY - perpY) + ..lineTo(needleStartX - perpX, needleStartY - perpY) + ..close(); + final widerPath = Path() + ..addRect(Rect.fromPoints( + Offset(needleStartX + cos(angle - pi / 2), + needleStartY + sin(angle + pi / 2)), + Offset( + needleEndX + cos(angle - pi / 2), needleEndY + sin(angle + pi / 2)), + )); + + needlePointerRect = + _needleStyle == NeedleStyle.gaugeNeedle ? needlePath : widerPath; + + canvas.drawPath(hitTestPath, Paint()..color = Colors.black + // ..strokeWidth = 10 + // ..shader + ); + _needleStyle == NeedleStyle.gaugeNeedle ? print("A") : print("B"); + // canvas.drawPath(needlePath, Paint()..color = Colors.blue.withOpacity(0.3)); // Needle Pointer paint if (getNeedleStyle == NeedleStyle.gaugeNeedle) { canvas.drawPath(needlePath, needlePaint); canvas.drawPath(circlePath, Paint()..color = _tailColor); } else { + print('Came here'); + Path apath = Path() + ..moveTo(needleStartX, needleStartY) + ..lineTo(needleEndX, needleEndY) + ..close(); + // Simple Needle canvas.drawLine(Offset(needleStartX, needleStartY), Offset(needleEndX, needleEndY), needlePaint); canvas.drawPath(circlePath, Paint()..color = _tailColor); + // canvas.drawPath( + // apath, + // Paint() + // ..color = Colors.green + // ..strokeWidth = 10 + // ..shader + // ..strokeWidth = needleWidth + // ..style = PaintingStyle.stroke); + // canvas.drawLine(Offset(needleStartX, needleStartY), + // Offset(needleEndX, needleEndY), needlePaint); + // canvas.drawPath(circlePath, Paint()..color = _tailColor); } } diff --git a/lib/src/radial_gauge/pointer/radial_widget_painter.dart b/lib/src/radial_gauge/pointer/radial_widget_painter.dart index fd14135e..6ebd4679 100644 --- a/lib/src/radial_gauge/pointer/radial_widget_painter.dart +++ b/lib/src/radial_gauge/pointer/radial_widget_painter.dart @@ -71,10 +71,15 @@ class RenderRadialWidgetPointer extends RenderProxyBox { double gaugeEnd = _radialGauge.track.end; // final center = Offset(offset.dx, offset.dy); + double containerWidth = constraints.maxWidth; + double containerHeight = constraints.maxHeight; + double containerShortestSide = min(containerWidth, containerHeight); + final childSize = child?.computeDryLayout(constraints); + final childOffsetX = (childSize?.width ?? 0.0) / 2; + final childOffsetY = (childSize?.height ?? 0.0) / 2; final center = Offset( - 1440 * _radialGauge.xCenterCoordinate - - 2 * _radialGauge.track.thickness, - 900 * _radialGauge.yCenterCoordinate - _radialGauge.track.thickness); + containerWidth * _radialGauge.xCenterCoordinate + offset.dx, + containerHeight * _radialGauge.yCenterCoordinate + offset.dy); double value = calculateValueAngle(_value, gaugeStart, gaugeEnd); double startAngle = (_radialGauge.track.startAngle - 180) * (pi / 180); double endAngle = (_radialGauge.track.endAngle - 180) * (pi / 180); @@ -82,10 +87,14 @@ class RenderRadialWidgetPointer extends RenderProxyBox { final double angle = startAngle + (value / 100) * (endAngle - startAngle); double circlePointerOffset = - (900 / 2 - _radialGauge.track.thickness) * _radialGauge.radiusFactor; + (containerShortestSide / 2 - _radialGauge.track.thickness) * + _radialGauge.radiusFactor; + + double circlePointerEndX = + center.dx + circlePointerOffset * cos(angle) - childOffsetX; + double circlePointerEndY = + center.dy + circlePointerOffset * sin(angle) - childOffsetY; - double circlePointerEndX = center.dx + circlePointerOffset * cos(angle); - double circlePointerEndY = center.dy + circlePointerOffset * sin(angle); // canvas.drawCircle(Offset(circlePointerEndX, circlePointerEndY), 30, // Paint()..color = Colors.red); super.paint(context, Offset(circlePointerEndX, circlePointerEndY)); From 9d27bffc45d95d4a126c529dbd9147c1cf9bb7d7 Mon Sep 17 00:00:00 2001 From: Afroz-Shaikh Date: Wed, 15 May 2024 11:57:32 +0530 Subject: [PATCH 4/7] Fix: Needle Hittest Area --- example/lib/main.dart | 18 +---- .../pointer/needle_pointer_painter.dart | 74 +------------------ .../pointer/radial_widget_painter.dart | 7 +- 3 files changed, 10 insertions(+), 89 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 3ae5190c..30e7c13b 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -6,7 +6,7 @@ void main() { runApp( const MaterialApp( debugShowCheckedModeBanner: false, - home: RadialGaugeExample(), + home: MyVerticalGauge(), ), ); } @@ -58,28 +58,18 @@ class RadialGaugeExample extends StatefulWidget { } class _RadialGaugeExampleState extends State { - double value = 0; @override Widget build(BuildContext context) { - return Scaffold( + return const Scaffold( backgroundColor: Colors.white, body: RadialGauge( - track: const RadialTrack( + track: RadialTrack( start: 0, end: 100, ), needlePointer: [ NeedlePointer( - isInteractive: true, - onChanged: (v) { - setState(() { - value = v; - }); - }, - needleHeight: 1000, - color: Colors.red.withOpacity(0.4), - needleStyle: NeedleStyle.flatNeedle, - value: value, + value: 30, ), ], ), diff --git a/lib/src/radial_gauge/pointer/needle_pointer_painter.dart b/lib/src/radial_gauge/pointer/needle_pointer_painter.dart index 5c8f7a5a..b9069a4d 100644 --- a/lib/src/radial_gauge/pointer/needle_pointer_painter.dart +++ b/lib/src/radial_gauge/pointer/needle_pointer_painter.dart @@ -157,7 +157,6 @@ class RenderNeedlePointer extends RenderBox { @override void performLayout() { - // size = Size(_needleWidth + _tailRadius, _needleHeight); size = Size(constraints.maxWidth, constraints.maxHeight); } @@ -211,14 +210,6 @@ class RenderNeedlePointer extends RenderBox { ) ..strokeCap = StrokeCap.round; -//! - Path path = Path() - ..moveTo(needleStartX, needleStartY) - ..lineTo(needleEndX, needleEndY); - // ..addOval( - // Rect.fromCircle(center: Offset(needleEndX, needleEndY), radius: 10)); - canvas.drawPath(path, Paint()..color = Colors.orange); - // Needle Path Path needlePath = Path(); needlePath.moveTo(offset.dx + getTailRadius / 2 * cos(angle + pi / 2), @@ -236,13 +227,7 @@ class RenderNeedlePointer extends RenderBox { needlePath.close(); - Path apath = Path() - ..moveTo(needleStartX, needleStartY) - ..lineTo(needleEndX, needleEndY) - ..close(); - final pathMetrics = apath.computeMetrics(); - final hitTestWidth = - _needleWidth; // adjust this to change the hit test area width + final hitTestWidth = _needleWidth; final dx = needleEndX - needleStartX; final dy = needleEndY - needleStartY; @@ -257,49 +242,19 @@ class RenderNeedlePointer extends RenderBox { ..lineTo(needleEndX - perpX, needleEndY - perpY) ..lineTo(needleStartX - perpX, needleStartY - perpY) ..close(); - final widerPath = Path() - ..addRect(Rect.fromPoints( - Offset(needleStartX + cos(angle - pi / 2), - needleStartY + sin(angle + pi / 2)), - Offset( - needleEndX + cos(angle - pi / 2), needleEndY + sin(angle + pi / 2)), - )); needlePointerRect = - _needleStyle == NeedleStyle.gaugeNeedle ? needlePath : widerPath; - - canvas.drawPath(hitTestPath, Paint()..color = Colors.black - // ..strokeWidth = 10 - // ..shader - ); - _needleStyle == NeedleStyle.gaugeNeedle ? print("A") : print("B"); - // canvas.drawPath(needlePath, Paint()..color = Colors.blue.withOpacity(0.3)); + _needleStyle == NeedleStyle.gaugeNeedle ? needlePath : hitTestPath; + // Needle Pointer paint if (getNeedleStyle == NeedleStyle.gaugeNeedle) { canvas.drawPath(needlePath, needlePaint); canvas.drawPath(circlePath, Paint()..color = _tailColor); } else { - print('Came here'); - Path apath = Path() - ..moveTo(needleStartX, needleStartY) - ..lineTo(needleEndX, needleEndY) - ..close(); - // Simple Needle canvas.drawLine(Offset(needleStartX, needleStartY), Offset(needleEndX, needleEndY), needlePaint); canvas.drawPath(circlePath, Paint()..color = _tailColor); - // canvas.drawPath( - // apath, - // Paint() - // ..color = Colors.green - // ..strokeWidth = 10 - // ..shader - // ..strokeWidth = needleWidth - // ..style = PaintingStyle.stroke); - // canvas.drawLine(Offset(needleStartX, needleStartY), - // Offset(needleEndX, needleEndY), needlePaint); - // canvas.drawPath(circlePath, Paint()..color = _tailColor); } } @@ -309,26 +264,3 @@ class RenderNeedlePointer extends RenderBox { return newValue; } } - -// @override -// void applyPaintTransform(RenderBox child, Matrix4 transform) { -// if (child is RenderNeedlePointer) { -// final centerX = size.width / 2; -// final centerY = size.height / 2; - -// transform.translate(centerX, centerY); -// double value = calculateValueAngle( -// child.getValue, getRadialGauge.track.start, getRadialGauge.track.end); -// double startAngle = (getRadialGauge.track.startAngle - 180) * (pi / 180); -// double endAngle = (getRadialGauge.track.endAngle - 180) * (pi / 180); -// double angle = startAngle + (value / 100) * (endAngle - startAngle); -// double toRotateAngle = angle - (pi / 2); -// transform.rotateZ(toRotateAngle); // Specify the rotation in radians -// transform.translate( -// -centerX - child.getNeedleWidth / 2 - child.getTailRadius / 2, -// -centerY - child.getNeedleHeight + child.getTailRadius / 2); - -// super.applyPaintTransform(child, transform); -// markNeedsLayout(); -// } -// } diff --git a/lib/src/radial_gauge/pointer/radial_widget_painter.dart b/lib/src/radial_gauge/pointer/radial_widget_painter.dart index 6ebd4679..2c45e283 100644 --- a/lib/src/radial_gauge/pointer/radial_widget_painter.dart +++ b/lib/src/radial_gauge/pointer/radial_widget_painter.dart @@ -69,17 +69,18 @@ class RenderRadialWidgetPointer extends RenderProxyBox { void paint(PaintingContext context, Offset offset) { double gaugeStart = _radialGauge.track.start; double gaugeEnd = _radialGauge.track.end; - - // final center = Offset(offset.dx, offset.dy); double containerWidth = constraints.maxWidth; double containerHeight = constraints.maxHeight; double containerShortestSide = min(containerWidth, containerHeight); + final childSize = child?.computeDryLayout(constraints); final childOffsetX = (childSize?.width ?? 0.0) / 2; final childOffsetY = (childSize?.height ?? 0.0) / 2; + final center = Offset( containerWidth * _radialGauge.xCenterCoordinate + offset.dx, containerHeight * _radialGauge.yCenterCoordinate + offset.dy); + double value = calculateValueAngle(_value, gaugeStart, gaugeEnd); double startAngle = (_radialGauge.track.startAngle - 180) * (pi / 180); double endAngle = (_radialGauge.track.endAngle - 180) * (pi / 180); @@ -95,8 +96,6 @@ class RenderRadialWidgetPointer extends RenderProxyBox { double circlePointerEndY = center.dy + circlePointerOffset * sin(angle) - childOffsetY; - // canvas.drawCircle(Offset(circlePointerEndX, circlePointerEndY), 30, - // Paint()..color = Colors.red); super.paint(context, Offset(circlePointerEndX, circlePointerEndY)); } From c410e783213aa84d9db6f05a21d31598590cd471 Mon Sep 17 00:00:00 2001 From: Afroz-Shaikh Date: Wed, 15 May 2024 12:15:53 +0530 Subject: [PATCH 5/7] Fix:Track precision and render-issues --- example/lib/main.dart | 12 +++---- .../linear_gauge_container.dart | 36 ++++++------------- lib/src/linear_gauge/linear_gauge_label.dart | 8 ++--- .../linear_gauge/linear_gauge_painter.dart | 3 -- 4 files changed, 18 insertions(+), 41 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 0b023b05..277b26e4 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,12 +1,7 @@ import 'dart:developer'; -import 'package:example/gauge_vertical.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; import 'package:geekyants_flutter_gauges/geekyants_flutter_gauges.dart'; -// import 'package:syncfusion_flutter_gauges/gauges.dart'; -import 'package:intl/intl.dart'; void main() { runApp( @@ -40,8 +35,11 @@ class _LinearGaugeExampleState extends State { child: Column( children: [ LinearGauge( - start: startVal, - end: 100, + trackLabelFormat: (p0) { + return ' ${p0.toStringAsFixed(2)}'; + }, + start: -70.33, + end: 62.4444, gaugeOrientation: GaugeOrientation.horizontal, enableGaugeAnimation: true, rulers: RulerStyle( diff --git a/lib/src/linear_gauge/gauge_container/linear_gauge_container.dart b/lib/src/linear_gauge/gauge_container/linear_gauge_container.dart index c8d402fa..48127366 100644 --- a/lib/src/linear_gauge/gauge_container/linear_gauge_container.dart +++ b/lib/src/linear_gauge/gauge_container/linear_gauge_container.dart @@ -19,7 +19,7 @@ class LinearGaugeContainer extends LeafRenderObjectWidget { return RenderLinearGaugeContainer( start: linearGauge.start!, end: linearGauge.end!, - trackLabelFormater: linearGauge.trackLabelFormat ?? + trackLabelFormat: linearGauge.trackLabelFormat ?? (double value) => ((value * 10).round() / 10).toString(), value: linearGauge.value!, steps: linearGauge.steps!, @@ -61,7 +61,7 @@ class LinearGaugeContainer extends LeafRenderObjectWidget { renderObject ..setStart = linearGauge.start! ..setEnd = linearGauge.end! - ..setTrackLabelFormater = linearGauge.trackLabelFormat ?? + ..setTrackLabelFormat = linearGauge.trackLabelFormat ?? ((double value) => ((value * 10).round() / 10).toString()) ..setValue = linearGauge.value! ..setSteps = linearGauge.steps! @@ -102,7 +102,7 @@ class RenderLinearGaugeContainer extends RenderBox { RenderLinearGaugeContainer({ required double start, required double end, - required final String Function(double)? trackLabelFormater, + required final String Function(double)? trackLabelFormat, required double steps, required double value, required GaugeOrientation gaugeOrientation, @@ -135,7 +135,7 @@ class RenderLinearGaugeContainer extends RenderBox { required LinearGradient? linearGradient, }) : _start = start, _end = end, - _trackLabelFormater = trackLabelFormater, + _trackLabelFormat = trackLabelFormat, _value = value, _steps = steps, _gaugeOrientation = gaugeOrientation, @@ -203,11 +203,11 @@ class RenderLinearGaugeContainer extends RenderBox { markNeedsLayout(); } - get getTrackLabelFormater => _trackLabelFormater; - String Function(double)? _trackLabelFormater; - set setTrackLabelFormater(String Function(double)? trackLabelFormater) { - if (_trackLabelFormater == trackLabelFormater) return; - _trackLabelFormater = trackLabelFormater; + get trackLabelFormat => _trackLabelFormat; + String Function(double)? _trackLabelFormat; + set setTrackLabelFormat(String Function(double)? trackLabelFormat) { + if (_trackLabelFormat == trackLabelFormat) return; + _trackLabelFormat = trackLabelFormat; markNeedsPaint(); } @@ -672,28 +672,12 @@ class RenderLinearGaugeContainer extends RenderBox { return largestPointer; } - // double getLargestWidgetPointerSize() { - // if (RenderLinearGauge.getWidgetPointers!.isNotEmpty) { - // RenderLinearGaugeWidgetPointer? largestPointer = - // getLargestWidgetPointer(RenderLinearGauge.getWidgetPointers); - - // if (getGaugeOrientation == GaugeOrientation.vertical) { - // return largestPointer?.size.width ?? 0; - // } else { - // return largestPointer?.size.width ?? 0; - // } - // } else { - // return 0; - // } - // } - void _setLinearGaugeContainerPaint() { _linearGaugeContainerPaint.color = setAnimatedColor(getLinearGaugeContainerBgColor); } void _calculateRulerPoints() { - print("Called _calculateRulerPoints"); _linearGaugeLabel.calculateStartAndEndLabelSize( getTextStyle, getStart, getEnd, getCustomLabels!, getInversedRulers); if (getCustomLabels!.isEmpty) { @@ -717,7 +701,7 @@ class RenderLinearGaugeContainer extends RenderBox { } _linearGaugeLabel.addLabels( - trackLableFormatter: getTrackLabelFormater, + trackLabelFormat: trackLabelFormat, distanceValueInRangeOfHundred: getSteps == 0.0 ? interval : getSteps, start: getStart, end: getEnd, diff --git a/lib/src/linear_gauge/linear_gauge_label.dart b/lib/src/linear_gauge/linear_gauge_label.dart index e392d298..e0d5979e 100644 --- a/lib/src/linear_gauge/linear_gauge_label.dart +++ b/lib/src/linear_gauge/linear_gauge_label.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:geekyants_flutter_gauges/geekyants_flutter_gauges.dart'; import 'package:geekyants_flutter_gauges/src/linear_gauge/gauge_container/linear_gauge_container.dart'; @@ -20,7 +18,7 @@ class LinearGaugeLabel { TextPainter(textDirection: TextDirection.ltr); void addLabels({ - required trackLableFormatter, + required trackLabelFormat, required double distanceValueInRangeOfHundred, required double start, required double end, @@ -28,7 +26,7 @@ class LinearGaugeLabel { _linearGaugeLabel.clear(); for (double i = start; i <= end; i += distanceValueInRangeOfHundred) { - text = trackLableFormatter(i); + text = trackLabelFormat(i); _linearGaugeLabel.add(LinearGaugeLabel(text: text, value: i)); } @@ -36,7 +34,7 @@ class LinearGaugeLabel { final LinearGaugeLabel localLabel = _linearGaugeLabel[_linearGaugeLabel.length - 1]; if (localLabel.value != end && localLabel.value! < end) { - String text = ((end * 10).round() / 10).toString(); + String text = trackLabelFormat(end); _linearGaugeLabel.add(LinearGaugeLabel(text: text, value: end)); } } diff --git a/lib/src/linear_gauge/linear_gauge_painter.dart b/lib/src/linear_gauge/linear_gauge_painter.dart index 088239f6..8222ebae 100644 --- a/lib/src/linear_gauge/linear_gauge_painter.dart +++ b/lib/src/linear_gauge/linear_gauge_painter.dart @@ -464,7 +464,6 @@ class RenderLinearGauge extends RenderBox /// Adds the ruler render object to widget . void addRulerLabel(RenderRulerLabel label) { - print('Called'); _renderRulerLabel = label; markNeedsLayout(); } @@ -2257,5 +2256,3 @@ class LinearGaugeParentData extends MultiChildLayoutParentData { this.gaugeEnd, this.linearGaugeLabel); } - -// class Temp implements MouseTrackerAnnotation {} From b0ccdfe8941d3faadbb838c4b8b30601d3f8711a Mon Sep 17 00:00:00 2001 From: Afroz-Shaikh Date: Wed, 15 May 2024 12:16:45 +0530 Subject: [PATCH 6/7] Fix:Track precision and render-issues --- example/lib/main.dart | 84 ++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 277b26e4..30e7c13b 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,5 +1,4 @@ -import 'dart:developer'; - +import 'package:example/gauge_vertical.dart'; import 'package:flutter/material.dart'; import 'package:geekyants_flutter_gauges/geekyants_flutter_gauges.dart'; @@ -7,7 +6,7 @@ void main() { runApp( const MaterialApp( debugShowCheckedModeBanner: false, - home: LinearGaugeExample(), + home: MyVerticalGauge(), ), ); } @@ -16,7 +15,6 @@ void main() { /// The following code is a Simple Example of [LinearGauge] Widget. /// You can customize the [LinearGauge] Widget as per your need. /// - class LinearGaugeExample extends StatefulWidget { const LinearGaugeExample({Key? key}) : super(key: key); @@ -25,50 +23,56 @@ class LinearGaugeExample extends StatefulWidget { } class _LinearGaugeExampleState extends State { - double startVal = 0.0; - ValueNotifier value = ValueNotifier(0.0); - @override Widget build(BuildContext context) { return Scaffold( body: Center( - child: Column( - children: [ - LinearGauge( - trackLabelFormat: (p0) { - return ' ${p0.toStringAsFixed(2)}'; - }, - start: -70.33, - end: 62.4444, - gaugeOrientation: GaugeOrientation.horizontal, - enableGaugeAnimation: true, - rulers: RulerStyle( - rulerPosition: RulerPosition.bottom, - ), - pointers: const [ - Pointer( - value: 50, - shape: PointerShape.circle, - ), - ], + child: LinearGauge( + gaugeOrientation: GaugeOrientation.horizontal, + enableGaugeAnimation: true, + rulers: RulerStyle( + rulerPosition: RulerPosition.bottom, + ), + pointers: const [ + Pointer( + value: 50, + shape: PointerShape.circle, ), - TextButton( - onPressed: () { - if (startVal == 0.0) { - setState(() { - startVal = 50.0; - }); - } else { - setState(() { - startVal = 0.0; - }); - } - log(startVal.toString()); - }, - child: const Text('Toggle Start')) ], ), ), ); } } + +/// +/// The following code is a Simple Example of [RadialGauge] Widget. +/// You can customize the [RadialGauge] Widget as per your need. +/// + +class RadialGaugeExample extends StatefulWidget { + const RadialGaugeExample({super.key}); + + @override + State createState() => _RadialGaugeExampleState(); +} + +class _RadialGaugeExampleState extends State { + @override + Widget build(BuildContext context) { + return const Scaffold( + backgroundColor: Colors.white, + body: RadialGauge( + track: RadialTrack( + start: 0, + end: 100, + ), + needlePointer: [ + NeedlePointer( + value: 30, + ), + ], + ), + ); + } +} From 221f6c6efddfc766bfb6f38f81a12f584e1e7a7a Mon Sep 17 00:00:00 2001 From: Afroz-Shaikh Date: Wed, 15 May 2024 14:24:38 +0530 Subject: [PATCH 7/7] Add: Assert for Valuebar --- example/lib/main.dart | 13 ++++++++++++- example/pubspec.lock | 2 +- lib/src/linear_gauge/linear_gauge.dart | 6 ++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 30e7c13b..0c2af6dd 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -6,7 +6,7 @@ void main() { runApp( const MaterialApp( debugShowCheckedModeBanner: false, - home: MyVerticalGauge(), + home: LinearGaugeExample(), ), ); } @@ -23,6 +23,7 @@ class LinearGaugeExample extends StatefulWidget { } class _LinearGaugeExampleState extends State { + double value = 20; @override Widget build(BuildContext context) { return Scaffold( @@ -33,6 +34,16 @@ class _LinearGaugeExampleState extends State { rulers: RulerStyle( rulerPosition: RulerPosition.bottom, ), + valueBar: [ + ValueBar( + value: 20, + offset: 300, + ) + ], + customLabels: [ + CustomRulerLabel(text: "Hello One", value: value), + CustomRulerLabel(text: "Hello Two", value: 60), + ], pointers: const [ Pointer( value: 50, diff --git a/example/pubspec.lock b/example/pubspec.lock index 7ead57d9..a66fc333 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -81,7 +81,7 @@ packages: path: ".." relative: true source: path - version: "1.0.3" + version: "1.0.4" leak_tracker: dependency: transitive description: diff --git a/lib/src/linear_gauge/linear_gauge.dart b/lib/src/linear_gauge/linear_gauge.dart index 0b45332b..e9235a4e 100644 --- a/lib/src/linear_gauge/linear_gauge.dart +++ b/lib/src/linear_gauge/linear_gauge.dart @@ -65,6 +65,12 @@ class LinearGauge extends StatefulWidget { this.curves = const [], }) : assert(() { if (customLabels!.isNotEmpty) { + if (valueBar != []) { + assert( + valueBar!.every( + (element) => element.value >= customLabels.first.value!), + "Valuebar value should be greater than or equal to customLabels start value"); + } assert(customLabels.length >= 2, "At least two CustomRulerLabel should be added");