libsurfer/
overview.rs
1use crate::message::Message;
2use crate::view::{DrawConfig, DrawingContext};
3use crate::{wave_data::WaveData, SystemState};
4use egui::{Context, Frame, PointerButton, Sense, TopBottomPanel, Ui};
5use emath::{Align2, Pos2, Rect, RectTransform, Vec2};
6use epaint::CornerRadiusF32;
7
8impl SystemState {
9 pub fn add_overview_panel(&self, ctx: &Context, waves: &WaveData, msgs: &mut Vec<Message>) {
10 TopBottomPanel::bottom("overview")
11 .frame(Frame {
12 fill: self.user.config.theme.primary_ui_color.background,
13 ..Default::default()
14 })
15 .show(ctx, |ui| {
16 self.draw_overview(ui, waves, msgs);
17 });
18 }
19
20 fn draw_overview(&self, ui: &mut Ui, waves: &WaveData, msgs: &mut Vec<Message>) {
21 let (response, mut painter) = ui.allocate_painter(ui.available_size(), Sense::drag());
22 let frame_width = response.rect.width();
23 let frame_height = response.rect.height();
24 let cfg = DrawConfig::new(
25 frame_height,
26 self.user.config.layout.waveforms_line_height,
27 self.user.config.layout.waveforms_text_size,
28 );
29 let container_rect = Rect::from_min_size(Pos2::ZERO, response.rect.size());
30 let to_screen = RectTransform::from_to(container_rect, response.rect);
31
32 let mut ctx = DrawingContext {
33 painter: &mut painter,
34 cfg: &cfg,
35 to_screen: &|x, y| to_screen.transform_pos(Pos2::new(x, y) + Vec2::new(0.5, 1.)),
39 theme: &self.user.config.theme,
40 };
41
42 let num_timestamps = waves.num_timestamps().unwrap_or(1.into());
43 let viewport_all = waves.viewport_all();
44 for vidx in 0..waves.viewports.len() {
45 let minx = viewport_all.pixel_from_absolute_time(
46 waves.viewports[vidx].curr_left.absolute(&num_timestamps),
47 frame_width,
48 &num_timestamps,
49 );
50 let maxx = viewport_all.pixel_from_absolute_time(
51 waves.viewports[vidx].curr_right.absolute(&num_timestamps),
52 frame_width,
53 &num_timestamps,
54 );
55 let min = (ctx.to_screen)(minx, 0.);
56 let max = (ctx.to_screen)(maxx, container_rect.max.y);
57 ctx.painter.rect_filled(
58 Rect { min, max },
59 CornerRadiusF32::ZERO,
60 self.user
61 .config
62 .theme
63 .canvas_colors
64 .foreground
65 .gamma_multiply(0.3),
66 );
67 }
68
69 waves.draw_cursor(
70 &self.user.config.theme,
71 &mut ctx,
72 response.rect.size(),
73 &viewport_all,
74 );
75
76 let mut ticks = waves.get_ticks(
77 &viewport_all,
78 &waves.inner.metadata().timescale,
79 frame_width,
80 cfg.text_size,
81 &self.user.wanted_timeunit,
82 &self.get_time_format(),
83 &self.user.config,
84 );
85
86 if ticks.len() >= 2 {
87 ticks.pop();
88 ticks.remove(0);
89 waves.draw_ticks(
90 None,
91 &ticks,
92 &ctx,
93 frame_height * 0.5,
94 Align2::CENTER_CENTER,
95 &self.user.config,
96 );
97 }
98
99 waves.draw_markers(
100 &self.user.config.theme,
101 &mut ctx,
102 response.rect.size(),
103 &viewport_all,
104 );
105
106 waves.draw_marker_number_boxes(
107 &mut ctx,
108 response.rect.size(),
109 &self.user.config.theme,
110 &viewport_all,
111 );
112 response.dragged_by(PointerButton::Primary).then(|| {
113 let pointer_pos_global = ui.input(|i| i.pointer.interact_pos());
114 let pos = pointer_pos_global.map(|p| to_screen.inverse().transform_pos(p));
115 if let Some(pos) = pos {
116 let timestamp = viewport_all.as_time_bigint(pos.x, frame_width, &num_timestamps);
117 msgs.push(Message::GoToTime(Some(timestamp), 0));
118 }
119 });
120 }
121}