From 7638ca99626e6ad54b1f409b5b94579894907475 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 24 Oct 2020 19:23:16 +0200 Subject: [PATCH] [app] Simplify interface to egui::app::App --- egui/benches/benchmark.rs | 4 ++-- egui/src/app.rs | 18 +++++++++++----- egui/src/context.rs | 2 +- egui/src/demos/app.rs | 38 ++++++++++++++++------------------ egui/src/demos/demo_windows.rs | 6 +++--- egui/src/lib.rs | 2 +- egui_glium/src/backend.rs | 20 +++++++++++------- egui_web/src/backend.rs | 25 ++++++++++++---------- example_glium/src/main.rs | 7 ++----- 9 files changed, 66 insertions(+), 56 deletions(-) diff --git a/egui/benches/benchmark.rs b/egui/benches/benchmark.rs index e36ade34..763bab74 100644 --- a/egui/benches/benchmark.rs +++ b/egui/benches/benchmark.rs @@ -13,7 +13,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { c.bench_function("demo_windows_minimal", |b| { b.iter(|| { ctx.begin_frame(raw_input.clone()); - demo_windows.ui(&ctx, &Default::default(), None); + demo_windows.ui(&ctx, &Default::default(), &mut None); ctx.end_frame() }) }); @@ -27,7 +27,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { c.bench_function("demo_windows_full", |b| { b.iter(|| { ctx.begin_frame(raw_input.clone()); - demo_windows.ui(&ctx, &Default::default(), None); + demo_windows.ui(&ctx, &Default::default(), &mut None); ctx.end_frame() }) }); diff --git a/egui/src/app.rs b/egui/src/app.rs index be79497d..65e4fec5 100644 --- a/egui/src/app.rs +++ b/egui/src/app.rs @@ -17,23 +17,31 @@ pub trait App { fn ui( &mut self, ctx: &std::sync::Arc, - info: &BackendInfo, - tex_allocator: Option<&mut dyn TextureAllocator>, - ) -> AppOutput; + integration_context: &mut IntegrationContext<'_>, + ); /// Called once on shutdown. Allows you to save state. fn on_exit(&mut self, _storage: &mut dyn Storage) {} } +pub struct IntegrationContext<'a> { + /// Information about the integration. + pub info: IntegrationInfo, + /// A way to allocate textures (on integrations that support it). + pub tex_allocator: Option<&'a mut dyn TextureAllocator>, + /// Where the app can issue commands back to the integration. + pub output: AppOutput, +} + #[derive(Clone, Debug)] pub struct WebInfo { /// e.g. "#fragment" part of "www.example.com/index.html#fragment" pub web_location_hash: String, } -/// Information about the backend passed to the use app each frame. +/// Information about the integration passed to the use app each frame. #[derive(Clone, Debug)] -pub struct BackendInfo { +pub struct IntegrationInfo { /// If the app is running in a Web context, this returns information about the environment. pub web_info: Option, diff --git a/egui/src/context.rs b/egui/src/context.rs index 74a512c0..6e50f6fb 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -90,7 +90,7 @@ impl Context { pub fn available_rect(&self) -> Rect { self.available_rect .lock() - .expect("Called `avaiblable_rect()` before `begin_frame()`") + .expect("Called `available_rect()` before `begin_frame()`") } pub fn memory(&self) -> MutexGuard<'_, Memory> { diff --git a/egui/src/demos/app.rs b/egui/src/demos/app.rs index 5f1ee686..4fba09a7 100644 --- a/egui/src/demos/app.rs +++ b/egui/src/demos/app.rs @@ -183,11 +183,11 @@ pub struct DemoApp { } impl DemoApp { - fn backend_ui(&mut self, ui: &mut Ui, info: &app::BackendInfo) -> app::AppOutput { + fn backend_ui(&mut self, ui: &mut Ui, integration_context: &mut app::IntegrationContext<'_>) { self.frame_history - .on_new_frame(ui.input().time, info.cpu_usage); + .on_new_frame(ui.input().time, integration_context.info.cpu_usage); - let is_web = info.web_info.is_some(); + let is_web = integration_context.info.web_info.is_some(); if is_web { ui.label("Egui is an immediate mode GUI written in Rust, compiled to WebAssembly, rendered with WebGL."); @@ -210,18 +210,16 @@ impl DemoApp { ui.separator(); - let mut output = app::AppOutput::default(); - output.pixels_per_point = self.pixels_per_point_ui(ui, info); + integration_context.output.pixels_per_point = + self.pixels_per_point_ui(ui, &integration_context.info); if !is_web { ui.separator(); - output.quit |= ui.button("Quit").clicked; + integration_context.output.quit |= ui.button("Quit").clicked; } - - output } - fn pixels_per_point_ui(&mut self, ui: &mut Ui, info: &app::BackendInfo) -> Option { + fn pixels_per_point_ui(&mut self, ui: &mut Ui, info: &app::IntegrationInfo) -> Option { self.pixels_per_point = self .pixels_per_point .or(info.native_pixels_per_point) @@ -276,10 +274,10 @@ impl app::App for DemoApp { fn ui( &mut self, ctx: &Arc, - info: &app::BackendInfo, - tex_allocator: Option<&mut dyn app::TextureAllocator>, - ) -> app::AppOutput { - let web_location_hash = info + integration_context: &mut crate::app::IntegrationContext<'_>, + ) { + let web_location_hash = integration_context + .info .web_info .as_ref() .map(|info| info.web_location_hash.clone()) @@ -292,27 +290,27 @@ impl app::App for DemoApp { }; let demo_environment = demos::DemoEnvironment { - seconds_since_midnight: info.seconds_since_midnight, + seconds_since_midnight: integration_context.info.seconds_since_midnight, link, }; - self.demo_windows.ui(ctx, &demo_environment, tex_allocator); - - let mut output = app::AppOutput::default(); + self.demo_windows.ui( + ctx, + &demo_environment, + &mut integration_context.tex_allocator, + ); crate::Window::new("Backend") .min_width(360.0) .scroll(false) .show(ctx, |ui| { - output = self.backend_ui(ui, info); + self.backend_ui(ui, integration_context); }); if self.run_mode == RunMode::Continuous { // Tell the backend to repaint as soon as possible ctx.request_repaint(); } - - output } #[cfg(feature = "serde_json")] diff --git a/egui/src/demos/demo_windows.rs b/egui/src/demos/demo_windows.rs index 7a38b45c..d8ecd33d 100644 --- a/egui/src/demos/demo_windows.rs +++ b/egui/src/demos/demo_windows.rs @@ -46,7 +46,7 @@ impl DemoWindows { &mut self, ctx: &Arc, env: &DemoEnvironment, - tex_allocator: Option<&mut dyn app::TextureAllocator>, + tex_allocator: &mut Option<&mut dyn app::TextureAllocator>, ) { if self.previous_link != env.link { match env.link { @@ -93,7 +93,7 @@ impl DemoWindows { &mut self, ctx: &Arc, env: &DemoEnvironment, - mut tex_allocator: Option<&mut dyn app::TextureAllocator>, + tex_allocator: &mut Option<&mut dyn app::TextureAllocator>, ) { let Self { open_windows, @@ -135,7 +135,7 @@ impl DemoWindows { .scroll(true) .open(&mut open_windows.color_test) .show(ctx, |ui| { - color_test.ui(ui, &mut tex_allocator); + color_test.ui(ui, tex_allocator); }); fractal_clock.window( diff --git a/egui/src/lib.rs b/egui/src/lib.rs index a32391be..e6ebf3ba 100644 --- a/egui/src/lib.rs +++ b/egui/src/lib.rs @@ -99,7 +99,7 @@ pub fn text_egui_e2e() { const NUM_FRAMES: usize = 5; for _ in 0..NUM_FRAMES { ctx.begin_frame(raw_input.clone()); - demo_windows.ui(&ctx, &Default::default(), None); + demo_windows.ui(&ctx, &Default::default(), &mut None); let (_output, paint_jobs) = ctx.end_frame(); assert!(!paint_jobs.is_empty()); } diff --git a/egui_glium/src/backend.rs b/egui_glium/src/backend.rs index 49b83a3f..511c5d60 100644 --- a/egui_glium/src/backend.rs +++ b/egui_glium/src/backend.rs @@ -75,15 +75,19 @@ pub fn run( raw_input.screen_size = screen_size_in_pixels(&display) / raw_input.pixels_per_point.unwrap(); - let backend_info = egui::app::BackendInfo { - web_info: None, - cpu_usage: previous_frame_time, - seconds_since_midnight: Some(seconds_since_midnight()), - native_pixels_per_point: Some(native_pixels_per_point(&display)), - }; - ctx.begin_frame(raw_input.take()); - let app_output = app.ui(&ctx, &backend_info, Some(&mut painter)); + let mut integration_context = egui::app::IntegrationContext { + info: egui::app::IntegrationInfo { + web_info: None, + cpu_usage: previous_frame_time, + seconds_since_midnight: Some(seconds_since_midnight()), + native_pixels_per_point: Some(native_pixels_per_point(&display)), + }, + tex_allocator: Some(&mut painter), + output: Default::default(), + }; + app.ui(&ctx, &mut integration_context); + let app_output = integration_context.output; let (egui_output, paint_jobs) = ctx.end_frame(); let frame_time = (Instant::now() - egui_start).as_secs_f64() as f32; diff --git a/egui_web/src/backend.rs b/egui_web/src/backend.rs index cf040d2a..f3e16f4d 100644 --- a/egui_web/src/backend.rs +++ b/egui_web/src/backend.rs @@ -150,21 +150,24 @@ impl AppRunner { resize_canvas_to_screen_size(self.web_backend.canvas_id()); let raw_input = self.web_input.new_frame(self.pixels_per_point); + self.web_backend.begin_frame(raw_input); - let backend_info = egui::app::BackendInfo { - web_info: Some(WebInfo { - web_location_hash: location_hash().unwrap_or_default(), - }), - cpu_usage: self.web_backend.previous_frame_time, - seconds_since_midnight: Some(seconds_since_midnight()), - native_pixels_per_point: Some(native_pixels_per_point()), + let mut integration_context = egui::app::IntegrationContext { + info: egui::app::IntegrationInfo { + web_info: Some(WebInfo { + web_location_hash: location_hash().unwrap_or_default(), + }), + cpu_usage: self.web_backend.previous_frame_time, + seconds_since_midnight: Some(seconds_since_midnight()), + native_pixels_per_point: Some(native_pixels_per_point()), + }, + tex_allocator: Some(&mut self.web_backend.painter), + output: Default::default(), }; - self.web_backend.begin_frame(raw_input); let egui_ctx = &self.web_backend.ctx; - let app_output = self - .app - .ui(egui_ctx, &backend_info, Some(&mut self.web_backend.painter)); + self.app.ui(egui_ctx, &mut integration_context); + let app_output = integration_context.output; let (egui_output, paint_jobs) = self.web_backend.end_frame()?; handle_output(&egui_output); diff --git a/example_glium/src/main.rs b/example_glium/src/main.rs index cffb2daa..4a548324 100644 --- a/example_glium/src/main.rs +++ b/example_glium/src/main.rs @@ -16,9 +16,8 @@ impl egui::app::App for MyApp { fn ui( &mut self, ctx: &std::sync::Arc, - _info: &egui::app::BackendInfo, - _tex_allocator: Option<&mut dyn egui::app::TextureAllocator>, - ) -> egui::app::AppOutput { + _integration_context: &mut egui::app::IntegrationContext, + ) { let MyApp { my_string, value } = self; // Example used in `README.md`. @@ -30,8 +29,6 @@ impl egui::app::App for MyApp { ui.text_edit(my_string); ui.add(egui::Slider::f32(value, 0.0..=1.0).text("float")); }); - - Default::default() } fn on_exit(&mut self, storage: &mut dyn egui::app::Storage) {