Skip to main content

Menu

Struct Menu 

Source
pub struct Menu { /* private fields */ }
Expand description

A vertical list of items navigated with the arrow keys.

KeyAction
Up / Downprevious / next item
Home / Endfirst / last item
Enter / Spacepress button, toggle checkbox, next choice, edit text
Left / Rightadjust slider or choice, toggle checkbox
Page Up / Page Downadjust slider by ten steps
Lettersjump to the next item starting with that letter
Escapeclose (if Menu::closable)
let menu = Menu::new("options", "Options")
    .slider("volume", "Volume", 80.0, 0.0, 100.0, 5.0)
    .choice("difficulty", "Difficulty", &["Easy", "Normal", "Hard"], 1)
    .checkbox("subtitles", "Speak hints", true)
    .text_field("name", "Player name", "Hero")
    .button("back", "Back")
    .music("menu_theme");

Implementations§

Source§

impl Menu

Source

pub fn new(id: impl Into<String>, title: impl Into<String>) -> Self

Creates an empty menu. title is spoken when it opens (may be empty).

Examples found in repository?
examples/beacon.rs (line 139)
137    fn start(&mut self, ctx: &mut Context) {
138        ctx.time.pause();
139        ctx.ui.open(Menu::new("pause", "Paused").button("resume", "Resume").button("quit", "Quit game"));
140    }
More examples
Hide additional examples
examples/menus.rs (line 18)
17fn main_menu() -> Menu {
18    Menu::new("main", "Main menu")
19        .button("play", "Play")
20        .button("options", "Options")
21        .button("name", "Change name")
22        .button("quit", "Quit")
23        .closable(false)
24        .wrap(true)
25}
26
27fn options_menu(s: &Settings) -> Menu {
28    Menu::new("options", "Options")
29        .slider("volume", "Volume", s.volume * 100.0, 0.0, 100.0, 10.0)
30        .choice("difficulty", "Difficulty", &["Easy", "Normal", "Hard"], s.difficulty)
31        .text_field("name", "Player name", s.name.clone())
32        .button("back", "Back")
33}
examples/bell_catcher.rs (line 52)
49fn title_menu(ctx: &Context) -> Menu {
50    let voice = ctx.speech.voice().map_or("default".to_string(), |v| v.name.clone());
51    let best: u32 = ctx.storage.get_or("best", 0);
52    Menu::new("title", "Bell Catcher")
53        .button("play", "Play")
54        .button("voice", format!("Voice: {voice}"))
55        .slider("rate", "Speech rate", ctx.storage.get_or("rate", 50.0), 0.0, 100.0, 5.0)
56        .button("help", "How to play")
57        .label(format!("Best score: {best}"))
58        .button("quit", "Quit")
59        .closable(false)
60        .wrap(true)
61}
62
63/// One button per voice, with the current one focused. `None` if the output has no voices.
64fn voice_menu(ctx: &Context) -> Option<Menu> {
65    let voices = ctx.speech.voices();
66    if voices.is_empty() {
67        return None;
68    }
69    let mut menu = Menu::new("voices", "Choose a voice").button("default", "Default voice");
70    for (i, voice) in voices.iter().enumerate() {
71        menu = menu.button(format!("voice{i}"), voice.to_string());
72    }
73    if let Some(i) = ctx.speech.voice().and_then(|current| voices.iter().position(|v| v == current)) {
74        menu = menu.focus(&format!("voice{i}"));
75    }
76    Some(menu.button("back", "Back"))
77}
Source

pub fn item(self, item: MenuItem) -> Self

Adds any item.

Source

pub fn button(self, id: impl Into<String>, label: impl Into<String>) -> Self

Adds a button.

