Dialogs: a dialog no longer keeps a taller one's height (#5118) (#5139)

This commit is contained in:
mmmaarian03-crypto authored and GitHub committed 2026-11-09 10:11:41 +08:00
1 parent ab7af72347
commit 06911895c6
3 files changed
+78 -1

No files matched your search

+12 -1
View File
@@ -127,7 +127,18 @@ fn dialogs(app: &mut PdfCraftApp, ctx: &egui::Context) {
app.custom_draft = Some((id, crate::CustomDraft { props: doc.custom_info(), ..Default::default() }));
}
let mut req = Pending::default();
let modal = widgets::show_modal(ctx, "dialog", |ui| {
// Every dialog shares this modal. A different dialog than the one shown before starts from
// its own size, not from the last one's: rows that fill the height they are offered would
// otherwise keep, say, Print as tall as Preferences (#5118). Tabs of one dialog keep its size;
// the kinds of Marks and Export are different dialogs.
let shown = egui::Id::unique("dialog").with("shown");
let kind = match dialog {
Dialog::Properties(_) => Dialog::Properties(PropsTab::Description),
_ => dialog,
};
let remeasure = ctx.data(|d| d.get_temp::<Dialog>(shown)) != Some(kind);
ctx.data_mut(|d| d.insert_temp(shown, kind));
let modal = widgets::show_modal_sized(ctx, "dialog", remeasure, |ui| {
ui.set_width(match dialog {
Dialog::Properties(_) => 640.0,
Dialog::Print => 820.0,
+15
View File
@@ -35,7 +35,22 @@ pub fn modal(ctx: &egui::Context, id: impl std::hash::Hash + std::fmt::Debug) ->
/// Show [`modal`], outline its controls, and remember the card rect for layout checks.
pub fn show_modal<R>(ctx: &egui::Context, id: &str, content: impl FnOnce(&mut egui::Ui) -> R) -> egui::ModalResponse<R> {
show_modal_sized(ctx, id, false, content)
}
/// [`show_modal`], growing from its contents' own height when `remeasure` is set rather than
/// from the height it had last frame: one modal id that shows different contents would
/// otherwise keep the height of the previous ones, since rows that fill the height offered to
/// them take all of it (#5118). The width stays, and the contents stay visible (no hidden
/// sizing frame), so the control channel can inspect a dialog the frame it opens.
pub fn show_modal_sized<R>(ctx: &egui::Context, id: &str, remeasure: bool, content: impl FnOnce(&mut egui::Ui) -> R) -> egui::ModalResponse<R> {
let stored = egui::Id::unique(id);
if remeasure && let Some(mut state) = egui::AreaState::load(ctx, stored) {
state.size = state.size.map(|s| egui::vec2(s.x, 0.0));
ctx.memory_mut(|m| m.areas_mut().set_state(egui::Modal::default_area(stored).layer(), state));
// The card is centred on the height it ends with: draw once more at that height.
ctx.request_repaint();
}
modal(ctx, id).show(ctx, |ui| {
begin_dialog(ui);
let inner = content(ui);
+51
View File
@@ -258,3 +258,54 @@ fn page_hover_cursors_stay_off_while_a_dialog_is_open() {
h.run_steps(2);
assert_eq!(h.output().platform_output.cursor_icon, egui::CursorIcon::Default, "nothing under the dialog's backdrop can be clicked");
}
#[test]
fn a_dialog_keeps_its_own_height_after_a_taller_one() {
// #5118: Print opened after Preferences was as tall as Preferences, with blank space below
// its buttons. Every dialog shares one modal, which kept the last dialog's size.
use pdfcraft_ui_egui::Dialog;
for dialog in [Dialog::Print, Dialog::RotatePages] {
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_eframe(|_cc| {
let mut app = PdfCraftApp::new();
app.set_option("language", "en").unwrap();
app.open_bytes("doc.pdf", None, fixture()).unwrap();
app
});
let show = |h: &mut Harness<'_, PdfCraftApp>, d: Dialog| {
h.state_mut().dialog = None;
h.run_steps(2);
h.state_mut().dialog = Some(d);
h.run_steps(6);
card(h, "dialog")
};
let fresh = show(&mut h, dialog);
let prefs = show(&mut h, Dialog::Preferences);
assert!(prefs.height() > fresh.height() + 20.0, "{dialog:?} {fresh:?} isn't shorter than Preferences {prefs:?}");
let after = show(&mut h, dialog);
assert!((after.height() - fresh.height()).abs() < 1.0, "{dialog:?} {fresh:?}, after Preferences {after:?}");
}
}
#[test]
fn each_kind_of_marks_dialog_keeps_its_own_height() {
// #5118: Header & Footer, Watermark and Background are one `Dialog::Marks` with different
// contents. Background opened after Header & Footer kept the taller dialog's height.
let mut h = Harness::builder().with_size(egui::vec2(1400.0, 900.0)).build_eframe(|_cc| {
let mut app = PdfCraftApp::new();
app.set_option("language", "en").unwrap();
app.open_bytes("doc.pdf", None, fixture()).unwrap();
app
});
let show = |h: &mut Harness<'_, PdfCraftApp>, d: &str| {
h.state_mut().dialog = None;
h.run_steps(2);
h.state_mut().set_option("dialog", d).unwrap();
h.run_steps(6);
card(h, "dialog")
};
let fresh = show(&mut h, "background");
let header = show(&mut h, "header-footer");
assert!(header.height() > fresh.height() + 20.0, "Background {fresh:?} isn't shorter than Header & Footer {header:?}");
let after = show(&mut h, "background");
assert!((after.height() - fresh.height()).abs() < 1.0, "Background {fresh:?}, after Header & Footer {after:?}");
}