From 54f6e6b9ae3caecc65ecb69b54f3e970ae584c1c Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 14 Nov 2023 19:52:28 +0100 Subject: [PATCH] Remove `id` from `ViewportBuilder` so it can implement `Default` --- crates/eframe/src/native/epi_integration.rs | 3 +- crates/egui/src/context.rs | 36 ++++--- crates/egui/src/viewport.rs | 114 ++++++++++---------- crates/epaint/src/image.rs | 9 ++ examples/multiple_viewports/src/main.rs | 7 +- examples/test_viewports/src/main.rs | 6 +- 6 files changed, 94 insertions(+), 81 deletions(-) diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index fada74d0698..ab469f817ac 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -85,10 +85,9 @@ pub fn window_builder( .. } = native_options; - let mut viewport_builder = egui::ViewportBuilder::new(ViewportId::ROOT); + let mut viewport_builder = egui::ViewportBuilder::ROOT; viewport_builder .with_title(title) - .with_close_button(true) // The default for all other viewports is `false`! .with_decorations(*decorated) .with_fullscreen(*fullscreen) .with_maximized(*maximized) diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 786cdeaf413..1c70ccf50fc 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -2554,6 +2554,8 @@ impl Context { /// This creates a new native window, if possible. /// + /// The given id must be unique for each viewport. + /// /// You need to call this each frame when the child viewport should exist. /// /// The given callback will be called whenever the child viewport needs repainting, @@ -2573,7 +2575,8 @@ impl Context { /// `ctx.viewport_id() != ctx.parent_viewport_id` if false you should create a [`crate::Window`]. pub fn show_viewport( &self, - viewport_builder: &ViewportBuilder, + new_viewport_id: ViewportId, + viewport_builder: ViewportBuilder, viewport_ui_cb: impl Fn(&Context) + Send + Sync + 'static, ) { crate::profile_function!(); @@ -2582,21 +2585,21 @@ impl Context { viewport_ui_cb(self); } else { self.write(|ctx| { - let viewport_id = ctx.viewport_id(); - if let Some(window) = ctx.viewports.get_mut(&viewport_builder.id) { - window.builder = viewport_builder.clone(); - window.ids.parent = viewport_id; + let parent_viewport_id = ctx.viewport_id(); + if let Some(window) = ctx.viewports.get_mut(&new_viewport_id) { + window.builder = viewport_builder; + window.ids.parent = parent_viewport_id; window.used = true; window.viewport_ui_cb = Some(Arc::new(Box::new(viewport_ui_cb))); } else { ctx.viewports.insert( - viewport_builder.id, + new_viewport_id, ViewportState { ids: ViewportIdPair { - this: viewport_builder.id, - parent: viewport_id, + this: new_viewport_id, + parent: parent_viewport_id, }, - builder: viewport_builder.clone(), + builder: viewport_builder, used: true, viewport_ui_cb: Some(Arc::new(Box::new(viewport_ui_cb))), }, @@ -2608,6 +2611,8 @@ impl Context { /// This creates a new native window, if possible. /// + /// The given id must be unique for each viewport. + /// /// You need to call this each frame when the child viewport should exist. /// /// The given ui function will be called immediately. @@ -2626,6 +2631,7 @@ impl Context { /// `ctx.viewport_id() != ctx.parent_viewport_id` if false you should create a [`crate::Window`]. pub fn show_viewport_immediate( &self, + new_viewport_id: ViewportId, builder: ViewportBuilder, viewport_ui_cb: impl FnOnce(&Context) -> T, ) -> T { @@ -2643,23 +2649,23 @@ impl Context { }; let ids = self.write(|ctx| { - let parent = ctx.viewport_id(); + let parent_viewport_id = ctx.viewport_id(); - if let Some(window) = ctx.viewports.get_mut(&builder.id) { + if let Some(window) = ctx.viewports.get_mut(&new_viewport_id) { // Existing window.builder = builder.clone(); - window.ids.parent = parent; + window.ids.parent = parent_viewport_id; window.used = true; window.viewport_ui_cb = None; window.ids } else { // New let ids = ViewportIdPair { - this: builder.id, - parent, + this: new_viewport_id, + parent: parent_viewport_id, }; ctx.viewports.insert( - builder.id, + new_viewport_id, ViewportState { builder: builder.clone(), ids, diff --git a/crates/egui/src/viewport.rs b/crates/egui/src/viewport.rs index 299df57eeba..e6efce8193d 100644 --- a/crates/egui/src/viewport.rs +++ b/crates/egui/src/viewport.rs @@ -99,11 +99,9 @@ pub type ImmediateViewportRendererCallback = dyn for<'a> Fn(&Context, ImmediateV /// Since egui is immediate mode, `ViewportBuilder` is accumulative in nature. /// Setting any option to `None` means "keep the current value", /// or "Use the default" if it is the first call. -#[derive(PartialEq, Eq, Clone)] +#[derive(Clone, Debug, Default, Eq, PartialEq)] #[allow(clippy::option_option)] pub struct ViewportBuilder { - pub id: ViewportId, - /// The title of the vieweport. /// `eframe` will use this as the title of the native window. pub title: Option, @@ -136,36 +134,37 @@ pub struct ViewportBuilder { } impl ViewportBuilder { + /// Default settings for the root viewport. + pub const ROOT: Self = Self { + title: None, + name: None, + position: None, + inner_size: Some(Some(Vec2::new(300.0, 200.0))), + fullscreen: None, + maximized: None, + resizable: Some(true), + transparent: Some(true), + decorations: Some(true), + icon: None, + active: Some(true), + visible: Some(true), + title_hidden: None, + titlebar_transparent: None, + fullsize_content_view: None, + min_inner_size: None, + max_inner_size: None, + drag_and_drop: Some(true), + close_button: Some(false), // We disable the close button by default because we haven't implemented closing of child viewports yet + minimize_button: Some(true), + maximize_button: Some(true), + hittest: Some(true), + }; + /// Default settings for a new child viewport. - /// - /// The given id must be unique for each viewport. - pub fn new(id: ViewportId) -> Self { - Self { - id, - title: None, - name: None, - position: None, - inner_size: Some(Some(Vec2::new(300.0, 200.0))), - fullscreen: None, - maximized: None, - resizable: Some(true), - transparent: Some(true), - decorations: Some(true), - icon: None, - active: Some(true), - visible: Some(true), - title_hidden: None, - titlebar_transparent: None, - fullsize_content_view: None, - min_inner_size: None, - max_inner_size: None, - drag_and_drop: Some(true), - close_button: Some(false), // We disable the close button by default because we haven't implemented closing of child viewports yet - minimize_button: Some(true), - maximize_button: Some(true), - hittest: Some(true), - } - } + pub const CHILD: Self = Self { + close_button: Some(false), // We disable the close button by default because we haven't implemented closing of child viewports yet + ..Self::ROOT + }; /// Empty settings for everything. /// @@ -173,33 +172,30 @@ impl ViewportBuilder { /// When used on subsequent frames, the current settings will be kept. /// /// The given id must be unique for each viewport. - pub fn empty(id: ViewportId) -> Self { - Self { - id, - title: None, - name: None, - position: None, - inner_size: None, - fullscreen: None, - maximized: None, - resizable: None, - transparent: None, - decorations: None, - icon: None, - active: None, - visible: None, - title_hidden: None, - titlebar_transparent: None, - fullsize_content_view: None, - min_inner_size: None, - max_inner_size: None, - drag_and_drop: None, - close_button: None, - minimize_button: None, - maximize_button: None, - hittest: None, - } - } + pub const EMPTY: Self = Self { + title: None, + name: None, + position: None, + inner_size: None, + fullscreen: None, + maximized: None, + resizable: None, + transparent: None, + decorations: None, + icon: None, + active: None, + visible: None, + title_hidden: None, + titlebar_transparent: None, + fullsize_content_view: None, + min_inner_size: None, + max_inner_size: None, + drag_and_drop: None, + close_button: None, + minimize_button: None, + maximize_button: None, + hittest: None, + }; /// Sets the initial title of the window in the title bar. /// diff --git a/crates/epaint/src/image.rs b/crates/epaint/src/image.rs index 0a40fe4a0c3..446f3fccead 100644 --- a/crates/epaint/src/image.rs +++ b/crates/epaint/src/image.rs @@ -238,6 +238,15 @@ impl From> for ImageData { } } +impl std::fmt::Debug for ColorImage { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("ColorImage") + .field("size", &self.size) + .field("pixel-count", &self.pixels.len()) + .finish_non_exhaustive() + } +} + // ---------------------------------------------------------------------------- /// A single-channel image designed for the font texture. diff --git a/examples/multiple_viewports/src/main.rs b/examples/multiple_viewports/src/main.rs index 2de2751770c..7321ab282e3 100644 --- a/examples/multiple_viewports/src/main.rs +++ b/examples/multiple_viewports/src/main.rs @@ -28,10 +28,13 @@ impl eframe::App for MyApp { ui.checkbox(&mut self.show_child_viewport, "Show secondary viewport"); }); + let mut viewport = egui::ViewportBuilder::CHILD; + viewport.with_title("Secondary Viewport"); + if self.show_child_viewport { ctx.show_viewport( - egui::ViewportBuilder::new(egui::ViewportId::from_hash_of("secondary_viewport")) - .with_title("Secondary Viewport"), + egui::ViewportId::from_hash_of("secondary_viewport"), + viewport, |ctx| { egui::CentralPanel::default().show(ctx, |ui| { ui.label("Hello from secondary viewport"); diff --git a/examples/test_viewports/src/main.rs b/examples/test_viewports/src/main.rs index e738f853b81..d05773778ab 100644 --- a/examples/test_viewports/src/main.rs +++ b/examples/test_viewports/src/main.rs @@ -65,21 +65,21 @@ impl ViewportState { let immediate = vp_state.read().immediate; let title = vp_state.read().title.clone(); - let mut vp_builder = ViewportBuilder::new(vp_id); + let mut vp_builder = ViewportBuilder::ROOT; vp_builder .with_title(&title) .with_inner_size(Some(egui::vec2(450.0, 400.0))); if immediate { let mut vp_state = vp_state.write(); - ctx.show_viewport_immediate(vp_builder, move |ctx| { + ctx.show_viewport_immediate(vp_id, vp_builder, move |ctx| { show_as_popup(ctx, &title, vp_id.into(), |ui: &mut egui::Ui| { generic_child_ui(ui, &mut vp_state); }); }); } else { let count = Arc::new(RwLock::new(0)); - ctx.show_viewport(&vp_builder, move |ctx| { + ctx.show_viewport(vp_id, vp_builder, move |ctx| { let mut vp_state = vp_state.write(); let count = count.clone(); show_as_popup(ctx, &title, vp_id.into(), move |ui: &mut egui::Ui| {