pub struct MenuState { /* private fields */ }Expand description
Selection index and scroll offset for an anchored popup menu. The menu is open iff a selection exists: there is no independent open flag to fall out of sync with it.
ListState’s sibling for content where some rows (separators,
headings) can never be selected: a dropdown, a combobox’s list, a command palette.
Holds no reference to the menu’s actual rows, the same design ListState uses: every
method that needs to know which rows exist takes len (the row count) and a selectable
predicate (impl Fn(usize) -> bool) rather than a concrete row type, so this stays reusable
across whatever row enum a call site defines (see
Menu/MenuRow for this crate’s own).
selectable must report the same answer every time it’s called this frame: passing a
predicate that disagrees with what was drawn (e.g. after an enabled flag changed
mid-frame) can select or skip past a row inconsistently with the render that follows.
Selection movement (select_next/select_previous)
clamps at the ends: stepping past the last selectable row stays on it rather than wrapping,
matching ListState’s default. open selects the first selectable row,
skipping any leading separators/labels; a menu with no selectable row at all never opens
(open becomes a no-op), so a caller can never end up with an open menu and no selection to
navigate.
§Examples
use retroglyph_ui::state::MenuState;
// rows: [Separator, "Cut" (disabled), "Copy", "Paste"]
let selectable = |i: usize| matches!(i, 2 | 3);
let mut state = MenuState::new();
state.open(4, selectable);
assert_eq!(state.selected(), Some(2)); // skipped the separator and the disabled item
state.select_next(4, selectable);
assert_eq!(state.selected(), Some(3));
state.select_next(4, selectable); // clamps: nothing selectable past index 3
assert_eq!(state.selected(), Some(3));Implementations§
Source§impl MenuState
impl MenuState
Sourcepub const fn offset(&self) -> usize
pub const fn offset(&self) -> usize
The current scroll offset (index of the first row a Menu draws,
not counting its own overflow indicator row).
Sourcepub const fn set_offset(&mut self, offset: usize)
pub const fn set_offset(&mut self, offset: usize)
Set the scroll offset directly.
Sourcepub const fn select(&mut self, index: Option<usize>)
pub const fn select(&mut self, index: Option<usize>)
Select an explicit row index directly, e.g. after resolving a click to a row, or close
the menu by passing None (equivalent to close). Stored verbatim, with
no selectable check of its own: callers that need “never select a disabled row” should
check that themselves first, the same responsibility
ListState::select leaves to its own callers.
Sourcepub fn open(&mut self, len: usize, selectable: impl Fn(usize) -> bool)
pub fn open(&mut self, len: usize, selectable: impl Fn(usize) -> bool)
Open the menu and select the first selectable row among 0..len, skipping any leading
separators/labels. A no-op (stays closed) if no row in 0..len is selectable: an empty
menu never opens.
Sourcepub fn select_next(&mut self, len: usize, selectable: impl Fn(usize) -> bool)
pub fn select_next(&mut self, len: usize, selectable: impl Fn(usize) -> bool)
Move the selection to the next selectable row among 0..len, skipping separators/labels.
Clamps at the last selectable row rather than wrapping. A no-op while the menu is closed:
navigation never opens it.
Sourcepub fn select_previous(
&mut self,
len: usize,
selectable: impl Fn(usize) -> bool,
)
pub fn select_previous( &mut self, len: usize, selectable: impl Fn(usize) -> bool, )
Move the selection to the previous selectable row among 0..len, skipping
separators/labels. Clamps at the first selectable row rather than wrapping. A no-op while
the menu is closed: navigation never opens it.
Sourcepub const fn ensure_visible(&mut self, visible_height: usize)
pub const fn ensure_visible(&mut self, visible_height: usize)
Nudge the scroll offset by the minimum amount needed to bring selected into the
visible_height-row window starting at offset. Same math as
ListState::ensure_visible; see its docs for why this
is a no-op unless a selection exists and is out of view, and why it’s cheap to call every
frame before rendering.
Sourcepub fn scroll_by(&mut self, delta: i32)
pub fn scroll_by(&mut self, delta: i32)
Move the scroll offset by delta, clamped at zero: the wheel-scroll half of “independent
wheel-scroll versus keyboard-nav scroll” – this never touches selected, the same split
List/ListState::scroll_by already
have between a click (which selects) and the wheel (which only scrolls).
Sourcepub fn handle_event(
&mut self,
event: &Event,
len: usize,
selectable: impl Fn(usize) -> bool,
) -> Option<usize>
pub fn handle_event( &mut self, event: &Event, len: usize, selectable: impl Fn(usize) -> bool, ) -> Option<usize>
Apply one keyboard event while the menu is open: Up/Down move the selection (via
select_previous/select_next), Enter
activates the current selection and closes the menu, and Escape
closes it without activating anything. Every other event, and every
event while is_open is false, is ignored.
Returns Some(index) for the one frame Enter activates a selectable row, None
otherwise – including on Escape or an outside close, which intentionally report no
activation (“closes without firing”).
Only KeyEventKind::Press/
Repeat drive this (via
KeyEvent::is_down); a release is ignored, the
same convention TextInputState::handle_event uses.
Trait Implementations§
impl Copy for MenuState
impl Eq for MenuState
impl StructuralPartialEq for MenuState
Auto Trait Implementations§
impl Freeze for MenuState
impl RefUnwindSafe for MenuState
impl Send for MenuState
impl Sync for MenuState
impl Unpin for MenuState
impl UnsafeUnpin for MenuState
impl UnwindSafe for MenuState
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<C> WithAlpha for Cwhere
C: Copy,
impl<C> WithAlpha for Cwhere
C: Copy,
§fn with_alpha_first<A>(self, alpha: A) -> AlphaFirst<A, Self>
fn with_alpha_first<A>(self, alpha: A) -> AlphaFirst<A, Self>
self with alpha, storing alpha before the color in memory
(see [AlphaFirst]).§fn with_alpha_last<A>(self, alpha: A) -> AlphaLast<A, Self>
fn with_alpha_last<A>(self, alpha: A) -> AlphaLast<A, Self>
self with alpha, storing alpha after the color in memory
(see [AlphaLast]).