The default constrain rect for `Area/Window` is now `ctx.screen_rect` (#4590)

By default, `Windows` can now cover already added panels. For instance:
in the egui demo app (egui.rs), windows can now cover the side-panels
and top bar.

To get the old behaviour, use
`window.constrain_to(ctx.available_rect())`.
This commit is contained in:
Emil Ernerfeldt 2024-05-31 10:01:45 +02:00 committed by GitHub
parent 8f5986125d
commit c0479cadf3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 18 additions and 45 deletions

View File

@ -228,7 +228,7 @@ impl Area {
self self
} }
/// Constrains this area to the screen bounds. /// Constrains this area to [`Context::screen_rect`]?
#[inline] #[inline]
pub fn constrain(mut self, constrain: bool) -> Self { pub fn constrain(mut self, constrain: bool) -> Self {
self.constrain = constrain; self.constrain = constrain;
@ -306,7 +306,7 @@ pub(crate) struct Prepared {
move_response: Response, move_response: Response,
enabled: bool, enabled: bool,
constrain: bool, constrain: bool,
constrain_rect: Option<Rect>, constrain_rect: Rect,
/// We always make windows invisible the first frame to hide "first-frame-jitters". /// We always make windows invisible the first frame to hide "first-frame-jitters".
/// ///
@ -349,6 +349,8 @@ impl Area {
fade_in, fade_in,
} = self; } = self;
let constrain_rect = constrain_rect.unwrap_or_else(|| ctx.screen_rect());
let layer_id = LayerId::new(order, id); let layer_id = LayerId::new(order, id);
let state = AreaState::load(ctx, id).map(|mut state| { let state = AreaState::load(ctx, id).map(|mut state| {
@ -373,7 +375,6 @@ impl Area {
} }
if constrain { if constrain {
let constrain_rect = constrain_rect.unwrap_or_else(|| ctx.screen_rect());
size = size.at_most(constrain_rect.size()); size = size.at_most(constrain_rect.size());
} }
@ -396,9 +397,11 @@ impl Area {
} }
if let Some((anchor, offset)) = anchor { if let Some((anchor, offset)) = anchor {
let screen = ctx.available_rect();
state.set_left_top_pos( state.set_left_top_pos(
anchor.align_size_within_rect(state.size, screen).left_top() + offset, anchor
.align_size_within_rect(state.size, constrain_rect)
.left_top()
+ offset,
); );
} }
@ -478,29 +481,14 @@ impl Prepared {
self.constrain self.constrain
} }
pub(crate) fn constrain_rect(&self) -> Option<Rect> { pub(crate) fn constrain_rect(&self) -> Rect {
self.constrain_rect self.constrain_rect
} }
pub(crate) fn content_ui(&self, ctx: &Context) -> Ui { pub(crate) fn content_ui(&self, ctx: &Context) -> Ui {
let screen_rect = ctx.screen_rect();
let constrain_rect = if let Some(constrain_rect) = self.constrain_rect {
constrain_rect.intersect(screen_rect) // protect against infinite bounds
} else {
let central_area = ctx.available_rect();
let is_within_central_area = central_area.contains_rect(self.state.rect().shrink(1.0));
if is_within_central_area {
central_area // let's try to not cover side panels
} else {
screen_rect
}
};
let max_rect = Rect::from_min_size(self.state.left_top_pos(), self.state.size); let max_rect = Rect::from_min_size(self.state.left_top_pos(), self.state.size);
let clip_rect = constrain_rect; // Don't paint outside our bounds let clip_rect = self.constrain_rect; // Don't paint outside our bounds
let mut ui = Ui::new( let mut ui = Ui::new(
ctx.clone(), ctx.clone(),
@ -563,6 +551,8 @@ fn automatic_area_position(ctx: &Context) -> Pos2 {
}); });
existing.sort_by_key(|r| r.left().round() as i32); existing.sort_by_key(|r| r.left().round() as i32);
// NOTE: for the benefit of the egui demo, we position the windows so they don't
// cover the side panels, which means we use `available_rect` here instead of `constrain_rect` or `screen_rect`.
let available_rect = ctx.available_rect(); let available_rect = ctx.available_rect();
let spacing = 16.0; let spacing = 16.0;

View File

@ -220,7 +220,7 @@ impl<'open> Window<'open> {
self self
} }
/// Constrains this window to the screen bounds. /// Constrains this window to [`Context::screen_rect`].
/// ///
/// To change the area to constrain to, use [`Self::constrain_to`]. /// To change the area to constrain to, use [`Self::constrain_to`].
/// ///
@ -471,11 +471,10 @@ impl<'open> Window<'open> {
}; };
{ {
// Prevent window from becoming larger than the constraint rect and/or screen rect. // Prevent window from becoming larger than the constrain rect.
let screen_rect = ctx.screen_rect(); let constrain_rect = area.constrain_rect();
let max_rect = area.constrain_rect().unwrap_or(screen_rect); let max_width = constrain_rect.width();
let max_width = max_rect.width(); let max_height = constrain_rect.height() - title_bar_height;
let max_height = max_rect.height() - title_bar_height;
resize.max_size.x = resize.max_size.x.min(max_width); resize.max_size.x = resize.max_size.x.min(max_width);
resize.max_size.y = resize.max_size.y.min(max_height); resize.max_size.y = resize.max_size.y.min(max_height);
} }

View File

@ -1776,23 +1776,7 @@ impl Context {
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
/// Constrain the position of a window/area so it fits within the provided boundary. /// Constrain the position of a window/area so it fits within the provided boundary.
/// pub(crate) fn constrain_window_rect_to_area(&self, window: Rect, area: Rect) -> Rect {
/// If area is `None`, will constrain to [`Self::available_rect`].
pub(crate) fn constrain_window_rect_to_area(&self, window: Rect, area: Option<Rect>) -> Rect {
let mut area = area.unwrap_or_else(|| self.available_rect());
if window.width() > area.width() {
// Allow overlapping side bars.
// This is important for small screens, e.g. mobiles running the web demo.
let screen_rect = self.screen_rect();
(area.min.x, area.max.x) = (screen_rect.min.x, screen_rect.max.x);
}
if window.height() > area.height() {
// Allow overlapping top/bottom bars:
let screen_rect = self.screen_rect();
(area.min.y, area.max.y) = (screen_rect.min.y, screen_rect.max.y);
}
let mut pos = window.min; let mut pos = window.min;
// Constrain to screen, unless window is too large to fit: // Constrain to screen, unless window is too large to fit: