libsurfer/
clock_highlighting.rs

1//! Drawing and handling of clock highlighting.
2use std::str::FromStr;
3
4use derive_more::Display;
5use egui::Ui;
6use emath::{Pos2, Rect};
7use enum_iterator::Sequence;
8use epaint::Stroke;
9use serde::Deserialize;
10
11use crate::{config::SurferConfig, message::Message, view::DrawingContext};
12
13#[derive(PartialEq, Copy, Clone, Debug, Deserialize, Display, Sequence)]
14pub enum ClockHighlightType {
15    /// Draw a line at every posedge of the clocks
16    #[display("Line")]
17    Line,
18
19    /// Highlight every other cycle
20    #[display("Cycle")]
21    Cycle,
22
23    /// No highlighting
24    #[display("None")]
25    None,
26}
27
28impl FromStr for ClockHighlightType {
29    type Err = String;
30
31    fn from_str(input: &str) -> Result<ClockHighlightType, Self::Err> {
32        match input {
33            "Line" => Ok(ClockHighlightType::Line),
34            "Cycle" => Ok(ClockHighlightType::Cycle),
35            "None" => Ok(ClockHighlightType::None),
36            _ => Err(format!(
37                "'{input}' is not a valid ClockHighlightType (Valid options: Line|Cycle|None)"
38            )),
39        }
40    }
41}
42
43pub fn draw_clock_edge(
44    x_start: f32,
45    x_end: f32,
46    cycle: bool,
47    ctx: &mut DrawingContext,
48    config: &SurferConfig,
49) {
50    match config.default_clock_highlight_type {
51        ClockHighlightType::Line => {
52            let Pos2 {
53                x: x_pos,
54                y: y_start,
55            } = (ctx.to_screen)(x_start, 0.);
56            ctx.painter.vline(
57                x_pos,
58                (y_start)..=(y_start + ctx.cfg.canvas_height),
59                Stroke {
60                    color: config.theme.clock_highlight_line.color,
61                    width: config.theme.clock_highlight_line.width,
62                },
63            );
64        }
65        ClockHighlightType::Cycle => {
66            if cycle {
67                let Pos2 {
68                    x: x_end,
69                    y: y_start,
70                } = (ctx.to_screen)(x_end, 0.);
71                ctx.painter.rect_filled(
72                    Rect {
73                        min: (ctx.to_screen)(x_start, 0.),
74                        max: Pos2 {
75                            x: x_end,
76                            y: ctx.cfg.canvas_height + y_start,
77                        },
78                    },
79                    0.0,
80                    config.theme.clock_highlight_cycle,
81                );
82            }
83        }
84        ClockHighlightType::None => (),
85    }
86}
87
88pub fn clock_highlight_type_menu(
89    ui: &mut Ui,
90    msgs: &mut Vec<Message>,
91    clock_highlight_type: ClockHighlightType,
92) {
93    for highlight_type in enum_iterator::all::<ClockHighlightType>() {
94        ui.radio(
95            highlight_type == clock_highlight_type,
96            highlight_type.to_string(),
97        )
98        .clicked()
99        .then(|| {
100            ui.close_menu();
101            msgs.push(Message::SetClockHighlightType(highlight_type));
102        });
103    }
104}