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

Remove Option<Option<X>> and simplify ViewportBuilder

This commit is contained in:
Emil Ernerfeldt
2023-11-15 18:22:30 +01:00
parent d21458d166
commit e36ef75f68
6 changed files with 64 additions and 63 deletions

View File

@@ -1,4 +1,4 @@
use std::{sync::Arc, time::Instant}; use std::time::Instant;
use winit::event_loop::EventLoopWindowTarget; use winit::event_loop::EventLoopWindowTarget;
@@ -92,17 +92,19 @@ pub fn window_builder<E>(
.with_maximized(*maximized) .with_maximized(*maximized)
.with_resizable(*resizable) .with_resizable(*resizable)
.with_transparent(*transparent) .with_transparent(*transparent)
.with_window_icon(icon_data.clone().map(|d| {
Arc::new(egui::ColorImage::from_rgba_premultiplied(
[d.width as usize, d.height as usize],
&d.rgba,
))
}))
.with_active(*active) .with_active(*active)
// Keep hidden until we've painted something. See https://github.com/emilk/egui/pull/2279 // Keep hidden until we've painted something. See https://github.com/emilk/egui/pull/2279
// We must also keep the window hidden until AccessKit is initialized. // We must also keep the window hidden until AccessKit is initialized.
.with_visible(false); .with_visible(false);
if let Some(icon_data) = icon_data {
viewport_builder =
viewport_builder.with_window_icon(egui::ColorImage::from_rgba_premultiplied(
[icon_data.width as usize, icon_data.height as usize],
&icon_data.rgba,
));
}
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
if *fullsize_content { if *fullsize_content {
viewport_builder = viewport_builder viewport_builder = viewport_builder
@@ -120,10 +122,10 @@ pub fn window_builder<E>(
} }
if let Some(min_size) = *min_window_size { if let Some(min_size) = *min_window_size {
viewport_builder = viewport_builder.with_min_inner_size(Some(min_size)); viewport_builder = viewport_builder.with_min_inner_size(min_size);
} }
if let Some(max_size) = *max_window_size { if let Some(max_size) = *max_window_size {
viewport_builder = viewport_builder.with_max_inner_size(Some(max_size)); viewport_builder = viewport_builder.with_max_inner_size(max_size);
} }
viewport_builder = viewport_builder.with_drag_and_drop(*drag_and_drop_support); viewport_builder = viewport_builder.with_drag_and_drop(*drag_and_drop_support);
@@ -141,13 +143,13 @@ pub fn window_builder<E>(
window_settings.inner_size_points() window_settings.inner_size_points()
} else { } else {
if let Some(pos) = *initial_window_pos { if let Some(pos) = *initial_window_pos {
viewport_builder = viewport_builder.with_position(Some(pos)); viewport_builder = viewport_builder.with_position(pos);
} }
if let Some(initial_window_size) = *initial_window_size { if let Some(initial_window_size) = *initial_window_size {
let initial_window_size = let initial_window_size =
initial_window_size.at_most(largest_monitor_point_size(event_loop)); initial_window_size.at_most(largest_monitor_point_size(event_loop));
viewport_builder = viewport_builder.with_inner_size(Some(initial_window_size)); viewport_builder = viewport_builder.with_inner_size(initial_window_size);
} }
*initial_window_size *initial_window_size
@@ -161,7 +163,7 @@ pub fn window_builder<E>(
if monitor_size.width > 0.0 && monitor_size.height > 0.0 { if monitor_size.width > 0.0 && monitor_size.height > 0.0 {
let x = (monitor_size.width - inner_size.x) / 2.0; let x = (monitor_size.width - inner_size.x) / 2.0;
let y = (monitor_size.height - inner_size.y) / 2.0; let y = (monitor_size.height - inner_size.y) / 2.0;
viewport_builder = viewport_builder.with_position(Some(egui::Pos2::new(x, y))); viewport_builder = viewport_builder.with_position([x, y]);
} }
} }
} }

View File