Examples found in repository?
examples/beacon.rs (line 139)
137    fn start(&mut self, ctx: &mut Context) {
138        ctx.time.pause();
139        ctx.ui.open(Menu::new("pause", "Paused").button("resume", "Resume").button("quit", "Quit game"));
140    }
More examples
Hide additional examples
examples/menus.rs (line 19)
17fn main_menu() -> Menu {
18    Menu::new("main", "Main menu")
19        .button("play", "Play")
20        .button("options", "Options")
21        .button("name", "Change name")
22        .button("quit", "Quit")
23        .closable(false)
24        .wrap(true)
25}
26
27fn options_menu(s: &Settings) -> Menu {
28    Menu::new("options", "Options")
29        .slider("volume", "Volume", s.volume * 100.0, 0.0, 100.0, 10.0)
30        .choice("difficulty", "Difficulty", &["Easy", "Normal", "Hard"], s.difficulty)
31        .text_field("name", "Player name", s.name.clone())
32        .button("back", "Back")
33}
examples/bell_catcher.rs (line 53)
49fn title_menu(ctx: &Context) -> Menu {
50    let voice = ctx.speech.voice().map_or("default".to_string(), |v| v.name.clone());
51    let best: u32 = ctx.storage.get_or("best", 0);
52    Menu::new("title", "Bell Catcher")
53        .button("play", "Play")
54        .button("voice", format!("Voice: {voice}"))
55        .slider("rate", "Speech rate", ctx.storage.get_or("rate", 50.0), 0.0, 100.0, 5.0)
56        .button("help", "How to play")
57        .label(format!("Best score: {best}"))
58        .button("quit", "Quit")
59        .closable(false)
60        .wrap(true)
61}
62
63/// One button per voice, with the current one focused. `None` if the output has no voices.
64fn voice_menu(ctx: &Context) -> Option<Menu> {
65    let voices = ctx.speech.voices();
66    if voices.is_empty() {
67        return None;
68    }
69    let mut menu = Menu::new("voices", "Choose a voice").button("default", "Default voice");
70    for (i, voice) in voices.iter().enumerate() {
71        menu = menu.button(format!("voice{i}"), voice.to_string());
72    }
73    if let Some(i) = ctx.speech.voice().and_then(|current| voices.iter().position(|v| v == current)) {
74        menu = menu.focus(&format!("voice{i}"));
75    }
76    Some(menu.button("back", "Back"))
77}
Source

pub fn checkbox( self, id: impl Into<String>, label: impl Into<String>, checked: bool, ) -> Self

Adds a checkbox.

Source

pub fn slider( self, id: impl Into<String>, label: impl Into<String>, value: f32, min: f32, max: f32, step: f32, ) -> Self

Adds a slider. value is the start value, min and max the range, and step how much Left and Right change it (Page Up and Page Down change it by ten steps). slider("volume", "Volume", 80.0, 0.0, 100.0, 5.0) starts at 80 and goes from 0 to 100 in steps of 5. Read the value with Value::as_f32.

Examples found in repository?
examples/menus.rs (line 29)
27fn options_menu(s: &Settings) -> Menu {
28    Menu::new("options", "Options")
29        .slider("volume", "Volume", s.volume * 100.0, 0.0, 100.0, 10.0)
30        .choice("difficulty", "Difficulty", &["Easy", "Normal", "Hard"], s.difficulty)
31        .text_field("name", "Player name", s.name.clone())
32        .button("back", "Back")
33}
More examples
Hide additional examples
examples/bell_catcher.rs (line 55)
49fn title_menu(ctx: &Context) -> Menu {
50    let voice = ctx.speech.voice().map_or("default".to_string(), |v| v.name.clone());
51    let best: u32 = ctx.storage.get_or("best", 0);
52    Menu::new("title", "Bell Catcher")
53        .button("play", "Play")
54        .button("voice", format!("Voice: {voice}"))
55        .slider("rate", "Speech rate", ctx.storage.get_or("rate", 50.0), 0.0, 100.0, 5.0)
56        .button("help", "How to play")
57        .label(format!("Best score: {best}"))
58        .button("quit", "Quit")
59        .closable(false)
60        .wrap(true)
61}
Source

