Skip to main content

gpui_types/
layout.rs

1//! Layout-space primitives and conversions to [`taffy`] types.
2//!
3//! These live here because Rust's orphan rules require `From` impls that bridge
4//! two foreign types to be defined in the crate that owns one of them. Now that
5//! [`Point`] and [`Size`] live in this crate, the conversions between them and
6//! taffy's geometry types must be defined here too.
7
8use core::fmt::Debug;
9
10use taffy::{
11    geometry::{Point as TaffyPoint, Size as TaffySize},
12    style::AvailableSpace as TaffyAvailableSpace,
13};
14
15use crate::{Pixels, Point, Size};
16
17impl<T, T2> From<TaffyPoint<T>> for Point<T2>
18where
19    T: Into<T2>,
20    T2: Clone + Debug + Default + PartialEq,
21{
22    fn from(point: TaffyPoint<T>) -> Point<T2> {
23        Point {
24            x: point.x.into(),
25            y: point.y.into(),
26        }
27    }
28}
29
30impl<T, T2> From<Point<T>> for TaffyPoint<T2>
31where
32    T: Into<T2> + Clone + Debug + Default + PartialEq,
33{
34    fn from(val: Point<T>) -> Self {
35        TaffyPoint {
36            x: val.x.into(),
37            y: val.y.into(),
38        }
39    }
40}
41
42impl<T, U> From<TaffySize<T>> for Size<U>
43where
44    T: Into<U>,
45    U: Clone + Debug + Default + PartialEq,
46{
47    fn from(taffy_size: TaffySize<T>) -> Self {
48        Size {
49            width: taffy_size.width.into(),
50            height: taffy_size.height.into(),
51        }
52    }
53}
54
55impl<T, U> From<Size<T>> for TaffySize<U>
56where
57    T: Into<U> + Clone + Debug + Default + PartialEq,
58{
59    fn from(size: Size<T>) -> Self {
60        TaffySize {
61            width: size.width.into(),
62            height: size.height.into(),
63        }
64    }
65}
66
67/// The space available for an element to be laid out in
68#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
69pub enum AvailableSpace {
70    /// The amount of space available is the specified number of pixels
71    Definite(Pixels),
72    /// The amount of space available is indefinite and the node should be laid out under a min-content constraint
73    #[default]
74    MinContent,
75    /// The amount of space available is indefinite and the node should be laid out under a max-content constraint
76    MaxContent,
77}
78
79impl AvailableSpace {
80    /// Returns a `Size` with both width and height set to `AvailableSpace::MinContent`.
81    ///
82    /// This function is useful when you want to create a `Size` with the minimum content constraints
83    /// for both dimensions.
84    pub const fn min_size() -> Size<Self> {
85        Size {
86            width: Self::MinContent,
87            height: Self::MinContent,
88        }
89    }
90}
91
92impl From<AvailableSpace> for TaffyAvailableSpace {
93    fn from(space: AvailableSpace) -> TaffyAvailableSpace {
94        match space {
95            AvailableSpace::Definite(Pixels(value)) => TaffyAvailableSpace::Definite(value),
96            AvailableSpace::MinContent => TaffyAvailableSpace::MinContent,
97            AvailableSpace::MaxContent => TaffyAvailableSpace::MaxContent,
98        }
99    }
100}
101
102impl From<TaffyAvailableSpace> for AvailableSpace {
103    fn from(space: TaffyAvailableSpace) -> AvailableSpace {
104        match space {
105            TaffyAvailableSpace::Definite(value) => AvailableSpace::Definite(Pixels(value)),
106            TaffyAvailableSpace::MinContent => AvailableSpace::MinContent,
107            TaffyAvailableSpace::MaxContent => AvailableSpace::MaxContent,
108        }
109    }
110}
111
112impl From<Pixels> for AvailableSpace {
113    fn from(pixels: Pixels) -> Self {
114        AvailableSpace::Definite(pixels)
115    }
116}
117
118impl From<Size<Pixels>> for Size<AvailableSpace> {
119    fn from(size: Size<Pixels>) -> Self {
120        Size {
121            width: AvailableSpace::Definite(size.width),
122            height: AvailableSpace::Definite(size.height),
123        }
124    }
125}