Skip to main content

libsurfer/
overview.rs

1use crate::message::Message;
2use crate::view::{DrawConfig, DrawingContext};
3use crate::viewport::Viewport;
4use crate::{SystemState, wave_data::WaveData};
5use egui::{Frame, Panel, PointerButton, Sense, Ui};
6use emath::{Align2, Pos2, Rect, RectTransform};
7use epaint::CornerRadius;
8
9impl SystemState {
10    pub fn add_overview_panel(&self, ui: &mut Ui, waves: &WaveData, msgs: &mut Vec<Message>) {
11        Panel::bottom("overview")
12            .frame(Frame {
13                fill: self.user.config.theme.primary_ui_color.background,
14                ..Default::default()
15            })
16            .show_inside(ui, |ui| {
17                self.draw_overview(ui, waves, msgs);
18            });
19    }
20
21    fn draw_overview(&self, ui: &mut Ui, waves: &WaveData, msgs: &mut Vec<Message>) {
22        let (response, mut painter) = ui.allocate_painter(ui.available_size(), Sense::drag());
23        let frame_size = response.rect.size();
24        let frame_width = frame_size.x;
25        let frame_height = frame_size.y;
26        let cfg = DrawConfig::new(
27            frame_height,
28            frame_width,
29            self.user.config.layout.waveforms_line_height,
30            self.user.config.layout.waveforms_text_size,
31        );
32        let container_rect = Rect::from_min_size(Pos2::ZERO, frame_size);
33        let to_screen = RectTransform::from_to(container_rect, response.rect);
34
35        let mut ctx = DrawingContext {
36            painter: &mut painter,
37            cfg: &cfg,
38            to_screen: &|x, y| to_screen.transform_pos(Pos2::new(x, y)),
39            theme: &self.user.config.theme,
40        };
41
42        let num_timestamps = waves.safe_num_timestamps();
43        let viewport_all = waves.viewport_all();
44        let fill_color = self
45            .user
46            .config
47            .theme
48            .canvas_colors
49            .foreground
50            .gamma_multiply(0.3);
51
52        // Draw rectangles for each viewport
53        waves
54            .viewports
55            .iter()
56            .map(|viewport| get_viewport_rect(&ctx, &num_timestamps, &viewport_all, viewport))
57            .for_each(|rect| {
58                ctx.painter
59                    .rect_filled(rect, CornerRadius::ZERO, fill_color);
60            });
61
62        // Draw cursor
63        waves.draw_cursor(&self.user.config.theme, &mut ctx, &viewport_all);
64
65        // Draw ticks
66        let mut ticks = self.get_ticks_for_viewport(waves, &viewport_all, &cfg);
67
68        if ticks.len() >= 2 {
69            // Remove first and last tick
70            ticks.pop();
71            ticks.remove(0);
72            // Draw ticks
73            waves.draw_ticks(
74                self.user.config.theme.foreground,
75                &ticks,
76                &ctx,
77                frame_height * 0.5,
78                Align2::CENTER_CENTER,
79            );
80        }
81
82        // Draw markers
83        waves.draw_markers(&self.user.config.theme, &mut ctx, &viewport_all);
84        waves.draw_marker_number_boxes(&mut ctx, &self.user.config.theme, &viewport_all);
85
86        // Handle dragging of the primary viewport
87        response.dragged_by(PointerButton::Primary).then(|| {
88            let pointer_pos_global = ui.input(|i| i.pointer.interact_pos());
89            let pos = pointer_pos_global.map(|p| to_screen.inverse().transform_pos(p));
90            if let Some(pos) = pos {
91                let timestamp = viewport_all.as_time_bigint(pos.x, frame_width, &num_timestamps);
92                msgs.push(Message::GoToTime(Some(timestamp), 0));
93            }
94        });
95    }
96}
97
98fn get_viewport_rect(
99    ctx: &DrawingContext<'_>,
100    num_timestamps: &num::BigInt,
101    viewport_all: &Viewport,
102    viewport: &Viewport,
103) -> Rect {
104    let minx = viewport_all.pixel_from_absolute_time(
105        viewport.curr_left.absolute(num_timestamps),
106        ctx.cfg.canvas_width,
107        num_timestamps,
108    );
109    let maxx = viewport_all.pixel_from_absolute_time(
110        viewport.curr_right.absolute(num_timestamps),
111        ctx.cfg.canvas_width,
112        num_timestamps,
113    );
114    let min = (ctx.to_screen)(minx, 0.);
115    let max = (ctx.to_screen)(maxx, ctx.cfg.canvas_height);
116    Rect { min, max }
117}