From a9a756e8f3e827c5f2d53d35029d580ef05e286c Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 30 Mar 2024 14:03:41 +0100 Subject: [PATCH] Overload operators for `Rect + Margin`, `Rect - Margin` etc (#4277) It's more ergonomic --- crates/egui/src/containers/frame.rs | 9 +- crates/egui/src/widgets/text_edit/builder.rs | 4 +- crates/epaint/src/margin.rs | 108 ++++++++++++++----- 3 files changed, 89 insertions(+), 32 deletions(-) diff --git a/crates/egui/src/containers/frame.rs b/crates/egui/src/containers/frame.rs index 6d7ba6e6..b982cfd0 100644 --- a/crates/egui/src/containers/frame.rs +++ b/crates/egui/src/containers/frame.rs @@ -240,7 +240,7 @@ impl Frame { let where_to_put_background = ui.painter().add(Shape::Noop); let outer_rect_bounds = ui.available_rect_before_wrap(); - let mut inner_rect = (self.inner_margin + self.outer_margin).shrink_rect(outer_rect_bounds); + let mut inner_rect = outer_rect_bounds - self.outer_margin - self.inner_margin; // Make sure we don't shrink to the negative: inner_rect.max.x = inner_rect.max.x.max(inner_rect.min.x); @@ -299,7 +299,7 @@ impl Frame { impl Prepared { fn content_with_margin(&self) -> Rect { - (self.frame.inner_margin + self.frame.outer_margin).expand_rect(self.content_ui.min_rect()) + self.content_ui.min_rect() + self.frame.inner_margin + self.frame.outer_margin } /// Allocate the the space that was used by [`Self::content_ui`]. @@ -315,10 +315,7 @@ impl Prepared { /// /// This can be called before or after [`Self::allocate_space`]. pub fn paint(&self, ui: &Ui) { - let paint_rect = self - .frame - .inner_margin - .expand_rect(self.content_ui.min_rect()); + let paint_rect = self.content_ui.min_rect() + self.frame.inner_margin; if ui.is_rect_visible(paint_rect) { let shape = self.frame.paint(paint_rect); diff --git a/crates/egui/src/widgets/text_edit/builder.rs b/crates/egui/src/widgets/text_edit/builder.rs index a8f60d1a..e320a1ae 100644 --- a/crates/egui/src/widgets/text_edit/builder.rs +++ b/crates/egui/src/widgets/text_edit/builder.rs @@ -397,7 +397,7 @@ impl<'t> TextEdit<'t> { // TODO(emilk): return full outer_rect in `TextEditOutput`. // Can't do it now because this fix is ging into a patch release. let outer_rect = output.response.rect; - let inner_rect = margin.shrink_rect(outer_rect); + let inner_rect = outer_rect - margin; output.response.rect = inner_rect; if frame { @@ -501,7 +501,7 @@ impl<'t> TextEdit<'t> { let desired_inner_size = vec2(desired_width, galley.size().y.max(desired_height)); let desired_outer_size = (desired_inner_size + margin.sum()).at_least(min_size); let (auto_id, outer_rect) = ui.allocate_space(desired_outer_size); - let rect = margin.shrink_rect(outer_rect); // inner rect (excluding frame/margin). + let rect = outer_rect - margin; // inner rect (excluding frame/margin). let id = id.unwrap_or_else(|| { if let Some(id_source) = id_source { diff --git a/crates/epaint/src/margin.rs b/crates/epaint/src/margin.rs index 815ff835..e2ade58f 100644 --- a/crates/epaint/src/margin.rs +++ b/crates/epaint/src/margin.rs @@ -2,6 +2,8 @@ use emath::{vec2, Rect, Vec2}; /// A value for all four sides of a rectangle, /// often used to express padding or spacing. +/// +/// Can be added and subtracted to/from [`Rect`]s. #[derive(Clone, Copy, Debug, Default, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Margin { @@ -19,6 +21,8 @@ impl Margin { bottom: 0.0, }; + /// The same margin on every side. + #[doc(alias = "symmetric")] #[inline] pub const fn same(margin: f32) -> Self { Self { @@ -56,16 +60,20 @@ impl Margin { vec2(self.right, self.bottom) } + /// Are the margin on every side the same? + #[doc(alias = "symmetric")] #[inline] pub fn is_same(&self) -> bool { self.left == self.right && self.left == self.top && self.left == self.bottom } + #[deprecated = "Use `rect + margin` instead"] #[inline] pub fn expand_rect(&self, rect: Rect) -> Rect { Rect::from_min_max(rect.min - self.left_top(), rect.max + self.right_bottom()) } + #[deprecated = "Use `rect - margin` instead"] #[inline] pub fn shrink_rect(&self, rect: Rect) -> Rect { Rect::from_min_max(rect.min + self.left_top(), rect.max - self.right_bottom()) @@ -86,6 +94,7 @@ impl From for Margin { } } +/// `Margin + Margin` impl std::ops::Add for Margin { type Output = Self; @@ -100,6 +109,7 @@ impl std::ops::Add for Margin { } } +/// `Margin + f32` impl std::ops::Add for Margin { type Output = Self; @@ -114,6 +124,7 @@ impl std::ops::Add for Margin { } } +/// `Margind += f32` impl std::ops::AddAssign for Margin { #[inline] fn add_assign(&mut self, v: f32) { @@ -124,30 +135,7 @@ impl std::ops::AddAssign for Margin { } } -impl std::ops::Div for Margin { - type Output = Self; - - #[inline] - fn div(self, v: f32) -> Self { - Self { - left: self.left / v, - right: self.right / v, - top: self.top / v, - bottom: self.bottom / v, - } - } -} - -impl std::ops::DivAssign for Margin { - #[inline] - fn div_assign(&mut self, v: f32) { - self.left /= v; - self.right /= v; - self.top /= v; - self.bottom /= v; - } -} - +/// `Margin * f32` impl std::ops::Mul for Margin { type Output = Self; @@ -162,6 +150,7 @@ impl std::ops::Mul for Margin { } } +/// `Margin *= f32` impl std::ops::MulAssign for Margin { #[inline] fn mul_assign(&mut self, v: f32) { @@ -172,6 +161,33 @@ impl std::ops::MulAssign for Margin { } } +/// `Margin / f32` +impl std::ops::Div for Margin { + type Output = Self; + + #[inline] + fn div(self, v: f32) -> Self { + Self { + left: self.left / v, + right: self.right / v, + top: self.top / v, + bottom: self.bottom / v, + } + } +} + +/// `Margin /= f32` +impl std::ops::DivAssign for Margin { + #[inline] + fn div_assign(&mut self, v: f32) { + self.left /= v; + self.right /= v; + self.top /= v; + self.bottom /= v; + } +} + +/// `Margin - Margin` impl std::ops::Sub for Margin { type Output = Self; @@ -186,6 +202,7 @@ impl std::ops::Sub for Margin { } } +/// `Margin - f32` impl std::ops::Sub for Margin { type Output = Self; @@ -200,6 +217,7 @@ impl std::ops::Sub for Margin { } } +/// `Margin -= f32` impl std::ops::SubAssign for Margin { #[inline] fn sub_assign(&mut self, v: f32) { @@ -209,3 +227,45 @@ impl std::ops::SubAssign for Margin { self.bottom -= v; } } + +/// `Rect + Margin` +impl std::ops::Add for Rect { + type Output = Self; + + #[inline] + fn add(self, margin: Margin) -> Self { + Self::from_min_max( + self.min - margin.left_top(), + self.max + margin.right_bottom(), + ) + } +} + +/// `Rect += Margin` +impl std::ops::AddAssign for Rect { + #[inline] + fn add_assign(&mut self, margin: Margin) { + *self = *self + margin; + } +} + +/// `Rect - Margin` +impl std::ops::Sub for Rect { + type Output = Self; + + #[inline] + fn sub(self, margin: Margin) -> Self { + Self::from_min_max( + self.min + margin.left_top(), + self.max - margin.right_bottom(), + ) + } +} + +/// `Rect -= Margin` +impl std::ops::SubAssign for Rect { + #[inline] + fn sub_assign(&mut self, margin: Margin) { + *self = *self - margin; + } +}