pub fn choice( self, id: impl Into<String>, label: impl Into<String>, options: &[&str], selected: usize, ) -> Self

Adds a choice between several options. selected is the index of the option chosen at the start (0 = the first one).

Examples found in repository?
examples/menus.rs (line 30)
27fn options_menu(s: &Settings) -> Menu {
28    Menu::new("options", "Options")
29        .slider("volume", "Volume", s.volume * 100.0, 0.0, 100.0, 10.0)
30        .choice("difficulty", "Difficulty", &["Easy", "Normal", "Hard"], s.difficulty)
31        .text_field("name", "Player name", s.name.clone())
32        .button("back", "Back")
33}
Source

pub fn text_field( self, id: impl Into<String>, label: impl Into<String>, value: impl Into<String>, ) -> Self

Adds an editable text field.

Examples found in repository?
examples/menus.rs (line 31)
27fn options_menu(s: &Settings) -> Menu {
28    Menu::new("options", "Options")
29        .slider("volume", "Volume", s.volume * 100.0, 0.0, 100.0, 10.0)
30        .choice("difficulty", "Difficulty", &["Easy", "Normal", "Hard"], s.difficulty)
31        .text_field("name", "Player name", s.name.clone())
32        .button("back", "Back")
33}
Source

pub fn password_field( self, id: impl Into<String>, label: impl Into<String>, ) -> Self

Adds a password field (content is never spoken).

Source

pub fn label(self, text: impl Into<String>) -> Self

Adds a line of information that cannot be activated.

Examples found in repository?
examples/bell_catcher.rs (line 57)
49fn title_menu(ctx: &Context) -> Menu {
50    let voice = ctx.speech.voice().map_or("default".to_string(), |v| v.name.clone());
51    let best: u32 = ctx.storage.get_or("best", 0);
52    Menu::new("title", "Bell Catcher")
53        .button("play", "Play")
54        .button("voice", format!("Voice: {voice}"))
55        .slider("rate", "Speech rate", ctx.storage.get_or("rate", 50.0), 0.0, 100.0, 5.0)
56        .button("help", "How to play")
57        .label(format!("Best score: {best}"))
58        .button("quit", "Quit")
59        .closable(false)
60        .wrap(true)
61}
Source

pub fn wrap(self, wrap: bool) -> Self

Jump from the last to the first item and back (default false).

Examples found in repository?
examples/menus.rs (line 24)
17fn main_menu() -> Menu {
18    Menu::new("main", "Main menu")
19        .button("play", "Play")
20        .button("options", "Options")
21        .button("name", "Change name")
22        .button("quit", "Quit")
23        .closable(false)
24        .wrap(true)
25}
More examples
Hide additional examples
examples/bell_catcher.rs (line 60)
49fn title_menu(ctx: &Context) -> Menu {
50    let voice = ctx.speech.voice().map_or("default".to_string(), |v| v.name.clone());
51    let best: u32 = ctx.storage.get_or("best", 0);
52    Menu::new("title", "Bell Catcher")
53        .button("play", "Play")
54        .button("voice", format!("Voice: {voice}"))
55        .slider("rate", "Speech rate", ctx.storage.get_or("rate", 50.0), 0.0, 100.0, 5.0)
56        .button("help", "How to play")
57        .label(format!("Best score: {best}"))
58        .button("quit", "Quit")
59        .closable(false)
60        .wrap(true)
61}
Source

pub fn closable(self, closable: bool) -> Self

Allow closing with Escape (default true). A main menu often sets this to false.

