diff --git a/crates/ui-egui/src/floating.rs b/crates/ui-egui/src/floating.rs index 21f0a5bb..3080a25c 100644 --- a/crates/ui-egui/src/floating.rs +++ b/crates/ui-egui/src/floating.rs @@ -496,12 +496,13 @@ mod tests { const SCREEN: Vec2 = vec2(1400.0, 900.0); - /// Frames of the whole window, 1400 × 900, with pointer input one event a frame (as the - /// control channel's `ui.drag` sends it). + /// Frames of the whole window, with pointer input one event a frame (as the control + /// channel's `ui.drag` sends it). struct Harness { app: VectorcraftApp, ctx: egui::Context, time: f64, + screen: Vec2, } fn button(pos: Pos2, pressed: bool) -> Event { @@ -510,16 +511,23 @@ mod tests { impl Harness { fn new() -> Self { + Self::on(SCREEN) + } + + /// The same window at another size. The icon column scrolls when it is too short for + /// every icon, which hides the ones past the bottom — a test that counts them needs + /// a window tall enough to show them all. + fn on(screen: Vec2) -> Self { let mut app = VectorcraftApp::new(Session::new(), Default::default()); app.run("file.new", json!({"width": 300, "height": 300})).unwrap(); - let mut h = Self { app, ctx: egui::Context::default(), time: 0.0 }; + let mut h = Self { app, ctx: egui::Context::default(), time: 0.0, screen }; h.settle(); h } fn frame(&mut self, events: Vec) { self.time += 0.05; - let screen = Rect::from_min_size(Pos2::ZERO, SCREEN); + let screen = Rect::from_min_size(Pos2::ZERO, self.screen); let raw = egui::RawInput { time: Some(self.time), screen_rect: Some(screen), events, ..Default::default() }; let app = &mut self.app; self.ctx @@ -651,10 +659,13 @@ mod tests { #[test] fn icons_dragged_out_float_stack_onto_another_group_and_tear_out_of_it() { - let mut h = Harness::new(); + // Tall enough that the icon column shows every icon, so counting them says what it + // means: one leaves the column, rather than one more scrolling into view. + let mut h = Harness::on(vec2(1400.0, 1600.0)); // Color, Color Guide, Swatches… top to bottom. let icons = h.icons(); let count = icons.len(); + assert_eq!(count, crate::state::ICON_PANEL_GROUPS.iter().map(|g| g.len()).sum::(), "every group's icons are drawn"); h.drag(icons[2].center(), pos2(500.0, 250.0)); assert_eq!(h.groups(), [["swatches"]]); assert_eq!(h.icons().len(), count - 1, "its icon left the column"); diff --git a/crates/ui-egui/src/panels/variables.rs b/crates/ui-egui/src/panels/variables.rs index 9cf14355..6785bc0c 100644 --- a/crates/ui-egui/src/panels/variables.rs +++ b/crates/ui-egui/src/panels/variables.rs @@ -293,6 +293,22 @@ mod tests { assert!(crate::icons::exists(row.2), "{} is not a bundled icon", row.2); } + /// The collapsed column draws `ICON_PANEL_GROUPS`, not `ICON_PANELS`: a panel registered + /// but in no group opens from the Window menu and then has nowhere to collapse to. Both + /// lists need an entry, and this is the one that was missing. + #[test] + fn the_panel_reaches_the_collapsed_icon_column() { + let in_column = crate::state::ICON_PANEL_GROUPS.iter().any(|g| g.contains(&ID)); + assert!(in_column, "{ID} is in ICON_PANELS but in no ICON_PANEL_GROUPS row, so the collapsed column never draws it"); + // Every id in a group names a panel that is registered with a label and an icon. + for group in crate::state::ICON_PANEL_GROUPS { + for id in *group { + let row = crate::state::ICON_PANELS.iter().find(|p| p.0 == *id).unwrap_or_else(|| panic!("{id} is in a group but not registered")); + assert!(!row.1.is_empty() && crate::icons::exists(row.2), "{id}: {} / {}", row.1, row.2); + } + } + } + /// Every Variables command is in the Window menu, so the feature is reachable without an /// agent: the palette runs these with empty params, which the dialogs turn into a form. #[test] diff --git a/crates/ui-egui/src/state.rs b/crates/ui-egui/src/state.rs index 0d3e3370..3b31518e 100644 --- a/crates/ui-egui/src/state.rs +++ b/crates/ui-egui/src/state.rs @@ -142,6 +142,10 @@ pub const ICON_PANELS: &[(&str, &str, &str)] = &[ ]; /// Groups of icon panels separated by dividers in the collapsed column. +/// +/// This, not [`ICON_PANELS`], is what the collapsed column draws: a panel listed there but in +/// no group can be opened from the Window menu and `window.panel`, but never appears as an +/// icon. A panel that belongs in the column needs a row here as well as its entry above. pub const ICON_PANEL_GROUPS: &[&[&str]] = &[ &["color", "colorGuide"], &["swatches", "brushes", "symbols", "patternOptions"], @@ -151,6 +155,7 @@ pub const ICON_PANEL_GROUPS: &[&[&str]] = &[ &["transform", "align", "pathfinder"], &["character", "paragraph", "glyphs"], &["history", "actions", "info", "navigator"], + &["variables"], ]; #[derive(Clone, Debug, Serialize, Deserialize)]