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 'dart:collection';
5 : import 'dart:math';
6 :
7 : import 'package:app_finance/_classes/herald/app_locale.dart';
8 : import 'package:app_finance/_classes/structure/interface_app_data.dart';
9 : import 'package:app_finance/_ext/build_context_ext.dart';
10 : import 'package:app_finance/charts/interface/chart_data.dart';
11 : import 'package:app_finance/charts/painter/bar_chart_painter.dart';
12 : import 'package:app_finance/charts/painter/foreground_chart_painter.dart';
13 : import 'package:app_finance/design/generic/empty_widget.dart';
14 : import 'package:flutter/material.dart';
15 : import 'package:intl/intl.dart';
16 :
17 : class BarRaceChart extends StatelessWidget {
18 : final double width;
19 : final double indent;
20 : final String tooltip;
21 : final List<InterfaceAppData> categories;
22 : final List<Offset> data;
23 :
24 0 : const BarRaceChart({
25 : super.key,
26 : required this.data,
27 : required this.categories,
28 : required this.width,
29 : this.indent = 0.0,
30 : this.tooltip = '',
31 : });
32 :
33 0 : List<ChartData> _getData() {
34 0 : final plot = SplayTreeMap<double, ChartData>();
35 0 : final rnd = Random();
36 0 : for (int i = 0; i < data.length; i++) {
37 0 : final key = data[i].dy + rnd.nextDouble();
38 0 : plot[key] = ChartData([data[i]], color: categories[i].color ?? Colors.grey, helper: categories[i]);
39 : }
40 0 : int idx = plot.values.length;
41 0 : return plot.values.map((e) {
42 0 : e.data.replaceRange(0, 1, [Offset(idx.toDouble(), e.data.first.dy)]);
43 0 : idx--;
44 : return e;
45 0 : }).toList();
46 : }
47 :
48 0 : @override
49 : Widget build(BuildContext context) {
50 0 : if (data.isEmpty) {
51 : return const EmptyWidget();
52 : }
53 0 : final bgColor = context.colorScheme.onSurface;
54 0 : final xMax = data.reduce((max, item) => item.dy > max.dy ? item : max).dy;
55 0 : final plot = _getData();
56 0 : final size = Size(width, 36.0 * (1 + plot.length));
57 0 : final bg = ForegroundChartPainter(
58 : size: size,
59 : color: bgColor,
60 : lineColor: bgColor,
61 0 : background: bgColor.withOpacity(0.1),
62 : yMin: 0.0,
63 0 : yMax: 1.0 + plot.length,
64 : yType: null,
65 : xMin: 0.0,
66 0 : xMax: (xMax * 1.2).ceilToDouble(),
67 : xType: double,
68 0 : xTpl: NumberFormat.compact(locale: AppLocale.code),
69 : );
70 0 : return SizedBox(
71 0 : height: size.height,
72 0 : width: size.width,
73 0 : child: CustomPaint(
74 : size: size,
75 0 : painter: BarChartPainter(
76 0 : indent: bg.shift,
77 : lineColor: bgColor,
78 : size: size,
79 : data: plot,
80 0 : yMax: bg.yMax + 0.4,
81 0 : xMin: bg.xMin,
82 0 : xMax: bg.xMax,
83 : ),
84 : foregroundPainter: bg,
85 : willChange: false,
86 0 : child: Padding(
87 0 : padding: EdgeInsets.only(top: indent / 4),
88 0 : child: Text(tooltip),
89 : ),
90 : ),
91 : );
92 : }
93 : }
|