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