Skip to main content

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}