LCOV - code coverage report
Current view: top level - chart - line_chart.dart (source / functions) Hit Total Coverage
Test: lcov_filtered.info Lines: 98 98 100.0 %
Date: 2019-08-23 11:26:09 Functions: 0 0 -

          Line data    Source code
       1             : import 'package:fl_animated_linechart/chart/chart_line.dart';
       2             : import 'package:fl_animated_linechart/chart/chart_point.dart';
       3             : import 'package:fl_animated_linechart/chart/datetime_chart_point.dart';
       4             : import 'package:fl_animated_linechart/chart/datetime_series_converter.dart';
       5             : import 'package:fl_animated_linechart/chart/highlight_point.dart';
       6             : import 'package:fl_animated_linechart/common/dates.dart';
       7             : import 'package:fl_animated_linechart/common/pair.dart';
       8             : import 'package:fl_animated_linechart/common/text_direction_helper.dart';
       9             : import 'package:flutter/material.dart';
      10             : import 'package:flutter/rendering.dart';
      11             : import 'package:intl/intl.dart';
      12             : 
      13             : class LineChart {
      14             : 
      15             :   final DateFormat _formatHoursMinutes = DateFormat('kk:mm');
      16             :   final DateFormat _formatDayMonth = DateFormat('dd/MM');
      17             : 
      18             :   static final double axisOffsetPX = 50.0;
      19             :   static final double stepCount = 5;
      20             : 
      21             :   final List<ChartLine> lines;
      22             :   final Dates fromTo;
      23             :   final String yAxisUnit;
      24             :   double _minX = 0;
      25             :   double _minY = 0;
      26             :   double _maxX = 0;
      27             :   double _maxY = 0;
      28             : 
      29             :   double _widthStepSize;
      30             :   double _heightStepSize;
      31             :   double _xScale;
      32             :   double _xOffset;
      33             :   double _yScale;
      34             :   Map<int, List<HighlightPoint>> _seriesMap;
      35             :   Map<int, Path> _pathMap;
      36             :   double _yTick;
      37             :   double _axisOffSetWithPadding;
      38             :   List<TextPainter> _axisTexts;
      39             :   List<TextPainter> _yAxisTexts;
      40             : 
      41           2 :   LineChart(this.lines, this.fromTo, this.yAxisUnit) {
      42           6 :       if (lines.length > 0) {
      43           8 :         _minX = lines[0].minX;
      44           8 :         _maxX = lines[0].maxX;
      45           8 :         _minY = lines[0].minY;
      46           8 :         _maxY = lines[0].maxY;
      47             :       }
      48             : 
      49           6 :       lines.forEach((p) {
      50           6 :         if (p.minX < _minX) {
      51           2 :           _minX = p.minX;
      52             :         }
      53           6 :         if (p.maxX > _maxX) {
      54           2 :           _maxX = p.maxX;
      55             :         }
      56           6 :         if (p.minY < _minY) {
      57           2 :           _minY = p.minY;
      58             :         }
      59           6 :         if (p.maxY > _maxY) {
      60           2 :           _maxY = p.maxY;
      61             :         }
      62             :       });
      63             :   }
      64             : 
      65           2 :   factory LineChart.fromDateTimeMaps(List<Map<DateTime, double>> series, List<Color> colors, String yAxisUnit) {
      66           2 :     Pair<List<ChartLine>, Dates> convertFromDateMaps = DateTimeSeriesConverter.convertFromDateMaps(series, colors);
      67           6 :     return LineChart(convertFromDateMaps.left, convertFromDateMaps.right, yAxisUnit);
      68             :   }
      69             : 
      70           8 :   double get width => _maxX - _minX;
      71           8 :   double get height => _maxY - _minY;
      72             : 
      73           4 :   double get minX => _minX;
      74           4 :   double get minY => _minY;
      75           2 :   double get maxX => _maxX;
      76           2 :   double get maxY => _maxY;
      77             : 
      78             :   //Calculate ui pixels values
      79           2 :   void initialize(double widthPX, double heightPX) {
      80           8 :     _widthStepSize = (widthPX-axisOffsetPX) / (stepCount+1);
      81           8 :     _heightStepSize = (heightPX-axisOffsetPX) / (stepCount+1);
      82             : 
      83           8 :     _xScale = (widthPX - axisOffsetPX)/width;
      84           8 :     _xOffset = minX * _xScale;
      85          10 :     _yScale = (heightPX - axisOffsetPX - 20)/height;
      86             : 
      87           4 :     _seriesMap = Map();
      88           4 :     _pathMap = Map();
      89             : 
      90             :     int index = 0;
      91           6 :     lines.forEach((chartLine) {
      92           6 :       chartLine.points.forEach((p) {
      93          10 :         double x = (p.x * xScale) - xOffset;
      94             : 
      95          14 :         double adjustedY = (p.y * yScale) - (minY * yScale);
      96           4 :         double y = (heightPX - axisOffsetPX) - adjustedY;
      97             : 
      98             :         //adjust to make room for axis values:
      99           2 :         x += axisOffsetPX;
     100           4 :         if (_seriesMap[index] == null) {
     101           6 :           _seriesMap[index] = List();
     102             :         }
     103             : 
     104           2 :         if (p is DateTimeChartPoint) {
     105          14 :           _seriesMap[index].add(HighlightPoint(DateTimeChartPoint(x, y, p.dateTime), p.y));
     106             :         } else {
     107           6 :           _seriesMap[index].add(HighlightPoint(ChartPoint(x, y), p.y));
     108             :         }
     109             :       });
     110             : 
     111           2 :       index++;
     112             :     });
     113             : 
     114           6 :     _yTick = height / 5;
     115             : 
     116           4 :     _axisOffSetWithPadding = axisOffsetPX - 5.0;
     117             : 
     118           4 :     _axisTexts = [];
     119             : 
     120           6 :     for (int c = 0; c <= (stepCount + 1); c++) {
     121          18 :       TextSpan span = new TextSpan(style: new TextStyle(color: Colors.grey[800], fontWeight: FontWeight.w200, fontSize: 10), text: '${(minY + yTick * c).round()}');
     122           4 :       TextPainter tp = new TextPainter(text: span, textAlign: TextAlign.right, textDirection: TextDirectionHelper.getDirection());
     123           2 :       tp.layout();
     124             : 
     125           4 :       _axisTexts.add(tp);
     126             :     }
     127             : 
     128           4 :     _yAxisTexts = [];
     129             : 
     130             :     //Todo: make the axis part generic, to support both string, dates, and numbers
     131          10 :     Duration duration = fromTo.max.difference(fromTo.min);
     132           8 :     double stepInSeconds = duration.inSeconds.toDouble() / (stepCount + 1);
     133             : 
     134           6 :     for (int c = 0; c <= (stepCount + 1); c++) {
     135          12 :       DateTime tick = fromTo.min.add(Duration(seconds: (stepInSeconds * c).round()));
     136             : 
     137           2 :       TextSpan span = new TextSpan(
     138           6 :           style: new TextStyle(color: Colors.grey[800], fontSize: 11.0, fontWeight: FontWeight.w200), text: _formatDateTime(tick, duration));
     139           2 :       TextPainter tp = new TextPainter(
     140             :           text: span, textAlign: TextAlign.right,
     141           2 :           textDirection: TextDirectionHelper.getDirection());
     142           2 :       tp.layout();
     143             : 
     144           4 :       _yAxisTexts.add(tp);
     145             :     }
     146             :   }
     147             : 
     148           2 :   String _formatDateTime(DateTime dateTime, Duration duration) {
     149           4 :     if (duration.inHours < 30) {
     150           6 :       return _formatHoursMinutes.format(dateTime.toLocal());
     151             :     } else {
     152           3 :       return _formatDayMonth.format(dateTime.toLocal());
     153             :     }
     154             :   }
     155             : 
     156           4 :   double get heightStepSize => _heightStepSize;
     157           4 :   double get widthStepSize => _widthStepSize;
     158             : 
     159           4 :   double get yScale => _yScale;
     160           4 :   double get xOffset => _xOffset;
     161           4 :   double get xScale => _xScale;
     162             : 
     163           4 :   Map<int, List<HighlightPoint>> get seriesMap => _seriesMap;
     164             : 
     165           4 :   double get yTick => _yTick;
     166             : 
     167           4 :   double get axisOffSetWithPadding => _axisOffSetWithPadding;
     168             : 
     169           4 :   List<TextPainter> get yAxisTexts => _axisTexts;
     170             : 
     171           4 :   List<TextPainter> get xAxisTexts => _yAxisTexts;
     172             : 
     173           2 :   List<HighlightPoint> getClosetHighlightPoints(double horizontalDragPosition) {
     174           2 :     List<HighlightPoint> highlights = List();
     175             : 
     176           6 :     seriesMap.forEach((key, list) {
     177           2 :       HighlightPoint closest = _findClosest(list, horizontalDragPosition);
     178           2 :       highlights.add(closest);
     179             :     });
     180             : 
     181             :     return highlights;
     182             :   }
     183             : 
     184           2 :   HighlightPoint _findClosest(List<HighlightPoint> list, double horizontalDragPosition) {
     185           2 :     HighlightPoint candidate = list[0];
     186             : 
     187           8 :     double candidateDist = ((candidate.chartPoint.x) - horizontalDragPosition).abs();
     188           4 :     list.forEach((alternative) {
     189           8 :       double alternativeDist = ((alternative.chartPoint.x) - horizontalDragPosition).abs();
     190             : 
     191           2 :       if (alternativeDist < candidateDist) {
     192             :         candidate = alternative;
     193           8 :         candidateDist = ((candidate.chartPoint.x) - horizontalDragPosition).abs();
     194             :       }
     195           2 :       if (alternativeDist > candidateDist) {
     196             :         return candidate;
     197             :       }
     198             :     });
     199             : 
     200             :     return candidate;
     201             :   }
     202             : 
     203           2 :   Path getPathCache(int index) {
     204           4 :     if (_pathMap.containsKey(index)) {
     205           4 :       return _pathMap[index];
     206             :     } else {
     207           2 :       Path path = Path();
     208             : 
     209             :       bool init = true;
     210             : 
     211           8 :       this.seriesMap[index].forEach((p) {
     212             :         if (init) {
     213             :           init = false;
     214          10 :           path.moveTo(p.chartPoint.x, p.chartPoint.y);
     215             :         }
     216             : 
     217          10 :         path.lineTo(p.chartPoint.x, p.chartPoint.y);
     218             :       });
     219             : 
     220           4 :       _pathMap[index] = path;
     221             : 
     222             :       return path;
     223             :     }
     224             :   }
     225             : }

Generated by: LCOV version 1.14