Skip to content

Commit

Permalink
Add UiBuilder::layer_id, and remove layer_id from Ui::new (#5195)
Browse files Browse the repository at this point in the history
This adds `UiBuilder::layer_id` to replace `ui.with_layer_id`
  • Loading branch information
emilk authored Oct 1, 2024
1 parent fe368ba commit 5f8f149
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 20 deletions.
3 changes: 2 additions & 1 deletion crates/egui/src/containers/area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ impl Prepared {

let mut ui_builder = UiBuilder::new()
.ui_stack_info(UiStackInfo::new(self.kind))
.layer_id(self.layer_id)
.max_rect(max_rect);

if !self.enabled {
Expand All @@ -549,7 +550,7 @@ impl Prepared {
ui_builder = ui_builder.sizing_pass().invisible();
}

let mut ui = Ui::new(ctx.clone(), self.layer_id, self.layer_id.id, ui_builder);
let mut ui = Ui::new(ctx.clone(), self.layer_id.id, ui_builder);
ui.set_clip_rect(self.constrain_rect); // Don't paint outside our bounds

if self.fade_in {
Expand Down
18 changes: 9 additions & 9 deletions crates/egui/src/containers/panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,14 +372,14 @@ impl SidePanel {
ctx: &Context,
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
) -> InnerResponse<R> {
let layer_id = LayerId::background();
let side = self.side;
let available_rect = ctx.available_rect();
let mut panel_ui = Ui::new(
ctx.clone(),
layer_id,
self.id,
UiBuilder::new().max_rect(available_rect),
UiBuilder::new()
.layer_id(LayerId::background())
.max_rect(available_rect),
);
panel_ui.set_clip_rect(ctx.screen_rect());

Expand Down Expand Up @@ -864,15 +864,15 @@ impl TopBottomPanel {
ctx: &Context,
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
) -> InnerResponse<R> {
let layer_id = LayerId::background();
let available_rect = ctx.available_rect();
let side = self.side;

let mut panel_ui = Ui::new(
ctx.clone(),
layer_id,
self.id,
UiBuilder::new().max_rect(available_rect),
UiBuilder::new()
.layer_id(LayerId::background())
.max_rect(available_rect),
);
panel_ui.set_clip_rect(ctx.screen_rect());

Expand Down Expand Up @@ -1131,14 +1131,14 @@ impl CentralPanel {
add_contents: Box<dyn FnOnce(&mut Ui) -> R + 'c>,
) -> InnerResponse<R> {
let available_rect = ctx.available_rect();
let layer_id = LayerId::background();
let id = Id::new((ctx.viewport_id(), "central_panel"));

let mut panel_ui = Ui::new(
ctx.clone(),
layer_id,
id,
UiBuilder::new().max_rect(available_rect),
UiBuilder::new()
.layer_id(LayerId::background())
.max_rect(available_rect),
);
panel_ui.set_clip_rect(ctx.screen_rect());

Expand Down
3 changes: 3 additions & 0 deletions crates/egui/src/painter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ impl Painter {
}

/// Redirect where you are painting.
///
/// It is undefined behavior to change the [`LayerId`]
/// of [`crate::Ui::painter`].
pub fn set_layer_id(&mut self, layer_id: LayerId) {
self.layer_id = layer_id;
}
Expand Down
22 changes: 14 additions & 8 deletions crates/egui/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,11 @@ impl Ui {
///
/// Normally you would not use this directly, but instead use
/// [`crate::SidePanel`], [`crate::TopBottomPanel`], [`crate::CentralPanel`], [`crate::Window`] or [`crate::Area`].
pub fn new(ctx: Context, layer_id: LayerId, id: Id, ui_builder: UiBuilder) -> Self {
pub fn new(ctx: Context, id: Id, ui_builder: UiBuilder) -> Self {
let UiBuilder {
id_salt,
ui_stack_info,
layer_id,
max_rect,
layout,
disabled,
Expand All @@ -133,6 +134,8 @@ impl Ui {
sense,
} = ui_builder;

let layer_id = layer_id.unwrap_or(LayerId::background());

debug_assert!(
id_salt.is_none(),
"Top-level Ui:s should not have an id_salt"
Expand Down Expand Up @@ -170,7 +173,7 @@ impl Ui {
};

// Register in the widget stack early, to ensure we are behind all widgets we contain:
let start_rect = Rect::NOTHING; // This will be overwritten when/if `remember_min_rect` is called
let start_rect = Rect::NOTHING; // This will be overwritten when `remember_min_rect` is called
ui.ctx().create_widget(
WidgetRect {
id: ui.unique_id,
Expand Down Expand Up @@ -247,6 +250,7 @@ impl Ui {
let UiBuilder {
id_salt,
ui_stack_info,
layer_id,
max_rect,
layout,
disabled,
Expand All @@ -262,6 +266,9 @@ impl Ui {
let max_rect = max_rect.unwrap_or_else(|| self.available_rect_before_wrap());
let mut layout = layout.unwrap_or(*self.layout());
let enabled = self.enabled && !disabled && !invisible;
if let Some(layer_id) = layer_id {
painter.set_layer_id(layer_id);
}
if invisible {
painter.set_invisible();
}
Expand Down Expand Up @@ -310,7 +317,7 @@ impl Ui {
};

// Register in the widget stack early, to ensure we are behind all widgets we contain:
let start_rect = Rect::NOTHING; // This will be overwritten when/if `remember_min_rect` is called
let start_rect = Rect::NOTHING; // This will be overwritten when `remember_min_rect` is called
child_ui.ctx().create_widget(
WidgetRect {
id: child_ui.unique_id,
Expand Down Expand Up @@ -2306,15 +2313,13 @@ impl Ui {
/// });
/// # });
/// ```
#[deprecated = "Use ui.scope_builder(UiBuilder::new().layer_id(…), …) instead"]
pub fn with_layer_id<R>(
&mut self,
layer_id: LayerId,
add_contents: impl FnOnce(&mut Self) -> R,
) -> InnerResponse<R> {
self.scope(|ui| {
ui.painter.set_layer_id(layer_id);
add_contents(ui)
})
self.scope_builder(UiBuilder::new().layer_id(layer_id), add_contents)
}

/// A [`CollapsingHeader`] that starts out collapsed.
Expand Down Expand Up @@ -2760,7 +2765,8 @@ impl Ui {

// Paint the body to a new layer:
let layer_id = LayerId::new(Order::Tooltip, id);
let InnerResponse { inner, response } = self.with_layer_id(layer_id, add_contents);
let InnerResponse { inner, response } =
self.scope_builder(UiBuilder::new().layer_id(layer_id), add_contents);

// Now we move the visuals of the body to where the mouse is.
// Normally you need to decide a location for a widget first,
Expand Down
10 changes: 9 additions & 1 deletion crates/egui/src/ui_builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{hash::Hash, sync::Arc};

use crate::{Id, Layout, Rect, Sense, Style, UiStackInfo};
use crate::{Id, LayerId, Layout, Rect, Sense, Style, UiStackInfo};

#[allow(unused_imports)] // Used for doclinks
use crate::Ui;
Expand All @@ -15,6 +15,7 @@ use crate::Ui;
pub struct UiBuilder {
pub id_salt: Option<Id>,
pub ui_stack_info: UiStackInfo,
pub layer_id: Option<LayerId>,
pub max_rect: Option<Rect>,
pub layout: Option<Layout>,
pub disabled: bool,
Expand Down Expand Up @@ -48,6 +49,13 @@ impl UiBuilder {
self
}

/// Show the [`Ui`] in a different [`LayerId`] from its parent.
#[inline]
pub fn layer_id(mut self, layer_id: LayerId) -> Self {
self.layer_id = Some(layer_id);
self
}

/// Set the max rectangle, within which widgets will go.
///
/// New widgets will *try* to fit within this rectangle.
Expand Down
8 changes: 8 additions & 0 deletions crates/egui/src/widget_rect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,14 @@ impl WidgetRects {
// e.g. calling `response.interact(…)` to add more interaction.
let (idx_in_layer, existing) = entry.get_mut();

debug_assert!(
existing.layer_id == widget_rect.layer_id,
"Widget {:?} changed layer_id during the frame from {:?} to {:?}",
widget_rect.id,
existing.layer_id,
widget_rect.layer_id
);

// Update it:
existing.rect = widget_rect.rect; // last wins
existing.interact_rect = widget_rect.interact_rect; // last wins
Expand Down
2 changes: 1 addition & 1 deletion tests/test_viewports/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ fn drag_source<R>(

// Paint the body to a new layer:
let layer_id = egui::LayerId::new(egui::Order::Tooltip, id);
let res = ui.with_layer_id(layer_id, body);
let res = ui.scope_builder(UiBuilder::new().layer_id(layer_id), body);

if let Some(pointer_pos) = ui.ctx().pointer_interact_pos() {
let delta = pointer_pos - res.response.rect.center();
Expand Down

0 comments on commit 5f8f149

Please sign in to comment.