Misc improvements to Bounds
in gpui geometry
* Makes `dilate` and `inset` return. * Implements `Add<Point<T>>` and `Sub<Point<T>>`. * Makes some trait constraints more precise.
This commit is contained in:
parent
a062c0f1bc
commit
ebf6804afd
2 changed files with 121 additions and 66 deletions
|
@ -10,7 +10,7 @@ use std::{
|
||||||
cmp::{self, PartialOrd},
|
cmp::{self, PartialOrd},
|
||||||
fmt,
|
fmt,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
ops::{Add, Div, Mul, MulAssign, Sub},
|
ops::{Add, Div, Mul, MulAssign, Neg, Sub},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{AppContext, DisplayId};
|
use crate::{AppContext, DisplayId};
|
||||||
|
@ -753,6 +753,25 @@ impl Bounds<Pixels> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Bounds<T>
|
||||||
|
where
|
||||||
|
T: Clone + Debug + Default,
|
||||||
|
{
|
||||||
|
/// Creates a new `Bounds` with the specified origin and size.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `origin` - A `Point<T>` representing the origin of the bounds.
|
||||||
|
/// * `size` - A `Size<T>` representing the size of the bounds.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// Returns a `Bounds<T>` that has the given origin and size.
|
||||||
|
pub fn new(origin: Point<T>, size: Size<T>) -> Self {
|
||||||
|
Bounds { origin, size }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Bounds<T>
|
impl<T> Bounds<T>
|
||||||
where
|
where
|
||||||
T: Clone + Debug + Sub<Output = T> + Default,
|
T: Clone + Debug + Sub<Output = T> + Default,
|
||||||
|
@ -823,25 +842,25 @@ where
|
||||||
|
|
||||||
Bounds { origin, size }
|
Bounds { origin, size }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new `Bounds` with the specified origin and size.
|
impl<T> Bounds<T>
|
||||||
///
|
where
|
||||||
/// # Arguments
|
T: Clone + Debug + Sub<T, Output = T> + Default + Half,
|
||||||
///
|
{
|
||||||
/// * `origin` - A `Point<T>` representing the origin of the bounds.
|
/// Creates a new bounds centered at the given point.
|
||||||
/// * `size` - A `Size<T>` representing the size of the bounds.
|
pub fn centered_at(center: Point<T>, size: Size<T>) -> Self {
|
||||||
///
|
let origin = Point {
|
||||||
/// # Returns
|
x: center.x - size.width.half(),
|
||||||
///
|
y: center.y - size.height.half(),
|
||||||
/// Returns a `Bounds<T>` that has the given origin and size.
|
};
|
||||||
pub fn new(origin: Point<T>, size: Size<T>) -> Self {
|
Self::new(origin, size)
|
||||||
Bounds { origin, size }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Bounds<T>
|
impl<T> Bounds<T>
|
||||||
where
|
where
|
||||||
T: Clone + Debug + PartialOrd + Add<T, Output = T> + Sub<Output = T> + Default + Half,
|
T: Clone + Debug + PartialOrd + Add<T, Output = T> + Default,
|
||||||
{
|
{
|
||||||
/// Checks if this `Bounds` intersects with another `Bounds`.
|
/// Checks if this `Bounds` intersects with another `Bounds`.
|
||||||
///
|
///
|
||||||
|
@ -885,49 +904,12 @@ where
|
||||||
&& self.origin.y < their_lower_right.y
|
&& self.origin.y < their_lower_right.y
|
||||||
&& my_lower_right.y > other.origin.y
|
&& my_lower_right.y > other.origin.y
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Dilates the bounds by a specified amount in all directions.
|
impl<T> Bounds<T>
|
||||||
///
|
where
|
||||||
/// This method expands the bounds by the given `amount`, increasing the size
|
T: Clone + Debug + Add<T, Output = T> + Default + Half,
|
||||||
/// and adjusting the origin so that the bounds grow outwards equally in all directions.
|
{
|
||||||
/// The resulting bounds will have its width and height increased by twice the `amount`
|
|
||||||
/// (since it grows in both directions), and the origin will be moved by `-amount`
|
|
||||||
/// in both the x and y directions.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `amount` - The amount by which to dilate the bounds.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use gpui::{Bounds, Point, Size};
|
|
||||||
/// let mut bounds = Bounds {
|
|
||||||
/// origin: Point { x: 10, y: 10 },
|
|
||||||
/// size: Size { width: 10, height: 10 },
|
|
||||||
/// };
|
|
||||||
/// bounds.dilate(5);
|
|
||||||
/// assert_eq!(bounds, Bounds {
|
|
||||||
/// origin: Point { x: 5, y: 5 },
|
|
||||||
/// size: Size { width: 20, height: 20 },
|
|
||||||
/// });
|
|
||||||
/// ```
|
|
||||||
pub fn dilate(&mut self, amount: T) {
|
|
||||||
self.origin.x = self.origin.x.clone() - amount.clone();
|
|
||||||
self.origin.y = self.origin.y.clone() - amount.clone();
|
|
||||||
let double_amount = amount.clone() + amount;
|
|
||||||
self.size.width = self.size.width.clone() + double_amount.clone();
|
|
||||||
self.size.height = self.size.height.clone() + double_amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// inset the bounds by a specified amount
|
|
||||||
/// Note that this may panic if T does not support negative values
|
|
||||||
pub fn inset(&self, amount: T) -> Self {
|
|
||||||
let mut result = self.clone();
|
|
||||||
result.dilate(T::default() - amount);
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the center point of the bounds.
|
/// Returns the center point of the bounds.
|
||||||
///
|
///
|
||||||
/// Calculates the center by taking the origin's x and y coordinates and adding half the width and height
|
/// Calculates the center by taking the origin's x and y coordinates and adding half the width and height
|
||||||
|
@ -955,7 +937,12 @@ where
|
||||||
y: self.origin.y.clone() + self.size.height.clone().half(),
|
y: self.origin.y.clone() + self.size.height.clone().half(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Bounds<T>
|
||||||
|
where
|
||||||
|
T: Clone + Debug + Add<T, Output = T> + Default,
|
||||||
|
{
|
||||||
/// Calculates the half perimeter of a rectangle defined by the bounds.
|
/// Calculates the half perimeter of a rectangle defined by the bounds.
|
||||||
///
|
///
|
||||||
/// The half perimeter is calculated as the sum of the width and the height of the rectangle.
|
/// The half perimeter is calculated as the sum of the width and the height of the rectangle.
|
||||||
|
@ -977,14 +964,56 @@ where
|
||||||
pub fn half_perimeter(&self) -> T {
|
pub fn half_perimeter(&self) -> T {
|
||||||
self.size.width.clone() + self.size.height.clone()
|
self.size.width.clone() + self.size.height.clone()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// centered_at creates a new bounds centered at the given point.
|
impl<T> Bounds<T>
|
||||||
pub fn centered_at(center: Point<T>, size: Size<T>) -> Self {
|
where
|
||||||
let origin = Point {
|
T: Clone + Debug + Add<T, Output = T> + Sub<Output = T> + Default,
|
||||||
x: center.x - size.width.half(),
|
{
|
||||||
y: center.y - size.height.half(),
|
/// Dilates the bounds by a specified amount in all directions.
|
||||||
};
|
///
|
||||||
Self::new(origin, size)
|
/// This method expands the bounds by the given `amount`, increasing the size
|
||||||
|
/// and adjusting the origin so that the bounds grow outwards equally in all directions.
|
||||||
|
/// The resulting bounds will have its width and height increased by twice the `amount`
|
||||||
|
/// (since it grows in both directions), and the origin will be moved by `-amount`
|
||||||
|
/// in both the x and y directions.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `amount` - The amount by which to dilate the bounds.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use gpui::{Bounds, Point, Size};
|
||||||
|
/// let mut bounds = Bounds {
|
||||||
|
/// origin: Point { x: 10, y: 10 },
|
||||||
|
/// size: Size { width: 10, height: 10 },
|
||||||
|
/// };
|
||||||
|
/// bounds.dilate(5);
|
||||||
|
/// assert_eq!(bounds, Bounds {
|
||||||
|
/// origin: Point { x: 5, y: 5 },
|
||||||
|
/// size: Size { width: 20, height: 20 },
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
|
pub fn dilate(&self, amount: T) -> Bounds<T> {
|
||||||
|
let double_amount = amount.clone() + amount.clone();
|
||||||
|
Bounds {
|
||||||
|
origin: self.origin.clone() - point(amount.clone(), amount),
|
||||||
|
size: self.size.clone() + size(double_amount.clone(), double_amount),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Bounds<T>
|
||||||
|
where
|
||||||
|
T: Clone + Debug + Add<T, Output = T> + Sub<T, Output = T> + Neg<Output = T> + Default,
|
||||||
|
{
|
||||||
|
/// Inset the bounds by a specified amount. Equivalent to `dilate` with the amount negated.
|
||||||
|
///
|
||||||
|
/// Note that this may panic if T does not support negative values.
|
||||||
|
pub fn inset(&self, amount: T) -> Self {
|
||||||
|
self.dilate(-amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1111,6 +1140,34 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Add<Point<T>> for Bounds<T>
|
||||||
|
where
|
||||||
|
T: Add<T, Output = T> + Default + Clone + Debug,
|
||||||
|
{
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, rhs: Point<T>) -> Self {
|
||||||
|
Self {
|
||||||
|
origin: self.origin + rhs,
|
||||||
|
size: self.size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Sub<Point<T>> for Bounds<T>
|
||||||
|
where
|
||||||
|
T: Sub<T, Output = T> + Default + Clone + Debug,
|
||||||
|
{
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Point<T>) -> Self {
|
||||||
|
Self {
|
||||||
|
origin: self.origin - rhs,
|
||||||
|
size: self.size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Bounds<T>
|
impl<T> Bounds<T>
|
||||||
where
|
where
|
||||||
T: Add<T, Output = T> + Clone + Default + Debug,
|
T: Add<T, Output = T> + Clone + Default + Debug,
|
||||||
|
|
|
@ -2281,9 +2281,7 @@ impl<'a> WindowContext<'a> {
|
||||||
let content_mask = self.content_mask();
|
let content_mask = self.content_mask();
|
||||||
let opacity = self.element_opacity();
|
let opacity = self.element_opacity();
|
||||||
for shadow in shadows {
|
for shadow in shadows {
|
||||||
let mut shadow_bounds = bounds;
|
let shadow_bounds = (bounds + shadow.offset).dilate(shadow.spread_radius);
|
||||||
shadow_bounds.origin += shadow.offset;
|
|
||||||
shadow_bounds.dilate(shadow.spread_radius);
|
|
||||||
self.window.next_frame.scene.insert_primitive(Shadow {
|
self.window.next_frame.scene.insert_primitive(Shadow {
|
||||||
order: 0,
|
order: 0,
|
||||||
blur_radius: shadow.blur_radius.scale(scale_factor),
|
blur_radius: shadow.blur_radius.scale(scale_factor),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue