From 8aa14d2faeacadad06b169905700d0232e3d64c8 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 6 Nov 2023 20:14:24 +0100 Subject: [PATCH] Allow changing titles --- crates/eframe/src/native/run.rs | 2 +- crates/egui-winit/src/lib.rs | 153 +++++++++++++++------------- crates/egui/src/context.rs | 4 +- crates/egui/src/viewport.rs | 10 +- examples/test_viewports/src/main.rs | 26 +++-- 5 files changed, 105 insertions(+), 90 deletions(-) diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 1e39a7f55..26c5812a1 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -1221,7 +1221,7 @@ mod glow_integration { .is_current(glutin.current_gl_context.as_ref().unwrap()) { let builder = &&glutin.builders[&window.id_pair.this]; - log::error!("egui::create_viewport_sync with title: `{}` is not created in main thread, try to use wgpu!", builder.title); + log::error!("egui::create_viewport_sync with title: `{:?}` is not created in main thread, try to use wgpu!", builder.title.clone().unwrap_or_default()); } egui_glow::painter::clear(gl, screen_size_in_pixels, [0.0, 0.0, 0.0, 0.0]); diff --git a/crates/egui-winit/src/lib.rs b/crates/egui-winit/src/lib.rs index 30de5e359..9584e3af6 100644 --- a/crates/egui-winit/src/lib.rs +++ b/crates/egui-winit/src/lib.rs @@ -1115,7 +1115,12 @@ pub fn process_viewport_commands( pub fn create_winit_window_builder(builder: &ViewportBuilder) -> winit::window::WindowBuilder { let mut window_builder = winit::window::WindowBuilder::new() - .with_title(builder.title.clone()) + .with_title( + builder + .title + .clone() + .unwrap_or_else(|| "egui window".to_owned()), + ) .with_transparent(builder.transparent.unwrap_or(false)) .with_decorations(builder.decorations.unwrap_or(true)) .with_resizable(builder.resizable.unwrap_or(true)) @@ -1210,78 +1215,82 @@ pub fn changes_between_builders( ) -> (Vec, bool) { let mut commands = Vec::new(); - // Title is not compared because if has a new title will create a new window - // The title of a available window can only be changed with ViewportCommand::Title + if let Some(new_title) = &new.title { + if Some(new_title) != last.title.as_ref() { + last.title = Some(new_title.clone()); + commands.push(ViewportCommand::Title(new_title.clone())); + } + } - if let Some(position) = new.position { - if Some(position) != last.position { - last.position = Some(position); - if let Some(position) = position { + if let Some(new_position) = new.position { + if Some(new_position) != last.position { + last.position = Some(new_position); + if let Some(position) = new_position { commands.push(ViewportCommand::OuterPosition(position)); } } } - if let Some(inner_size) = new.inner_size { - if Some(inner_size) != last.inner_size { - last.inner_size = Some(inner_size); - if let Some(inner_size) = inner_size { + if let Some(new_inner_size) = new.inner_size { + if Some(new_inner_size) != last.inner_size { + last.inner_size = Some(new_inner_size); + if let Some(inner_size) = new_inner_size { commands.push(ViewportCommand::InnerSize(inner_size)); } } } - if let Some(min_inner_size) = new.min_inner_size { - if Some(min_inner_size) != last.min_inner_size { - last.min_inner_size = Some(min_inner_size); - commands.push(ViewportCommand::MinInnerSize(min_inner_size)); + if let Some(new_min_inner_size) = new.min_inner_size { + if Some(new_min_inner_size) != last.min_inner_size { + last.min_inner_size = Some(new_min_inner_size); + commands.push(ViewportCommand::MinInnerSize(new_min_inner_size)); } } - if let Some(max_inner_size) = new.max_inner_size { - if Some(max_inner_size) != last.max_inner_size { - last.max_inner_size = Some(max_inner_size); - commands.push(ViewportCommand::MaxInnerSize(max_inner_size)); + if let Some(new_max_inner_size) = new.max_inner_size { + if Some(new_max_inner_size) != last.max_inner_size { + last.max_inner_size = Some(new_max_inner_size); + commands.push(ViewportCommand::MaxInnerSize(new_max_inner_size)); } } - if let Some(fullscreen) = new.fullscreen { - if Some(fullscreen) != last.fullscreen { - last.fullscreen = Some(fullscreen); - commands.push(ViewportCommand::Fullscreen(fullscreen)); + if let Some(new_fullscreen) = new.fullscreen { + if Some(new_fullscreen) != last.fullscreen { + last.fullscreen = Some(new_fullscreen); + commands.push(ViewportCommand::Fullscreen(new_fullscreen)); } } - if let Some(maximized) = new.maximized { - if Some(maximized) != last.maximized { - last.maximized = Some(maximized); - commands.push(ViewportCommand::Maximized(maximized)); + if let Some(new_maximized) = new.maximized { + if Some(new_maximized) != last.maximized { + last.maximized = Some(new_maximized); + commands.push(ViewportCommand::Maximized(new_maximized)); } } - if let Some(resizable) = new.resizable { - if Some(resizable) != last.resizable { - last.resizable = Some(resizable); - commands.push(ViewportCommand::Resizable(resizable)); + if let Some(new_resizable) = new.resizable { + if Some(new_resizable) != last.resizable { + last.resizable = Some(new_resizable); + commands.push(ViewportCommand::Resizable(new_resizable)); } } - if let Some(transparent) = new.transparent { - if Some(transparent) != last.transparent { - last.transparent = Some(transparent); - commands.push(ViewportCommand::Transparent(transparent)); + if let Some(new_transparent) = new.transparent { + if Some(new_transparent) != last.transparent { + last.transparent = Some(new_transparent); + commands.push(ViewportCommand::Transparent(new_transparent)); } } - if let Some(decorations) = new.decorations { - if Some(decorations) != last.decorations { - last.decorations = Some(decorations); - commands.push(ViewportCommand::Decorations(decorations)); + if let Some(new_decorations) = new.decorations { + if Some(new_decorations) != last.decorations { + last.decorations = Some(new_decorations); + commands.push(ViewportCommand::Decorations(new_decorations)); } } - if let Some(icon) = new.icon.clone() { - let eq = match &icon { + if let Some(new_icon) = new.icon.clone() { + let eq = match &new_icon { Some(icon) => { if let Some(last_icon) = &last.icon { matches!(last_icon, Some(last_icon) if Arc::ptr_eq(icon, last_icon)) @@ -1294,23 +1303,23 @@ pub fn changes_between_builders( if !eq { commands.push(ViewportCommand::WindowIcon( - icon.as_ref().map(|i| i.as_ref().clone()), + new_icon.as_ref().map(|i| i.as_ref().clone()), )); - last.icon = Some(icon); + last.icon = Some(new_icon); } } - if let Some(visible) = new.visible { - if Some(visible) != last.active { - last.visible = Some(visible); - commands.push(ViewportCommand::Visible(visible)); + if let Some(new_visible) = new.visible { + if Some(new_visible) != last.active { + last.visible = Some(new_visible); + commands.push(ViewportCommand::Visible(new_visible)); } } - if let Some(hittest) = new.hittest { - if Some(hittest) != last.hittest { - last.hittest = Some(hittest); - commands.push(ViewportCommand::CursorHitTest(hittest)); + if let Some(new_hittest) = new.hittest { + if Some(new_hittest) != last.hittest { + last.hittest = Some(new_hittest); + commands.push(ViewportCommand::CursorHitTest(new_hittest)); } } @@ -1318,51 +1327,51 @@ pub fn changes_between_builders( let mut recreate_window = false; - if let Some(active) = new.active { - if Some(active) != last.active { - last.active = Some(active); + if let Some(new_active) = new.active { + if Some(new_active) != last.active { + last.active = Some(new_active); recreate_window = true; } } - if let Some(close_button) = new.close_button { - if Some(close_button) != last.close_button { - last.close_button = Some(close_button); + if let Some(new_close_button) = new.close_button { + if Some(new_close_button) != last.close_button { + last.close_button = Some(new_close_button); recreate_window = true; } } - if let Some(minimize_button) = new.minimize_button { - if Some(minimize_button) != last.minimize_button { - last.minimize_button = Some(minimize_button); + if let Some(new_minimize_button) = new.minimize_button { + if Some(new_minimize_button) != last.minimize_button { + last.minimize_button = Some(new_minimize_button); recreate_window = true; } } - if let Some(maximized_button) = new.maximize_button { - if Some(maximized_button) != last.maximize_button { - last.maximize_button = Some(maximized_button); + if let Some(new_maximized_button) = new.maximize_button { + if Some(new_maximized_button) != last.maximize_button { + last.maximize_button = Some(new_maximized_button); recreate_window = true; } } - if let Some(title_hidden) = new.title_hidden { - if Some(title_hidden) != last.title_hidden { - last.title_hidden = Some(title_hidden); + if let Some(new_title_hidden) = new.title_hidden { + if Some(new_title_hidden) != last.title_hidden { + last.title_hidden = Some(new_title_hidden); recreate_window = true; } } - if let Some(titlebar_transparent) = new.titlebar_transparent { - if Some(titlebar_transparent) != last.titlebar_transparent { - last.titlebar_transparent = Some(titlebar_transparent); + if let Some(new_titlebar_transparent) = new.titlebar_transparent { + if Some(new_titlebar_transparent) != last.titlebar_transparent { + last.titlebar_transparent = Some(new_titlebar_transparent); recreate_window = true; } } - if let Some(value) = new.fullsize_content_view { - if Some(value) != last.fullsize_content_view { - last.fullsize_content_view = Some(value); + if let Some(new_fullsize_content_view) = new.fullsize_content_view { + if Some(new_fullsize_content_view) != last.fullsize_content_view { + last.fullsize_content_view = Some(new_fullsize_content_view); recreate_window = true; } } diff --git a/crates/egui/src/context.rs b/crates/egui/src/context.rs index 17a31b276..d7613aefa 100644 --- a/crates/egui/src/context.rs +++ b/crates/egui/src/context.rs @@ -1149,7 +1149,7 @@ impl Context { /// /// This will repaint the current viewport pub fn request_repaint(&self) { - self.request_repaint_for(self.viewport_id()); + self.request_repaint_of(self.viewport_id()); } /// Call this if there is need to repaint the UI, i.e. if you are showing an animation. @@ -1162,7 +1162,7 @@ impl Context { /// (this will work on `eframe`). /// /// This will repaint the specified viewport - pub fn request_repaint_for(&self, id: ViewportId) { + pub fn request_repaint_of(&self, id: ViewportId) { self.write(|ctx| ctx.repaint.request_repaint(id)); } diff --git a/crates/egui/src/viewport.rs b/crates/egui/src/viewport.rs index a4ce59c0d..64abf1d81 100644 --- a/crates/egui/src/viewport.rs +++ b/crates/egui/src/viewport.rs @@ -102,7 +102,7 @@ pub struct ViewportBuilder { /// The title of the vieweport. /// `eframe` will use this as the title of the native window. - pub title: String, + pub title: Option, /// This is wayland only. See [`Self::with_name`]. pub name: Option<(String, String)>, @@ -138,7 +138,7 @@ impl ViewportBuilder { pub fn new(id: ViewportId) -> Self { Self { id, - title: "egui".into(), + title: None, name: None, position: None, inner_size: Some(Some(Vec2::new(300.0, 200.0))), @@ -172,7 +172,7 @@ impl ViewportBuilder { pub fn empty(id: ViewportId) -> Self { Self { id, - title: "egui".into(), + title: None, name: None, position: None, inner_size: None, @@ -199,11 +199,9 @@ impl ViewportBuilder { /// Sets the initial title of the window in the title bar. /// - /// The default is `"egui"`. - /// /// Look at winit for more details pub fn with_title(mut self, title: impl Into) -> Self { - self.title = title.into(); + self.title = Some(title.into()); self } diff --git a/examples/test_viewports/src/main.rs b/examples/test_viewports/src/main.rs index 65fb1eebc..58bbf53f0 100644 --- a/examples/test_viewports/src/main.rs +++ b/examples/test_viewports/src/main.rs @@ -26,7 +26,6 @@ pub struct ViewportState { pub id: ViewportId, pub visible: bool, pub sync: bool, - pub count: usize, pub title: String, pub children: Vec>>, } @@ -40,7 +39,6 @@ impl ViewportState { id: ViewportId::from_hash_of(title), visible: false, sync: false, - count: 0, title: title.into(), children, })) @@ -54,7 +52,6 @@ impl ViewportState { id: ViewportId::from_hash_of(title), visible: false, sync: true, - count: 0, title: title.into(), children, })) @@ -132,8 +129,7 @@ fn show_async_viewport( move |ctx| { let mut vp_state = vp_state.write(); show_as_popup(ctx, &title, id, move |ui: &mut egui::Ui| { - ui.add(egui::DragValue::new(&mut vp_state.count).prefix("Count: ")); - generic_ui(ui, &vp_state.children); + generic_child_ui(ui, &mut vp_state); }); }, ); @@ -141,15 +137,15 @@ fn show_async_viewport( fn show_sync_viewport(ctx: &egui::Context, vp_id: ViewportId, vp_state: &mut ViewportState) { let id = Id::from(vp_id); + let title = vp_state.title.clone(); ctx.create_viewport_sync( ViewportBuilder::new(vp_id) - .with_title(vp_state.title.clone()) + .with_title(&title) .with_inner_size(Some(egui::vec2(450.0, 400.0))), move |ctx| { - show_as_popup(ctx, &vp_state.title, id, |ui: &mut egui::Ui| { - ui.add(egui::DragValue::new(&mut vp_state.count).prefix("Count: ")); - generic_ui(ui, &vp_state.children); + show_as_popup(ctx, &title, id, |ui: &mut egui::Ui| { + generic_child_ui(ui, vp_state); }); }, ); @@ -164,6 +160,18 @@ fn show_as_popup(ctx: &egui::Context, title: &str, id: Id, content: impl FnOnce( } } +fn generic_child_ui(ui: &mut egui::Ui, vp_state: &mut ViewportState) { + ui.horizontal(|ui| { + ui.label("Title:"); + if ui.text_edit_singleline(&mut vp_state.title).changed() { + // Title changes happen at the parent level: + ui.ctx().request_repaint_of(ui.ctx().parent_viewport_id()); + } + }); + + generic_ui(ui, &vp_state.children); +} + fn generic_ui(ui: &mut egui::Ui, children: &[Arc>]) { let container_id = ui.id();