[menu] click outside a menu to close it
This commit is contained in:
parent
3962fae76e
commit
2861bc956a
5 changed files with 79 additions and 27 deletions
|
@ -1,7 +1,6 @@
|
|||
pub(crate) mod area;
|
||||
pub(crate) mod collapsing_header;
|
||||
pub(crate) mod frame;
|
||||
pub mod menu;
|
||||
pub(crate) mod popup;
|
||||
pub(crate) mod resize;
|
||||
pub(crate) mod scroll_area;
|
||||
|
|
|
@ -215,6 +215,32 @@ impl InputState {
|
|||
|| self.scroll_delta != Vec2::zero()
|
||||
|| !self.events.is_empty()
|
||||
}
|
||||
|
||||
/// Was the given key pressed this frame?
|
||||
pub fn key_pressed(&self, desired_key: Key) -> bool {
|
||||
self.events.iter().any(|event| {
|
||||
matches!(
|
||||
event,
|
||||
Event::Key {
|
||||
key,
|
||||
pressed: true
|
||||
} if *key == desired_key
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Was the given key released this frame?
|
||||
pub fn key_released(&self, desired_key: Key) -> bool {
|
||||
self.events.iter().any(|event| {
|
||||
matches!(
|
||||
event,
|
||||
Event::Key {
|
||||
key,
|
||||
pressed: false
|
||||
} if *key == desired_key
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl MouseInput {
|
||||
|
|
|
@ -33,6 +33,7 @@ mod layers;
|
|||
mod layout;
|
||||
pub mod math;
|
||||
mod memory;
|
||||
pub mod menu;
|
||||
mod movement_tracker;
|
||||
pub mod paint;
|
||||
mod painter;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use crate::{
|
||||
containers::{area, collapsing_header, menu, resize, scroll_area, window},
|
||||
widgets::text_edit,
|
||||
Id, Layer, Pos2, Rect,
|
||||
area, collapsing_header, menu, resize, scroll_area, widgets::text_edit, window, Id, Layer,
|
||||
Pos2, Rect,
|
||||
};
|
||||
|
||||
/// The data that Egui persists between frames.
|
||||
|
|
|
@ -1,6 +1,21 @@
|
|||
use crate::{widgets::*, *};
|
||||
//! Menu bar functionality.
|
||||
//!
|
||||
//! Usage:
|
||||
//! ``` rust
|
||||
//! fn show_menu(ui: &mut egui::Ui) {
|
||||
//! use egui::{menu, Button};
|
||||
//!
|
||||
//! menu::bar(ui, |ui| {
|
||||
//! menu::menu(ui, "File", |ui| {
|
||||
//! if ui.add(Button::new("Open")).clicked {
|
||||
//! // ...
|
||||
//! }
|
||||
//! });
|
||||
//! });
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use super::*;
|
||||
use crate::{widgets::*, *};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "with_serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
|
@ -21,6 +36,26 @@ impl Default for BarState {
|
|||
}
|
||||
}
|
||||
|
||||
impl BarState {
|
||||
fn load(ctx: &Context, bar_id: &Id) -> Self {
|
||||
ctx.memory()
|
||||
.menu_bar
|
||||
.get(bar_id)
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn save(self, ctx: &Context, bar_id: Id) {
|
||||
ctx.memory().menu_bar.insert(bar_id, self);
|
||||
}
|
||||
|
||||
fn close_menus(ctx: &Context, bar_id: Id) {
|
||||
let mut bar_state = BarState::load(ctx, &bar_id);
|
||||
bar_state.open_menu = None;
|
||||
bar_state.save(ctx, bar_id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bar<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Rect) {
|
||||
ui.inner_layout(Layout::horizontal(Align::Center), |ui| {
|
||||
Frame::menu_bar(ui.style()).show(ui, |ui| {
|
||||
|
@ -38,7 +73,17 @@ pub fn bar<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Rect)
|
|||
let height = ui.style().menu_bar.height;
|
||||
ui.set_desired_height(height);
|
||||
ui.expand_to_size(vec2(ui.available().width(), height));
|
||||
add_contents(ui)
|
||||
|
||||
let ret = add_contents(ui);
|
||||
|
||||
let clicked_outside = !ui.hovered(ui.rect()) && ui.input().mouse.released;
|
||||
if clicked_outside || ui.input().key_pressed(Key::Escape) {
|
||||
// TODO: this prevent sub-menus in menus. We should fix that.
|
||||
let bar_id = ui.id();
|
||||
BarState::close_menus(ui.ctx(), bar_id);
|
||||
}
|
||||
|
||||
ret
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -57,12 +102,7 @@ fn menu_impl<'c>(
|
|||
let bar_id = ui.id();
|
||||
let menu_id = bar_id.with(&title);
|
||||
|
||||
let mut bar_state = ui
|
||||
.memory()
|
||||
.menu_bar
|
||||
.get(&bar_id)
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
let mut bar_state = BarState::load(ui.ctx(), &bar_id);
|
||||
|
||||
let mut button = Button::new(title);
|
||||
|
||||
|
@ -105,7 +145,7 @@ fn menu_impl<'c>(
|
|||
}
|
||||
}
|
||||
|
||||
ui.memory().menu_bar.insert(bar_id, bar_state);
|
||||
bar_state.save(ui.ctx(), bar_id);
|
||||
}
|
||||
|
||||
fn interact_with_menu_button(
|
||||
|
@ -138,17 +178,4 @@ fn interact_with_menu_button(
|
|||
if button_interact.hovered && bar_state.open_menu.is_some() {
|
||||
bar_state.open_menu = Some(menu_id);
|
||||
}
|
||||
|
||||
let pressed_escape = input.events.iter().any(|event| {
|
||||
matches!(
|
||||
event,
|
||||
Event::Key {
|
||||
key: Key::Escape,
|
||||
pressed: true
|
||||
}
|
||||
)
|
||||
});
|
||||
if pressed_escape {
|
||||
bar_state.open_menu = None;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue