[menu] simplify menu interactions, fixing an annoying bug
This commit is contained in:
parent
22fffc1793
commit
d8021843f8
2 changed files with 17 additions and 67 deletions
|
@ -25,6 +25,7 @@ pub struct Memory {
|
||||||
|
|
||||||
// states of various types of widgets
|
// states of various types of widgets
|
||||||
pub(crate) collapsing_headers: HashMap<Id, collapsing_header::State>,
|
pub(crate) collapsing_headers: HashMap<Id, collapsing_header::State>,
|
||||||
|
#[cfg_attr(feature = "serde", serde(skip))]
|
||||||
pub(crate) menu_bar: HashMap<Id, menu::BarState>,
|
pub(crate) menu_bar: HashMap<Id, menu::BarState>,
|
||||||
pub(crate) resize: HashMap<Id, resize::State>,
|
pub(crate) resize: HashMap<Id, resize::State>,
|
||||||
pub(crate) scroll_areas: HashMap<Id, scroll_area::State>,
|
pub(crate) scroll_areas: HashMap<Id, scroll_area::State>,
|
||||||
|
|
|
@ -18,23 +18,9 @@
|
||||||
use crate::{color::TRANSPARENT, paint::Stroke, widgets::*, *};
|
use crate::{color::TRANSPARENT, paint::Stroke, widgets::*, *};
|
||||||
|
|
||||||
/// What is saved between frames.
|
/// What is saved between frames.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
|
||||||
pub(crate) struct BarState {
|
pub(crate) struct BarState {
|
||||||
#[cfg_attr(feature = "serde", serde(skip))]
|
|
||||||
open_menu: Option<Id>,
|
open_menu: Option<Id>,
|
||||||
#[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 {
|
impl BarState {
|
||||||
|
@ -49,12 +35,6 @@ impl BarState {
|
||||||
fn save(self, ctx: &Context, bar_id: Id) {
|
fn save(self, ctx: &Context, bar_id: Id) {
|
||||||
ctx.memory().menu_bar.insert(bar_id, self);
|
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) {
|
pub fn bar<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Rect) {
|
||||||
|
@ -75,16 +55,7 @@ pub fn bar<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Rect)
|
||||||
ui.set_desired_height(height);
|
ui.set_desired_height(height);
|
||||||
ui.expand_to_size(vec2(ui.available().width(), height));
|
ui.expand_to_size(vec2(ui.available().width(), height));
|
||||||
|
|
||||||
let ret = add_contents(ui);
|
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
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -112,8 +83,16 @@ fn menu_impl<'c>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let button_response = ui.add(button);
|
let button_response = ui.add(button);
|
||||||
|
if button_response.clicked {
|
||||||
interact_with_menu_button(&mut bar_state, ui.input(), menu_id, &button_response);
|
// 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) {
|
if bar_state.open_menu == Some(menu_id) {
|
||||||
let area = Area::new(menu_id)
|
let area = Area::new(menu_id)
|
||||||
|
@ -121,7 +100,7 @@ fn menu_impl<'c>(
|
||||||
.fixed_pos(button_response.rect.left_bottom());
|
.fixed_pos(button_response.rect.left_bottom());
|
||||||
let frame = Frame::menu(ui.style());
|
let frame = Frame::menu(ui.style());
|
||||||
|
|
||||||
let menu_response = area.show(ui.ctx(), |ui| {
|
area.show(ui.ctx(), |ui| {
|
||||||
frame.show(ui, |ui| {
|
frame.show(ui, |ui| {
|
||||||
let mut style = ui.style().clone();
|
let mut style = ui.style().clone();
|
||||||
style.spacing.button_padding = vec2(2.0, 0.0);
|
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.open_menu = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bar_state.save(ui.ctx(), bar_id);
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue