old school music tracker
1pub mod confirm;
2pub mod page_menu;
3pub mod slider_dialog;
4
5use winit::event::{KeyEvent, Modifiers};
6
7use crate::{
8 EventQueue,
9 dialog::{confirm::ConfirmDialog, page_menu::MainMenu, slider_dialog::SliderDialog},
10 draw_buffer::DrawBuffer,
11};
12
13#[derive(PartialEq, Eq)]
14pub enum DialogResponse {
15 RequestRedraw,
16 // should also close all Dialogs
17 // SwitchToPage(PagesEnum),
18 Close,
19 /// (global_event to be sent, should close the current dialog)
20 // GlobalEvent(GlobalEvent, bool),
21 None,
22}
23
24pub trait Dialog {
25 fn draw(&self, draw_buffer: &mut DrawBuffer);
26 fn process_input(
27 &mut self,
28 key_event: &KeyEvent,
29 modifiers: &Modifiers,
30 events: &mut EventQueue<'_>,
31 ) -> DialogResponse;
32 #[cfg(feature = "accesskit")]
33 fn build_tree(
34 &self,
35 tree: &mut Vec<(accesskit::NodeId, accesskit::Node)>,
36 ) -> crate::AccessResponse;
37}
38
39pub struct DialogManager {
40 stack: Vec<DialogEnum>,
41}
42
43pub enum DialogEnum {
44 Main(MainMenu),
45 Slider(SliderDialog),
46 Confirm(ConfirmDialog),
47}
48
49impl DialogEnum {
50 fn get_mut(&mut self) -> &mut dyn Dialog {
51 match self {
52 DialogEnum::Main(d) => d,
53 DialogEnum::Slider(d) => d,
54 DialogEnum::Confirm(d) => d,
55 }
56 }
57
58 fn get(&self) -> &dyn Dialog {
59 match self {
60 DialogEnum::Main(d) => d,
61 DialogEnum::Slider(d) => d,
62 DialogEnum::Confirm(d) => d,
63 }
64 }
65}
66
67impl Dialog for DialogEnum {
68 fn draw(&self, draw_buffer: &mut DrawBuffer) {
69 match self {
70 DialogEnum::Main(d) => d.draw(draw_buffer),
71 DialogEnum::Slider(d) => d.draw(draw_buffer),
72 DialogEnum::Confirm(d) => d.draw(draw_buffer),
73 }
74 }
75
76 fn process_input(
77 &mut self,
78 key_event: &KeyEvent,
79 modifiers: &Modifiers,
80 events: &mut EventQueue<'_>,
81 ) -> DialogResponse {
82 match self {
83 DialogEnum::Main(d) => d.process_input(key_event, modifiers, events),
84 DialogEnum::Slider(d) => d.process_input(key_event, modifiers, events),
85 DialogEnum::Confirm(d) => d.process_input(key_event, modifiers, events),
86 }
87 }
88
89 #[cfg(feature = "accesskit")]
90 fn build_tree(
91 &self,
92 tree: &mut Vec<(accesskit::NodeId, accesskit::Node)>,
93 ) -> crate::AccessResponse {
94 match self {
95 DialogEnum::Main(d) => d.build_tree(tree),
96 DialogEnum::Slider(d) => d.build_tree(tree),
97 DialogEnum::Confirm(d) => d.build_tree(tree),
98 }
99 }
100}
101
102impl DialogManager {
103 pub fn new() -> Self {
104 // try to match the capacity to the actually used maximum depth
105 Self {
106 stack: Vec::with_capacity(3),
107 }
108 }
109
110 pub fn active_dialog_mut(&mut self) -> Option<&mut dyn Dialog> {
111 self.stack.last_mut().map(|d| d.get_mut())
112 }
113
114 pub fn active_dialog(&self) -> Option<&dyn Dialog> {
115 self.stack.last().map(|d| d.get())
116 }
117
118 pub fn is_active(&self) -> bool {
119 !self.stack.is_empty()
120 }
121
122 pub fn open_dialog(&mut self, dialog: DialogEnum) {
123 self.stack.push(dialog);
124 }
125
126 pub fn close_dialog(&mut self) {
127 self.stack.pop();
128 }
129
130 pub fn close_all(&mut self) {
131 self.stack.clear();
132 }
133
134 /// draws all currently open dialogs
135 pub fn draw(&self, draw_buffer: &mut DrawBuffer) {
136 self.stack
137 .iter()
138 .for_each(|dialog| dialog.draw(draw_buffer));
139 }
140}