1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-01 06:10:06 -04:00

Remove id from ViewportBuilder so it can implement Default

This commit is contained in:
Emil Ernerfeldt
2023-11-14 19:52:28 +01:00
parent 09a728ba34
commit 54f6e6b9ae
6 changed files with 94 additions and 81 deletions

View File

@@ -85,10 +85,9 @@ pub fn window_builder<E>(
.. ..
} = native_options; } = native_options;
let mut viewport_builder = egui::ViewportBuilder::new(ViewportId::ROOT); let mut viewport_builder = egui::ViewportBuilder::ROOT;
viewport_builder viewport_builder
.with_title(title) .with_title(title)
.with_close_button(true) // The default for all other viewports is `false`!
.with_decorations(*decorated) .with_decorations(*decorated)
.with_fullscreen(*fullscreen) .with_fullscreen(*fullscreen)
.with_maximized(*maximized) .with_maximized(*maximized)

View File

@@ -2554,6 +2554,8 @@ impl Context {
/// This creates a new native window, if possible. /// 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. /// 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, /// 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`]. /// `ctx.viewport_id() != ctx.parent_viewport_id` if false you should create a [`crate::Window`].
pub fn show_viewport( pub fn show_viewport(
&self, &self,
viewport_builder: &ViewportBuilder, new_viewport_id: ViewportId,
viewport_builder: ViewportBuilder,
viewport_ui_cb: impl Fn(&Context) + Send + Sync + 'static, viewport_ui_cb: impl Fn(&Context) + Send + Sync + 'static,
) { ) {
crate::profile_function!(); crate::profile_function!();
@@ -2582,21 +2585,21 @@ impl Context {
viewport_ui_cb(self); viewport_ui_cb(self);
} else { } else {
self.write(|ctx| { self.write(|ctx| {
let viewport_id = ctx.viewport_id(); let parent_viewport_id = ctx.viewport_id();
if let Some(window) = ctx.viewports.get_mut(&viewport_builder.id) { if let Some(window) = ctx.viewports.get_mut(&new_viewport_id) {
window.builder = viewport_builder.clone(); window.builder = viewport_builder;
window.ids.parent = viewport_id; window.ids.parent = parent_viewport_id;
window.used = true; window.used = true;
window.viewport_ui_cb = Some(Arc::new(Box::new(viewport_ui_cb))); window.viewport_ui_cb = Some(Arc::new(Box::new(viewport_ui_cb)));
} else { } else {
ctx.viewports.insert( ctx.viewports.insert(
viewport_builder.id, new_viewport_id,
ViewportState { ViewportState {
ids: ViewportIdPair { ids: ViewportIdPair {
this: viewport_builder.id, this: new_viewport_id,
parent: viewport_id, parent: parent_viewport_id,
}, },
builder: viewport_builder.clone(), builder: viewport_builder,
used: true, used: true,
viewport_ui_cb: Some(Arc::new(Box::new(viewport_ui_cb))), 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. /// 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. /// You need to call this each frame when the child viewport should exist.
/// ///
/// The given ui function will be called immediately. /// 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`]. /// `ctx.viewport_id() != ctx.parent_viewport_id` if false you should create a [`crate::Window`].
pub fn show_viewport_immediate<T>( pub fn show_viewport_immediate<T>(
&self, &self,
new_viewport_id: ViewportId,
builder: ViewportBuilder, builder: ViewportBuilder,
viewport_ui_cb: impl FnOnce(&Context) -> T, viewport_ui_cb: impl FnOnce(&Context) -> T,
) -> T { ) -> T {
@@ -2643,23 +2649,23 @@ impl Context {
}; };
let ids = self.write(|ctx| { 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 // Existing
window.builder = builder.clone(); window.builder = builder.clone();
window.ids.parent = parent; window.ids.parent = parent_viewport_id;
window.used = true; window.used = true;
window.viewport_ui_cb = None; window.viewport_ui_cb = None;
window.ids window.ids
} else { } else {
// New // New
let ids = ViewportIdPair { let ids = ViewportIdPair {
this: builder.id, this: new_viewport_id,
parent, parent: parent_viewport_id,
}; };
ctx.viewports.insert( ctx.viewports.insert(
builder.id, new_viewport_id,
ViewportState { ViewportState {
builder: builder.clone(), builder: builder.clone(),
ids, ids,

View File

@@ -99,11 +99,9 @@ pub type ImmediateViewportRendererCallback = dyn for<'a> Fn(&Context, ImmediateV
/// Since egui is immediate mode, `ViewportBuilder` is accumulative in nature. /// Since egui is immediate mode, `ViewportBuilder` is accumulative in nature.
/// Setting any option to `None` means "keep the current value", /// Setting any option to `None` means "keep the current value",
/// or "Use the default" if it is the first call. /// or "Use the default" if it is the first call.
#[derive(PartialEq, Eq, Clone)] #[derive(Clone, Debug, Default, Eq, PartialEq)]
#[allow(clippy::option_option)] #[allow(clippy::option_option)]
pub struct ViewportBuilder { pub struct ViewportBuilder {
pub id: ViewportId,
/// The title of the vieweport. /// The title of the vieweport.
/// `eframe` will use this as the title of the native window. /// `eframe` will use this as the title of the native window.
pub title: Option<String>, pub title: Option<String>,
@@ -136,36 +134,37 @@ pub struct ViewportBuilder {
} }
impl 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. /// Default settings for a new child viewport.
/// pub const CHILD: Self = Self {
/// The given id must be unique for each viewport. close_button: Some(false), // We disable the close button by default because we haven't implemented closing of child viewports yet
pub fn new(id: ViewportId) -> Self { ..Self::ROOT
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),
}
}
/// Empty settings for everything. /// Empty settings for everything.
/// ///
@@ -173,33 +172,30 @@ impl ViewportBuilder {
/// When used on subsequent frames, the current settings will be kept. /// When used on subsequent frames, the current settings will be kept.
/// ///
/// The given id must be unique for each viewport. /// The given id must be unique for each viewport.
pub fn empty(id: ViewportId) -> Self { pub const EMPTY: Self = Self {
Self { title: None,
id, name: None,
title: None, position: None,
name: None, inner_size: None,
position: None, fullscreen: None,
inner_size: None, maximized: None,
fullscreen: None, resizable: None,
maximized: None, transparent: None,
resizable: None, decorations: None,
transparent: None, icon: None,
decorations: None, active: None,
icon: None, visible: None,
active: None, title_hidden: None,
visible: None, titlebar_transparent: None,
title_hidden: None, fullsize_content_view: None,
titlebar_transparent: None, min_inner_size: None,
fullsize_content_view: None, max_inner_size: None,
min_inner_size: None, drag_and_drop: None,
max_inner_size: None, close_button: None,
drag_and_drop: None, minimize_button: None,
close_button: None, maximize_button: None,
minimize_button: None, hittest: None,
maximize_button: None, };
hittest: None,
}
}
/// Sets the initial title of the window in the title bar. /// Sets the initial title of the window in the title bar.
/// ///

View File

@@ -238,6 +238,15 @@ impl From<Arc<ColorImage>> 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. /// A single-channel image designed for the font texture.

View File

@@ -28,10 +28,13 @@ impl eframe::App for MyApp {
ui.checkbox(&mut self.show_child_viewport, "Show secondary viewport"); 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 { if self.show_child_viewport {
ctx.show_viewport( ctx.show_viewport(
egui::ViewportBuilder::new(egui::ViewportId::from_hash_of("secondary_viewport")) egui::ViewportId::from_hash_of("secondary_viewport"),
.with_title("Secondary Viewport"), viewport,
|ctx| { |ctx| {
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
ui.label("Hello from secondary viewport"); ui.label("Hello from secondary viewport");

View File

@@ -65,21 +65,21 @@ impl ViewportState {
let immediate = vp_state.read().immediate; let immediate = vp_state.read().immediate;
let title = vp_state.read().title.clone(); let title = vp_state.read().title.clone();
let mut vp_builder = ViewportBuilder::new(vp_id); let mut vp_builder = ViewportBuilder::ROOT;
vp_builder vp_builder
.with_title(&title) .with_title(&title)
.with_inner_size(Some(egui::vec2(450.0, 400.0))); .with_inner_size(Some(egui::vec2(450.0, 400.0)));
if immediate { if immediate {
let mut vp_state = vp_state.write(); 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| { show_as_popup(ctx, &title, vp_id.into(), |ui: &mut egui::Ui| {
generic_child_ui(ui, &mut vp_state); generic_child_ui(ui, &mut vp_state);
}); });
}); });
} else { } else {
let count = Arc::new(RwLock::new(0)); 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 mut vp_state = vp_state.write();
let count = count.clone(); let count = count.clone();
show_as_popup(ctx, &title, vp_id.into(), move |ui: &mut egui::Ui| { show_as_popup(ctx, &title, vp_id.into(), move |ui: &mut egui::Ui| {