1use egui::{Context, Frame, Layout, Margin, TopBottomPanel, Ui};
2use emath::Align;
3use web_time::{Duration, Instant};
4
5use crate::time::{time_string, timeunit_menu};
6use crate::wave_source::draw_progress_information;
7use crate::{SystemState, message::Message, wave_data::WaveData};
8
9const PROGRESS_DEBOUNCE_MS: u64 = 100;
12
13impl SystemState {
14 pub fn add_statusbar_panel(
15 &self,
16 ctx: &Context,
17 waves: Option<&WaveData>,
18 msgs: &mut Vec<Message>,
19 ) {
20 TopBottomPanel::bottom("statusbar")
21 .frame(Frame {
22 fill: self.user.config.theme.primary_ui_color.background,
23 inner_margin: Margin {
24 left: 5,
25 right: 5,
26 top: 0,
27 bottom: 5,
28 },
29 ..Default::default()
30 })
31 .show(ctx, |ui| {
32 self.draw_statusbar(ui, waves, msgs);
33 });
34 }
35
36 fn draw_statusbar(&self, ui: &mut Ui, waves: Option<&WaveData>, msgs: &mut Vec<Message>) {
37 ui.visuals_mut().override_text_color =
38 Some(self.user.config.theme.primary_ui_color.foreground);
39 ui.with_layout(Layout::left_to_right(Align::RIGHT), |ui| {
40 self.draw_statusbar_left(ui, waves);
41 self.draw_statusbar_right(ui, waves, msgs);
42 });
43 }
44
45 fn draw_statusbar_left(&self, ui: &mut Ui, waves: Option<&WaveData>) {
47 if let Some(waves) = waves {
48 ui.label(waves.source.to_string());
49 if let Some(idx) = self.user.selected_server_file_index
50 && let Some(infos) = self.user.surver_file_infos.as_ref()
51 && let Some(file) = infos.get(idx)
52 {
53 ui.separator();
54 ui.label(&file.filename);
55 }
56 if let Some(datetime) = waves.inner.metadata().date {
57 ui.separator();
58 ui.label(format!("Generated: {datetime}"));
59 }
60 }
61
62 if let Some(state_file) = &self.user.state_file {
63 ui.separator();
64 ui.label(state_file.to_string_lossy());
65 }
66
67 if let Some(progress_data) = &self.progress_tracker
68 && Instant::now().duration_since(progress_data.started)
69 > Duration::from_millis(PROGRESS_DEBOUNCE_MS)
70 {
71 ui.separator();
72 draw_progress_information(ui, progress_data);
73 }
74
75 if let Some(waves) = waves {
77 let in_progress_count = waves.inflight_caches.len();
78 if in_progress_count > 0 {
79 ui.separator();
80 ui.spinner();
81 if in_progress_count == 1 {
82 ui.label("Building analog cache…");
83 } else {
84 ui.label(format!("Building {in_progress_count} analog caches…"));
85 }
86 }
87 }
88 }
89
90 fn draw_statusbar_right(&self, ui: &mut Ui, waves: Option<&WaveData>, msgs: &mut Vec<Message>) {
92 if let Some(waves) = waves {
93 ui.with_layout(Layout::right_to_left(Align::RIGHT), |ui| {
94 if let Some(time) = &waves.cursor {
95 ui.label(time_string(
96 time,
97 &waves.inner.metadata().timescale,
98 &self.user.wanted_timeunit,
99 &self.get_time_format(),
100 ))
101 .context_menu(|ui| timeunit_menu(ui, msgs, &self.user.wanted_timeunit));
102 }
103 if let Some(undo_op) = &self.undo_stack.last() {
104 ui.separator();
105 ui.label(format!("Undo: {}", undo_op.message));
106 }
107 if let Some(count) = &self.user.count {
108 ui.separator();
109 ui.label(format!("Count: {count}"));
110 }
111 });
112 }
113 }
114}