Update area struct to allow force resizing (#7114)

This is a really small PR so I am skipping the issue (based on
contributing.md). This change adds an optional field and thus non
breaking for the API.

I ran into an issue during my development of an alerts manager widget
([see PR](https://github.com/blackberryfloat/egui_widget_ext/pull/2))
where I needed a scrollable overlay that did not block clicking areas of
a parent widget when my alerts did not take up the entire parent. To
achieve this I detect the sizing pass via the invisible flag and only
render the alerts content and then on the next pass I add the scroll bar
in around the alert content. Whenever the alert content changed though I
would need to create a new Area with a new id to get proper sizing. That
is a memory leak so I wanted to reset the size state to trigger a sizing
pass. Memory is rightfully protected enough that the path to remove
memory was dropped and I just added a hook to set a resize flag.

I am sure there are better ways but this is what made sense to me.
Looking forward to thoughts.

~~Logistics wise, I have proposed it as a patch because I was based off
0.31.1 for testing. I was also thinking it could be released quickly. I
am happy to cherry pick onto main after. If that is not allowed I can
rebase to main and pull against that.~~ (rebased on main)

---------

Co-authored-by: Wesley Murray <murraywj97@gmail.com>
This commit is contained in:
Blackberry Float 2025-07-03 07:14:07 -04:00 committed by GitHub
parent 6d312cc4c7
commit db3543d034
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 28 additions and 0 deletions

View File

@ -121,6 +121,7 @@ pub struct Area {
new_pos: Option<Pos2>,
fade_in: bool,
layout: Layout,
sizing_pass: bool,
}
impl WidgetWithState for Area {
@ -147,6 +148,7 @@ impl Area {
anchor: None,
fade_in: true,
layout: Layout::default(),
sizing_pass: false,
}
}
@ -357,6 +359,27 @@ impl Area {
self.layout = layout;
self
}
/// While true, a sizing pass will be done. This means the area will be invisible
/// and the contents will be laid out to estimate the proper containing size of the area.
/// If false, there will be no change to the default area behavior. This is useful if the
/// area contents area dynamic and you need to need to make sure the area adjusts its size
/// accordingly.
///
/// This should only be set to true during the specific frames you want force a sizing pass.
/// Do NOT hard-code this as `.sizing_pass(true)`, as it will cause the area to never be
/// visible.
///
/// # Arguments
/// - resize: If true, the area will be resized to fit its contents. False will keep the
/// default area resizing behavior.
///
/// Default: `false`.
#[inline]
pub fn sizing_pass(mut self, resize: bool) -> Self {
self.sizing_pass = resize;
self
}
}
pub(crate) struct Prepared {
@ -410,6 +433,7 @@ impl Area {
constrain_rect,
fade_in,
layout,
sizing_pass: force_sizing_pass,
} = self;
let constrain_rect = constrain_rect.unwrap_or_else(|| ctx.screen_rect());
@ -425,6 +449,10 @@ impl Area {
interactable,
last_became_visible_at: None,
});
if force_sizing_pass {
sizing_pass = true;
state.size = None;
}
state.pivot = pivot;
state.interactable = interactable;
if let Some(new_pos) = new_pos {