diff --git a/crates/egui/src/containers/resize.rs b/crates/egui/src/containers/resize.rs index e2654ca5a6c..b6bc3a59625 100644 --- a/crates/egui/src/containers/resize.rs +++ b/crates/egui/src/containers/resize.rs @@ -10,7 +10,7 @@ pub(crate) struct State { pub(crate) desired_size: Vec2, /// Actual size of content last frame - last_content_size: Vec2, + pub(crate) last_content_size: Vec2, /// Externally requested size (e.g. by Window) for the next frame pub(crate) requested_size: Option, @@ -38,6 +38,7 @@ pub struct Resize { pub(crate) min_size: Vec2, pub(crate) max_size: Vec2, + pub(crate) margins: Vec2, default_size: Vec2, @@ -52,6 +53,7 @@ impl Default for Resize { resizable: Vec2b::TRUE, min_size: Vec2::splat(16.0), max_size: Vec2::splat(f32::INFINITY), + margins: Vec2::ZERO, default_size: vec2(320.0, 128.0), // TODO(emilk): preferred size of [`Resize`] area. with_stroke: true, } @@ -205,17 +207,9 @@ impl Resize { let mut state = State::load(ui.ctx(), id).unwrap_or_else(|| { ui.ctx().request_repaint(); // counter frame delay - let default_size = self - .default_size - .at_least(self.min_size) - .at_most(self.max_size) - .at_most( - ui.ctx().screen_rect().size() - ui.spacing().window_margin.sum(), // hack for windows - ); - State { - desired_size: default_size, - last_content_size: vec2(0.0, 0.0), + desired_size: self.default_size, + last_content_size: Vec2::ZERO, requested_size: None, } }); @@ -223,7 +217,8 @@ impl Resize { state.desired_size = state .desired_size .at_least(self.min_size) - .at_most(self.max_size); + .at_most(self.max_size) + .at_most(ui.ctx().screen_rect().size() - self.margins); let mut user_requested_size = state.requested_size.take(); @@ -306,13 +301,14 @@ impl Resize { // We show how large we are, // so we must follow the contents: - state.desired_size[d] = state.desired_size[d].max(state.last_content_size[d]); + state.desired_size[d] = state.desired_size[d].at_least(state.last_content_size[d]); // We are as large as we look size[d] = state.desired_size[d]; } else { // Probably a window. - size[d] = state.last_content_size[d]; + state.desired_size[d] = state.last_content_size[d]; + size[d] = state.desired_size[d]; } } ui.advance_cursor_after_rect(Rect::from_min_size(content_ui.min_rect().min, size)); @@ -369,8 +365,6 @@ impl Resize { } } -use epaint::Stroke; - pub fn paint_resize_corner(ui: &Ui, response: &Response) { let stroke = ui.style().interact(response).fg_stroke; paint_resize_corner_with_style(ui, &response.rect, stroke.color, Align2::RIGHT_BOTTOM); diff --git a/crates/egui/src/containers/window.rs b/crates/egui/src/containers/window.rs index 4cf2c174ed8..4eea5ace683 100644 --- a/crates/egui/src/containers/window.rs +++ b/crates/egui/src/containers/window.rs @@ -419,7 +419,7 @@ impl<'open> Window<'open> { open, area, frame, - resize, + mut resize, scroll, collapsible, default_open, @@ -452,12 +452,6 @@ impl<'open> Window<'open> { let is_collapsed = with_title_bar && !collapsing.is_open(); let possible = PossibleInteractions::new(&area, &resize, is_collapsed); - let resize = resize.resizable(false); // We resize it manually - let mut resize = resize.id(resize_id); - - let on_top = Some(area_layer_id) == ctx.top_layer_id(); - let mut area = area.begin(ctx); - // Calculate roughly how much larger the window size is compared to the inner rect let (title_bar_height, title_content_spacing) = if with_title_bar { let style = ctx.style(); @@ -470,9 +464,25 @@ impl<'open> Window<'open> { (0.0, 0.0) }; + let margins = window_frame.outer_margin.sum() + + window_frame.inner_margin.sum() + + vec2(0.0, title_bar_height); + resize.margins = margins; + + let resize = resize.resizable(false); // We resize it manually + let mut resize = resize.id(resize_id); + + if let Some(mut resize_state) = resize::State::load(ctx, resize_id) { + resize_state.desired_size = Vec2::ZERO; + resize_state.store(ctx, resize_id); + } + + let mut prepared_area = area.begin(ctx); + let last_frame_outer_rect = prepared_area.state().rect(); + { // Prevent window from becoming larger than the constrain rect. - let constrain_rect = area.constrain_rect(); + let constrain_rect = prepared_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); @@ -480,24 +490,19 @@ impl<'open> Window<'open> { } // First check for resize to avoid frame delay: - let last_frame_outer_rect = area.state().rect(); let resize_interaction = resize_interaction(ctx, possible, area_layer_id, last_frame_outer_rect); - let margins = window_frame.outer_margin.sum() - + window_frame.inner_margin.sum() - + vec2(0.0, title_bar_height); - resize_response( resize_interaction, ctx, - margins, + resize, area_layer_id, - &mut area, + &mut prepared_area, resize_id, ); - let mut area_content_ui = area.content_ui(ctx); + let mut area_content_ui = prepared_area.content_ui(ctx); if is_open { // `Area` already takes care of fade-in animations, // so we only need to handle fade-out animations here. @@ -571,6 +576,7 @@ impl<'open> Window<'open> { }, ); + let on_top = Some(area_layer_id) == ctx.top_layer_id(); title_rect = area_content_ui.painter().round_rect_to_pixels(title_rect); if on_top && area_content_ui.visuals().window_highlight_topmost { @@ -612,7 +618,7 @@ impl<'open> Window<'open> { content_inner }; - let full_response = area.end(ctx, area_content_ui); + let full_response = prepared_area.end(ctx, area_content_ui); let inner_response = InnerResponse { inner: content_inner, @@ -765,7 +771,7 @@ impl ResizeInteraction { fn resize_response( resize_interaction: ResizeInteraction, ctx: &Context, - margins: Vec2, + resize: Resize, area_layer_id: LayerId, area: &mut area::Prepared, resize_id: Id, @@ -784,7 +790,7 @@ fn resize_response( if resize_interaction.any_dragged() { if let Some(mut state) = resize::State::load(ctx, resize_id) { - state.requested_size = Some(new_rect.size() - margins); + state.requested_size = Some(new_rect.size() - resize.margins); state.store(ctx, resize_id); } }