morpheus_bootloader/tui/widgets/
list.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use crate::tui::renderer::{Screen, EFI_BLACK, EFI_GREEN, EFI_LIGHTGREEN};

pub struct ListItem {
    pub label: &'static str,
}

pub struct List {
    pub x: usize,
    pub y: usize,
    pub width: usize,
    pub height: usize,
    pub items: [ListItem; 10],
    pub item_count: usize,
    pub selected_index: usize,
    pub scroll_offset: usize,
}

impl List {
    pub fn new(x: usize, y: usize, width: usize, height: usize) -> Self {
        Self {
            x,
            y,
            width,
            height,
            items: [
                ListItem { label: "" },
                ListItem { label: "" },
                ListItem { label: "" },
                ListItem { label: "" },
                ListItem { label: "" },
                ListItem { label: "" },
                ListItem { label: "" },
                ListItem { label: "" },
                ListItem { label: "" },
                ListItem { label: "" },
            ],
            item_count: 0,
            selected_index: 0,
            scroll_offset: 0,
        }
    }

    pub fn add_item(&mut self, label: &'static str) {
        if self.item_count < self.items.len() {
            self.items[self.item_count].label = label;
            self.item_count += 1;
        }
    }

    pub fn select_next(&mut self) {
        if self.selected_index < self.item_count - 1 {
            self.selected_index += 1;
            if self.selected_index >= self.scroll_offset + self.height {
                self.scroll_offset += 1;
            }
        }
    }

    pub fn select_prev(&mut self) {
        if self.selected_index > 0 {
            self.selected_index -= 1;
            if self.selected_index < self.scroll_offset {
                self.scroll_offset -= 1;
            }
        }
    }

    pub fn render(&self, screen: &mut Screen) {
        let visible_end = (self.scroll_offset + self.height).min(self.item_count);

        for i in self.scroll_offset..visible_end {
            let y = self.y + (i - self.scroll_offset);
            let is_selected = i == self.selected_index;

            let (fg, bg) = if is_selected {
                (EFI_BLACK, EFI_LIGHTGREEN)
            } else {
                (EFI_GREEN, EFI_BLACK)
            };

            // Build line
            let mut buf = [0u8; 128];
            let mut idx = 0;

            if is_selected {
                buf[idx] = b'>';
                idx += 1;
                buf[idx] = b' ';
                idx += 1;
            } else {
                buf[idx] = b' ';
                idx += 1;
                buf[idx] = b' ';
                idx += 1;
            }

            for &b in self.items[i].label.as_bytes() {
                if idx >= buf.len() {
                    break;
                }
                buf[idx] = b;
                idx += 1;
            }

            let text = core::str::from_utf8(&buf[..idx]).unwrap_or("");
            screen.put_str_at(self.x, y, text, fg, bg);
        }
    }
}