Skip to main content

MenuBar

Struct MenuBar 

Source
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, matching MenuState::select_next’s own default); Up/Down/Enter/Escape forward to the open label’s own MenuState::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>

Source

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).

Source

pub const fn style(self, style: Style) -> Self

Set the style of an unopened label.

Source

pub const fn open_style(self, style: Style) -> Self

Set the style of the label whose popup is currently open.

Source

pub const fn column_spacing(self, spacing: u16) -> Self

Set the number of blank columns between labels.

Source

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<'_>

Source

pub fn draw(&self, surface: &mut Surface<'_>, open: Option<usize>)

Draw this bar into surface.area(), highlighting open (if any) with MenuBar::open_style.

Source

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.

Source

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§

Source§

impl<'a> Clone for MenuBar<'a>

Source§

fn clone(&self) -> MenuBar<'a>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'a> Copy for MenuBar<'a>

Source§

impl<'a> Debug for MenuBar<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<C> WithAlpha for C
where C: Copy,

§

fn with_alpha_first<A>(self, alpha: A) -> AlphaFirst<A, Self>

Wraps self with alpha, storing alpha before the color in memory (see [AlphaFirst]).
§

fn with_alpha_last<A>(self, alpha: A) -> AlphaLast<A, Self>

Wraps self with alpha, storing alpha after the color in memory (see [AlphaLast]).