Skip to main content

gpui_component/chart/
mod.rs

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