diff --git a/crates/ui/src/panes/mod.rs b/crates/ui/src/panes/mod.rs
index 618678f2..28124fa7 100644
--- a/crates/ui/src/panes/mod.rs
+++ b/crates/ui/src/panes/mod.rs
@@ -205,6 +205,7 @@ struct DragOut {
canceled: bool,
}
+#[derive(Clone)]
struct Shown
{
pane: P,
id: Id,
@@ -349,6 +350,8 @@ impl PaneHost {
states(pane).or_else(|| ctx.data(|data| data.get_temp::(id.with("state")))).unwrap_or_else(|| content.default_state(pane));
shown.push(Shown { pane: pane.clone(), id, state });
}
+ // Before the one-slot filter: a drop can reveal a pane this frame hides.
+ let open_panes = shown.clone();
self.one_slot(&mut shown, content);
let previous = memory.active.filter(|active| shown.iter().any(|s| s.id == *active));
@@ -379,12 +382,12 @@ impl PaneHost {
for edge in [Edge::Start, Edge::End, Edge::Bottom] {
for s in shown.iter().filter(|s| s.state.place == Place::Docked(edge)) {
let rect =
- self.docked(ui, &shown, s, edge, content, &style, focus_target == Some(s.id), bounds, &mut memory, &preview, &mut requests);
+ self.docked(ui, &open_panes, s, edge, content, &style, focus_target == Some(s.id), bounds, &mut memory, &preview, &mut requests);
regions.push(Region { pane: s.id, rect, floating: None });
}
}
for s in shown.iter().filter(|s| s.state.place == Place::Floating) {
- let (rect, layer) = self.floating(&ctx, &shown, s, content, &style, focus_target == Some(s.id), bounds, &preview, &mut requests);
+ let (rect, layer) = self.floating(&ctx, &open_panes, s, content, &style, focus_target == Some(s.id), bounds, &preview, &mut requests);
regions.push(Region { pane: s.id, rect, floating: Some(layer) });
}
@@ -546,7 +549,10 @@ impl PaneHost {
let side = self.side(edge);
let extent = if side == Side::Bottom { bounds.height() } else { bounds.width() };
let (min, max) = self.limits(content, &s.pane, extent);
- let size = self.docked_size(content, s, edge, bounds);
+ // A side pane takes no more than the width the panes outside it leave: egui would place
+ // a wider one partly beyond the host's edge.
+ let room = if side == Side::Bottom { f32::INFINITY } else { ui.available_rect_before_wrap().width().max(0.0) };
+ let size = self.docked_size(content, s, edge, bounds).min(room);
let panel_id = s.id.with("panel");
let panel = match side {
Side::Left => egui::Panel::left(panel_id),
diff --git a/crates/ui/src/panes/tests.rs b/crates/ui/src/panes/tests.rs
index eac2fce4..25622e63 100644
--- a/crates/ui/src/panes/tests.rs
+++ b/crates/ui/src/panes/tests.rs
@@ -299,6 +299,26 @@ fn one_slot_previews_a_pane_beside_the_context_pane() {
assert_eq!(panel(&h, Pane::Styles), landing);
}
+#[test]
+fn one_slot_previews_the_room_a_pane_it_reveals_leaves() {
+ // Nav and Styles share the start slot, so only Styles shows. Moved to the end, it reveals
+ // Nav, which takes 500 of the host's 784 pt.
+ let mut app = App::new(&[Pane::Nav, Pane::Styles]);
+ app.policy = SidePolicy::OneSlot;
+ for pane in [Pane::Nav, Pane::Styles] {
+ app.states.insert(pane, PaneState::docked(Edge::Start, 500.0));
+ }
+ let mut h = harness(app);
+ let from = title(&h, Pane::Styles).center();
+ let to = pos2(R - 10.0, 300.0);
+ hold(&mut h, from, to);
+ let landing = Rect::from_x_y_ranges(L + 500.0..=R, 8.0..=592.0);
+ assert_eq!(previews(&h), vec![landing]);
+ send(&mut h, vec![button(to, false)]);
+ h.run_steps(2);
+ assert_eq!(panel(&h, Pane::Styles), landing);
+}
+
#[test]
fn escape_and_focus_loss_restore_a_floating_pane_during_a_move() {
let mut app = App::new(&[Pane::Styles]);