diff --git a/crates/ui-egui/src/docking.rs b/crates/ui-egui/src/docking.rs index 58fd71a678..4531709046 100644 --- a/crates/ui-egui/src/docking.rs +++ b/crates/ui-egui/src/docking.rs @@ -396,12 +396,17 @@ pub fn show(app: &mut crate::PdfCraftApp, ui: &mut egui::Ui) { // Availability is a render projection: the saved group, selection and width survive Home. let _ = rendered.apply(Action::Close { panel: Panel::Inspector }); } + // Tools docked on its own is drawn bare, without a tab strip, like Acrobat's tool pane. Grouped + // with another panel, or floating, it keeps its tab so it can be dragged away again; moving it + // to the other side stays a preference and a command. + let bare_tools = rendered.location(&Panel::Tools).is_ok_and(|l| l.floating.is_none() && matches!(l.placement, Placement::Split(_))); + let render_permissions = move |panel: &Panel| if bare_tools && *panel == Panel::Tools { Permissions::PROTECTED } else { permissions(panel) }; let output = DockArea::new(egui::Id::new("pdfcraft-docking")).show_with_limits( ui, &rendered, &style, |panel| crate::i18n::t(panel.label()).into(), - permissions, + render_permissions, panel_limits, |ui, panel| match panel { Panel::Canvas => { diff --git a/crates/ui-egui/tests/control.rs b/crates/ui-egui/tests/control.rs index 20fa4cb230..7de5c59997 100644 --- a/crates/ui-egui/tests/control.rs +++ b/crates/ui-egui/tests/control.rs @@ -1299,19 +1299,13 @@ fn docking_pointer_group_float_close_restore_and_document_commands() { let (mut h, c) = harness(); ok(&mut h, &c, "ui.set", json!({"key":"panel", "value":"bookmarks"})); h.run_steps(4); - let from = h.get_by_role_and_label(egui::accesskit::Role::Tab, "Inspector").rect().center(); - let to = h.get_by_role_and_label(egui::accesskit::Role::Tab, "Tools").rect().center(); - h.event(egui::Event::PointerMoved(from)); - h.run_steps(2); - h.event(egui::Event::PointerButton { pos: from, button: egui::PointerButton::Primary, pressed: true, modifiers: egui::Modifiers::NONE }); - h.run_steps(2); - for step in 1..=8 { - h.event(egui::Event::PointerMoved(from.lerp(to, step as f32 / 8.0))); - h.run_steps(1); - } - h.event(egui::Event::PointerButton { pos: to, button: egui::PointerButton::Primary, pressed: false, modifiers: egui::Modifiers::NONE }); + // Tools docked alone has no tab strip (as Acrobat's tool pane), so it is grouped by command. + assert!(h.query_by_role_and_label(egui::accesskit::Role::Tab, "Tools").is_none()); + ok(&mut h, &c, "ui.dock", json!({"operation":"move", "panel":"inspector", "target":"tools", "zone":"center"})); h.run_steps(4); assert_eq!(h.state().docking.layout.location(&Panel::Inspector).unwrap().anchor, Some(Panel::Tools)); + // Grouped, Tools has its tab again. + h.get_by_role_and_label(egui::accesskit::Role::Tab, "Tools"); h.get_by_role_and_label(egui::accesskit::Role::Tab, "Inspector").click_button(egui::PointerButton::Secondary); h.run_steps(3); h.get_by_label("Float panel").click();