diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index 8edace2a..13763239 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -160,10 +160,11 @@ pub fn invoke(app: &mut FigApp, id: &str) { /// Every visible top-level frame of the page as one PDF page each, through a save dialog. fn export_frames_pdf(app: &mut FigApp) { let name = app.session.doc().map(|d| d.name.clone()).unwrap_or_else(|_| "Untitled".into()); - let Some(p) = app.services.pick_save(tr("Export"), &format!("{name}.pdf"), &["pdf"]) else { return }; - if app.run("file.exportFramesPdf", json!({"path": p.to_string_lossy()})).is_some() { - app.toast(trf("Exported {name}", &[("name", &p.file_name().map(|f| f.to_string_lossy().to_string()).unwrap_or_default())])); - } + app.pick_save(tr("Export"), &format!("{name}.pdf"), &["pdf"], |app, p| { + if app.run("file.exportFramesPdf", json!({"path": p.to_string_lossy()})).is_some() { + app.toast(trf("Exported {name}", &[("name", &p.file_name().map(|f| f.to_string_lossy().to_string()).unwrap_or_default())])); + } + }); } fn figcraft_svg_export(doc: &figcraft_doc::Document, ids: &[figcraft_doc::NodeId]) -> Option { diff --git a/crates/ui-egui/tests/file_menu_pdf.rs b/crates/ui-egui/tests/file_menu_pdf.rs index 140dbc6a..30b847b7 100644 --- a/crates/ui-egui/tests/file_menu_pdf.rs +++ b/crates/ui-egui/tests/file_menu_pdf.rs @@ -5,14 +5,25 @@ use std::path::PathBuf; use figcraft_engine::Session; -use figcraft_ui_egui::{FigApp, Services, menus}; +use figcraft_ui_egui::{DialogFuture, FigApp, Services, menus}; use serde_json::json; /// Services whose save dialog always returns the given path. struct SaveTo(PathBuf); impl Services for SaveTo { - fn pick_save(&mut self, _title: &str, _name: &str, _exts: &[&str]) -> Option { - Some(self.0.clone()) + fn pick_save(&mut self, _title: &str, _name: &str, _exts: &[&str]) -> DialogFuture { + Box::pin(std::future::ready(Some(self.0.clone()))) + } +} + +/// The menu item, then a frame: the save dialog answers asynchronously and the frame takes its answer. +fn invoke(app: &mut FigApp, id: &str) { + menus::invoke(app, id); + let ctx = egui::Context::default(); + for _ in 0..2 { + let input = + egui::RawInput { screen_rect: Some(egui::Rect::from_min_size(egui::Pos2::ZERO, egui::vec2(1440.0, 900.0))), ..Default::default() }; + ctx.run_ui(input, |ui| app.ui(ui)).textures_delta.clear(); } } @@ -37,7 +48,7 @@ fn frames_pdf_menu_saves_the_pdf() { let path = out_path("one"); let mut app = FigApp::new(Session::new(), Box::new(SaveTo(path.clone()))); frame(&mut app, 0, 0); - menus::invoke(&mut app, "file.exportFramesPdf"); + invoke(&mut app, "file.exportFramesPdf"); assert!(app.ui.last_error.is_none(), "{:?}", app.ui.last_error); let bytes = std::fs::read(&path).expect("the menu writes the PDF where the user chose"); let _ = std::fs::remove_file(&path); @@ -60,7 +71,7 @@ fn frames_pdf_menu_one_page_per_visible_frame() { let hidden = frame(&mut app, 600, 0); let id = hidden["id"].clone(); app.session.execute("node.set", &json!({"id": id, "visible": false})).unwrap(); - menus::invoke(&mut app, "file.exportFramesPdf"); + invoke(&mut app, "file.exportFramesPdf"); assert!(app.ui.last_error.is_none(), "{:?}", app.ui.last_error); let bytes = std::fs::read(&path).expect("the menu writes the PDF where the user chose"); let _ = std::fs::remove_file(&path);