1use super::actions::ReplaySpeed;
6use crate::theme::Theme;
7use crate::tokens::DESIGN_TOKENS;
8use egui::Color32;
9
10#[derive(Debug, Clone, PartialEq)]
12pub struct ReplayColors {
13 pub play_color: Color32,
15 pub pause_color: Color32,
17 pub stop_color: Color32,
19 pub progress_bg: Color32,
21 pub progress_fill: Color32,
23 pub progress_cursor: Color32,
25 pub marker_color: Color32,
27 pub speed_color: Color32,
29 pub active_indicator: Color32,
31 pub disabled_color: Color32,
33}
34
35impl ReplayColors {
36 pub fn from_theme(theme: &Theme) -> Self {
41 let ui = &theme.ui;
42 Self {
43 play_color: ui.success,
44 pause_color: ui.warning,
45 stop_color: ui.error,
46 progress_bg: ui.btn_bg_hover,
47 progress_fill: ui.accent,
48 progress_cursor: ui.text,
49 marker_color: ui.warning,
50 speed_color: ui.text,
51 active_indicator: ui.success,
52 disabled_color: ui.text_muted,
53 }
54 }
55}
56
57impl Default for ReplayColors {
58 fn default() -> Self {
59 Self::from_theme(&Theme::dark())
60 }
61}
62
63#[derive(Debug, Clone)]
65pub struct ReplayLayout {
66 pub control_bar_height: f32,
68 pub btn_size: f32,
70 pub small_button_size: f32,
72 pub btn_spacing: f32,
74 pub progress_bar_height: f32,
76 pub progress_bar_width: Option<f32>,
78 pub padding: f32,
80 pub speed_dropdown_width: f32,
82 pub date_display_width: f32,
84}
85
86impl ReplayLayout {
87 pub(super) fn resolved(&self, theme: &Theme) -> Self {
88 let defaults = Self::default();
89 let mut layout = self.clone();
90 for (value, default, themed) in [
91 (
92 &mut layout.btn_spacing,
93 defaults.btn_spacing,
94 theme.spacing.sm,
95 ),
96 (
97 &mut layout.progress_bar_height,
98 defaults.progress_bar_height,
99 theme.spacing.lg,
100 ),
101 (&mut layout.padding, defaults.padding, theme.spacing.lg),
102 ] {
103 if *value == default {
104 *value = themed;
105 }
106 }
107 layout
108 }
109}
110
111impl Default for ReplayLayout {
112 fn default() -> Self {
113 Self {
114 control_bar_height: DESIGN_TOKENS.sizing.replay.control_bar_height,
115 btn_size: DESIGN_TOKENS.sizing.replay.button_size,
116 small_button_size: DESIGN_TOKENS.sizing.button_sm,
117 btn_spacing: crate::theme::Theme::default().spacing.sm,
118 progress_bar_height: crate::theme::Theme::default().spacing.lg,
119 progress_bar_width: None,
120 padding: crate::theme::Theme::default().spacing.lg,
121 speed_dropdown_width: DESIGN_TOKENS.sizing.replay.speed_dropdown_width,
122 date_display_width: DESIGN_TOKENS.sizing.replay.date_display_width,
123 }
124 }
125}
126
127#[derive(Debug, Clone)]
129pub struct ReplayBehavior {
130 pub default_speed: ReplaySpeed,
132 pub loop_playback: bool,
134 pub auto_scroll: bool,
136 pub lookahead_bars: usize,
138 pub pause_on_interaction: bool,
140 pub min_bar_duration: f64,
142 pub max_bar_duration: f64,
144 pub show_bar_counter: bool,
146 pub show_elapsed_time: bool,
148 pub show_remaining_time: bool,
150}
151
152impl Default for ReplayBehavior {
153 fn default() -> Self {
154 Self {
155 default_speed: ReplaySpeed::Normal,
156 loop_playback: false,
157 auto_scroll: true,
158 lookahead_bars: 10,
159 pause_on_interaction: false,
160 min_bar_duration: 0.01,
161 max_bar_duration: 10.0,
162 show_bar_counter: true,
163 show_elapsed_time: true,
164 show_remaining_time: true,
165 }
166 }
167}
168
169#[derive(Debug, Clone, Default)]
171pub struct ReplayConfig {
172 pub colors: ReplayColors,
174 pub layout: ReplayLayout,
176 pub behavior: ReplayBehavior,
178}
179
180impl ReplayConfig {
181 pub fn new() -> Self {
183 Self::default()
184 }
185
186 pub fn with_colors(mut self, colors: ReplayColors) -> Self {
188 self.colors = colors;
189 self
190 }
191
192 pub fn with_layout(mut self, layout: ReplayLayout) -> Self {
194 self.layout = layout;
195 self
196 }
197
198 pub fn with_behavior(mut self, behavior: ReplayBehavior) -> Self {
200 self.behavior = behavior;
201 self
202 }
203
204 pub fn compact() -> Self {
206 Self {
207 layout: ReplayLayout {
208 control_bar_height: DESIGN_TOKENS.sizing.icon_xxl,
209 btn_size: DESIGN_TOKENS.sizing.icon_lg,
210 small_button_size: DESIGN_TOKENS.sizing.technical_labels.elliott_label_size,
211 btn_spacing: crate::theme::Theme::default().spacing.xs,
212 progress_bar_height: crate::theme::Theme::default().spacing.md,
213 padding: crate::theme::Theme::default().spacing.sm,
214 speed_dropdown_width: DESIGN_TOKENS.sizing.technical_labels.pattern_label_width
215 - crate::theme::Theme::default().spacing.xxxl,
216 date_display_width: DESIGN_TOKENS.sizing.replay.date_display_width
217 - (crate::theme::Theme::default().spacing.xxxl
218 + crate::theme::Theme::default().spacing.xxl),
219 ..Default::default()
220 },
221 ..Default::default()
222 }
223 }
224
225 pub fn minimal() -> Self {
227 Self {
228 layout: ReplayLayout {
229 control_bar_height: DESIGN_TOKENS.sizing.replay.button_size,
230 btn_size: DESIGN_TOKENS.sizing.button_sm,
231 small_button_size: DESIGN_TOKENS.sizing.icon_md,
232 btn_spacing: crate::theme::Theme::default().spacing.xs,
233 progress_bar_height: crate::theme::Theme::default().spacing.sm,
234 padding: crate::theme::Theme::default().spacing.sm,
235 speed_dropdown_width: DESIGN_TOKENS.sizing.technical_labels.line_label_width,
236 date_display_width: DESIGN_TOKENS.sizing.replay.date_display_width
237 - DESIGN_TOKENS.sizing.technical_labels.pattern_label_width
238 + crate::theme::Theme::default().spacing.xxxl
239 + crate::theme::Theme::default().spacing.xxl,
240 ..Default::default()
241 },
242 behavior: ReplayBehavior {
243 show_bar_counter: false,
244 show_elapsed_time: false,
245 show_remaining_time: false,
246 ..Default::default()
247 },
248 ..Default::default()
249 }
250 }
251}