Skip to content

Commit

Permalink
Remove id from ViewportBuilder so it can implement Default
Browse files Browse the repository at this point in the history
  • Loading branch information
emilk committed Nov 14, 2023
1 parent 09a728b commit 54f6e6b
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 81 deletions.
3 changes: 1 addition & 2 deletions crates/eframe/src/native/epi_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,9 @@ pub fn window_builder<E>(
..
} = 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)
Expand Down
36 changes: 21 additions & 15 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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!();
Expand All @@ -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))),
},
Expand All @@ -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.
Expand All @@ -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<T>(
&self,
new_viewport_id: ViewportId,
builder: ViewportBuilder,
viewport_ui_cb: impl FnOnce(&Context) -> T,
) -> T {
Expand All @@ -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,
Expand Down
114 changes: 55 additions & 59 deletions crates/egui/src/viewport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,
Expand Down Expand Up @@ -136,70 +134,68 @@ 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.
///
/// If used the first frame, backend-specific defaults will be used.
/// 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.
///
Expand Down
9 changes: 9 additions & 0 deletions crates/epaint/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 5 additions & 2 deletions examples/multiple_viewports/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
6 changes: 3 additions & 3 deletions examples/test_viewports/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down

0 comments on commit 54f6e6b

Please sign in to comment.