LCOV - code coverage report
Current view: top level - lib/charts/painter - gauge_painter.dart Coverage Total Hit
Test: lcov.info Lines: 96.9 % 65 63
Test Date: 2026-11-14 15:04:37 Functions: - 0 0

            Line data    Source code
       1              : // Copyright 2023 The terCAD team. All rights reserved.
       2              : // Use of this source code is governed by a CC BY-NC-ND 4.0 license that can be found in the LICENSE file.
       3              : 
       4              : import 'package:app_finance/_classes/herald/app_locale.dart';
       5              : import 'package:material_ui/material_ui.dart';
       6              : import 'package:intl/intl.dart' as intl;
       7              : import 'dart:math';
       8              : 
       9              : typedef FnShift = double Function(double dx, TextPainter textPainter);
      10              : 
      11              : class GaugePainter extends CustomPainter {
      12              :   final double value;
      13              :   final double max;
      14              :   final double min;
      15              :   final Color color;
      16              :   late final intl.NumberFormat formatter;
      17              :   final double threshold = 80;
      18              :   final double fontSize;
      19              : 
      20            1 :   GaugePainter({
      21              :     required this.value,
      22              :     required this.max,
      23              :     required this.min,
      24              :     this.color = Colors.grey,
      25              :     this.fontSize = 12,
      26              :   }) {
      27            2 :     formatter = intl.NumberFormat.compact(locale: AppLocale.code);
      28              :   }
      29              : 
      30            1 :   @override
      31              :   void paint(Canvas canvas, Size size) {
      32            4 :     final center = Offset(size.width / 2, size.height);
      33            2 :     final radius = size.width / 2;
      34              : 
      35            1 :     _drawArc(canvas, size, radius, center);
      36            3 :     if (size.width > threshold) {
      37            2 :       for (double i = 0.15; i < 1; i += 0.33) {
      38            1 :         _drawValue(canvas, size, radius, center, i);
      39              :       }
      40              :     }
      41            1 :     _drawLine(canvas, size, radius, center);
      42              :   }
      43              : 
      44            1 :   void _paintText(Canvas canvas, Size size, Offset position, String text) {
      45            1 :     callback(double dx, TextPainter textPainter) {
      46            5 :       double shift = cos(pi * position.dx / size.width);
      47            2 :       if (shift.toStringAsFixed(2) == '0.00') {
      48            0 :         shift = -textPainter.width / 2;
      49            4 :       } else if (position.dx >= size.width / 2) {
      50            3 :         shift = shift * textPainter.width * 1.5;
      51              :       } else {
      52            3 :         shift *= textPainter.width / 2;
      53              :       }
      54              :       return shift;
      55              :     }
      56              : 
      57            1 :     paintText(canvas, size, callback, position, text);
      58              :   }
      59              : 
      60            1 :   void paintText(Canvas canvas, Size size, FnShift shift, Offset position, String text) {
      61            1 :     final textPainter = TextPainter(
      62            1 :       text: TextSpan(
      63              :         text: text,
      64            1 :         style: TextStyle(
      65            2 :           color: color.withValues(alpha: 0.8),
      66            5 :           fontSize: size.width > threshold * 2 ? fontSize : 9,
      67              :         ),
      68              :       ),
      69              :       textDirection: TextDirection.ltr,
      70              :     );
      71            1 :     textPainter.layout();
      72            7 :     textPainter.paint(canvas, Offset(position.dx + shift(position.dx, textPainter), position.dy));
      73              :   }
      74              : 
      75            1 :   void _drawValue(Canvas canvas, Size size, double radius, Offset center, double pos) {
      76            1 :     final line = Paint()
      77            3 :       ..color = color.withValues(alpha: 0.5)
      78            1 :       ..strokeWidth = 1
      79            1 :       ..style = PaintingStyle.fill;
      80            1 :     final position = _getTip(radius, center, pos, 15);
      81            1 :     canvas.drawCircle(position, 1.5, line);
      82            7 :     _paintText(canvas, size, position, formatter.format(min + max * pos));
      83              :   }
      84              : 
      85            1 :   void _drawArc(Canvas canvas, Size size, double radius, Offset center) {
      86            1 :     final paint = Paint()
      87            2 :       ..color = Colors.green.shade500
      88            1 :       ..strokeWidth = 10
      89            1 :       ..style = PaintingStyle.stroke;
      90              : 
      91            3 :     double startPoint = (1 / 2.4 - 1) * pi;
      92            3 :     canvas.drawArc(Rect.fromCircle(center: center, radius: radius), startPoint, -startPoint, false, paint);
      93            5 :     canvas.drawArc(Rect.fromCircle(center: center, radius: radius), startPoint - pi / 3.8, pi / 4, false,
      94            1 :         paint..color = Colors.orange);
      95            1 :     canvas.drawArc(
      96            5 :         Rect.fromCircle(center: center, radius: radius), -pi, pi / 7.1, false, paint..color = Colors.red.shade900);
      97              :   }
      98              : 
      99            1 :   Offset _getTip(double radius, Offset center, double pos, [double needle = 20]) {
     100            1 :     final needleLength = radius - needle;
     101            2 :     final needleAngle = pi + pi * pos;
     102            5 :     return center.translate(needleLength * cos(needleAngle), needleLength * sin(needleAngle));
     103              :   }
     104              : 
     105            1 :   void _drawLine(Canvas canvas, Size size, double radius, Offset center) {
     106            5 :     final needleTip = _getTip(radius, center, value, size.width > threshold ? 20 : 0);
     107            1 :     final line = Paint()
     108            2 :       ..color = color
     109            1 :       ..strokeWidth = 2
     110            1 :       ..style = PaintingStyle.fill;
     111            3 :     final rnd = size.width > threshold ? 6.0 : 3.0;
     112            4 :     final shift = rnd / 2 * (needleTip.dx > radius ? 1 : -1);
     113            1 :     final path = Path()
     114            4 :       ..moveTo(radius - shift, size.height - rnd)
     115            3 :       ..lineTo(needleTip.dx, needleTip.dy)
     116            4 :       ..lineTo(radius + shift, size.height + rnd);
     117            1 :     canvas.drawPath(path, line);
     118            1 :     canvas.drawCircle(center, rnd, line);
     119              :   }
     120              : 
     121            0 :   @override
     122              :   bool shouldRepaint(CustomPainter oldDelegate) {
     123              :     return false;
     124              :   }
     125              : }
        

Generated by: LCOV version 2.0-1