1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 14:49:06 -04:00

Make App 'static

This commit is contained in:
Emil Ernerfeldt
2026-01-05 18:35:10 +01:00
parent faccc12c09
commit 3ffbed8d61
7 changed files with 31 additions and 35 deletions

View File

@@ -43,8 +43,7 @@ type DynError = Box<dyn std::error::Error + Send + Sync>;
/// This is how your app is created.
///
/// You can use the [`CreationContext`] to setup egui, restore state, setup OpenGL things, etc.
pub type AppCreator<'app> =
Box<dyn 'app + FnOnce(&CreationContext<'_>) -> Result<Box<dyn 'app + App>, DynError>>;
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.
pub struct CreationContext<'s> {
@@ -131,7 +130,7 @@ impl CreationContext<'_> {
// ----------------------------------------------------------------------------
/// Implement this trait to write apps that can be compiled for both web/wasm and desktop/native using [`eframe`](https://github.com/emilk/egui/tree/main/crates/eframe).
pub trait App {
pub trait App: std::any::Any {
/// Called once before each call to [`Self::ui`],
/// and additionally also called when the UI is hidden, but [`egui::Context::request_repaint`] was called.
///

View File

@@ -256,7 +256,7 @@ pub mod icon_data;
pub fn run_native(
app_name: &str,
mut native_options: NativeOptions,
app_creator: AppCreator<'_>,
app_creator: AppCreator,
) -> Result {
let renderer = init_native(app_name, &mut native_options);
@@ -325,7 +325,7 @@ pub fn run_native(
pub fn create_native<'a>(
app_name: &str,
mut native_options: NativeOptions,
app_creator: AppCreator<'a>,
app_creator: AppCreator,
event_loop: &winit::event_loop::EventLoop<UserEvent>,
) -> EframeWinitApplication<'a> {
let renderer = init_native(app_name, &mut native_options);

View File

@@ -45,24 +45,24 @@ use super::{
// ----------------------------------------------------------------------------
// Types:
pub struct GlowWinitApp<'app> {
pub struct GlowWinitApp {
repaint_proxy: Arc<egui::mutex::Mutex<EventLoopProxy<UserEvent>>>,
app_name: String,
native_options: NativeOptions,
running: Option<GlowWinitRunning<'app>>,
running: Option<GlowWinitRunning>,
// Note that since this `AppCreator` is FnOnce we are currently unable to support
// re-initializing the `GlowWinitRunning` state on Android if the application
// suspends and resumes.
app_creator: Option<AppCreator<'app>>,
app_creator: Option<AppCreator>,
}
/// State that is initialized when the application is first starts running via
/// a Resumed event. On Android this ensures that any graphics state is only
/// initialized once the application has an associated `SurfaceView`.
struct GlowWinitRunning<'app> {
struct GlowWinitRunning {
integration: EpiIntegration,
app: Box<dyn 'app + App>,
app: Box<dyn App>,
// These needs to be shared with the immediate viewport renderer, hence the Rc/Arc/RefCells:
glutin: Rc<RefCell<GlutinWindowContext>>,
@@ -123,12 +123,12 @@ struct Viewport {
// ----------------------------------------------------------------------------
impl<'app> GlowWinitApp<'app> {
impl GlowWinitApp {
pub fn new(
event_loop: &EventLoop<UserEvent>,
app_name: &str,
native_options: NativeOptions,
app_creator: AppCreator<'app>,
app_creator: AppCreator,
) -> Self {
profiling::function_scope!();
Self {
@@ -191,10 +191,7 @@ impl<'app> GlowWinitApp<'app> {
Ok((glutin_window_context, painter))
}
fn init_run_state(
&mut self,
event_loop: &ActiveEventLoop,
) -> Result<&mut GlowWinitRunning<'app>> {
fn init_run_state(&mut self, event_loop: &ActiveEventLoop) -> Result<&mut GlowWinitRunning> {
profiling::function_scope!();
let storage = if let Some(file) = &self.native_options.persistence_path {
@@ -290,7 +287,7 @@ impl<'app> GlowWinitApp<'app> {
let app_creator = std::mem::take(&mut self.app_creator)
.expect("Single-use AppCreator has unexpectedly already been taken");
let app: Box<dyn 'app + App> = {
let app: Box<dyn App> = {
// Use latest raw_window_handle for eframe compatibility
use raw_window_handle::{HasDisplayHandle as _, HasWindowHandle as _};
@@ -344,7 +341,7 @@ impl<'app> GlowWinitApp<'app> {
}
}
impl WinitApp for GlowWinitApp<'_> {
impl WinitApp for GlowWinitApp {
fn egui_ctx(&self) -> Option<&egui::Context> {
self.running.as_ref().map(|r| &r.integration.egui_ctx)
}
@@ -496,7 +493,7 @@ impl WinitApp for GlowWinitApp<'_> {
}
}
impl GlowWinitRunning<'_> {
impl GlowWinitRunning {
fn run_ui_and_paint(
&mut self,
event_loop: &ActiveEventLoop,

View File

@@ -347,7 +347,7 @@ fn run_and_exit(event_loop: EventLoop<UserEvent>, winit_app: impl WinitApp) -> R
pub fn run_glow(
app_name: &str,
mut native_options: epi::NativeOptions,
app_creator: epi::AppCreator<'_>,
app_creator: epi::AppCreator,
) -> Result {
use super::glow_integration::GlowWinitApp;
@@ -368,7 +368,7 @@ pub fn run_glow(
pub fn create_glow<'a>(
app_name: &str,
native_options: epi::NativeOptions,
app_creator: epi::AppCreator<'a>,
app_creator: epi::AppCreator,
event_loop: &EventLoop<UserEvent>,
) -> impl ApplicationHandler<UserEvent> + 'a {
use super::glow_integration::GlowWinitApp;
@@ -383,7 +383,7 @@ pub fn create_glow<'a>(
pub fn run_wgpu(
app_name: &str,
mut native_options: epi::NativeOptions,
app_creator: epi::AppCreator<'_>,
app_creator: epi::AppCreator,
) -> Result {
use super::wgpu_integration::WgpuWinitApp;
@@ -404,7 +404,7 @@ pub fn run_wgpu(
pub fn create_wgpu<'a>(
app_name: &str,
native_options: epi::NativeOptions,
app_creator: epi::AppCreator<'a>,
app_creator: epi::AppCreator,
event_loop: &EventLoop<UserEvent>,
) -> impl ApplicationHandler<UserEvent> + 'a {
use super::wgpu_integration::WgpuWinitApp;

View File

@@ -35,26 +35,26 @@ use super::{epi_integration, event_loop_context, winit_integration, winit_integr
// ----------------------------------------------------------------------------
// Types:
pub struct WgpuWinitApp<'app> {
pub struct WgpuWinitApp {
repaint_proxy: Arc<Mutex<EventLoopProxy<UserEvent>>>,
app_name: String,
native_options: NativeOptions,
/// Set at initialization, then taken and set to `None` in `init_run_state`.
app_creator: Option<AppCreator<'app>>,
app_creator: Option<AppCreator>,
/// Set when we are actually up and running.
running: Option<WgpuWinitRunning<'app>>,
running: Option<WgpuWinitRunning>,
}
/// State that is initialized when the application is first starts running via
/// a Resumed event. On Android this ensures that any graphics state is only
/// initialized once the application has an associated `SurfaceView`.
struct WgpuWinitRunning<'app> {
struct WgpuWinitRunning {
integration: EpiIntegration,
/// The users application.
app: Box<dyn 'app + App>,
app: Box<dyn App>,
/// Wrapped in an `Rc<RefCell<…>>` so it can be re-entrantly shared via a weak-pointer.
shared: Rc<RefCell<SharedState>>,
@@ -97,12 +97,12 @@ pub struct Viewport {
// ----------------------------------------------------------------------------
impl<'app> WgpuWinitApp<'app> {
impl WgpuWinitApp {
pub fn new(
event_loop: &EventLoop<UserEvent>,
app_name: &str,
native_options: NativeOptions,
app_creator: AppCreator<'app>,
app_creator: AppCreator,
) -> Self {
profiling::function_scope!();
@@ -182,7 +182,7 @@ impl<'app> WgpuWinitApp<'app> {
storage: Option<Box<dyn Storage>>,
window: Window,
builder: ViewportBuilder,
) -> crate::Result<&mut WgpuWinitRunning<'app>> {
) -> crate::Result<&mut WgpuWinitRunning> {
profiling::function_scope!();
let mut painter = pollster::block_on(egui_wgpu::winit::Painter::new(
egui_ctx.clone(),
@@ -341,7 +341,7 @@ impl<'app> WgpuWinitApp<'app> {
}
}
impl WinitApp for WgpuWinitApp<'_> {
impl WinitApp for WgpuWinitApp {
fn egui_ctx(&self) -> Option<&egui::Context> {
self.running.as_ref().map(|r| &r.integration.egui_ctx)
}
@@ -510,7 +510,7 @@ impl WinitApp for WgpuWinitApp<'_> {
}
}
impl WgpuWinitRunning<'_> {
impl WgpuWinitRunning {
/// Saves the application state
fn save(&mut self) {
let shared = self.shared.borrow();

View File

@@ -43,7 +43,7 @@ impl AppRunner {
pub async fn new(
canvas: web_sys::HtmlCanvasElement,
web_options: crate::WebOptions,
app_creator: epi::AppCreator<'static>,
app_creator: epi::AppCreator,
text_agent: TextAgent,
) -> Result<Self, String> {
let egui_ctx = egui::Context::default();

View File

@@ -58,7 +58,7 @@ impl WebRunner {
&self,
canvas: web_sys::HtmlCanvasElement,
web_options: crate::WebOptions,
app_creator: epi::AppCreator<'static>,
app_creator: epi::AppCreator,
) -> Result<(), JsValue> {
self.destroy();