@@ -345,7 +345,12 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) {
);
editor.update(cx, |view, cx| {
- view.update_selection(DisplayPoint::new(3, 3), 0, gpui::Point::<f32>::zero(), cx);
+ view.update_selection(
+ DisplayPoint::new(3, 3),
+ 0,
+ gpui::Point::<f32>::default(),
+ cx,
+ );
});
assert_eq!(
@@ -356,7 +361,12 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) {
);
editor.update(cx, |view, cx| {
- view.update_selection(DisplayPoint::new(1, 1), 0, gpui::Point::<f32>::zero(), cx);
+ view.update_selection(
+ DisplayPoint::new(1, 1),
+ 0,
+ gpui::Point::<f32>::default(),
+ cx,
+ );
});
assert_eq!(
@@ -368,7 +378,12 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) {
editor.update(cx, |view, cx| {
view.end_selection(cx);
- view.update_selection(DisplayPoint::new(3, 3), 0, gpui::Point::<f32>::zero(), cx);
+ view.update_selection(
+ DisplayPoint::new(3, 3),
+ 0,
+ gpui::Point::<f32>::default(),
+ cx,
+ );
});
assert_eq!(
@@ -380,7 +395,12 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) {
editor.update(cx, |view, cx| {
view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
- view.update_selection(DisplayPoint::new(0, 0), 0, gpui::Point::<f32>::zero(), cx);
+ view.update_selection(
+ DisplayPoint::new(0, 0),
+ 0,
+ gpui::Point::<f32>::default(),
+ cx,
+ );
});
assert_eq!(
@@ -423,7 +443,12 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) {
});
view.update(cx, |view, cx| {
- view.update_selection(DisplayPoint::new(3, 3), 0, gpui::Point::<f32>::zero(), cx);
+ view.update_selection(
+ DisplayPoint::new(3, 3),
+ 0,
+ gpui::Point::<f32>::default(),
+ cx,
+ );
assert_eq!(
view.selections.display_ranges(cx),
[DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
@@ -432,7 +457,12 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) {
view.update(cx, |view, cx| {
view.cancel(&Cancel, cx);
- view.update_selection(DisplayPoint::new(1, 1), 0, gpui::Point::<f32>::zero(), cx);
+ view.update_selection(
+ DisplayPoint::new(1, 1),
+ 0,
+ gpui::Point::<f32>::default(),
+ cx,
+ );
assert_eq!(
view.selections.display_ranges(cx),
[DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
@@ -643,11 +673,21 @@ fn test_cancel(cx: &mut TestAppContext) {
view.update(cx, |view, cx| {
view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
- view.update_selection(DisplayPoint::new(1, 1), 0, gpui::Point::<f32>::zero(), cx);
+ view.update_selection(
+ DisplayPoint::new(1, 1),
+ 0,
+ gpui::Point::<f32>::default(),
+ cx,
+ );
view.end_selection(cx);
view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
- view.update_selection(DisplayPoint::new(0, 3), 0, gpui::Point::<f32>::zero(), cx);
+ view.update_selection(
+ DisplayPoint::new(0, 3),
+ 0,
+ gpui::Point::<f32>::default(),
+ cx,
+ );
view.end_selection(cx);
assert_eq!(
view.selections.display_ranges(cx),
@@ -8,6 +8,18 @@ use std::{
ops::{Add, Div, Mul, MulAssign, Sub},
};
+/// Describes a location in a 2D cartesian coordinate space.
+///
+/// It holds two public fields, `x` and `y`, which represent the coordinates in the space.
+/// The type `T` for the coordinates can be any type that implements `Default`, `Clone`, and `Debug`.
+///
+/// # Examples
+///
+/// ```
+/// # use zed::Point;
+/// let point = Point { x: 10, y: 20 };
+/// println!("{:?}", point); // Outputs: Point { x: 10, y: 20 }
+/// ```
#[derive(Refineable, Default, Add, AddAssign, Sub, SubAssign, Copy, Debug, PartialEq, Eq, Hash)]
#[refineable(Debug)]
#[repr(C)]
@@ -16,19 +28,66 @@ pub struct Point<T: Default + Clone + Debug> {
pub y: T,
}
+/// Constructs a new `Point<T>` with the given x and y coordinates.
+///
+/// # Arguments
+///
+/// * `x` - The x coordinate of the point.
+/// * `y` - The y coordinate of the point.
+///
+/// # Returns
+///
+/// Returns a `Point<T>` with the specified coordinates.
+///
+/// # Examples
+///
+/// ```
+/// # use zed::Point;
+/// let p = point(10, 20);
+/// assert_eq!(p.x, 10);
+/// assert_eq!(p.y, 20);
+/// ```
pub fn point<T: Clone + Debug + Default>(x: T, y: T) -> Point<T> {
Point { x, y }
}
impl<T: Clone + Debug + Default> Point<T> {
+ /// Creates a new `Point` with the specified `x` and `y` coordinates.
+ ///
+ /// # Arguments
+ ///
+ /// * `x` - The horizontal coordinate of the point.
+ /// * `y` - The vertical coordinate of the point.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let p = Point::new(10, 20);
+ /// assert_eq!(p.x, 10);
+ /// assert_eq!(p.y, 20);
+ /// ```
pub const fn new(x: T, y: T) -> Self {
Self { x, y }
}
- pub fn zero() -> Self {
- Self::new(T::default(), T::default())
- }
-
+ /// Transforms the point to a `Point<U>` by applying the given function to both coordinates.
+ ///
+ /// This method allows for converting a `Point<T>` to a `Point<U>` by specifying a closure
+ /// that defines how to convert between the two types. The closure is applied to both the `x`
+ /// and `y` coordinates, resulting in a new point of the desired type.
+ ///
+ /// # Arguments
+ ///
+ /// * `f` - A closure that takes a value of type `T` and returns a value of type `U`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::Point;
+ /// let p = Point { x: 3, y: 4 };
+ /// let p_float = p.map(|coord| coord as f32);
+ /// assert_eq!(p_float, Point { x: 3.0, y: 4.0 });
+ /// ```
pub fn map<U: Clone + Default + Debug>(&self, f: impl Fn(T) -> U) -> Point<U> {
Point {
x: f(self.x.clone()),
@@ -38,6 +97,21 @@ impl<T: Clone + Debug + Default> Point<T> {
}
impl Point<Pixels> {
+ /// Scales the point by a given factor, which is typically derived from the resolution
+ /// of a target display to ensure proper sizing of UI elements.
+ ///
+ /// # Arguments
+ ///
+ /// * `factor` - The scaling factor to apply to both the x and y coordinates.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Point, Pixels, ScaledPixels};
+ /// let p = Point { x: Pixels(10.0), y: Pixels(20.0) };
+ /// let scaled_p = p.scale(1.5);
+ /// assert_eq!(scaled_p, Point { x: ScaledPixels(15.0), y: ScaledPixels(30.0) });
+ /// ```
pub fn scale(&self, factor: f32) -> Point<ScaledPixels> {
Point {
x: self.x.scale(factor),
@@ -45,6 +119,16 @@ impl Point<Pixels> {
}
}
+ /// Calculates the Euclidean distance from the origin (0, 0) to this point.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::Point;
+ /// # use zed::Pixels;
+ /// let p = Point { x: Pixels(3.0), y: Pixels(4.0) };
+ /// assert_eq!(p.magnitude(), 5.0);
+ /// ```
pub fn magnitude(&self) -> f64 {
((self.x.0.powi(2) + self.y.0.powi(2)) as f64).sqrt()
}
@@ -95,14 +179,29 @@ impl<T> Point<T>
where
T: PartialOrd + Clone + Default + Debug,
{
+ /// Returns a new point with the maximum values of each dimension from `self` and `other`.
+ ///
+ /// # Arguments
+ ///
+ /// * `other` - A reference to another `Point` to compare with `self`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::Point;
+ /// let p1 = Point { x: 3, y: 7 };
+ /// let p2 = Point { x: 5, y: 2 };
+ /// let max_point = p1.max(&p2);
+ /// assert_eq!(max_point, Point { x: 5, y: 7 });
+ /// ```
pub fn max(&self, other: &Self) -> Self {
Point {
- x: if self.x >= other.x {
+ x: if self.x > other.x {
self.x.clone()
} else {
other.x.clone()
},
- y: if self.y >= other.y {
+ y: if self.y > other.y {
self.y.clone()
} else {
other.y.clone()
@@ -110,6 +209,21 @@ where
}
}
+ /// Returns a new point with the minimum values of each dimension from `self` and `other`.
+ ///
+ /// # Arguments
+ ///
+ /// * `other` - A reference to another `Point` to compare with `self`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::Point;
+ /// let p1 = Point { x: 3, y: 7 };
+ /// let p2 = Point { x: 5, y: 2 };
+ /// let min_point = p1.min(&p2);
+ /// assert_eq!(min_point, Point { x: 3, y: 2 });
+ /// ```
pub fn min(&self, other: &Self) -> Self {
Point {
x: if self.x <= other.x {
@@ -125,6 +239,32 @@ where
}
}
+ /// Clamps the point to a specified range.
+ ///
+ /// Given a minimum point and a maximum point, this method constrains the current point
+ /// such that its coordinates do not exceed the range defined by the minimum and maximum points.
+ /// If the current point's coordinates are less than the minimum, they are set to the minimum.
+ /// If they are greater than the maximum, they are set to the maximum.
+ ///
+ /// # Arguments
+ ///
+ /// * `min` - A reference to a `Point` representing the minimum allowable coordinates.
+ /// * `max` - A reference to a `Point` representing the maximum allowable coordinates.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::Point;
+ /// let p = Point { x: 10, y: 20 };
+ /// let min = Point { x: 0, y: 5 };
+ /// let max = Point { x: 15, y: 25 };
+ /// let clamped_p = p.clamp(&min, &max);
+ /// assert_eq!(clamped_p, Point { x: 10, y: 20 });
+ ///
+ /// let p_out_of_bounds = Point { x: -5, y: 30 };
+ /// let clamped_p_out_of_bounds = p_out_of_bounds.clamp(&min, &max);
+ /// assert_eq!(clamped_p_out_of_bounds, Point { x: 0, y: 25 });
+ /// ```
pub fn clamp(&self, min: &Self, max: &Self) -> Self {
self.max(min).min(max)
}
@@ -139,6 +279,10 @@ impl<T: Clone + Default + Debug> Clone for Point<T> {
}
}
+/// A structure representing a two-dimensional size with width and height in a given unit.
+///
+/// This struct is generic over the type `T`, which can be any type that implements `Clone`, `Default`, and `Debug`.
+/// It is commonly used to specify dimensions for elements in a UI, such as a window or element.
#[derive(Refineable, Default, Clone, Copy, PartialEq, Div, Hash, Serialize, Deserialize)]
#[refineable(Debug)]
#[repr(C)]
@@ -147,6 +291,21 @@ pub struct Size<T: Clone + Default + Debug> {
pub height: T,
}
+/// Constructs a new `Size<T>` with the provided width and height.
+///
+/// # Arguments
+///
+/// * `width` - The width component of the `Size`.
+/// * `height` - The height component of the `Size`.
+///
+/// # Examples
+///
+/// ```
+/// # use zed::Size;
+/// let my_size = size(10, 20);
+/// assert_eq!(my_size.width, 10);
+/// assert_eq!(my_size.height, 20);
+/// ```
pub fn size<T>(width: T, height: T) -> Size<T>
where
T: Clone + Default + Debug,
@@ -158,6 +317,24 @@ impl<T> Size<T>
where
T: Clone + Default + Debug,
{
+ /// Applies a function to the width and height of the size, producing a new `Size<U>`.
+ ///
+ /// This method allows for converting a `Size<T>` to a `Size<U>` by specifying a closure
+ /// that defines how to convert between the two types. The closure is applied to both the `width`
+ /// and `height`, resulting in a new size of the desired type.
+ ///
+ /// # Arguments
+ ///
+ /// * `f` - A closure that takes a value of type `T` and returns a value of type `U`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::Size;
+ /// let my_size = Size { width: 10, height: 20 };
+ /// let my_new_size = my_size.map(|dimension| dimension as f32 * 1.5);
+ /// assert_eq!(my_new_size, Size { width: 15.0, height: 30.0 });
+ /// ```
pub fn map<U>(&self, f: impl Fn(T) -> U) -> Size<U>
where
U: Clone + Default + Debug,
@@ -170,6 +347,24 @@ where
}
impl Size<Pixels> {
+ /// Scales the size by a given factor.
+ ///
+ /// This method multiplies both the width and height by the provided scaling factor,
+ /// resulting in a new `Size<ScaledPixels>` that is proportionally larger or smaller
+ /// depending on the factor.
+ ///
+ /// # Arguments
+ ///
+ /// * `factor` - The scaling factor to apply to the width and height.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Size, Pixels, ScaledPixels};
+ /// let size = Size { width: Pixels(100.0), height: Pixels(50.0) };
+ /// let scaled_size = size.scale(2.0);
+ /// assert_eq!(scaled_size, Size { width: ScaledPixels(200.0), height: ScaledPixels(100.0) });
+ /// ```
pub fn scale(&self, factor: f32) -> Size<ScaledPixels> {
Size {
width: self.width.scale(factor),
@@ -182,6 +377,21 @@ impl<T> Size<T>
where
T: PartialOrd + Clone + Default + Debug,
{
+ /// Returns a new `Size` with the maximum width and height from `self` and `other`.
+ ///
+ /// # Arguments
+ ///
+ /// * `other` - A reference to another `Size` to compare with `self`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::Size;
+ /// let size1 = Size { width: 30, height: 40 };
+ /// let size2 = Size { width: 50, height: 20 };
+ /// let max_size = size1.max(&size2);
+ /// assert_eq!(max_size, Size { width: 50, height: 40 });
+ /// ```
pub fn max(&self, other: &Self) -> Self {
Size {
width: if self.width >= other.width {
@@ -286,6 +496,14 @@ impl From<Size<Pixels>> for Size<AbsoluteLength> {
}
impl Size<Length> {
+ /// Returns a `Size` with both width and height set to fill the available space.
+ ///
+ /// This function creates a `Size` instance where both the width and height are set to `Length::Definite(DefiniteLength::Fraction(1.0))`,
+ /// which represents 100% of the available space in both dimensions.
+ ///
+ /// # Returns
+ ///
+ /// A `Size<Length>` that will fill the available space when used in a layout.
pub fn full() -> Self {
Self {
width: relative(1.).into(),
@@ -294,16 +512,16 @@ impl Size<Length> {
}
}
-impl Size<DefiniteLength> {
- pub fn zero() -> Self {
- Self {
- width: px(0.).into(),
- height: px(0.).into(),
- }
- }
-}
-
impl Size<Length> {
+ /// Returns a `Size` with both width and height set to `auto`, which allows the layout engine to determine the size.
+ ///
+ /// This function creates a `Size` instance where both the width and height are set to `Length::Auto`,
+ /// indicating that their size should be computed based on the layout context, such as the content size or
+ /// available space.
+ ///
+ /// # Returns
+ ///
+ /// A `Size<Length>` with width and height set to `Length::Auto`.
pub fn auto() -> Self {
Self {
width: Length::Auto,
@@ -312,6 +530,23 @@ impl Size<Length> {
}
}
+/// Represents a rectangular area in a 2D space with an origin point and a size.
+///
+/// The `Bounds` struct is generic over a type `T` which represents the type of the coordinate system.
+/// The origin is represented as a `Point<T>` which defines the upper-left corner of the rectangle,
+/// and the size is represented as a `Size<T>` which defines the width and height of the rectangle.
+///
+/// # Examples
+///
+/// ```
+/// # use zed::{Bounds, Point, Size};
+/// let origin = Point { x: 0, y: 0 };
+/// let size = Size { width: 10, height: 20 };
+/// let bounds = Bounds::new(origin, size);
+///
+/// assert_eq!(bounds.origin, origin);
+/// assert_eq!(bounds.size, size);
+/// ```
#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
#[refineable(Debug)]
#[repr(C)]
@@ -324,6 +559,33 @@ impl<T> Bounds<T>
where
T: Clone + Debug + Sub<Output = T> + Default,
{
+ /// Constructs a `Bounds` from two corner points: the upper-left and lower-right corners.
+ ///
+ /// This function calculates the origin and size of the `Bounds` based on the provided corner points.
+ /// The origin is set to the upper-left corner, and the size is determined by the difference between
+ /// the x and y coordinates of the lower-right and upper-left points.
+ ///
+ /// # Arguments
+ ///
+ /// * `upper_left` - A `Point<T>` representing the upper-left corner of the rectangle.
+ /// * `lower_right` - A `Point<T>` representing the lower-right corner of the rectangle.
+ ///
+ /// # Returns
+ ///
+ /// Returns a `Bounds<T>` that encompasses the area defined by the two corner points.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Bounds, Point};
+ /// let upper_left = Point { x: 0, y: 0 };
+ /// let lower_right = Point { x: 10, y: 10 };
+ /// let bounds = Bounds::from_corners(upper_left, lower_right);
+ ///
+ /// assert_eq!(bounds.origin, upper_left);
+ /// assert_eq!(bounds.size.width, 10);
+ /// assert_eq!(bounds.size.height, 10);
+ /// ```
pub fn from_corners(upper_left: Point<T>, lower_right: Point<T>) -> Self {
let origin = Point {
x: upper_left.x.clone(),
@@ -336,6 +598,16 @@ where
Bounds { origin, size }
}
+ /// 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 }
}
@@ -345,6 +617,39 @@ impl<T> Bounds<T>
where
T: Clone + Debug + PartialOrd + Add<T, Output = T> + Sub<Output = T> + Default + Half,
{
+ /// Checks if this `Bounds` intersects with another `Bounds`.
+ ///
+ /// Two `Bounds` instances intersect if they overlap in the 2D space they occupy.
+ /// This method checks if there is any overlapping area between the two bounds.
+ ///
+ /// # Arguments
+ ///
+ /// * `other` - A reference to another `Bounds` to check for intersection with.
+ ///
+ /// # Returns
+ ///
+ /// Returns `true` if there is any intersection between the two bounds, `false` otherwise.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Bounds, Point, Size};
+ /// let bounds1 = Bounds {
+ /// origin: Point { x: 0, y: 0 },
+ /// size: Size { width: 10, height: 10 },
+ /// };
+ /// let bounds2 = Bounds {
+ /// origin: Point { x: 5, y: 5 },
+ /// size: Size { width: 10, height: 10 },
+ /// };
+ /// let bounds3 = Bounds {
+ /// origin: Point { x: 20, y: 20 },
+ /// size: Size { width: 10, height: 10 },
+ /// };
+ ///
+ /// assert_eq!(bounds1.intersects(&bounds2), true); // Overlapping bounds
+ /// assert_eq!(bounds1.intersects(&bounds3), false); // Non-overlapping bounds
+ /// ```
pub fn intersects(&self, other: &Bounds<T>) -> bool {
let my_lower_right = self.lower_right();
let their_lower_right = other.lower_right();
@@ -355,6 +660,32 @@ where
&& my_lower_right.y > other.origin.y
}
+ /// Dilates the bounds by a specified amount in all directions.
+ ///
+ /// 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 zed::{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();
@@ -363,6 +694,27 @@ where
self.size.height = self.size.height.clone() + double_amount;
}
+ /// 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
+ /// of the bounds, respectively. The center is represented as a `Point<T>` where `T` is the type of the
+ /// coordinate system.
+ ///
+ /// # Returns
+ ///
+ /// A `Point<T>` representing the center of the bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Bounds, Point, Size};
+ /// let bounds = Bounds {
+ /// origin: Point { x: 0, y: 0 },
+ /// size: Size { width: 10, height: 20 },
+ /// };
+ /// let center = bounds.center();
+ /// assert_eq!(center, Point { x: 5, y: 10 });
+ /// ```
pub fn center(&self) -> Point<T> {
Point {
x: self.origin.x.clone() + self.size.width.clone().half(),
@@ -372,12 +724,78 @@ where
}
impl<T: Clone + Default + Debug + PartialOrd + Add<T, Output = T> + Sub<Output = T>> Bounds<T> {
+ /// Calculates the intersection of two `Bounds` objects.
+ ///
+ /// This method computes the overlapping region of two `Bounds`. If the bounds do not intersect,
+ /// the resulting `Bounds` will have a size with width and height of zero.
+ ///
+ /// # Arguments
+ ///
+ /// * `other` - A reference to another `Bounds` to intersect with.
+ ///
+ /// # Returns
+ ///
+ /// Returns a `Bounds` representing the intersection area. If there is no intersection,
+ /// the returned `Bounds` will have a size with width and height of zero.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Bounds, Point, Size};
+ /// let bounds1 = Bounds {
+ /// origin: Point { x: 0, y: 0 },
+ /// size: Size { width: 10, height: 10 },
+ /// };
+ /// let bounds2 = Bounds {
+ /// origin: Point { x: 5, y: 5 },
+ /// size: Size { width: 10, height: 10 },
+ /// };
+ /// let intersection = bounds1.intersect(&bounds2);
+ ///
+ /// assert_eq!(intersection, Bounds {
+ /// origin: Point { x: 5, y: 5 },
+ /// size: Size { width: 5, height: 5 },
+ /// });
+ /// ```
pub fn intersect(&self, other: &Self) -> Self {
let upper_left = self.origin.max(&other.origin);
let lower_right = self.lower_right().min(&other.lower_right());
Self::from_corners(upper_left, lower_right)
}
+ /// Computes the union of two `Bounds`.
+ ///
+ /// This method calculates the smallest `Bounds` that contains both the current `Bounds` and the `other` `Bounds`.
+ /// The resulting `Bounds` will have an origin that is the minimum of the origins of the two `Bounds`,
+ /// and a size that encompasses the furthest extents of both `Bounds`.
+ ///
+ /// # Arguments
+ ///
+ /// * `other` - A reference to another `Bounds` to create a union with.
+ ///
+ /// # Returns
+ ///
+ /// Returns a `Bounds` representing the union of the two `Bounds`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Bounds, Point, Size};
+ /// let bounds1 = Bounds {
+ /// origin: Point { x: 0, y: 0 },
+ /// size: Size { width: 10, height: 10 },
+ /// };
+ /// let bounds2 = Bounds {
+ /// origin: Point { x: 5, y: 5 },
+ /// size: Size { width: 15, height: 15 },
+ /// };
+ /// let union_bounds = bounds1.union(&bounds2);
+ ///
+ /// assert_eq!(union_bounds, Bounds {
+ /// origin: Point { x: 0, y: 0 },
+ /// size: Size { width: 20, height: 20 },
+ /// });
+ /// ```
pub fn union(&self, other: &Self) -> Self {
let top_left = self.origin.min(&other.origin);
let bottom_right = self.lower_right().max(&other.lower_right());
@@ -432,22 +850,59 @@ impl<T> Bounds<T>
where
T: Add<T, Output = T> + Clone + Default + Debug,
{
+ /// Returns the top edge of the bounds.
+ ///
+ /// # Returns
+ ///
+ /// A value of type `T` representing the y-coordinate of the top edge of the bounds.
pub fn top(&self) -> T {
self.origin.y.clone()
}
+ /// Returns the bottom edge of the bounds.
+ ///
+ /// # Returns
+ ///
+ /// A value of type `T` representing the y-coordinate of the bottom edge of the bounds.
pub fn bottom(&self) -> T {
self.origin.y.clone() + self.size.height.clone()
}
+ /// Returns the left edge of the bounds.
+ ///
+ /// # Returns
+ ///
+ /// A value of type `T` representing the x-coordinate of the left edge of the bounds.
pub fn left(&self) -> T {
self.origin.x.clone()
}
+ /// Returns the right edge of the bounds.
+ ///
+ /// # Returns
+ ///
+ /// A value of type `T` representing the x-coordinate of the right edge of the bounds.
pub fn right(&self) -> T {
self.origin.x.clone() + self.size.width.clone()
}
+ /// Returns the upper-right corner point of the bounds.
+ ///
+ /// # Returns
+ ///
+ /// A `Point<T>` representing the upper-right corner of the bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Bounds, Point, Size};
+ /// let bounds = Bounds {
+ /// origin: Point { x: 0, y: 0 },
+ /// size: Size { width: 10, height: 20 },
+ /// };
+ /// let upper_right = bounds.upper_right();
+ /// assert_eq!(upper_right, Point { x: 10, y: 0 });
+ /// ```
pub fn upper_right(&self) -> Point<T> {
Point {
x: self.origin.x.clone() + self.size.width.clone(),
@@ -455,6 +910,23 @@ where
}
}
+ /// Returns the lower-right corner point of the bounds.
+ ///
+ /// # Returns
+ ///
+ /// A `Point<T>` representing the lower-right corner of the bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Bounds, Point, Size};
+ /// let bounds = Bounds {
+ /// origin: Point { x: 0, y: 0 },
+ /// size: Size { width: 10, height: 20 },
+ /// };
+ /// let lower_right = bounds.lower_right();
+ /// assert_eq!(lower_right, Point { x: 10, y: 20 });
+ /// ```
pub fn lower_right(&self) -> Point<T> {
Point {
x: self.origin.x.clone() + self.size.width.clone(),
@@ -462,6 +934,23 @@ where
}
}
+ /// Returns the lower-left corner point of the bounds.
+ ///
+ /// # Returns
+ ///
+ /// A `Point<T>` representing the lower-left corner of the bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Bounds, Point, Size};
+ /// let bounds = Bounds {
+ /// origin: Point { x: 0, y: 0 },
+ /// size: Size { width: 10, height: 20 },
+ /// };
+ /// let lower_left = bounds.lower_left();
+ /// assert_eq!(lower_left, Point { x: 0, y: 20 });
+ /// ```
pub fn lower_left(&self) -> Point<T> {
Point {
x: self.origin.x.clone(),
@@ -474,6 +963,35 @@ impl<T> Bounds<T>
where
T: Add<T, Output = T> + PartialOrd + Clone + Default + Debug,
{
+ /// Checks if the given point is within the bounds.
+ ///
+ /// This method determines whether a point lies inside the rectangle defined by the bounds,
+ /// including the edges. The point is considered inside if its x-coordinate is greater than
+ /// or equal to the left edge and less than or equal to the right edge, and its y-coordinate
+ /// is greater than or equal to the top edge and less than or equal to the bottom edge of the bounds.
+ ///
+ /// # Arguments
+ ///
+ /// * `point` - A reference to a `Point<T>` that represents the point to check.
+ ///
+ /// # Returns
+ ///
+ /// Returns `true` if the point is within the bounds, `false` otherwise.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Point, Bounds};
+ /// let bounds = Bounds {
+ /// origin: Point { x: 0, y: 0 },
+ /// size: Size { width: 10, height: 10 },
+ /// };
+ /// let inside_point = Point { x: 5, y: 5 };
+ /// let outside_point = Point { x: 15, y: 15 };
+ ///
+ /// assert!(bounds.contains_point(&inside_point));
+ /// assert!(!bounds.contains_point(&outside_point));
+ /// ```
pub fn contains_point(&self, point: &Point<T>) -> bool {
point.x >= self.origin.x
&& point.x <= self.origin.x.clone() + self.size.width.clone()
@@ -481,6 +999,34 @@ where
&& point.y <= self.origin.y.clone() + self.size.height.clone()
}
+ /// Applies a function to the origin and size of the bounds, producing a new `Bounds<U>`.
+ ///
+ /// This method allows for converting a `Bounds<T>` to a `Bounds<U>` by specifying a closure
+ /// that defines how to convert between the two types. The closure is applied to the `origin` and
+ /// `size` fields, resulting in new bounds of the desired type.
+ ///
+ /// # Arguments
+ ///
+ /// * `f` - A closure that takes a value of type `T` and returns a value of type `U`.
+ ///
+ /// # Returns
+ ///
+ /// Returns a new `Bounds<U>` with the origin and size mapped by the provided function.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Bounds, Point, Size};
+ /// let bounds = Bounds {
+ /// origin: Point { x: 10.0, y: 10.0 },
+ /// size: Size { width: 10.0, height: 20.0 },
+ /// };
+ /// let new_bounds = bounds.map(|value| value as f64 * 1.5);
+ ///
+ /// assert_eq!(new_bounds, Bounds {
+ /// origin: Point { x: 15.0, y: 15.0 },
+ /// size: Size { width: 15.0, height: 30.0 },
+ /// });
pub fn map<U>(&self, f: impl Fn(T) -> U) -> Bounds<U>
where
U: Clone + Default + Debug,
@@ -493,6 +1039,36 @@ where
}
impl Bounds<Pixels> {
+ /// Scales the bounds by a given factor, typically used to adjust for display scaling.
+ ///
+ /// This method multiplies the origin and size of the bounds by the provided scaling factor,
+ /// resulting in a new `Bounds<ScaledPixels>` that is proportionally larger or smaller
+ /// depending on the scaling factor. This can be used to ensure that the bounds are properly
+ /// scaled for different display densities.
+ ///
+ /// # Arguments
+ ///
+ /// * `factor` - The scaling factor to apply to the origin and size, typically the display's scaling factor.
+ ///
+ /// # Returns
+ ///
+ /// Returns a new `Bounds<ScaledPixels>` that represents the scaled bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::{Bounds, Point, Size, Pixels};
+ /// let bounds = Bounds {
+ /// origin: Point { x: Pixels(10.0), y: Pixels(20.0) },
+ /// size: Size { width: Pixels(30.0), height: Pixels(40.0) },
+ /// };
+ /// let display_scale_factor = 2.0;
+ /// let scaled_bounds = bounds.scale(display_scale_factor);
+ /// assert_eq!(scaled_bounds, Bounds {
+ /// origin: Point { x: ScaledPixels(20.0), y: ScaledPixels(40.0) },
+ /// size: Size { width: ScaledPixels(60.0), height: ScaledPixels(80.0) },
+ /// });
+ /// ```
pub fn scale(&self, factor: f32) -> Bounds<ScaledPixels> {
Bounds {
origin: self.origin.scale(factor),
@@ -503,6 +1079,26 @@ impl Bounds<Pixels> {
impl<T: Clone + Debug + Copy + Default> Copy for Bounds<T> {}
+/// Represents the edges of a box in a 2D space, such as padding or margin.
+///
+/// Each field represents the size of the edge on one side of the box: `top`, `right`, `bottom`, and `left`.
+///
+/// # Examples
+///
+/// ```
+/// # use zed::Edges;
+/// let edges = Edges {
+/// top: 10.0,
+/// right: 20.0,
+/// bottom: 30.0,
+/// left: 40.0,
+/// };
+///
+/// assert_eq!(edges.top, 10.0);
+/// assert_eq!(edges.right, 20.0);
+/// assert_eq!(edges.bottom, 30.0);
+/// assert_eq!(edges.left, 40.0);
+/// ```
#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
#[refineable(Debug)]
#[repr(C)]
@@ -545,6 +1141,30 @@ where
impl<T: Clone + Default + Debug + Copy> Copy for Edges<T> {}
impl<T: Clone + Default + Debug> Edges<T> {
+ /// Constructs `Edges` where all sides are set to the same specified value.
+ ///
+ /// This function creates an `Edges` instance with the `top`, `right`, `bottom`, and `left` fields all initialized
+ /// to the same value provided as an argument. This is useful when you want to have uniform edges around a box,
+ /// such as padding or margin with the same size on all sides.
+ ///
+ /// # Arguments
+ ///
+ /// * `value` - The value to set for all four sides of the edges.
+ ///
+ /// # Returns
+ ///
+ /// An `Edges` instance with all sides set to the given value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::Edges;
+ /// let uniform_edges = Edges::all(10.0);
+ /// assert_eq!(uniform_edges.top, 10.0);
+ /// assert_eq!(uniform_edges.right, 10.0);
+ /// assert_eq!(uniform_edges.bottom, 10.0);
+ /// assert_eq!(uniform_edges.left, 10.0);
+ /// ```
pub fn all(value: T) -> Self {
Self {
top: value.clone(),
@@ -554,6 +1174,28 @@ impl<T: Clone + Default + Debug> Edges<T> {
}
}
+ /// Applies a function to each field of the `Edges`, producing a new `Edges<U>`.
+ ///
+ /// This method allows for converting an `Edges<T>` to an `Edges<U>` by specifying a closure
+ /// that defines how to convert between the two types. The closure is applied to each field
+ /// (`top`, `right`, `bottom`, `left`), resulting in new edges of the desired type.
+ ///
+ /// # Arguments
+ ///
+ /// * `f` - A closure that takes a reference to a value of type `T` and returns a value of type `U`.
+ ///
+ /// # Returns
+ ///
+ /// Returns a new `Edges<U>` with each field mapped by the provided function.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::Edges;
+ /// let edges = Edges { top: 10, right: 20, bottom: 30, left: 40 };
+ /// let edges_float = edges.map(|&value| value as f32 * 1.1);
+ /// assert_eq!(edges_float, Edges { top: 11.0, right: 22.0, bottom: 33.0, left: 44.0 });
+ /// ```
pub fn map<U>(&self, f: impl Fn(&T) -> U) -> Edges<U>
where
U: Clone + Default + Debug,
@@ -566,6 +1208,33 @@ impl<T: Clone + Default + Debug> Edges<T> {
}
}
+ /// Checks if any of the edges satisfy a given predicate.
+ ///
+ /// This method applies a predicate function to each field of the `Edges` and returns `true` if any field satisfies the predicate.
+ ///
+ /// # Arguments
+ ///
+ /// * `predicate` - A closure that takes a reference to a value of type `T` and returns a `bool`.
+ ///
+ /// # Returns
+ ///
+ /// Returns `true` if the predicate returns `true` for any of the edge values, `false` otherwise.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::Edges;
+ /// let edges = Edges {
+ /// top: 10,
+ /// right: 0,
+ /// bottom: 5,
+ /// left: 0,
+ /// };
+ ///
+ /// assert!(edges.any(|value| *value == 0));
+ /// assert!(edges.any(|value| *value > 0));
+ /// assert!(!edges.any(|value| *value > 10));
+ /// ```
pub fn any<F: Fn(&T) -> bool>(&self, predicate: F) -> bool {
predicate(&self.top)
|| predicate(&self.right)
@@ -575,6 +1244,24 @@ impl<T: Clone + Default + Debug> Edges<T> {
}
impl Edges<Length> {
+ /// Sets the edges of the `Edges` struct to `auto`, which is a special value that allows the layout engine to automatically determine the size of the edges.
+ ///
+ /// This is typically used in layout contexts where the exact size of the edges is not important, or when the size should be calculated based on the content or container.
+ ///
+ /// # Returns
+ ///
+ /// Returns an `Edges<Length>` with all edges set to `Length::Auto`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::Edges;
+ /// let auto_edges = Edges::auto();
+ /// assert_eq!(auto_edges.top, Length::Auto);
+ /// assert_eq!(auto_edges.right, Length::Auto);
+ /// assert_eq!(auto_edges.bottom, Length::Auto);
+ /// assert_eq!(auto_edges.left, Length::Auto);
+ /// ```
pub fn auto() -> Self {
Self {
top: Length::Auto,
@@ -584,6 +1271,25 @@ impl Edges<Length> {
}
}
+ /// Sets the edges of the `Edges` struct to zero, which means no size or thickness.
+ ///
+ /// This is typically used when you want to specify that a box (like a padding or margin area)
+ /// should have no edges, effectively making it non-existent or invisible in layout calculations.
+ ///
+ /// # Returns
+ ///
+ /// Returns an `Edges<Length>` with all edges set to zero length.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use zed::Edges;
+ /// let no_edges = Edges::zero();
+ /// assert_eq!(no_edges.top, Length::Definite(DefiniteLength::from(Pixels(0.))));
+ /// assert_eq!(no_edges.right, Length::Definite(DefiniteLength::from(Pixels(0.))));
+ /// assert_eq!(no_edges.bottom, Length::Definite(DefiniteLength::from(Pixels(0.))));
+ /// assert_eq!(no_edges.left, Length::Definite(DefiniteLength::from(Pixels(0.))));
+ /// ```
pub fn zero() -> Self {
Self {
top: px(0.).into(),