mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Menus: keep scroll bar clear of shortcuts and stop above the status bar (#2086)
This commit is contained in:
committed by
bflatastic
parent
0c3a5929c7
commit
8e58b9a23f
@@ -826,7 +826,7 @@ fn hint_segments(tool: &str) -> Vec<(Cow<'static, str>, bool)> {
|
||||
|
||||
pub fn hint_bar(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
let t = Tokens::get(ui.ctx());
|
||||
egui::Panel::bottom("hint_bar")
|
||||
let panel = egui::Panel::bottom("hint_bar")
|
||||
.exact_size(28.0)
|
||||
.frame(egui::Frame::NONE.fill(t.panel).inner_margin(egui::Margin::symmetric(10, 0)).stroke(Stroke::new(1.0, t.border)))
|
||||
.show(ui, |ui| {
|
||||
@@ -850,6 +850,7 @@ pub fn hint_bar(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
ui.label(job);
|
||||
});
|
||||
});
|
||||
widgets::set_menu_floor(ui.ctx(), panel.response.rect.top());
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1310,6 +1310,9 @@ impl VectorcraftApp {
|
||||
if self.ui.status_bar && self.ui.screen_mode < 3 {
|
||||
chrome::status_bar(self, ui);
|
||||
chrome::hint_bar(self, ui);
|
||||
} else {
|
||||
// Keeps the previous frame's value valid for menus drawn above, before the bars.
|
||||
widgets::set_menu_floor(&ctx, ctx.content_rect().bottom());
|
||||
}
|
||||
if self.ui.toolbar && self.ui.screen_mode < 3 {
|
||||
toolbar::show(self, ui);
|
||||
|
||||
@@ -840,17 +840,33 @@ pub fn popover<R>(resp: &Response, toggle: bool, content: impl FnOnce(&mut Ui) -
|
||||
inner
|
||||
}
|
||||
|
||||
/// The body of a menu or popup list: as tall as its items up to the bottom of the window, and
|
||||
/// scrolling only past that, so long menus (Window, Effect, a panel's menu) stay reachable on
|
||||
/// small windows.
|
||||
pub fn menu_scroll<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> R {
|
||||
// Room left below the popup's first item, less the popup frame and a small gap.
|
||||
/// Records where the bottom bars (status and hint bars) start this frame, so menus can stop above
|
||||
/// them (#2086). Without bars it is the bottom of the window.
|
||||
pub fn set_menu_floor(ctx: &egui::Context, y: f32) {
|
||||
ctx.data_mut(|d| d.insert_temp(egui::Id::new("menu_floor"), y));
|
||||
}
|
||||
|
||||
/// The height a menu list may take: from `top` down to `floor` less a small gap, at least 120 pt.
|
||||
pub fn menu_room(floor: f32, top: f32) -> f32 {
|
||||
const BOTTOM_GAP: f32 = 12.0;
|
||||
const MIN_HEIGHT: f32 = 120.0;
|
||||
let room = (ui.ctx().content_rect().bottom() - ui.next_widget_position().y - BOTTOM_GAP).max(MIN_HEIGHT);
|
||||
// The minimum lets the list grow past a popup's default 400 pt size; it still shrinks to
|
||||
// its items when they need less.
|
||||
egui::ScrollArea::vertical().max_height(room).min_scrolled_height(room).show(ui, add_contents).inner
|
||||
(floor - top - BOTTOM_GAP).max(MIN_HEIGHT)
|
||||
}
|
||||
|
||||
/// The body of a menu or popup list: as tall as its items up to the bottom bars of the window, and
|
||||
/// scrolling only past that, so long menus (Window, Effect, a panel's menu) stay reachable on
|
||||
/// small windows. Its scroll bar has a column of its own, so it never covers the shortcuts or the
|
||||
/// submenu arrows (#2086).
|
||||
pub fn menu_scroll<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> R {
|
||||
let floor = ui.ctx().data(|d| d.get_temp::<f32>(egui::Id::new("menu_floor"))).unwrap_or_else(|| ui.ctx().content_rect().bottom());
|
||||
let room = menu_room(floor, ui.next_widget_position().y);
|
||||
ui.scope(|ui| {
|
||||
ui.spacing_mut().scroll = egui::style::ScrollStyle { bar_width: 6.0, bar_inner_margin: 2.0, ..egui::style::ScrollStyle::solid() };
|
||||
// The minimum lets the list grow past a popup's default 400 pt size; it still shrinks to
|
||||
// its items when they need less.
|
||||
egui::ScrollArea::vertical().max_height(room).min_scrolled_height(room).show(ui, add_contents).inner
|
||||
})
|
||||
.inner
|
||||
}
|
||||
|
||||
/// A column of tool or panel buttons (the toolbar, the dock's icon column) that scrolls when the
|
||||
@@ -1950,3 +1966,19 @@ mod spinner_modifier_tests {
|
||||
assert_eq!(spinner_step(0.0, 1.0, 0.0, false, egui::Modifiers::SHIFT), 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod menu_room_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn menu_stops_above_the_bottom_bars() {
|
||||
// Window 1000 pt tall, bars start at 948: a menu opening at y = 100 gets 836 pt, not 888.
|
||||
assert_eq!(menu_room(948.0, 100.0), 836.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn menu_keeps_a_minimum_height() {
|
||||
assert_eq!(menu_room(300.0, 290.0), 120.0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user