mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Font menu: the scroll bar no longer covers the favourite stars (#2277)
The family list scrolled with egui's floating scroll bar, which is drawn over the rows' right ends, where each family's star is: with the pointer there the bar widened over the star and a click went to the bar. The list now takes the scroll bar the menus got for the same reason (#2086), slim and in a column of its own; `widgets::list_scroll_style` holds it for both.
This commit is contained in:
@@ -372,6 +372,9 @@ fn list(ui: &mut Ui, state_id: egui::Id, st: &mut MenuState, current: &str, samp
|
||||
let mut toggled: Option<String> = None;
|
||||
let mut starred: Option<String> = None;
|
||||
ui.spacing_mut().item_spacing.y = 0.0;
|
||||
// The scroll bar beside the rows, not over them: a floating one covered the stars at their
|
||||
// right ends, so a favourite was hard to click (#2277).
|
||||
ui.spacing_mut().scroll = widgets::list_scroll_style();
|
||||
let shown = area.show_rows(ui, row_h, rows.len(), |ui, range| {
|
||||
for i in range {
|
||||
let Some(row) = rows.get(i) else { continue };
|
||||
@@ -775,6 +778,45 @@ mod tests {
|
||||
assert_eq!(super::script_label(3), "Thai");
|
||||
}
|
||||
|
||||
/// #2277: the list's scroll bar has a column of its own, so the stars at the rows' right ends
|
||||
/// stay clear of it.
|
||||
#[test]
|
||||
fn the_scroll_bar_leaves_the_stars_clear() {
|
||||
// Every family starred, so each row draws its star.
|
||||
let all = vectorcraft_text::FontDb::global().families();
|
||||
let families = all.len();
|
||||
let ctx = egui::Context::default();
|
||||
let area = egui::Rect::from_min_size(egui::pos2(0.0, 0.0), egui::vec2(300.0, 160.0));
|
||||
let mut st = super::MenuState::default();
|
||||
let look = super::MenuLook { samples: false, favorites: &all, ..Default::default() };
|
||||
let mut stars = vec![];
|
||||
for _ in 0..3 {
|
||||
let mut out = ctx.run_ui(egui::RawInput { screen_rect: Some(area), ..Default::default() }, |ui| {
|
||||
let mut child = ui.new_child(egui::UiBuilder::new().max_rect(area));
|
||||
super::list(&mut child, egui::Id::new("fonts"), &mut st, "", None, look);
|
||||
});
|
||||
out.textures_delta.clear();
|
||||
stars = out
|
||||
.shapes
|
||||
.iter()
|
||||
.filter_map(|c| match &c.shape {
|
||||
// The rows' stars, not the ★ filter button at the top left.
|
||||
egui::Shape::Text(t) if t.galley.text() == "★" && t.pos.x > area.center().x => Some(t.visual_bounding_rect().right()),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
assert!(!stars.is_empty() || families == 0, "{families} families, no row stars drawn");
|
||||
// The rows don't fill the list without enough families to scroll, and then there is no bar.
|
||||
if families as f32 * look.row > area.height() {
|
||||
let bar = super::widgets::list_scroll_style();
|
||||
let column = bar.bar_width + bar.bar_inner_margin + bar.bar_outer_margin;
|
||||
for right in stars {
|
||||
assert!(right <= area.right() - column + 0.5, "a star at {right} runs under the scroll bar");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use super::{Row, remap_highlight};
|
||||
|
||||
fn family(name: &str) -> Row {
|
||||
|
||||
@@ -861,6 +861,12 @@ pub fn menu_room(floor: f32, top: f32) -> f32 {
|
||||
(floor - top - BOTTOM_GAP).max(MIN_HEIGHT)
|
||||
}
|
||||
|
||||
/// The scroll bar of a menu's list: slim, in a column of its own beside the items, so it never
|
||||
/// covers what sits at their right end (shortcuts, submenu arrows, a font's favourite star).
|
||||
pub fn list_scroll_style() -> egui::style::ScrollStyle {
|
||||
egui::style::ScrollStyle { bar_width: 6.0, bar_inner_margin: 2.0, ..egui::style::ScrollStyle::solid() }
|
||||
}
|
||||
|
||||
/// 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
|
||||
@@ -869,7 +875,7 @@ 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() };
|
||||
ui.spacing_mut().scroll = list_scroll_style();
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user