Support returning errors when creating the app (#4565)
The closure passed to `eframe::run_native` now returns a `Result`, allowing you to return an error during app creation, which will be returned to the caller of `run_native`. This means you need to wrap your `Box::new(MyApp::new(…))` in an `Ok(…)`. * Closes https://github.com/emilk/egui/issues/4474
This commit is contained in:
parent
54429e0549
commit
942fe4ab31
|
|
@ -41,10 +41,12 @@ pub type EventLoopBuilderHook = Box<dyn FnOnce(&mut EventLoopBuilder<UserEvent>)
|
||||||
#[cfg(any(feature = "glow", feature = "wgpu"))]
|
#[cfg(any(feature = "glow", feature = "wgpu"))]
|
||||||
pub type WindowBuilderHook = Box<dyn FnOnce(egui::ViewportBuilder) -> egui::ViewportBuilder>;
|
pub type WindowBuilderHook = Box<dyn FnOnce(egui::ViewportBuilder) -> egui::ViewportBuilder>;
|
||||||
|
|
||||||
|
type DynError = Box<dyn std::error::Error>;
|
||||||
|
|
||||||
/// This is how your app is created.
|
/// This is how your app is created.
|
||||||
///
|
///
|
||||||
/// You can use the [`CreationContext`] to setup egui, restore state, setup OpenGL things, etc.
|
/// You can use the [`CreationContext`] to setup egui, restore state, setup OpenGL things, etc.
|
||||||
pub type AppCreator = Box<dyn FnOnce(&CreationContext<'_>) -> Box<dyn App>>;
|
pub type AppCreator = Box<dyn FnOnce(&CreationContext<'_>) -> Result<Box<dyn App>, DynError>>;
|
||||||
|
|
||||||
/// Data that is passed to [`AppCreator`] that can be used to setup and initialize your app.
|
/// Data that is passed to [`AppCreator`] that can be used to setup and initialize your app.
|
||||||
pub struct CreationContext<'s> {
|
pub struct CreationContext<'s> {
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
//!
|
//!
|
||||||
//! fn main() {
|
//! fn main() {
|
||||||
//! let native_options = eframe::NativeOptions::default();
|
//! let native_options = eframe::NativeOptions::default();
|
||||||
//! eframe::run_native("My egui App", native_options, Box::new(|cc| Box::new(MyEguiApp::new(cc))));
|
//! eframe::run_native("My egui App", native_options, Box::new(|cc| Ok(Box::new(MyEguiApp::new(cc)))));
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! #[derive(Default)]
|
//! #[derive(Default)]
|
||||||
|
|
@ -90,7 +90,7 @@
|
||||||
//! .start(
|
//! .start(
|
||||||
//! canvas_id,
|
//! canvas_id,
|
||||||
//! eframe::WebOptions::default(),
|
//! eframe::WebOptions::default(),
|
||||||
//! Box::new(|cc| Box::new(MyEguiApp::new(cc))),
|
//! Box::new(|cc| Ok(Box::new(MyEguiApp::new(cc))),)
|
||||||
//! )
|
//! )
|
||||||
//! .await
|
//! .await
|
||||||
//! }
|
//! }
|
||||||
|
|
@ -199,7 +199,7 @@ pub mod icon_data;
|
||||||
///
|
///
|
||||||
/// fn main() -> eframe::Result<()> {
|
/// fn main() -> eframe::Result<()> {
|
||||||
/// let native_options = eframe::NativeOptions::default();
|
/// let native_options = eframe::NativeOptions::default();
|
||||||
/// eframe::run_native("MyApp", native_options, Box::new(|cc| Box::new(MyEguiApp::new(cc))))
|
/// eframe::run_native("MyApp", native_options, Box::new(|cc| Ok(Box::new(MyEguiApp::new(cc)))))
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// #[derive(Default)]
|
/// #[derive(Default)]
|
||||||
|
|
@ -324,7 +324,7 @@ pub fn run_simple_native(
|
||||||
run_native(
|
run_native(
|
||||||
app_name,
|
app_name,
|
||||||
native_options,
|
native_options,
|
||||||
Box::new(|_cc| Box::new(SimpleApp { update_fun })),
|
Box::new(|_cc| Ok(Box::new(SimpleApp { update_fun }))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -333,6 +333,9 @@ pub fn run_simple_native(
|
||||||
/// The different problems that can occur when trying to run `eframe`.
|
/// The different problems that can occur when trying to run `eframe`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
/// Something went wrong in user code when creating the app.
|
||||||
|
AppCreation(Box<dyn std::error::Error>),
|
||||||
|
|
||||||
/// An error from [`winit`].
|
/// An error from [`winit`].
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
Winit(winit::error::OsError),
|
Winit(winit::error::OsError),
|
||||||
|
|
@ -403,6 +406,8 @@ impl From<egui_wgpu::WgpuError> for Error {
|
||||||
impl std::fmt::Display for Error {
|
impl std::fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
Self::AppCreation(err) => write!(f, "app creation error: {err}"),
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
Self::Winit(err) => {
|
Self::Winit(err) => {
|
||||||
write!(f, "winit error: {err}")
|
write!(f, "winit error: {err}")
|
||||||
|
|
|
||||||
|
|
@ -313,7 +313,7 @@ impl GlowWinitApp {
|
||||||
raw_window_handle: window.window_handle().map(|h| h.as_raw()),
|
raw_window_handle: window.window_handle().map(|h| h.as_raw()),
|
||||||
};
|
};
|
||||||
crate::profile_scope!("app_creator");
|
crate::profile_scope!("app_creator");
|
||||||
app_creator(&cc)
|
app_creator(&cc).map_err(crate::Error::AppCreation)?
|
||||||
};
|
};
|
||||||
|
|
||||||
let glutin = Rc::new(RefCell::new(glutin));
|
let glutin = Rc::new(RefCell::new(glutin));
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ impl WgpuWinitApp {
|
||||||
storage: Option<Box<dyn Storage>>,
|
storage: Option<Box<dyn Storage>>,
|
||||||
window: Window,
|
window: Window,
|
||||||
builder: ViewportBuilder,
|
builder: ViewportBuilder,
|
||||||
) -> Result<&mut WgpuWinitRunning, egui_wgpu::WgpuError> {
|
) -> crate::Result<&mut WgpuWinitRunning> {
|
||||||
crate::profile_function!();
|
crate::profile_function!();
|
||||||
|
|
||||||
#[allow(unsafe_code, unused_mut, unused_unsafe)]
|
#[allow(unsafe_code, unused_mut, unused_unsafe)]
|
||||||
|
|
@ -272,7 +272,7 @@ impl WgpuWinitApp {
|
||||||
};
|
};
|
||||||
let app = {
|
let app = {
|
||||||
crate::profile_scope!("user_app_creator");
|
crate::profile_scope!("user_app_creator");
|
||||||
app_creator(&cc)
|
app_creator(&cc).map_err(crate::Error::AppCreation)?
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut viewport_from_window = HashMap::default();
|
let mut viewport_from_window = HashMap::default();
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ impl Drop for AppRunner {
|
||||||
|
|
||||||
impl AppRunner {
|
impl AppRunner {
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// Failure to initialize WebGL renderer.
|
/// Failure to initialize WebGL renderer, or failure to create app.
|
||||||
pub async fn new(
|
pub async fn new(
|
||||||
canvas_id: &str,
|
canvas_id: &str,
|
||||||
web_options: crate::WebOptions,
|
web_options: crate::WebOptions,
|
||||||
|
|
@ -71,7 +71,7 @@ impl AppRunner {
|
||||||
let theme = system_theme.unwrap_or(web_options.default_theme);
|
let theme = system_theme.unwrap_or(web_options.default_theme);
|
||||||
egui_ctx.set_visuals(theme.egui_visuals());
|
egui_ctx.set_visuals(theme.egui_visuals());
|
||||||
|
|
||||||
let app = app_creator(&epi::CreationContext {
|
let cc = epi::CreationContext {
|
||||||
egui_ctx: egui_ctx.clone(),
|
egui_ctx: egui_ctx.clone(),
|
||||||
integration_info: info.clone(),
|
integration_info: info.clone(),
|
||||||
storage: Some(&storage),
|
storage: Some(&storage),
|
||||||
|
|
@ -86,7 +86,8 @@ impl AppRunner {
|
||||||
wgpu_render_state: painter.render_state(),
|
wgpu_render_state: painter.render_state(),
|
||||||
#[cfg(all(feature = "wgpu", feature = "glow"))]
|
#[cfg(all(feature = "wgpu", feature = "glow"))]
|
||||||
wgpu_render_state: None,
|
wgpu_render_state: None,
|
||||||
});
|
};
|
||||||
|
let app = app_creator(&cc).map_err(|err| err.to_string())?;
|
||||||
|
|
||||||
let frame = epi::Frame {
|
let frame = epi::Frame {
|
||||||
info,
|
info,
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ impl WebRunner {
|
||||||
/// Create the application, install callbacks, and start running the app.
|
/// Create the application, install callbacks, and start running the app.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// Failing to initialize graphics.
|
/// Failing to initialize graphics, or failure to create app.
|
||||||
pub async fn start(
|
pub async fn start(
|
||||||
&self,
|
&self,
|
||||||
canvas_id: &str,
|
canvas_id: &str,
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"egui demo app",
|
"egui demo app",
|
||||||
options,
|
options,
|
||||||
Box::new(|cc| Box::new(egui_demo_app::WrapApp::new(cc))),
|
Box::new(|cc| Ok(Box::new(egui_demo_app::WrapApp::new(cc)))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ impl WebHandle {
|
||||||
.start(
|
.start(
|
||||||
canvas_id,
|
canvas_id,
|
||||||
eframe::WebOptions::default(),
|
eframe::WebOptions::default(),
|
||||||
Box::new(|cc| Box::new(WrapApp::new(cc))),
|
Box::new(|cc| Ok(Box::new(WrapApp::new(cc)))),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"Confirm exit",
|
"Confirm exit",
|
||||||
options,
|
options,
|
||||||
Box::new(|_cc| Box::<MyApp>::default()),
|
Box::new(|_cc| Ok(Box::<MyApp>::default())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"Custom 3D painting in eframe using glow",
|
"Custom 3D painting in eframe using glow",
|
||||||
options,
|
options,
|
||||||
Box::new(|cc| Box::new(MyApp::new(cc))),
|
Box::new(|cc| Ok(Box::new(MyApp::new(cc)))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"egui example: custom font",
|
"egui example: custom font",
|
||||||
options,
|
options,
|
||||||
Box::new(|cc| Box::new(MyApp::new(cc))),
|
Box::new(|cc| Ok(Box::new(MyApp::new(cc)))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"egui example: global font style",
|
"egui example: global font style",
|
||||||
options,
|
options,
|
||||||
Box::new(|cc| Box::new(MyApp::new(cc))),
|
Box::new(|cc| Ok(Box::new(MyApp::new(cc)))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
// This gives us image support:
|
// This gives us image support:
|
||||||
egui_extras::install_image_loaders(&cc.egui_ctx);
|
egui_extras::install_image_loaders(&cc.egui_ctx);
|
||||||
|
|
||||||
Box::<MyApp>::default()
|
Ok(Box::<MyApp>::default())
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"Plot",
|
"Plot",
|
||||||
options,
|
options,
|
||||||
Box::new(|_cc| Box::<PlotExample>::default()),
|
Box::new(|_cc| Ok(Box::<PlotExample>::default())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"Custom window frame", // unused title
|
"Custom window frame", // unused title
|
||||||
options,
|
options,
|
||||||
Box::new(|_cc| Box::<MyApp>::default()),
|
Box::new(|_cc| Ok(Box::<MyApp>::default())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"Native file dialogs and drag-and-drop files",
|
"Native file dialogs and drag-and-drop files",
|
||||||
options,
|
options,
|
||||||
Box::new(|_cc| Box::<MyApp>::default()),
|
Box::new(|_cc| Ok(Box::<MyApp>::default())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
// This gives us image support:
|
// This gives us image support:
|
||||||
egui_extras::install_image_loaders(&cc.egui_ctx);
|
egui_extras::install_image_loaders(&cc.egui_ctx);
|
||||||
|
|
||||||
Box::<MyApp>::default()
|
Ok(Box::<MyApp>::default())
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"My parallel egui App",
|
"My parallel egui App",
|
||||||
options,
|
options,
|
||||||
Box::new(|_cc| Box::new(MyApp::new())),
|
Box::new(|_cc| Ok(Box::new(MyApp::new()))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
Box::new(|cc| {
|
Box::new(|cc| {
|
||||||
// This gives us image support:
|
// This gives us image support:
|
||||||
egui_extras::install_image_loaders(&cc.egui_ctx);
|
egui_extras::install_image_loaders(&cc.egui_ctx);
|
||||||
Box::<MyApp>::default()
|
Ok(Box::<MyApp>::default())
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"Keyboard events",
|
"Keyboard events",
|
||||||
options,
|
options,
|
||||||
Box::new(|_cc| Box::<Content>::default()),
|
Box::new(|_cc| Ok(Box::<Content>::default())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"Multiple viewports",
|
"Multiple viewports",
|
||||||
options,
|
options,
|
||||||
Box::new(|_cc| Box::<MyApp>::default()),
|
Box::new(|_cc| Ok(Box::<MyApp>::default())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
Box::new(|_cc| Box::<MyApp>::default()),
|
Box::new(|_cc| Ok(Box::<MyApp>::default())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"My egui App with a plot",
|
"My egui App with a plot",
|
||||||
options,
|
options,
|
||||||
Box::new(|_cc| Box::<MyApp>::default()),
|
Box::new(|_cc| Ok(Box::<MyApp>::default())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"Take screenshots and display with eframe/egui",
|
"Take screenshots and display with eframe/egui",
|
||||||
options,
|
options,
|
||||||
Box::new(|_cc| Box::<MyApp>::default()),
|
Box::new(|_cc| Ok(Box::<MyApp>::default())),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"First Window",
|
"First Window",
|
||||||
options.clone(),
|
options.clone(),
|
||||||
Box::new(|_cc| Box::new(MyApp { has_next: true })),
|
Box::new(|_cc| Ok(Box::new(MyApp { has_next: true }))),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
std::thread::sleep(std::time::Duration::from_secs(2));
|
std::thread::sleep(std::time::Duration::from_secs(2));
|
||||||
|
|
@ -32,7 +32,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"Second Window",
|
"Second Window",
|
||||||
options.clone(),
|
options.clone(),
|
||||||
Box::new(|_cc| Box::new(MyApp { has_next: true })),
|
Box::new(|_cc| Ok(Box::new(MyApp { has_next: true }))),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
std::thread::sleep(std::time::Duration::from_secs(2));
|
std::thread::sleep(std::time::Duration::from_secs(2));
|
||||||
|
|
@ -41,7 +41,7 @@ fn main() -> Result<(), eframe::Error> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"Third Window",
|
"Third Window",
|
||||||
options,
|
options,
|
||||||
Box::new(|_cc| Box::new(MyApp { has_next: false })),
|
Box::new(|_cc| Ok(Box::new(MyApp { has_next: false }))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ fn main() -> eframe::Result<()> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"User attention test",
|
"User attention test",
|
||||||
native_options,
|
native_options,
|
||||||
Box::new(|cc| Box::new(Application::new(cc))),
|
Box::new(|cc| Ok(Box::new(Application::new(cc)))),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
eframe::run_native(
|
eframe::run_native(
|
||||||
"My test app",
|
"My test app",
|
||||||
options,
|
options,
|
||||||
Box::new(|_cc| Box::<MyTestApp>::default()),
|
Box::new(|_cc| Ok(Box::<MyTestApp>::default())),
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ fn main() {
|
||||||
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
Box::new(|_| Box::<App>::default()),
|
Box::new(|_cc| Ok(Box::<App>::default())),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue