From d8021843f8be81967f02fba866fcaa1ce86ce7d8 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 25 Sep 2020 15:31:27 +0200 Subject: [PATCH] [menu] simplify menu interactions, fixing an annoying bug --- egui/src/memory.rs | 1 + egui/src/menu.rs | 83 +++++++++------------------------------------- 2 files changed, 17 insertions(+), 67 deletions(-) diff --git a/egui/src/memory.rs b/egui/src/memory.rs index 1cc170f0..017120ba 100644 --- a/egui/src/memory.rs +++ b/egui/src/memory.rs @@ -25,6 +25,7 @@ pub struct Memory { // states of various types of widgets pub(crate) collapsing_headers: HashMap, + #[cfg_attr(feature = "serde", serde(skip))] pub(crate) menu_bar: HashMap, pub(crate) resize: HashMap, pub(crate) scroll_areas: HashMap, diff --git a/egui/src/menu.rs b/egui/src/menu.rs index f93e1a89..9be946d8 100644 --- a/egui/src/menu.rs +++ b/egui/src/menu.rs @@ -18,23 +18,9 @@ use crate::{color::TRANSPARENT, paint::Stroke, widgets::*, *}; /// What is saved between frames. -#[derive(Clone, Copy, Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[derive(Clone, Copy, Debug, Default)] pub(crate) struct BarState { - #[cfg_attr(feature = "serde", serde(skip))] open_menu: Option, - #[cfg_attr(feature = "serde", serde(skip))] - /// When did we open a menu? - open_time: f64, -} - -impl Default for BarState { - fn default() -> Self { - Self { - open_menu: None, - open_time: f64::NEG_INFINITY, - } - } } impl BarState { @@ -49,12 +35,6 @@ impl BarState { 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(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Rect) { @@ -75,16 +55,7 @@ pub fn bar(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Rect) ui.set_desired_height(height); ui.expand_to_size(vec2(ui.available().width(), height)); - let ret = add_contents(ui); - - let clicked_outside = !ui.hovered(ui.rect()) && ui.input().mouse.click; - if clicked_outside || ui.input().key_pressed(Key::Escape) { - // TODO: this prevents sub-menus in menus. We should fix that. - let bar_id = ui.id(); - BarState::close_menus(ui.ctx(), bar_id); - } - - ret + add_contents(ui) }) }) } @@ -112,8 +83,16 @@ fn menu_impl<'c>( } let button_response = ui.add(button); - - interact_with_menu_button(&mut bar_state, ui.input(), menu_id, &button_response); + if button_response.clicked { + // Toggle + if bar_state.open_menu == Some(menu_id) { + bar_state.open_menu = None; + } else { + bar_state.open_menu = Some(menu_id); + } + } else if button_response.hovered && bar_state.open_menu.is_some() { + bar_state.open_menu = Some(menu_id); + } if bar_state.open_menu == Some(menu_id) { let area = Area::new(menu_id) @@ -121,7 +100,7 @@ fn menu_impl<'c>( .fixed_pos(button_response.rect.left_bottom()); let frame = Frame::menu(ui.style()); - let menu_response = area.show(ui.ctx(), |ui| { + area.show(ui.ctx(), |ui| { frame.show(ui, |ui| { let mut style = ui.style().clone(); style.spacing.button_padding = vec2(2.0, 0.0); @@ -137,42 +116,12 @@ fn menu_impl<'c>( }) }); - if menu_response.hovered && ui.input().mouse.released { + // TODO: this prevents sub-menus in menus. We should fix that. + if ui.input().key_pressed(Key::Escape) || ui.input().mouse.click && !button_response.clicked + { bar_state.open_menu = None; } } bar_state.save(ui.ctx(), bar_id); } - -fn interact_with_menu_button( - bar_state: &mut BarState, - input: &InputState, - menu_id: Id, - button_response: &Response, -) { - if button_response.hovered && input.mouse.pressed { - if bar_state.open_menu.is_some() { - bar_state.open_menu = None; - } else { - bar_state.open_menu = Some(menu_id); - bar_state.open_time = input.time; - } - } - - if button_response.hovered && input.mouse.released && bar_state.open_menu.is_some() { - let time_since_open = input.time - bar_state.open_time; - if time_since_open < 0.4 { - // A quick click - bar_state.open_menu = Some(menu_id); - bar_state.open_time = input.time; - } else { - // A long hold, then release - bar_state.open_menu = None; - } - } - - if button_response.hovered && bar_state.open_menu.is_some() { - bar_state.open_menu = Some(menu_id); - } -}