Tabs: Above Text keeps the panel's bar inside the window

With text near the top of the window, Position Panel Above Text put the
panel, and its OS window, above the main window's content and could put
the bar above every screen. The panel now goes no higher than the top of
the main window's content.
This commit is contained in:
dotCooCoo
2026-11-02 14:32:49 +07:00
committed by bflatastic
parent d8394d5d87
commit 48e2bc6508
2 changed files with 36 additions and 2 deletions
+3 -1
View File
@@ -265,7 +265,9 @@ fn above_text(app: &mut VectorcraftApp, ctx: &egui::Context, n: &Node, span: f64
}
let width = span as f32 * per + RULER_LEFT * 2.0;
let height = crate::panel_docking::layout_of(&app.ui).floating.iter().find(|w| w.contains(&"tabs".to_string())).map_or(240.0, |w| w.rect[3]);
let pos = egui::pos2(on_screen.left() - RULER_LEFT, on_screen.top() - height - 6.0);
// Text near the top of the window: the panel's bar stays inside the window, where it can be
// grabbed, not above the screen.
let pos = egui::pos2(on_screen.left() - RULER_LEFT, (on_screen.top() - height - 6.0).max(0.0));
let origin = ctx.input(|i| i.raw.viewports.get(&egui::ViewportId::ROOT).and_then(|v| v.inner_rect)).map(|r| r.min);
crate::panel_docking::place_floating(app, "tabs", pos, width, origin).ok()?;
Some(())
+33 -1
View File
@@ -991,7 +991,8 @@ fn above_text_puts_the_ruler_over_the_text_at_the_zoom() {
let mut app = VectorcraftApp::new(Session::new(), Default::default());
app.session.execute("file.new", &json!({"width": 600, "height": 400})).unwrap();
app.session.execute("text.create", &json!({"x": 40, "y": 200, "text": "a b", "area": {"width": 300, "height": 100}})).unwrap();
app.canvas_rect = Some(egui::Rect::from_min_size(egui::pos2(50.0, 40.0), vec2(1000.0, 700.0)));
// The canvas starts low enough in the window for the panel to fit above the text at 200%.
app.canvas_rect = Some(egui::Rect::from_min_size(egui::pos2(50.0, 440.0), vec2(1000.0, 700.0)));
for zoom in [1.0, 2.0] {
if let Some(v) = app.view_mut() {
v.zoom = zoom;
@@ -1044,3 +1045,34 @@ fn above_text_moves_a_panel_floating_in_its_own_window() {
assert_eq!([native[0], native[1]], [200.0 + g.rect[0], 100.0 + g.rect[1]], "the OS window goes above the text");
assert_eq!([native[2], native[3]], [g.rect[2], g.rect[3]]);
}
/// Text near the top of the window: Position Panel Above Text keeps the panel's bar inside the
/// window, so neither the panel nor its OS window goes above the screen.
#[test]
fn above_text_keeps_the_panel_bar_in_the_window() {
let mut app = VectorcraftApp::new(Session::new(), Default::default());
app.session.execute("file.new", &json!({"width": 600, "height": 400})).unwrap();
app.session.execute("text.create", &json!({"x": 40, "y": 10, "text": "a b", "area": {"width": 300, "height": 100}})).unwrap();
app.canvas_rect = Some(egui::Rect::from_min_size(egui::pos2(50.0, 40.0), vec2(1000.0, 700.0)));
if let Some(v) = app.view_mut() {
v.zoom = 1.0;
}
let (node, _, span) = current(&app).unwrap();
let xf = crate::canvas::Xf::new(app.canvas_rect.unwrap(), app.view().unwrap());
assert!(xf.rect_to_screen(node.geometric_bounds().unwrap()).top() < 240.0, "no room above the text");
let ctx = egui::Context::default();
above_text(&mut app, &ctx, &node, span).unwrap();
let mut layout = app.ui.docking.clone().unwrap();
let window = layout.floating.iter_mut().find(|w| w.contains(&"tabs".to_string())).unwrap();
assert_eq!(window.rect[1], 0.0, "the panel's bar at the window's top");
window.native = Some([1500.0, 900.0, window.rect[2], window.rect[3]]);
app.ui.docking = Some(layout);
let mut raw = egui::RawInput::default();
raw.viewports.entry(egui::ViewportId::ROOT).or_default().inner_rect =
Some(egui::Rect::from_min_size(egui::pos2(200.0, 100.0), vec2(1200.0, 800.0)));
ctx.run_ui(raw, |_| {}).textures_delta.clear();
above_text(&mut app, &ctx, &node, span).unwrap();
let layout = app.ui.docking.clone().unwrap();
let g = layout.floating.iter().find(|w| w.contains(&"tabs".to_string())).unwrap();
assert_eq!(g.native.unwrap()[1], 100.0, "the OS window's bar at the main window's content top");
}