use crate::chart::coords::ChartMapping;
use crate::studies::{Indicator, IndicatorValue};
use crate::tokens::DESIGN_TOKENS;
use egui::{Color32, Painter, Pos2, Stroke};
#[derive(Clone, Debug)]
pub struct SelectionDotConfig {
pub radius: f32,
pub fill_color: Color32,
pub border_color: Color32,
pub border_width: f32,
pub dot_interval: usize,
}
impl Default for SelectionDotConfig {
fn default() -> Self {
Self {
radius: 4.0,
fill_color: Color32::WHITE,
border_color: DESIGN_TOKENS.semantic.brand.accent, border_width: 2.0,
dot_interval: 5,
}
}
}
pub fn render_indicator_selection_dots<F>(
painter: &Painter,
indicator: &dyn Indicator,
line_idx: usize,
visible_range: std::ops::Range<usize>,
coords: &ChartMapping,
price_to_y: F,
config: &SelectionDotConfig,
) where
F: Fn(f64) -> f32,
{
let values = indicator.values();
for i in visible_range.clone() {
if i % config.dot_interval != 0 {
continue;
}
let value = match values.get(i) {
Some(IndicatorValue::Single(v)) => Some(*v),
Some(IndicatorValue::Multiple(vals)) => vals.get(line_idx).copied(),
_ => None,
};
let Some(value) = value else { continue };
let x = coords.idx_to_x(i);
let y = price_to_y(value);
if x < coords.rect.min.x || x > coords.rect.max.x {
continue;
}
if y < coords.rect.min.y || y > coords.rect.max.y {
continue;
}
let center = Pos2::new(x, y);
painter.circle(
center,
config.radius + config.border_width,
config.border_color,
Stroke::NONE,
);
painter.circle(center, config.radius, config.fill_color, Stroke::NONE);
}
}