Browse Source

Add `UiBuilder::layer_id`, and remove `layer_id` from `Ui::new` (#5195)

This adds `UiBuilder::layer_id` to replace `ui.with_layer_id`
pull/5204/head
Emil Ernerfeldt 1 month ago
committed by GitHub
parent
commit
5f8f149444
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      crates/egui/src/containers/area.rs
  2. 18
      crates/egui/src/containers/panel.rs
  3. 3
      crates/egui/src/painter.rs
  4. 22
      crates/egui/src/ui.rs
  5. 10
      crates/egui/src/ui_builder.rs
  6. 8
      crates/egui/src/widget_rect.rs
  7. 2
      tests/test_viewports/src/main.rs

3
crates/egui/src/containers/area.rs

@ -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 {
@ -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 {

18
crates/egui/src/containers/panel.rs

@ -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());
@ -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());
@ -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());

3
crates/egui/src/painter.rs

@ -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;
}

22
crates/egui/src/ui.rs

@ -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,
@ -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"
@ -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,
@ -247,6 +250,7 @@ impl Ui {
let UiBuilder {
id_salt,
ui_stack_info,
layer_id,
max_rect,
layout,
disabled,
@ -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();
}
@ -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,
@ -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.
@ -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,

10
crates/egui/src/ui_builder.rs

@ -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;
@ -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,
@ -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.

8
crates/egui/src/widget_rect.rs

@ -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

2
tests/test_viewports/src/main.rs

@ -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();

Loading…
Cancel
Save