Skip to main content

libsurfer/
clock_highlighting.rs

1//! Drawing and handling of clock highlighting.
2use derive_more::{Display, FromStr};
3use egui::Ui;
4use emath::{Pos2, Rect};
5use enum_iterator::Sequence;
6use epaint::Stroke;
7use serde::{Deserialize, Serialize};
8
9use crate::{config::SurferConfig, message::Message, view::DrawingContext};
10
11#[derive(PartialEq, Copy, Clone, Debug, Deserialize, Display, FromStr, Sequence, Serialize)]
12pub enum ClockHighlightType {
13    /// Draw a line at every posedge of the clocks
14    Line,
15
16    /// Highlight every other cycle
17    Cycle,
18
19    /// No highlighting
20    None,
21}
22
23pub fn draw_clock_edge_marks(
24    clock_edges: &[f32],
25    ctx: &mut DrawingContext,
26    config: &SurferConfig,
27    clock_highlight_type: ClockHighlightType,
28) {
29    match clock_highlight_type {
30        ClockHighlightType::Line => {
31            let stroke = Stroke::from(&config.theme.clock_highlight_line);
32
33            for x in clock_edges {
34                let Pos2 {
35                    x: x_pos,
36                    y: y_start,
37                } = (ctx.to_screen)(*x, 0.);
38                ctx.painter
39                    .vline(x_pos, (y_start)..=(y_start + ctx.cfg.canvas_height), stroke);
40            }
41        }
42        ClockHighlightType::Cycle => {
43            // Process clock edges in pairs: every other cycle gets highlighted
44            let fill_color = config.theme.clock_highlight_cycle;
45
46            for chunk in clock_edges.chunks(2) {
47                if let [x_start, x_end] = chunk {
48                    let Pos2 {
49                        x: x_end_screen,
50                        y: y_start,
51                    } = (ctx.to_screen)(*x_end, 0.);
52                    ctx.painter.rect_filled(
53                        Rect {
54                            min: (ctx.to_screen)(*x_start, 0.),
55                            max: Pos2 {
56                                x: x_end_screen,
57                                y: ctx.cfg.canvas_height + y_start,
58                            },
59                        },
60                        0.0,
61                        fill_color,
62                    );
63                }
64            }
65        }
66        ClockHighlightType::None => (),
67    }
68}
69
70pub fn clock_highlight_type_menu(
71    ui: &mut Ui,
72    msgs: &mut Vec<Message>,
73    clock_highlight_type: ClockHighlightType,
74) {
75    for highlight_type in enum_iterator::all::<ClockHighlightType>() {
76        if ui
77            .radio(
78                highlight_type == clock_highlight_type,
79                highlight_type.to_string(),
80            )
81            .clicked()
82        {
83            msgs.push(Message::SetClockHighlightType(highlight_type));
84        }
85    }
86}