shuyi_ui/widgets/menu/view.rs
1//! What a [`Menu`](super::Menu) shows, as plain data: its items with their
2//! labels and which one is focused, no cells or positions. A screen puts
3//! the [`MenuView`] in its own view and its skin paints it
4//! ([`super::glyph::paint`] today; game ADR-0054).
5
6use crate::prelude::*;
7use crate::text::Label;
8
9/// The whole menu, as it is this frame.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct MenuView {
12 /// The items, top to bottom: all of them, also those scrolled out of
13 /// the box.
14 pub items: Vec<MenuItemView>,
15 /// The first item the box shows (0 unless the menu has scrolled).
16 pub first_shown: usize,
17 /// How many items the box shows from `first_shown` (all of them unless
18 /// the menu scrolls).
19 pub shown: usize,
20}
21
22impl MenuView {
23 /// A view of `items` that shows them all.
24 pub fn new(items: Vec<MenuItemView>) -> Self {
25 Self {
26 shown: items.len(),
27 items,
28 first_shown: 0,
29 }
30 }
31
32 /// The items the box shows, top to bottom.
33 pub fn shown_items(&self) -> &[MenuItemView] {
34 let first = self.first_shown.min(self.items.len());
35 let end = (first + self.shown).min(self.items.len());
36 &self.items[first..end]
37 }
38
39 /// Whether items are scrolled out above the box, so a skin can mark it.
40 pub fn more_above(&self) -> bool {
41 self.first_shown > 0
42 }
43
44 /// Whether items are scrolled out below the box.
45 pub fn more_below(&self) -> bool {
46 self.first_shown + self.shown < self.items.len()
47 }
48
49 /// The focused item, if there is one.
50 pub fn focused(&self) -> Option<&MenuItemView> {
51 self.items.iter().find(|i| i.focused)
52 }
53}
54
55/// One item of a menu.
56#[derive(Debug, Clone, PartialEq, Eq)]
57pub struct MenuItemView {
58 /// Its text, as the menu holds it: the skin puts a key in the player's
59 /// language when it paints ([`Ctx::label`](crate::Ctx::label)).
60 pub label: Label,
61 /// Text that follows the label (e.g. why it can't be chosen) and what
62 /// it is.
63 pub suffix: Option<(String, SuffixKind)>,
64 /// What it does, shown under the list while it has the focus.
65 pub note: Option<String>,
66 /// Whether it can be chosen: a disabled item is dimmed (and skipped by
67 /// the cursor, unless the menu browses disabled items).
68 pub enabled: bool,
69 /// Whether the cursor is on it.
70 pub focused: bool,
71}
72
73/// What the text after an item's label is.
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub enum SuffixKind {
76 /// A warning: why the item can't be chosen, or that it is broken.
77 Warning,
78 /// A detail aside, such as what it costs.
79 Aside,
80}