Skip to main content

rgpui_component/chart/
mod.rs

1mod area_chart;
2mod bar_chart;
3mod candlestick_chart;
4mod line_chart;
5mod pie_chart;
6
7pub use area_chart::AreaChart;
8pub use bar_chart::BarChart;
9pub use candlestick_chart::CandlestickChart;
10pub use line_chart::LineChart;
11pub use pie_chart::PieChart;
12
13use rgpui::{Hsla, SharedString, TextAlign};
14
15use crate::plot::{
16    AxisText,
17    scale::{Scale, ScaleBand, ScalePoint},
18};
19
20/// Build x-axis labels for point-based scales (`LineChart`, `AreaChart`).
21///
22/// Point scales place items at evenly spaced positions. The first label is
23/// left-aligned, the last is right-aligned, and the rest are centered.
24pub(crate) fn build_point_x_labels<T, X>(
25    data: &[T],
26    x_fn: &dyn Fn(&T) -> X,
27    x_scale: &ScalePoint<X>,
28    tick_margin: usize,
29    color: Hsla,
30) -> Vec<AxisText>
31where
32    X: PartialEq + Into<SharedString>,
33{
34    let data_len = data.len();
35    data.iter()
36        .enumerate()
37        .filter_map(|(i, d)| {
38            if (i + 1) % tick_margin != 0 {
39                return None;
40            }
41            x_scale.tick(&x_fn(d)).map(|x_tick| {
42                let align = match i {
43                    0 if data_len == 1 => TextAlign::Center,
44                    0 => TextAlign::Left,
45                    i if i == data_len - 1 => TextAlign::Right,
46                    _ => TextAlign::Center,
47                };
48                // Call x_fn again to get an owned value for the label text.
49                AxisText::new(x_fn(d).into(), x_tick, color).align(align)
50            })
51        })
52        .collect()
53}
54
55/// Build axis labels for band-based scales (`BarChart`, `CandlestickChart`).
56///
57/// Band scales place items in evenly sized bands. The returned `tick`
58/// coordinate is the centre of each band along the band axis; the caller
59/// decides whether to feed the result to `PlotAxis::x_label` (vertical
60/// charts) or `PlotAxis::y_label` (horizontal charts).
61pub(crate) fn build_band_labels<T, X>(
62    data: &[T],
63    x_fn: &dyn Fn(&T) -> X,
64    x_scale: &ScaleBand<X>,
65    band_width: f32,
66    tick_margin: usize,
67    color: Hsla,
68) -> Vec<AxisText>
69where
70    X: PartialEq + Into<SharedString>,
71{
72    data.iter()
73        .enumerate()
74        .filter_map(|(i, d)| {
75            if (i + 1) % tick_margin != 0 {
76                return None;
77            }
78            x_scale.tick(&x_fn(d)).map(|x_tick| {
79                // Call x_fn again to get an owned value for the label text.
80                AxisText::new(x_fn(d).into(), x_tick + band_width / 2., color)
81                    .align(TextAlign::Center)
82            })
83        })
84        .collect()
85}