Skip to content

Commit

Permalink
The default constrain rect for Area/Window is now ctx.screen_rect (
Browse files Browse the repository at this point in the history
…emilk#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())`.
  • Loading branch information
emilk authored and hacknus committed Oct 30, 2024
1 parent 47df7dd commit 60db457
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 45 deletions.
34 changes: 12 additions & 22 deletions crates/egui/src/containers/area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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".
///
Expand Down Expand Up @@ -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| {
Expand All @@ -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());
}

Expand All @@ -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,
);
}

Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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;
Expand Down
11 changes: 5 additions & 6 deletions crates/egui/src/containers/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`].
///
Expand Down Expand Up @@ -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);
}
Expand Down
18 changes: 1 addition & 17 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit 60db457

Please sign in to comment.