LCOV - code coverage report
Current view: top level - lib/charts/painter - gauge_painter.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 63 65 96.9 %
Date: 2024-10-04 11:09:33 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:flutter/material.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           3 :     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.withOpacity(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.withOpacity(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 1.14