Skip to main content

egui_charts/chart/series/
settings.rs

1//! Series settings for customizing chart series appearance.
2//!
3//! Provides configurable colors and options for candlestick/bar chart series.
4
5use crate::model::{PriceSource, SeriesAlerts};
6use crate::scales::PriceScaleMode;
7use crate::tokens::DESIGN_TOKENS;
8use egui::Color32;
9
10/// Settings for chart series appearance
11#[derive(Clone, Debug)]
12pub struct SeriesSettings {
13    /// Active chart type, used by the dialog to choose the controls to show.
14    /// Applying settings keeps the chart's currently selected type.
15    pub chart_type: crate::model::ChartType,
16    /// Retained styles and chart type parameters.
17    pub chart_type_params: crate::model::ChartTypeParams,
18    // === Symbol Tab: Colors ===
19    /// Bullish candle body color
20    pub bullish_color: Color32,
21    /// Bearish candle body color
22    pub bearish_color: Color32,
23    /// Bullish candle border color (None = same as fill)
24    pub bullish_border_color: Option<Color32>,
25    /// Bearish candle border color (None = same as fill)
26    pub bearish_border_color: Option<Color32>,
27    /// Bullish wick color (None = same as fill)
28    pub bullish_wick_color: Option<Color32>,
29    /// Bearish wick color (None = same as fill)
30    pub bearish_wick_color: Option<Color32>,
31    /// Price source for line calculations
32    pub price_source: PriceSource,
33
34    // === Symbol Tab: Visibility ===
35    /// Whether to show on all timeframes
36    pub visible_all_timeframes: bool,
37    /// Specific visible timeframes (when not all)
38    pub visible_timeframes: Vec<String>,
39
40    // === Status Line Tab ===
41    /// Show OHLC values in status line
42    pub show_ohlc_values: bool,
43    /// Show price change in status line
44    pub show_change: bool,
45    /// Show volume in status line
46    pub show_volume: bool,
47    /// Show bar change (open to close) in status line
48    pub show_bar_change: bool,
49    /// Decimal places for price display
50    pub decimal_places: u8,
51
52    // === Scales Tab ===
53    /// Price scale mode (Normal, Log, Percentage, IndexedTo100)
54    pub price_scale_mode: PriceScaleMode,
55    /// Show last price horizontal line
56    pub show_price_line: bool,
57    /// Show previous close line
58    pub show_prev_close_line: bool,
59    /// Invert the price scale
60    pub invert_scale: bool,
61
62    /// Visibility and style of this series' alert levels
63    pub alerts: SeriesAlerts,
64
65    // === Canvas Tab ===
66    /// Background type: 0 = Solid, 1 = Gradient
67    pub background_type: u8,
68    /// Show vertical grid lines
69    pub show_vertical_grid: bool,
70    /// Show horizontal grid lines
71    pub show_horizontal_grid: bool,
72    /// Crosshair mode: 0 = Full, 1 = Cross, 2 = None
73    pub crosshair_mode: u8,
74}
75
76impl Default for SeriesSettings {
77    fn default() -> Self {
78        Self {
79            chart_type: crate::model::ChartType::default(),
80            chart_type_params: crate::model::ChartTypeParams::default(),
81            // Symbol Tab: Colors
82            bullish_color: DESIGN_TOKENS.semantic.extended.bullish,
83            bearish_color: DESIGN_TOKENS.semantic.extended.bearish,
84            bullish_border_color: None,
85            bearish_border_color: None,
86            bullish_wick_color: None,
87            bearish_wick_color: None,
88            price_source: PriceSource::default(),
89            // Symbol Tab: Visibility
90            visible_all_timeframes: true,
91            visible_timeframes: Vec::new(),
92            // Status Line Tab
93            show_ohlc_values: true,
94            show_change: true,
95            show_volume: true,
96            show_bar_change: false,
97            decimal_places: 2,
98            // Scales Tab
99            price_scale_mode: PriceScaleMode::Normal,
100            show_price_line: true,
101            show_prev_close_line: false,
102            invert_scale: false,
103            alerts: SeriesAlerts::default(),
104            // Canvas Tab
105            background_type: 0, // Solid
106            show_vertical_grid: true,
107            show_horizontal_grid: true,
108            crosshair_mode: 0, // Full
109        }
110    }
111}
112
113impl SeriesSettings {
114    /// Create new settings with default values
115    pub fn new() -> Self {
116        Self::default()
117    }
118
119    /// Get the effective bullish border color
120    pub fn effective_bullish_border(&self) -> Color32 {
121        self.bullish_border_color.unwrap_or(self.bullish_color)
122    }
123
124    /// Get the effective bearish border color
125    pub fn effective_bearish_border(&self) -> Color32 {
126        self.bearish_border_color.unwrap_or(self.bearish_color)
127    }
128
129    /// Get the effective bullish wick color
130    pub fn effective_bullish_wick(&self) -> Color32 {
131        self.bullish_wick_color.unwrap_or(self.bullish_color)
132    }
133
134    /// Get the effective bearish wick color
135    pub fn effective_bearish_wick(&self) -> Color32 {
136        self.bearish_wick_color.unwrap_or(self.bearish_color)
137    }
138
139    /// Reset settings to defaults, keeping the active chart type for dialog context.
140    pub fn reset_to_default(&mut self) {
141        *self = Self {
142            chart_type: self.chart_type,
143            ..Self::default()
144        };
145    }
146
147    /// Compute the line value for a bar based on the configured price source.
148    ///
149    /// Use this when rendering line charts to respect the user's price source selection.
150    /// For example: `settings.compute_line_value(bar.open, bar.high, bar.low, bar.close)`
151    pub fn compute_line_value(&self, open: f64, high: f64, low: f64, close: f64) -> f64 {
152        self.price_source.compute(open, high, low, close)
153    }
154
155    /// Compute line values for a slice of bars based on price source.
156    ///
157    /// Returns a Vec of computed values matching the input bars.
158    pub fn compute_line_values(&self, bars: &[crate::model::Bar]) -> Vec<f64> {
159        bars.iter()
160            .map(|bar| self.compute_line_value(bar.open, bar.high, bar.low, bar.close))
161            .collect()
162    }
163}