Examples found in repository?
examples/menus.rs (line 23)
17fn main_menu() -> Menu {
18    Menu::new("main", "Main menu")
19        .button("play", "Play")
20        .button("options", "Options")
21        .button("name", "Change name")
22        .button("quit", "Quit")
23        .closable(false)
24        .wrap(true)
25}
More examples
Hide additional examples
examples/bell_catcher.rs (line 59)
49fn title_menu(ctx: &Context) -> Menu {
50    let voice = ctx.speech.voice().map_or("default".to_string(), |v| v.name.clone());
51    let best: u32 = ctx.storage.get_or("best", 0);
52    Menu::new("title", "Bell Catcher")
53        .button("play", "Play")
54        .button("voice", format!("Voice: {voice}"))
55        .slider("rate", "Speech rate", ctx.storage.get_or("rate", 50.0), 0.0, 100.0, 5.0)
56        .button("help", "How to play")
57        .label(format!("Best score: {best}"))
58        .button("quit", "Quit")
59        .closable(false)
60        .wrap(true)
61}
Source

pub fn positions(self, positions: bool) -> Self

Speak “2 of 5” after each item (default false).

Source

pub fn close_on_activate(self, close: bool) -> Self

Close the menu automatically after a button was pressed (default false).

Source

pub fn sounds(self, sounds: UiSounds) -> Self

Use these sounds instead of the global ones for this menu.

Source

pub fn sound(self, kind: UiSound, name: Option<&str>) -> Self

Changes one sound for this menu only, e.g. a special click for the main menu. None makes it silent. All other sounds stay as they are.

Source

pub fn music(self, name: impl Into<String>) -> Self

Plays the music name in a loop while this menu is open (a file or registered sound). Submenus and dialogs on top keep it playing unless they have music of their own. When the menu closes, the music that played before comes back, or the music fades out.

Source

pub fn focus(self, id: &str) -> Self

Start with the item id focused.

Examples found in repository?
examples/bell_catcher.rs (line 74)
64fn voice_menu(ctx: &Context) -> Option<Menu> {
65    let voices = ctx.speech.voices();
66    if voices.is_empty() {
67        return None;
68    }
69    let mut menu = Menu::new("voices", "Choose a voice").button("default", "Default voice");
70    for (i, voice) in voices.iter().enumerate() {
71        menu = menu.button(format!("voice{i}"), voice.to_string());
72    }
73    if let Some(i) = ctx.speech.voice().and_then(|current| voices.iter().position(|v| v == current)) {
74        menu = menu.focus(&format!("voice{i}"));
75    }
76    Some(menu.button("back", "Back"))
77}
78
79/// Reopens the title menu so its labels show the new values, focused on `item`.
80fn refresh_title(ctx: &mut Context, item: &str) {
81    ctx.ui.close_id("title");
82    let menu = title_menu(ctx).focus(item);
83    ctx.ui.open(menu);
84}
Source

pub fn items(&self) -> &[MenuItem]

The items of this menu.

Source

pub fn current(&self) -> Option<&MenuItem>

The focused item.

Trait Implementations§

Source§

impl Clone for Menu

Source§

fn clone(&self) -> Self

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 Debug for Menu

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Widget for Menu

Source§

fn id(&self) -> &str

Identifier used in events.
Source§

fn open(&mut self, ui: &mut UiContext<'_>)

Called once when the widget becomes active. Announce yourself here.
Source§

fn resume(&mut self, value: Option<Value>, ui: &mut UiContext<'_>)

Called when the widget becomes the top again after the one above closed. value is what the closed widget passed with Status::CloseWith.
Source§

fn update(&mut self, ui: &mut UiContext<'_>) -> Status

Called every frame while this widget is on top of the stack.
Source§

fn value(&self, item: &str) -> Option<Value>

Current value of an item, used by Ui::value.
Source§

fn music(&self) -> Option<&str>

Music that plays while this widget is open, see Menu::music. Widgets above it without music of their own keep it playing.

Auto Trait Implementations§

§

impl Freeze for Menu

§

impl RefUnwindSafe for Menu

§

impl Send for Menu

§

impl Sync for Menu

§

impl Unpin for Menu

§

impl UnsafeUnpin for Menu

§

impl UnwindSafe for Menu

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync> ⓘ

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more