1use crate::font::print;
2use crate::font::Font;
3use crate::BitmapARGB32;
4use alloc::boxed::Box;
5use alloc::string::String;
6use alloc::vec::Vec;
7use alloc::string::ToString;
8
9pub struct DbgMenu {
11 title: &'static str,
12 menu_items: Vec<DbgMenuItem>,
13 cursor_index: usize,
14}
15
16pub struct DbgMenuItem {
17 pub text: String,
18 pub callback: Box<dyn Fn(&mut DbgMenu)>,
19}
20
21impl DbgMenu {
22 pub fn builder() -> DbgMenuBuilder {
23 DbgMenuBuilder::new()
24 }
25
26 fn assemble_string(&self) -> String {
27 let mut result = String::new();
28 result.push('[');
29 result.push_str(self.title);
30 result.push_str("]\n");
31 for (i, item) in self.menu_items.iter().enumerate() {
32 if i == self.cursor_index {
33 result.push('*');
34 } else {
35 result.push(' ');
36 }
37 result.push_str(&item.text);
38 result.push('\n');
39 }
40 result
41 }
42
43 pub fn draw(&self, font: &Font, dest: &mut BitmapARGB32, x: usize, y: usize) {
44 let text = self.assemble_string();
45 print(x, y, font, dest, &text);
46 }
47}
48
49pub struct DbgMenuBuilder {
50 title: &'static str,
51 font: Option<Font>,
52 menu_items: Vec<DbgMenuItem>,
53}
54
55impl DbgMenuBuilder {
56 pub fn new() -> Self {
57 Self {
58 title: "???",
59 font: None,
60 menu_items: Vec::new(),
61 }
62 }
63
64 pub fn title(mut self, title: &'static str) -> Self {
65 self.title = title;
66 self
67 }
68
69 pub fn font(mut self, font: Font) -> Self {
70 self.font = Some(font);
71 self
72 }
73
74 pub fn add_item(mut self, text: &str, callback: impl Fn(&mut DbgMenu) + 'static) -> Self {
75 self.menu_items.push(DbgMenuItem {
76 text: text.to_string(),
77 callback: Box::new(callback),
78 });
79 self
80 }
81
82 pub fn build(self) -> DbgMenu {
83 DbgMenu {
84 title: self.title,
85 menu_items: self.menu_items,
86 cursor_index: 0,
87 }
88 }
89}