@@ -1035,10 +1035,14 @@ pub fn process_viewport_commands(
window.set_outer_position(LogicalPosition::new(pos.x, pos.y)); window.set_outer_position(LogicalPosition::new(pos.x, pos.y));
} }
ViewportCommand::MinInnerSize(s) => { ViewportCommand::MinInnerSize(s) => {
window.set_min_inner_size(s.map(|s| LogicalSize::new(s.x, s.y))); window.set_min_inner_size(
(s.is_finite() && s != Vec2::ZERO).then_some(LogicalSize::new(s.x, s.y)),
);
} }
ViewportCommand::MaxInnerSize(s) => { ViewportCommand::MaxInnerSize(s) => {
window.set_max_inner_size(s.map(|s| LogicalSize::new(s.x, s.y))); window.set_max_inner_size(
(s.is_finite() && s != Vec2::INFINITY).then_some(LogicalSize::new(s.x, s.y)),
);
} }
ViewportCommand::ResizeIncrements(s) => { ViewportCommand::ResizeIncrements(s) => {
window.set_resize_increments(s.map(|s| LogicalSize::new(s.x, s.y))); window.set_resize_increments(s.map(|s| LogicalSize::new(s.x, s.y)));
@@ -1168,31 +1172,31 @@ pub fn create_winit_window_builder(builder: &ViewportBuilder) -> winit::window::
}) })
.with_active(builder.active.unwrap_or(true)); .with_active(builder.active.unwrap_or(true));
if let Some(Some(inner_size)) = builder.inner_size { if let Some(inner_size) = builder.inner_size {
window_builder = window_builder window_builder = window_builder
.with_inner_size(winit::dpi::LogicalSize::new(inner_size.x, inner_size.y)); .with_inner_size(winit::dpi::LogicalSize::new(inner_size.x, inner_size.y));
} }
if let Some(Some(min_inner_size)) = builder.min_inner_size { if let Some(min_inner_size) = builder.min_inner_size {
window_builder = window_builder.with_min_inner_size(winit::dpi::LogicalSize::new( window_builder = window_builder.with_min_inner_size(winit::dpi::LogicalSize::new(
min_inner_size.x, min_inner_size.x,
min_inner_size.y, min_inner_size.y,
)); ));
} }
if let Some(Some(max_inner_size)) = builder.max_inner_size { if let Some(max_inner_size) = builder.max_inner_size {
window_builder = window_builder.with_max_inner_size(winit::dpi::LogicalSize::new( window_builder = window_builder.with_max_inner_size(winit::dpi::LogicalSize::new(
max_inner_size.x, max_inner_size.x,
max_inner_size.y, max_inner_size.y,
)); ));
} }
if let Some(Some(position)) = builder.position { if let Some(position) = builder.position {
window_builder = window_builder =
window_builder.with_position(winit::dpi::LogicalPosition::new(position.x, position.y)); window_builder.with_position(winit::dpi::LogicalPosition::new(position.x, position.y));
} }
if let Some(Some(icon)) = builder.icon.clone() { if let Some(icon) = builder.icon.clone() {
window_builder = window_builder.with_window_icon(Some( window_builder = window_builder.with_window_icon(Some(
winit::window::Icon::from_rgba( winit::window::Icon::from_rgba(
icon.as_raw().to_owned(), icon.as_raw().to_owned(),

View File

@@ -60,12 +60,12 @@ impl WindowSettings {
self.outer_position_pixels self.outer_position_pixels
}; };
if let Some(pos) = pos_px { if let Some(pos) = pos_px {
viewport_builder = viewport_builder.with_position(Some(pos)); viewport_builder = viewport_builder.with_position(pos);
} }
if let Some(inner_size_points) = self.inner_size_points { if let Some(inner_size_points) = self.inner_size_points {
viewport_builder = viewport_builder viewport_builder = viewport_builder
.with_inner_size(Some(inner_size_points)) .with_inner_size(inner_size_points)
.with_fullscreen(self.fullscreen); .with_fullscreen(self.fullscreen);
} }

View File

@@ -112,21 +112,22 @@ pub struct ViewportBuilder {
/// This is wayland only. See [`Self::with_name`]. /// This is wayland only. See [`Self::with_name`].
pub name: Option<(String, String)>, pub name: Option<(String, String)>,
pub position: Option<Option<Pos2>>, pub position: Option<Pos2>,
pub inner_size: Option<Option<Vec2>>, pub inner_size: Option<Vec2>,
pub min_inner_size: Option<Vec2>,
pub max_inner_size: Option<Vec2>,
pub fullscreen: Option<bool>, pub fullscreen: Option<bool>,
pub maximized: Option<bool>, pub maximized: Option<bool>,
pub resizable: Option<bool>, pub resizable: Option<bool>,
pub transparent: Option<bool>, pub transparent: Option<bool>,
pub decorations: Option<bool>, pub decorations: Option<bool>,
pub icon: Option<Option<Arc<ColorImage>>>, pub icon: Option<Arc<ColorImage>>,
pub active: Option<bool>, pub active: Option<bool>,
pub visible: Option<bool>, pub visible: Option<bool>,
pub title_hidden: Option<bool>, pub title_hidden: Option<bool>,
pub titlebar_transparent: Option<bool>, pub titlebar_transparent: Option<bool>,
pub fullsize_content_view: Option<bool>, pub fullsize_content_view: Option<bool>,
pub min_inner_size: Option<Option<Vec2>>,
pub max_inner_size: Option<Option<Vec2>>,
pub drag_and_drop: Option<bool>, pub drag_and_drop: Option<bool>,
pub close_button: Option<bool>, pub close_button: Option<bool>,
@@ -209,8 +210,8 @@ impl ViewportBuilder {
/// The icon needs to be wrapped in Arc because will be cloned every frame /// The icon needs to be wrapped in Arc because will be cloned every frame
#[inline] #[inline]
pub fn with_window_icon(mut self, icon: Option<Arc<ColorImage>>) -> Self { pub fn with_window_icon(mut self, icon: impl Into<Arc<ColorImage>>) -> Self {
self.icon = Some(icon); self.icon = Some(icon.into());
self self
} }
@@ -274,8 +275,8 @@ impl ViewportBuilder {
/// Should be bigger then 0 /// Should be bigger then 0
/// Look at winit for more details /// Look at winit for more details
#[inline] #[inline]
pub fn with_inner_size(mut self, value: Option<Vec2>) -> Self { pub fn with_inner_size(mut self, size: impl Into<Vec2>) -> Self {
self.inner_size = Some(value); self.inner_size = Some(size.into());
self self
} }
@@ -287,8 +288,8 @@ impl ViewportBuilder {
/// Should be bigger then 0 /// Should be bigger then 0
/// Look at winit for more details /// Look at winit for more details
#[inline] #[inline]
pub fn with_min_inner_size(mut self, value: Option<Vec2>) -> Self { pub fn with_min_inner_size(mut self, size: impl Into<Vec2>) -> Self {
self.min_inner_size = Some(value); self.min_inner_size = Some(size.into());
self self
} }
@@ -300,8 +301,8 @@ impl ViewportBuilder {
/// Should be bigger then 0 /// Should be bigger then 0
/// Look at winit for more details /// Look at winit for more details
#[inline] #[inline]
pub fn with_max_inner_size(mut self, value: Option<Vec2>) -> Self { pub fn with_max_inner_size(mut self, size: impl Into<Vec2>) -> Self {
self.max_inner_size = Some(value); self.max_inner_size = Some(size.into());
self self
} }
@@ -335,8 +336,8 @@ impl ViewportBuilder {
/// This will probably not work as expected! /// This will probably not work as expected!
#[inline] #[inline]
pub fn with_position(mut self, value: Option<Pos2>) -> Self { pub fn with_position(mut self, pos: impl Into<Pos2>) -> Self {
self.position = Some(value); self.position = Some(pos.into());
self self
} }
@@ -378,18 +379,14 @@ impl ViewportBuilder {
if let Some(new_position) = new.position { if let Some(new_position) = new.position {
if Some(new_position) != self.position { if Some(new_position) != self.position {
self.position = Some(new_position); self.position = Some(new_position);
if let Some(position) = new_position { commands.push(ViewportCommand::OuterPosition(new_position));
commands.push(ViewportCommand::OuterPosition(position));
}
} }
} }
if let Some(new_inner_size) = new.inner_size { if let Some(new_inner_size) = new.inner_size {
if Some(new_inner_size) != self.inner_size { if Some(new_inner_size) != self.inner_size {
self.inner_size = Some(new_inner_size); self.inner_size = Some(new_inner_size);
if let Some(inner_size) = new_inner_size { commands.push(ViewportCommand::InnerSize(new_inner_size));
commands.push(ViewportCommand::InnerSize(inner_size));
}
} }
} }
@@ -442,23 +439,15 @@ impl ViewportBuilder {
} }
} }
if let Some(new_icon) = new.icon.clone() { if let Some(new_icon) = &new.icon {
let eq = match &new_icon { let is_new = match &self.icon {
Some(icon) => { Some(existing) => !Arc::ptr_eq(new_icon, existing),
if let Some(self_icon) = &self.icon { None => true,
matches!(self_icon, Some(self_icon) if Arc::ptr_eq(icon, self_icon))
} else {
false
}
}
None => self.icon == Some(None),
}; };
if !eq { if is_new {
commands.push(ViewportCommand::WindowIcon( commands.push(ViewportCommand::WindowIcon(Some(new_icon.clone())));
new_icon.as_ref().map(|i| i.as_ref().clone()), self.icon = Some(new_icon.clone());
));
self.icon = Some(new_icon);
} }
} }
@@ -587,6 +576,8 @@ pub enum ResizeDirection {
/// You can send a [`ViewportCommand`] to the viewport with [`Context::viewport_command`]. /// You can send a [`ViewportCommand`] to the viewport with [`Context::viewport_command`].
/// ///
/// All coordinates are in logical points. /// All coordinates are in logical points.
///
/// This is essentially a way to diff [`ViewportBuilder`].
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum ViewportCommand { pub enum ViewportCommand {
@@ -612,10 +603,10 @@ pub enum ViewportCommand {
InnerSize(Vec2), InnerSize(Vec2),
/// Should be bigger then 0 /// Should be bigger then 0
MinInnerSize(Option<Vec2>), MinInnerSize(Vec2),
/// Should be bigger then 0 /// Should be bigger then 0
MaxInnerSize(Option<Vec2>), MaxInnerSize(Vec2),
/// Should be bigger then 0 /// Should be bigger then 0
ResizeIncrements(Option<Vec2>), ResizeIncrements(Option<Vec2>),
@@ -644,7 +635,7 @@ pub enum ViewportCommand {
Decorations(bool), Decorations(bool),
WindowLevel(WindowLevel), WindowLevel(WindowLevel),
WindowIcon(Option<ColorImage>), WindowIcon(Option<Arc<ColorImage>>),
IMEPosition(Pos2), IMEPosition(Pos2),
IMEAllowed(bool), IMEAllowed(bool),

View File

@@ -52,7 +52,9 @@ impl eframe::App for MyApp {
if self.show_immediate_viewport { if self.show_immediate_viewport {
ctx.show_viewport_immediate( ctx.show_viewport_immediate(
egui::ViewportId::from_hash_of("immediate_viewport"), egui::ViewportId::from_hash_of("immediate_viewport"),
egui::ViewportBuilder::default().with_title("Immediate Viewport"), egui::ViewportBuilder::default()
.with_title("Immediate Viewport")
.with_inner_size([200.0, 100.0]),
|ctx| { |ctx| {
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
ui.label("Hello from immediate viewport"); ui.label("Hello from immediate viewport");
@@ -70,7 +72,9 @@ impl eframe::App for MyApp {
let show_deferred_viewport = self.show_deferred_viewport.clone(); let show_deferred_viewport = self.show_deferred_viewport.clone();
ctx.show_viewport_immediate( ctx.show_viewport_immediate(
egui::ViewportId::from_hash_of("deferred_viewport"), egui::ViewportId::from_hash_of("deferred_viewport"),
egui::ViewportBuilder::default().with_title("Deferred Viewport"), egui::ViewportBuilder::default()
.with_title("Deferred Viewport")
.with_inner_size([200.0, 100.0]),
|ctx| { |ctx| {
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
ui.label("Hello from deferred viewport"); ui.label("Hello from deferred viewport");

View File

@@ -67,7 +67,7 @@ impl ViewportState {
let viewport = ViewportBuilder::default() let viewport = ViewportBuilder::default()
.with_title(&title) .with_title(&title)
.with_inner_size(Some(egui::vec2(450.0, 400.0))); .with_inner_size([450.0, 400.0]);
if immediate { if immediate {
let mut vp_state = vp_state.write(); let mut vp_state = vp_state.write();