pub struct MenuBar<'a> { /* private fields */ }Expand description
A horizontal row of titles, each anchoring the Menu built from the matching slice of
rows: a “File Edit View” menu bar.
The app-specific layer a dropdown’s own anchored-popup core (Menu) doesn’t have an
opinion on. titles and rows are parallel slices (rows[i] is the popup shown for titles[i]); a
mismatched length is a caller bug the same way it would be for two Vecs meant to stay in
lockstep, not something this widget can check for you.
Interaction lives entirely in MenuBar::show/MenuBar::handle_event, mirroring the
click-and-keyboard half of Menu::show/MenuState::handle_event:
- A click on a label toggles that label’s popup open or closed.
- Hovering a different label while one is already open switches to it. A cold hover (no
popup open yet) does nothing: this is deliberately not a
Button-style hover highlight that opens on its own, matching how a desktop menu bar only starts following the pointer once you’ve clicked into it once. MenuBar::handle_event’s Left/Right step which label is open (clamped at the ends, not wrapping, matchingMenuState::select_next’s own default); Up/Down/Enter/Escape forward to the open label’s ownMenuState::handle_event.
style/open_style name the unopened/opened label styles (not selected_style: nothing
here is a persistent selection the way Tabs’s is, it’s literally “this
label’s popup is open right now” and reverts the instant it closes). Both default to
Theme::DARK (as if MenuBar::theme had been called), and that same theme is forwarded
to the Menu popup MenuBar::show builds internally, so the bar and its popups always
read as one themed unit.
§Examples
use retroglyph_core::grid::{Grid, Rect};
use retroglyph_ui::state::MenuBarState;
use retroglyph_ui::widget::{Marker, MenuBar, MenuRow};
use retroglyph_ui::Surface;
let file_rows = [
MenuRow::Item { label: "New", marker: Marker::None, enabled: true },
MenuRow::Item { label: "Open", marker: Marker::None, enabled: true },
];
let edit_rows = [
MenuRow::Item { label: "Cut", marker: Marker::None, enabled: true },
];
let titles = ["File", "Edit"];
let rows: [&[MenuRow]; 2] = [&file_rows, &edit_rows];
let bar = MenuBar::new(&titles, &rows);
let mut state = MenuBarState::new();
let area = Rect::new(0, 0, 20, 1);
let mut grid = Grid::new(20, 1);
bar.draw(&mut Surface::new(&mut grid, area, 0), state.open_label());Implementations§
Source§impl<'a> MenuBar<'a>
impl<'a> MenuBar<'a>
Sourcepub fn new(titles: &'a [&'a str], rows: &'a [&'a [MenuRow<'a>]]) -> Self
pub fn new(titles: &'a [&'a str], rows: &'a [&'a [MenuRow<'a>]]) -> Self
A menu bar over titles, each anchoring the popup built from the matching entry of
rows, styled from Theme::DARK (as if MenuBar::theme had been called).
Sourcepub const fn open_style(self, style: Style) -> Self
pub const fn open_style(self, style: Style) -> Self
Set the style of the label whose popup is currently open.
Sourcepub const fn column_spacing(self, spacing: u16) -> Self
pub const fn column_spacing(self, spacing: u16) -> Self
Set the number of blank columns between labels.
Sourcepub fn theme(self, theme: Theme) -> Self
pub fn theme(self, theme: Theme) -> Self
Applies theme’s named roles to this bar and the Menu popup MenuBar::show builds
from it: style becomes theme.dim on theme.panel_bg, open_style becomes theme.bg
on theme.accent (the same unselected/selected mapping Tabs::theme
uses), and the popup itself is themed via Menu::theme.
Call before any manual MenuBar::style/MenuBar::open_style override you want to
keep.
Source§impl MenuBar<'_>
impl MenuBar<'_>
Sourcepub fn draw(&self, surface: &mut Surface<'_>, open: Option<usize>)
pub fn draw(&self, surface: &mut Surface<'_>, open: Option<usize>)
Draw this bar into surface.area(), highlighting open (if any) with
MenuBar::open_style.
Sourcepub fn show<Id: Copy + PartialEq>(
&self,
ui: &mut Ui<'_, '_, Id>,
screen: Rect,
bar_area: Rect,
popup_size: Size,
ids: MenuBarIds<Id>,
state: &mut MenuBarState,
) -> Option<(usize, usize)>
pub fn show<Id: Copy + PartialEq>( &self, ui: &mut Ui<'_, '_, Id>, screen: Rect, bar_area: Rect, popup_size: Size, ids: MenuBarIds<Id>, state: &mut MenuBarState, ) -> Option<(usize, usize)>
Draw and interact with this bar, and whichever label’s popup MenuBarState::open_label
reports, for one frame.
The popup (if any) is shown before the label row itself is registered/drawn, the
reverse of Menu::show’s own internal ordering of its backdrop-then-content: show
there registers a full-screen backdrop so a click anywhere outside the popup closes it,
but that backdrop would otherwise sit on top of (and shadow hit-testing for) every label
in this bar, including the very one whose click should switch or close it. Drawing/
registering the label row after the popup puts the bar back on top for hit-testing (see
Ui::modal’s “later registered wins” rule), so a click or hover on any label – open
one included – always reaches the bar, and only a click truly outside both the bar and
the popup reaches the backdrop.
A consequence of that ordering: the popup for state’s own change (open, close, or
switch) applied in this same call – from a click resolved below, or from
MenuBar::handle_event called earlier this frame – isn’t drawn until the next
frame’s show, since this call already decided what to draw from state.open_label()
before that change happens. One extra frame on top of the usual one-frame click-latency
this crate already has everywhere (see Interaction),
not a bug: correctly prioritizing the bar over the popup’s own backdrop for every
subsequent frame (so a click or hover can still reach and switch/close it) requires
registering the bar after the popup, which is exactly what makes the fresh transition
itself one frame slower to render.
popup_size is used for every label’s popup; bar_area anchors each label’s own popup
Side::Below itself via anchored_rect, clamped to screen.
Returns Some((label, row)) for the one frame a selectable row in label’s popup is
clicked, the same “checkbox items fire and close” contract Menu::show has.
Sourcepub fn handle_event(
&self,
event: &Event,
state: &mut MenuBarState,
) -> Option<(usize, usize)>
pub fn handle_event( &self, event: &Event, state: &mut MenuBarState, ) -> Option<(usize, usize)>
Apply one keyboard event to state: Left/Right move which label is open, clamped at the
ends (see the type docs); every other event forwards to the open label’s own
MenuState::handle_event, returning
Some((label, row)) for the one frame Enter activates a row.
A no-op, on every key, while nothing is open: Left/Right don’t open a label from cold any
more than a hover does (see the type docs), and there is no open label’s MenuState to
forward anything else to.
Trait Implementations§
Auto Trait Implementations§
impl<'a> Freeze for MenuBar<'a>
impl<'a> RefUnwindSafe for MenuBar<'a>
impl<'a> Send for MenuBar<'a>
impl<'a> Sync for MenuBar<'a>
impl<'a> Unpin for MenuBar<'a>
impl<'a> UnsafeUnpin for MenuBar<'a>
impl<'a> UnwindSafe for MenuBar<'a>
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]).