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
}
/// Constrains this area to the screen bounds.
/// Constrains this area to [`Context::screen_rect`]?
#[inline]
pub fn constrain(mut self, constrain: bool) -> Self {
self.constrain = constrain;
@ -306,7 +306,7 @@ pub(crate) struct Prepared {
move_response: Response,
enabled: bool,
constrain: bool,
constrain_rect: Option<Rect>,
constrain_rect: Rect,
/// We always make windows invisible the first frame to hide "first-frame-jitters".
///
@ -349,6 +349,8 @@ impl Area {
fade_in,
} = self;
let constrain_rect = constrain_rect.unwrap_or_else(|| ctx.screen_rect());
let layer_id = LayerId::new(order, id);
let state = AreaState::load(ctx, id).map(|mut state| {
@ -373,7 +375,6 @@ impl Area {
}
if constrain {
let constrain_rect = constrain_rect.unwrap_or_else(|| ctx.screen_rect());
size = size.at_most(constrain_rect.size());
}
@ -396,9 +397,11 @@ impl Area {
}
if let Some((anchor, offset)) = anchor {
let screen = ctx.available_rect();
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
}
pub(crate) fn constrain_rect(&self) -> Option<Rect> {
pub(crate) fn constrain_rect(&self) -> Rect {
self.constrain_rect
}
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 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(
ctx.clone(),
@ -563,6 +551,8 @@ fn automatic_area_position(ctx: &Context) -> Pos2 {
});
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 spacing = 16.0;

View File

@ -220,7 +220,7 @@ impl<'open> Window<'open> {
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`].
///
@ -471,11 +471,10 @@ impl<'open> Window<'open> {
};
{
// Prevent window from becoming larger than the constraint rect and/or screen rect.
let screen_rect = ctx.screen_rect();
let max_rect = area.constrain_rect().unwrap_or(screen_rect);
let max_width = max_rect.width();
let max_height = max_rect.height() - title_bar_height;
// Prevent window from becoming larger than the constrain rect.
let constrain_rect = area.constrain_rect();
let max_width = constrain_rect.width();
let max_height = constrain_rect.height() - title_bar_height;
resize.max_size.x = resize.max_size.x.min(max_width);
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.
///
/// 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);
}
pub(crate) fn constrain_window_rect_to_area(&self, window: Rect, area: Rect) -> Rect {
let mut pos = window.min;
// Constrain to screen, unless window is too large to fit: