1use ratatui::widgets::Tabs;
5use ratatui::text::{Span, Line};
6use ratatui::style::{Color, Modifier, Style};
7use ratatui::widgets::{Block, Borders};
8use ratatui::Frame;
9use ratatui::layout::Rect;
10
11use crate::colors::{
12 ColorTheme
13};
14
15#[derive(Copy, Clone, Debug, PartialEq)]
16pub enum ActiveMenu {
17 MainMenu,
18 RBMenu,
19 Paddles,
20 Trigger,
21 Events,
22 Monitoring,
23 Heartbeats,
24 Telemetry,
25}
26
27#[derive(Copy, Clone, Debug, PartialEq)]
28pub enum MenuItem {
29 Home,
30 TofEvents,
35 TofSummary,
36 TofHits,
37 RBWaveform,
38 ReadoutBoards,
39 MasterTrigger,
40 TOFCpu,
41 Telemetry,
42 Settings,
43 Quit,
44}
45
46
47impl From<MenuItem> for usize {
48 fn from(input: MenuItem) -> usize {
49 match input {
50 MenuItem::Home => 0,
51 MenuItem::TofEvents => 1,
52 MenuItem::ReadoutBoards => 2,
53 MenuItem::TofSummary => 3,
54 MenuItem::RBWaveform => 4,
55 MenuItem::TofHits => 5,
56 MenuItem::MasterTrigger => 6,
60 MenuItem::TOFCpu => 7,
61 MenuItem::Telemetry => 8,
62 MenuItem::Settings => 9,
63 MenuItem::Quit => 10,
64 }
65 }
66}
67
68
69#[derive(Copy, Clone, Debug, PartialEq)]
70pub enum UIMenuItem {
71 Unknown,
72 Home,
74 Back,
75 Events,
76 ReadoutBoards,
77 Paddles,
78 Trigger,
79 Monitoring,
80 Telemetry,
81 Commands,
82 Settings,
83 Alerts,
84 Quit,
85 Waveforms,
87 GlobalRates,
88 RBMoniData,
89 PAMoniData,
90 PBMoniData,
91 LTBMoniData,
92 SelectBoard,
93 TofSummary,
95 TofEvents,
96 TofHits,
97 RBWaveform,
98 PreampBias,
100 PreampTemp,
101 LTBThresholds,
102 Signal,
104 RecoVars,
105 Heartbeats,
107 EventBuilderHB,
108 TriggerHB,
109 DataSenderHB,
110 Yes,
112 No,
113 Stream,
115 MergedEvents,
116 GPS,
117}
118
119impl UIMenuItem {
120
121 pub fn get_title(&self) -> String {
122 match self {
123 UIMenuItem::Unknown => String::from("Unknown" ),
124 UIMenuItem::Home => String::from("Home" ),
125 UIMenuItem::Back => String::from("Back" ),
126 UIMenuItem::Events => String::from("Events" ),
127 UIMenuItem::ReadoutBoards => String::from("ReadoutBoards" ),
128 UIMenuItem::Trigger => String::from("Trigger" ),
129 UIMenuItem::Alerts => String::from("Alerts" ),
130 UIMenuItem::Monitoring => String::from("Monitoring" ),
131 UIMenuItem::Telemetry => String::from("Telemetry" ),
132 UIMenuItem::Settings => String::from("Settings" ),
133 UIMenuItem::Commands => String::from("Commands" ),
134 UIMenuItem::Quit => String::from("Quit" ),
135 UIMenuItem::Waveforms => String::from("Waveforms" ),
136 UIMenuItem::GlobalRates => String::from("GlobalRates" ),
137 UIMenuItem::RBMoniData => String::from("RBMoniData" ),
138 UIMenuItem::PAMoniData => String::from("PAMoniData" ),
139 UIMenuItem::PBMoniData => String::from("PBMoniData" ),
140 UIMenuItem::LTBMoniData => String::from("LTBMoniData" ),
141 UIMenuItem::SelectBoard => String::from("SelectBoard" ),
142 UIMenuItem::TofSummary => String::from("TofSummary" ),
143 UIMenuItem::TofEvents => String::from("TofEvents" ),
144 UIMenuItem::TofHits => String::from("TofHits" ),
145 UIMenuItem::RBWaveform => String::from("RBWaveform" ),
146 UIMenuItem::PreampBias => String::from("Preamp Bias Voltages" ),
147 UIMenuItem::PreampTemp => String::from("Preamp Temps"),
148 UIMenuItem::LTBThresholds => String::from("LTBThresholds"),
149 UIMenuItem::Paddles => String::from("Paddles"),
150 UIMenuItem::Signal => String::from("Wf & Charge"),
151 UIMenuItem::RecoVars => String::from("Reco Vars"),
152 UIMenuItem::Heartbeats => String::from("Heartbeats"),
153 UIMenuItem::EventBuilderHB => String::from("EventBuilderHB"),
154 UIMenuItem::TriggerHB => String::from("TriggerHB"),
155 UIMenuItem::DataSenderHB => String::from("DataSenderHB"),
156 UIMenuItem::Yes => String::from("Yes"),
157 UIMenuItem::No => String::from("No"),
158 UIMenuItem::Stream => String::from("Stream"),
159 UIMenuItem::MergedEvents => String::from("MergedEvents"),
160 UIMenuItem::GPS => String::from("GPS"),
161 }
163 }
164}
165
166
167pub trait UIMenu<'a> {
168
169 fn get_max_idx() -> usize {
170 Self::get_items().len() - 1
171 }
172
173 fn get_items() -> Vec<UIMenuItem>;
174
175 fn get_active_menu_item(&self) -> UIMenuItem;
176
177 fn set_active_menu_item(&mut self, item : UIMenuItem);
178
179 fn get_active_idx(&self) -> usize;
180
181 fn set_active_idx(&mut self, idx : usize);
182
183 fn get_theme(&self) -> ColorTheme;
184
185 fn get_titles(theme : ColorTheme) -> Vec<Line<'a>> {
186 let mut titles = Vec::<Line>::new();
187 for item in Self::get_items().clone() {
188 let ti = item.get_title().clone();
189 let line = Line::from(vec![Span::styled(ti, theme.style()),]);
190 titles.push(line);
191 }
192 titles
193 }
194
195 fn next(&mut self) {
196 if self.get_active_idx() + 1 > Self::get_max_idx() {
197 self.set_active_menu_item(Self::get_items()[0]);
198 self.set_active_idx(0);
199 } else {
200 self.set_active_menu_item(Self::get_items()[self.get_active_idx() + 1]);
201 self.set_active_idx(self.get_active_idx() + 1);
202 }
203 }
204
205 fn prev(&mut self) {
206 if self.get_active_idx() == 0 {
207 self.set_active_menu_item(Self::get_items()[Self::get_max_idx()]);
208 self.set_active_idx(Self::get_max_idx());
209 } else {
210 self.set_active_menu_item(Self::get_items()[self.get_active_idx() -1]);
211 self.set_active_idx(self.get_active_idx() - 1);
212 }
213 }
214
215 fn render(&mut self, main_window : &Rect, frame : &mut Frame) {
216 let theme = self.get_theme();
217 let tabs = Tabs::new(Self::get_titles(theme))
218 .select(self.get_active_idx())
219 .block(Block::default().title("Menu").borders(Borders::ALL))
220 .style(self.get_theme().style())
221 .highlight_style(self.get_theme().highlight())
222 .divider(Span::raw("|"));
223 frame.render_widget(tabs, *main_window);
224 }
225}
226
227
228#[derive(Debug, Clone)]
229pub struct MainMenu<'a> {
230 pub theme : ColorTheme,
231 pub active_index : usize,
232 pub titles : Vec<Line<'a>>,
233 pub active_menu_item : MenuItem,
234 pub active_menu_item2 : UIMenuItem,
235}
236
237impl UIMenu<'_> for MainMenu<'_> {
238 fn get_items() -> Vec<UIMenuItem> {
239 let items = vec![UIMenuItem::Home,
240 UIMenuItem::Events,
241 UIMenuItem::ReadoutBoards,
242 UIMenuItem::Paddles,
243 UIMenuItem::Trigger,
244 UIMenuItem::Alerts,
245 UIMenuItem::Heartbeats,
246 UIMenuItem::Monitoring,
247 UIMenuItem::Telemetry,
248 UIMenuItem::Commands,
249 UIMenuItem::Settings,
250 UIMenuItem::Quit];
251 items
252 }
253
254 fn get_theme(&self) -> ColorTheme {
255 self.theme.clone()
256 }
257
258 fn set_active_menu_item(&mut self, item : UIMenuItem) {
259 self.active_menu_item2 = item;
260 }
261
262 fn set_active_idx(&mut self, idx : usize) {
263 self.active_index = idx;
264 }
265
266 fn get_active_idx(&self) -> usize {
267 self.active_index
268 }
269
270 fn get_active_menu_item(&self) -> UIMenuItem {
271 self.active_menu_item2
272 }
273}
274
275impl MainMenu<'_> {
276 pub fn new(theme : ColorTheme) -> Self {
277 let titles = Self::get_titles(theme);
278 let theme_cl = theme.clone();
279 Self {
280 theme : theme_cl,
281 active_index : 0,
282 titles,
283 active_menu_item : MenuItem::Home,
284 active_menu_item2 : UIMenuItem::Home,
285 }
286 }
287}
288
289#[derive(Debug, Clone)]
292pub struct RBMenu2<'a> {
293 pub theme : ColorTheme,
294 pub active_menu_item : RBMenuItem,
295 pub active_menu_item2 : UIMenuItem,
296 pub active_index : usize,
297 pub titles : Vec<Line<'a>>,
298}
299
300impl UIMenu<'_> for RBMenu2<'_> {
301
302 fn get_items() -> Vec<UIMenuItem> {
303 let items = vec![UIMenuItem::Back,
304 UIMenuItem::Waveforms,
305 UIMenuItem::GlobalRates,
306 UIMenuItem::RBMoniData,
307 UIMenuItem::PBMoniData,
308 UIMenuItem::PAMoniData,
309 UIMenuItem::LTBMoniData];
310 items
312 }
313
314 fn get_theme(&self) -> ColorTheme {
315 self.theme
316 }
317
318 fn set_active_idx(&mut self, idx : usize) {
319 self.active_index = idx;
320 }
321
322 fn get_active_idx(&self) -> usize {
323 self.active_index
324 }
325
326 fn set_active_menu_item(&mut self, item : UIMenuItem) {
327 self.active_menu_item2 = item;
328 }
329
330 fn get_active_menu_item(&self) -> UIMenuItem {
331 match self.active_index {
332 0 => UIMenuItem::Back,
333 1 => UIMenuItem::Waveforms,
334 2 => UIMenuItem::GlobalRates,
335 3 => UIMenuItem::RBMoniData,
336 4 => UIMenuItem::PAMoniData,
337 5 => UIMenuItem::PBMoniData,
338 6 => UIMenuItem::LTBMoniData,
339 7 => UIMenuItem::SelectBoard,
340 8 => UIMenuItem::Quit,
341 _ => UIMenuItem::Unknown
342 }
343 }
344}
345
346impl RBMenu2<'_> {
347
348 pub fn new(theme : ColorTheme) -> Self {
349 let title_str = vec!["Back",
350 "Waveforms",
351 "GlobalRates",
352 "RBMoniData",
353 "PBMoniData", "PAMoniData",
354 "LTBMoniData",
355 "SelectBoards [LTB & RB]"];
356
357 let titles : Vec<Line> = title_str
358 .iter()
359 .map(|t| {
360 Line::from(vec![
361 Span::styled(*t, theme.style()),
362 ])
363 })
364 .collect();
365
366 Self {
367 theme,
368 active_index : 0,
369 titles,
370 active_menu_item : RBMenuItem::Home,
371 active_menu_item2 : UIMenuItem::Home,
372 }
373 }
374}
375
376#[derive(Debug, Clone)]
377pub struct TriggerMenu<'a> {
378 pub theme : ColorTheme,
379 pub active_menu_item : UIMenuItem,
380 pub active_index : usize,
381 pub titles : Vec<Line<'a>>,
382}
383
384impl UIMenu<'_> for TriggerMenu<'_> {
385
386 fn get_items() -> Vec<UIMenuItem> {
387 let items = vec![UIMenuItem::Back,
388 UIMenuItem::Quit];
389 items
390 }
391
392 fn get_theme(&self) -> ColorTheme {
393 self.theme
394 }
395
396 fn set_active_idx(&mut self, idx : usize) {
397 self.active_index = idx;
398 }
399
400 fn get_active_idx(&self) -> usize {
401 self.active_index
402 }
403
404 fn set_active_menu_item(&mut self, item : UIMenuItem) {
405 self.active_menu_item = item;
406 }
407
408 fn get_active_menu_item(&self) -> UIMenuItem {
409 self.active_menu_item
410 }
411}
412
413impl TriggerMenu<'_> {
414
415 pub fn new(theme : ColorTheme) -> Self {
416 let theme_c = theme.clone();
417 let titles = Self::get_titles(theme_c);
418 Self {
419 theme,
420 active_index : 0,
421 titles,
422 active_menu_item : UIMenuItem::Back,
423 }
424 }
425}
426
427#[derive(Debug, Clone)]
430pub struct EventMenu<'a> {
431 pub theme : ColorTheme,
432 pub active_menu_item : UIMenuItem,
433 pub active_index : usize,
434 pub titles : Vec<Line<'a>>,
435}
436
437impl UIMenu<'_> for EventMenu<'_> {
438
439 fn get_items() -> Vec<UIMenuItem> {
440 let items = vec![UIMenuItem::Back,
441 UIMenuItem::TofSummary];
442 items
443 }
444
445 fn get_theme(&self) -> ColorTheme {
446 self.theme
447 }
448
449 fn set_active_idx(&mut self, idx : usize) {
450 self.active_index = idx;
451 }
452
453 fn get_active_idx(&self) -> usize {
454 self.active_index
455 }
456
457 fn set_active_menu_item(&mut self, item : UIMenuItem) {
458 self.active_menu_item = item;
459 }
460
461 fn get_active_menu_item(&self) -> UIMenuItem {
462 self.active_menu_item
463 }
464}
465
466impl EventMenu<'_> {
467
468 pub fn new(theme : ColorTheme) -> Self {
469 let theme_c = theme.clone();
470 let titles = Self::get_titles(theme_c);
471 Self {
472 theme,
473 active_index : 0,
474 titles,
475 active_menu_item : UIMenuItem::Back,
476 }
477 }
478}
479
480#[derive(Debug, Clone)]
483pub struct PaddleMenu<'a> {
484 pub theme : ColorTheme,
485 pub active_menu_item : UIMenuItem,
486 pub active_index : usize,
487 pub titles : Vec<Line<'a>>,
488}
489
490impl UIMenu<'_> for PaddleMenu<'_> {
491
492 fn get_items() -> Vec<UIMenuItem> {
493 let items = vec![UIMenuItem::Back,
494 UIMenuItem::Signal,
495 UIMenuItem::RecoVars];
496 items
497 }
498
499 fn get_theme(&self) -> ColorTheme {
500 self.theme
501 }
502
503 fn set_active_idx(&mut self, idx : usize) {
504 self.active_index = idx;
505 }
506
507 fn get_active_idx(&self) -> usize {
508 self.active_index
509 }
510
511 fn set_active_menu_item(&mut self, item : UIMenuItem) {
512 self.active_menu_item = item;
513 }
514
515 fn get_active_menu_item(&self) -> UIMenuItem {
516 self.active_menu_item
517 }
518}
519
520impl PaddleMenu<'_> {
521
522 pub fn new(theme : ColorTheme) -> Self {
523 let theme_c = theme.clone();
524 let titles = Self::get_titles(theme_c);
525 Self {
526 theme,
527 active_index : 0,
528 titles,
529 active_menu_item : UIMenuItem::Back,
530 }
531 }
532}
533
534#[derive(Debug, Clone)]
537pub struct HBMenu<'a> {
538 pub theme : ColorTheme,
539 pub active_menu_item : UIMenuItem,
540 pub active_index : usize,
541 pub titles : Vec<Line<'a>>,
542}
543
544impl UIMenu<'_> for HBMenu<'_> {
545
546 fn get_items() -> Vec<UIMenuItem> {
547 let items = vec![UIMenuItem::Back,
548 UIMenuItem::EventBuilderHB,
549 UIMenuItem::TriggerHB,
550 UIMenuItem::DataSenderHB];
551 items
552 }
553
554 fn get_theme(&self) -> ColorTheme {
555 self.theme
556 }
557
558 fn set_active_idx(&mut self, idx : usize) {
559 self.active_index = idx;
560 }
561
562 fn get_active_idx(&self) -> usize {
563 self.active_index
564 }
565
566 fn set_active_menu_item(&mut self, item : UIMenuItem) {
567 self.active_menu_item = item;
568 }
569
570 fn get_active_menu_item(&self) -> UIMenuItem {
571 self.active_menu_item
572 }
573}
574
575impl HBMenu<'_> {
576
577 pub fn new(theme : ColorTheme) -> Self {
578 let theme_c = theme.clone();
579 let titles = Self::get_titles(theme_c);
580 Self {
581 theme,
582 active_index : 0,
583 titles,
584 active_menu_item : UIMenuItem::Back,
585 }
586 }
587}
588
589#[derive(Debug, Clone)]
592pub struct TelemetryMenu<'a> {
593 pub theme : ColorTheme,
594 pub active_menu_item : UIMenuItem,
595 pub active_index : usize,
596 pub titles : Vec<Line<'a>>,
597}
598
599impl UIMenu<'_> for TelemetryMenu<'_> {
600
601 fn get_items() -> Vec<UIMenuItem> {
602 let items = vec![UIMenuItem::Back,
603 UIMenuItem::MergedEvents];
604 items
605 }
606
607 fn get_theme(&self) -> ColorTheme {
608 self.theme
609 }
610
611 fn set_active_idx(&mut self, idx : usize) {
612 self.active_index = idx;
613 }
614
615 fn get_active_idx(&self) -> usize {
616 self.active_index
617 }
618
619 fn set_active_menu_item(&mut self, item : UIMenuItem) {
620 self.active_menu_item = item;
621 }
622
623 fn get_active_menu_item(&self) -> UIMenuItem {
624 self.active_menu_item
625 }
626}
627
628impl TelemetryMenu<'_> {
629
630 pub fn new(theme : ColorTheme) -> Self {
631 let theme_c = theme.clone();
632 let titles = Self::get_titles(theme_c);
633 Self {
634 theme,
635 active_index : 0,
636 titles,
637 active_menu_item : UIMenuItem::Back,
638 }
639 }
640}
641
642#[derive(Debug, Clone)]
645pub struct MoniMenu<'a> {
646 pub theme : ColorTheme,
647 pub active_menu_item : UIMenuItem,
648 pub active_index : usize,
649 pub titles : Vec<Line<'a>>,
650}
651
652impl UIMenu<'_> for MoniMenu<'_> {
653
654 fn get_items() -> Vec<UIMenuItem> {
655 let items = vec![UIMenuItem::Back,
656 UIMenuItem::PreampBias,
657 UIMenuItem::PreampTemp,
658 UIMenuItem::LTBThresholds,
659 UIMenuItem::Quit];
660 items
661 }
662
663 fn get_theme(&self) -> ColorTheme {
664 self.theme
665 }
666
667 fn set_active_idx(&mut self, idx : usize) {
668 self.active_index = idx;
669 }
670
671 fn get_active_idx(&self) -> usize {
672 self.active_index
673 }
674
675 fn set_active_menu_item(&mut self, item : UIMenuItem) {
676 self.active_menu_item = item;
677 }
678
679 fn get_active_menu_item(&self) -> UIMenuItem {
680 self.active_menu_item
681 }
682}
683
684impl MoniMenu<'_> {
685
686 pub fn new(theme : ColorTheme) -> Self {
687 let theme_c = theme.clone();
688 let titles = Self::get_titles(theme_c);
689 Self {
690 theme,
691 active_index : 0,
692 titles,
693 active_menu_item : UIMenuItem::Back,
694 }
695 }
696}
697
698#[derive(Debug, Copy, Clone)]
703pub enum MTMenuItem {
704 Home,
705 Quit
706}
707
708impl From<MTMenuItem> for usize {
709 fn from(input: MTMenuItem) -> usize {
710 match input {
711 MTMenuItem::Home => 0,
712 MTMenuItem::Quit => 1,
713 }
714 }
715}
716
717
718#[derive(Debug, Copy, Clone)]
722pub enum TEMenuItem {
723 Home,
724 Quit
725}
726
727impl From<TEMenuItem> for usize {
728 fn from(input: TEMenuItem) -> usize {
729 match input {
730 TEMenuItem::Home => 0,
731 TEMenuItem::Quit => 1,
732 }
733 }
734}
735
736
737#[derive(Debug, Copy, Clone, PartialEq)]
740pub enum RBMenuItem {
741 Home,
742 Info,
743 Waveforms,
744 RBMoniData,
745 PAMoniData,
746 PBMoniData,
747 LTBMoniData,
748 SelectRB,
749 Quit,
750}
751
752impl From<RBMenuItem> for usize {
753 fn from(input: RBMenuItem) -> usize {
754 match input {
755 RBMenuItem::Home => 0,
756 RBMenuItem::Info => 1,
757 RBMenuItem::Waveforms => 2,
758 RBMenuItem::RBMoniData => 3,
759 RBMenuItem::PAMoniData => 4,
760 RBMenuItem::PBMoniData => 5,
761 RBMenuItem::LTBMoniData => 6,
762 RBMenuItem::SelectRB => 7,
763 RBMenuItem::Quit => 8,
764 }
765 }
766}
767
768#[derive(Debug, Copy, Clone, PartialEq)]
769pub enum PAMoniMenuItem {
770 Back,
771 Temperatures,
772 Biases,
773 Quit,
774}
775
776impl From<PAMoniMenuItem> for usize {
777 fn from(input: PAMoniMenuItem) -> usize {
778 match input {
779 PAMoniMenuItem::Back => 0,
780 PAMoniMenuItem::Temperatures => 1,
781 PAMoniMenuItem::Biases => 2,
782 PAMoniMenuItem::Quit => 3
783 }
784 }
785}
786
787#[derive(Debug, Clone)]
788pub struct PAMoniMenu {
789 pub theme : ColorTheme,
790 pub active_menu_item : PAMoniMenuItem,
791}
792
793impl PAMoniMenu {
794 pub fn new(theme : ColorTheme) -> Self {
795 Self {
796 theme,
797 active_menu_item : PAMoniMenuItem::Temperatures,
798 }
799 }
800
801 pub fn render(&mut self, main_window : &Rect, frame : &mut Frame) {
802 let menu_titles = vec!["Back", "Temperatures", "Biases", "Quit"];
803 let menu : Vec<Line> = menu_titles
804 .iter()
805 .map(|t| {
806 if t == &"Biases" {
807 let (a, b) = t.split_at(2);
808 let (highlight, c) = b.split_at(1);
809 Line::from(vec![
810 Span::styled(a, self.theme.style()),
811 Span::styled(
812 highlight,
813 Style::default()
814 .fg(self.theme.hc)
815 .add_modifier(Modifier::UNDERLINED),
816 ),
817 Span::styled(c, self.theme.style()),
818 ])
819 } else {
820 let (first, rest) = t.split_at(1);
821 Line::from(vec![
822 Span::styled(
823 first,
824 Style::default()
825 .fg(self.theme.hc)
826 .add_modifier(Modifier::UNDERLINED),
827 ),
828 Span::styled(rest, self.theme.style()),
829 ])
830 }
831 })
832 .collect();
833
834 let tabs = Tabs::new(menu)
835 .select(usize::from(self.active_menu_item))
836 .block(Block::default().title("Menu").borders(Borders::ALL))
837 .style(self.theme.style())
838 .highlight_style(self.theme.highlight())
839 .divider(Span::raw("|"));
840 frame.render_widget(tabs, *main_window);
841 }
842}
843
844#[derive(Debug, Clone)]
845pub struct RBMenu {
846 pub theme : ColorTheme,
847 pub active_menu_item : RBMenuItem,
848}
849
850impl RBMenu {
851
852 pub fn new(theme : ColorTheme) -> RBMenu {
853 RBMenu {
854 theme,
855 active_menu_item : RBMenuItem::Home,
856 }
857 }
858
859 pub fn render(&mut self, main_window : &Rect, frame : &mut Frame) {
860 let menu_titles = vec!["Home", "Info", "Waveforms", "RBMoniData", "PAMoniData", "PBMoniData", "LTBMoniData", "SelectBoards [LTB & RB]", "Quit" ];
861 let menu : Vec<Line> = menu_titles
862 .iter()
863 .map(|t| {
864 if t == &"PBMoniData" || t == &"Hits" {
865 let (second, rest) = t.split_at(2);
866 Line::from(vec![
867 Span::styled(
868 second,
869 Style::default()
870 .fg(self.theme.hc)
871 .add_modifier(Modifier::UNDERLINED),
872 ),
873 Span::styled(rest, self.theme.style()),
874 ])
875 } else {
876 let (first, rest) = t.split_at(1);
877 Line::from(vec![
878 Span::styled(
879 first,
880 Style::default()
881 .fg(self.theme.hc)
882 .add_modifier(Modifier::UNDERLINED),
883 ),
884 Span::styled(rest, self.theme.style()),
885 ])
886 }
887 })
888 .collect();
889
890 let tabs = Tabs::new(menu)
891 .select(usize::from(self.active_menu_item))
892 .block(Block::default().title("Menu").borders(Borders::ALL))
893 .style(self.theme.style())
894 .highlight_style(self.theme.highlight())
895 .divider(Span::raw("|"));
896 frame.render_widget(tabs, *main_window);
897 }
898}
899
900#[derive(Debug, Copy, Clone)]
903pub enum SettingsMenuItem {
904 Home,
905 Quit
906}
907
908impl From<SettingsMenuItem> for usize {
909 fn from(input: SettingsMenuItem) -> usize {
910 match input {
911 SettingsMenuItem::Home => 0,
912 SettingsMenuItem::Quit => 1,
913 }
914 }
915}
916
917#[derive(Debug, Clone)]
918pub struct SettingsMenu {
919 pub theme : ColorTheme,
920 pub active_menu_item : SettingsMenuItem,
921}
922
923impl SettingsMenu {
924
925 pub fn new(theme : ColorTheme) -> SettingsMenu {
926 SettingsMenu {
927 theme,
928 active_menu_item : SettingsMenuItem::Home,
929 }
930 }
931
932 pub fn render(&mut self, main_window : &Rect, frame : &mut Frame) {
933 let menu_titles : Vec<&str> = vec!["Home", "Quit" ];
934 let menu : Vec<Line> = menu_titles
935 .iter()
936 .map(|t| {
937 let (first, rest) = t.split_at(1);
938 Line::from(vec![
939 Span::styled(
940 first,
941 Style::default()
942 .fg(Color::Yellow)
943 .add_modifier(Modifier::UNDERLINED),
944 ),
945 Span::styled(rest, self.theme.style()),
946 ])
947 })
948 .collect();
949
950 let tabs = Tabs::new(menu)
951 .select(usize::from(self.active_menu_item))
952 .block(Block::default().title("Menu").borders(Borders::ALL))
953 .style(self.theme.style())
954 .highlight_style(self.theme.highlight())
955 .divider(Span::raw("|"));
956 frame.render_widget(tabs, *main_window);
957 }
958}
959
960#[derive(Debug, Copy, Clone)]
963pub enum TSMenuItem {
964 Home,
965 Quit
966}
967
968impl From<TSMenuItem> for usize {
969 fn from(input: TSMenuItem) -> usize {
970 match input {
971 TSMenuItem::Home => 0,
972 TSMenuItem::Quit => 1,
973 }
974 }
975}
976
977#[derive(Debug, Clone)]
978pub struct TSMenu {
979 pub theme : ColorTheme,
980 pub active_menu_item : TSMenuItem,
981}
982
983impl TSMenu {
984
985 pub fn new(theme : ColorTheme) -> TSMenu {
986 TSMenu {
987 theme,
988 active_menu_item : TSMenuItem::Home,
989 }
990 }
991
992 pub fn render(&mut self, main_window : &Rect, frame : &mut Frame) {
993 let menu_titles : Vec<&str> = vec!["Home", "Quit" ];
994 let menu : Vec<Line> = menu_titles
995 .iter()
996 .map(|t| {
997 let (first, rest) = t.split_at(1);
998 Line::from(vec![
999 Span::styled(
1000 first,
1001 Style::default()
1002 .fg(self.theme.hc)
1003 .add_modifier(Modifier::UNDERLINED),
1004 ),
1005 Span::styled(rest, self.theme.style()),
1006 ])
1007 })
1008 .collect();
1009
1010 let tabs = Tabs::new(menu)
1011 .select(usize::from(self.active_menu_item))
1012 .block(Block::default().title("Menu").borders(Borders::ALL))
1013 .style(self.theme.style())
1014 .highlight_style(self.theme.highlight())
1015 .divider(Span::raw("|"));
1016 frame.render_widget(tabs, *main_window);
1017 }
1018}
1019
1020#[derive(Debug, Copy, Clone)]
1023pub enum RWMenuItem {
1024 Home,
1025 Quit
1026}
1027
1028impl From<RWMenuItem> for usize {
1029 fn from(input: RWMenuItem) -> usize {
1030 match input {
1031 RWMenuItem::Home => 0,
1032 RWMenuItem::Quit => 1,
1033 }
1034 }
1035}
1036
1037#[derive(Debug, Clone)]
1038pub struct RWMenu {
1039 pub theme : ColorTheme,
1040 pub active_menu_item : RWMenuItem,
1041}
1042
1043impl RWMenu {
1044
1045 pub fn new(theme : ColorTheme) -> RWMenu {
1046 RWMenu {
1047 theme,
1048 active_menu_item : RWMenuItem::Home,
1049 }
1050 }
1051
1052 pub fn render(&mut self, main_window : &Rect, frame : &mut Frame) {
1053 let menu_titles : Vec<&str> = vec!["Home", "Quit" ];
1054 let menu : Vec<Line> = menu_titles
1055 .iter()
1056 .map(|t| {
1057 let (first, rest) = t.split_at(1);
1058 Line::from(vec![
1059 Span::styled(
1060 first,
1061 Style::default()
1062 .fg(self.theme.hc)
1063 .add_modifier(Modifier::UNDERLINED),
1064 ),
1065 Span::styled(rest, self.theme.style()),
1066 ])
1067 })
1068 .collect();
1069
1070 let tabs = Tabs::new(menu)
1071 .select(usize::from(self.active_menu_item))
1072 .block(Block::default().title("Menu").borders(Borders::ALL))
1073 .style(self.theme.style())
1074 .highlight_style(self.theme.highlight())
1075 .divider(Span::raw("|"));
1076 frame.render_widget(tabs, *main_window);
1077 }
1078}
1079
1080#[derive(Debug, Copy, Clone)]
1083pub enum THMenuItem {
1084 Home,
1085 Hits,
1086 Pulses,
1087 Paddles,
1088 SelectPaddle,
1089 Quit
1090}
1091
1092impl From<THMenuItem> for usize {
1093 fn from(input: THMenuItem) -> usize {
1094 match input {
1095 THMenuItem::Home => 0,
1096 THMenuItem::Hits => 1,
1097 THMenuItem::Pulses => 2,
1098 THMenuItem::Paddles => 3,
1099 THMenuItem::SelectPaddle => 4,
1100 THMenuItem::Quit => 5,
1101 }
1102 }
1103}
1104
1105#[derive(Debug, Clone)]
1106pub struct THMenu {
1107 pub theme : ColorTheme,
1108 pub active_menu_item : THMenuItem,
1109}
1110
1111impl THMenu {
1112
1113 pub fn new(theme : ColorTheme) -> THMenu {
1114 THMenu {
1115 theme,
1116 active_menu_item : THMenuItem::Home,
1117 }
1118 }
1119
1120 pub fn render(&mut self, main_window : &Rect, frame : &mut Frame) {
1121 let menu_titles : Vec<&str> = vec!["Home", "Hits", "Pulses", "Paddles", "SelectPaddle", "Quit" ];
1122 let menu : Vec<Line> = menu_titles
1123 .iter()
1124 .map(|t| {
1125 if t == &"Paddles" || t == &"Hits" {
1126 let (second, rest) = t.split_at(2);
1127 Line::from(vec![
1128 Span::styled(
1129 second,
1130 Style::default()
1131 .fg(self.theme.hc)
1132 .add_modifier(Modifier::UNDERLINED),
1133 ),
1134 Span::styled(rest, self.theme.style()),
1135 ])
1136 } else {
1137 let (first, rest) = t.split_at(1);
1138 Line::from(vec![
1139 Span::styled(
1140 first,
1141 Style::default()
1142 .fg(self.theme.hc)
1143 .add_modifier(Modifier::UNDERLINED),
1144 ),
1145 Span::styled(rest, self.theme.style()),
1146 ])
1147 }
1148 })
1149 .collect();
1150
1151 let tabs = Tabs::new(menu)
1152 .select(usize::from(self.active_menu_item))
1153 .block(Block::default().title("Menu").borders(Borders::ALL))
1154 .style(self.theme.style())
1155 .highlight_style(self.theme.highlight())
1156 .divider(Span::raw("|"));
1157 frame.render_widget(tabs, *main_window);
1158 }
1159}
1160
1161