taffy.rs

  1use super::{
  2    AbsoluteLength, Bounds, DefiniteLength, Edges, Layout, Length, Pixels, Point, Result, Size,
  3    Style,
  4};
  5use std::fmt::Debug;
  6pub use taffy::tree::NodeId as LayoutId;
  7pub use taffy::*;
  8pub struct TaffyLayoutEngine(Taffy);
  9
 10impl TaffyLayoutEngine {
 11    pub fn new() -> Self {
 12        TaffyLayoutEngine(Taffy::new())
 13    }
 14
 15    pub fn request_layout(
 16        &mut self,
 17        style: Style,
 18        rem_size: Pixels,
 19        children: &[LayoutId],
 20    ) -> Result<LayoutId> {
 21        let style = style.to_taffy(rem_size);
 22        if children.is_empty() {
 23            Ok(self.0.new_leaf(style)?)
 24        } else {
 25            Ok(self.0.new_with_children(style, children)?)
 26        }
 27    }
 28
 29    pub fn layout(&mut self, id: LayoutId) -> Result<Layout> {
 30        Ok(self.0.layout(id).map(Into::into)?)
 31    }
 32}
 33
 34trait ToTaffy<Output> {
 35    fn to_taffy(&self, rem_size: Pixels) -> Output;
 36}
 37
 38impl ToTaffy<taffy::style::Style> for Style {
 39    fn to_taffy(&self, rem_size: Pixels) -> taffy::style::Style {
 40        taffy::style::Style {
 41            display: self.display,
 42            overflow: self.overflow.clone().into(),
 43            scrollbar_width: self.scrollbar_width,
 44            position: self.position,
 45            inset: self.inset.to_taffy(rem_size),
 46            size: self.size.to_taffy(rem_size),
 47            min_size: self.min_size.to_taffy(rem_size),
 48            max_size: self.max_size.to_taffy(rem_size),
 49            aspect_ratio: self.aspect_ratio,
 50            margin: self.margin.to_taffy(rem_size),
 51            padding: self.padding.to_taffy(rem_size),
 52            border: self.border_widths.to_taffy(rem_size),
 53            align_items: self.align_items,
 54            align_self: self.align_self,
 55            align_content: self.align_content,
 56            justify_content: self.justify_content,
 57            gap: self.gap.to_taffy(rem_size),
 58            flex_direction: self.flex_direction,
 59            flex_wrap: self.flex_wrap,
 60            flex_basis: self.flex_basis.to_taffy(rem_size),
 61            flex_grow: self.flex_grow,
 62            flex_shrink: self.flex_shrink,
 63            ..Default::default() // Ignore grid properties for now
 64        }
 65    }
 66}
 67
 68// impl ToTaffy for Bounds<Length> {
 69//     type Output = taffy::prelude::Bounds<taffy::prelude::LengthPercentageAuto>;
 70
 71//     fn to_taffy(
 72//         &self,
 73//         rem_size: Pixels,
 74//     ) -> taffy::prelude::Bounds<taffy::prelude::LengthPercentageAuto> {
 75//         taffy::prelude::Bounds {
 76//             origin: self.origin.to_taffy(rem_size),
 77//             size: self.size.to_taffy(rem_size),
 78//         }
 79//     }
 80// }
 81
 82impl ToTaffy<taffy::style::LengthPercentageAuto> for Length {
 83    fn to_taffy(&self, rem_size: Pixels) -> taffy::prelude::LengthPercentageAuto {
 84        match self {
 85            Length::Definite(length) => length.to_taffy(rem_size),
 86            Length::Auto => taffy::prelude::LengthPercentageAuto::Auto,
 87        }
 88    }
 89}
 90
 91impl ToTaffy<taffy::style::Dimension> for Length {
 92    fn to_taffy(&self, rem_size: Pixels) -> taffy::prelude::Dimension {
 93        match self {
 94            Length::Definite(length) => length.to_taffy(rem_size),
 95            Length::Auto => taffy::prelude::Dimension::Auto,
 96        }
 97    }
 98}
 99
100impl ToTaffy<taffy::style::LengthPercentage> for DefiniteLength {
101    fn to_taffy(&self, rem_size: Pixels) -> taffy::style::LengthPercentage {
102        match self {
103            DefiniteLength::Absolute(length) => match length {
104                AbsoluteLength::Pixels(pixels) => {
105                    taffy::style::LengthPercentage::Length(pixels.into())
106                }
107                AbsoluteLength::Rems(rems) => {
108                    taffy::style::LengthPercentage::Length((*rems * rem_size).into())
109                }
110            },
111            DefiniteLength::Fraction(fraction) => {
112                taffy::style::LengthPercentage::Percent(*fraction)
113            }
114        }
115    }
116}
117
118impl ToTaffy<taffy::style::LengthPercentageAuto> for DefiniteLength {
119    fn to_taffy(&self, rem_size: Pixels) -> taffy::style::LengthPercentageAuto {
120        match self {
121            DefiniteLength::Absolute(length) => match length {
122                AbsoluteLength::Pixels(pixels) => {
123                    taffy::style::LengthPercentageAuto::Length(pixels.into())
124                }
125                AbsoluteLength::Rems(rems) => {
126                    taffy::style::LengthPercentageAuto::Length((*rems * rem_size).into())
127                }
128            },
129            DefiniteLength::Fraction(fraction) => {
130                taffy::style::LengthPercentageAuto::Percent(*fraction)
131            }
132        }
133    }
134}
135
136impl ToTaffy<taffy::style::Dimension> for DefiniteLength {
137    fn to_taffy(&self, rem_size: Pixels) -> taffy::style::Dimension {
138        match self {
139            DefiniteLength::Absolute(length) => match length {
140                AbsoluteLength::Pixels(pixels) => taffy::style::Dimension::Length(pixels.into()),
141                AbsoluteLength::Rems(rems) => {
142                    taffy::style::Dimension::Length((*rems * rem_size).into())
143                }
144            },
145            DefiniteLength::Fraction(fraction) => taffy::style::Dimension::Percent(*fraction),
146        }
147    }
148}
149
150impl ToTaffy<taffy::style::LengthPercentage> for AbsoluteLength {
151    fn to_taffy(&self, rem_size: Pixels) -> taffy::style::LengthPercentage {
152        match self {
153            AbsoluteLength::Pixels(pixels) => taffy::style::LengthPercentage::Length(pixels.into()),
154            AbsoluteLength::Rems(rems) => {
155                taffy::style::LengthPercentage::Length((*rems * rem_size).into())
156            }
157        }
158    }
159}
160
161impl<T, T2: Clone + Debug> From<taffy::geometry::Point<T>> for Point<T2>
162where
163    T: Into<T2>,
164{
165    fn from(point: taffy::geometry::Point<T>) -> Point<T2> {
166        Point {
167            x: point.x.into(),
168            y: point.y.into(),
169        }
170    }
171}
172
173impl<T: Clone + Debug, T2> Into<taffy::geometry::Point<T2>> for Point<T>
174where
175    T: Into<T2>,
176{
177    fn into(self) -> taffy::geometry::Point<T2> {
178        taffy::geometry::Point {
179            x: self.x.into(),
180            y: self.y.into(),
181        }
182    }
183}
184
185impl<T: ToTaffy<U> + Clone + Debug, U> ToTaffy<taffy::geometry::Size<U>> for Size<T> {
186    fn to_taffy(&self, rem_size: Pixels) -> taffy::geometry::Size<U> {
187        taffy::geometry::Size {
188            width: self.width.to_taffy(rem_size).into(),
189            height: self.height.to_taffy(rem_size).into(),
190        }
191    }
192}
193
194impl<T, U> ToTaffy<taffy::geometry::Rect<U>> for Edges<T>
195where
196    T: ToTaffy<U> + Clone + Debug,
197{
198    fn to_taffy(&self, rem_size: Pixels) -> taffy::geometry::Rect<U> {
199        taffy::geometry::Rect {
200            top: self.top.to_taffy(rem_size).into(),
201            right: self.right.to_taffy(rem_size).into(),
202            bottom: self.bottom.to_taffy(rem_size).into(),
203            left: self.left.to_taffy(rem_size).into(),
204        }
205    }
206}
207
208impl<S, T: Clone + Default + Debug> From<taffy::geometry::Size<S>> for Size<T>
209where
210    S: Into<T>,
211{
212    fn from(value: taffy::geometry::Size<S>) -> Self {
213        Self {
214            width: value.width.into(),
215            height: value.height.into(),
216        }
217    }
218}
219
220impl From<&taffy::tree::Layout> for Layout {
221    fn from(layout: &taffy::tree::Layout) -> Self {
222        Layout {
223            order: layout.order,
224            bounds: Bounds {
225                origin: layout.location.into(),
226                size: layout.size.into(),
227            },
228        }
229    }
230}
231
232impl From<f32> for Pixels {
233    fn from(pixels: f32) -> Self {
234        Pixels(pixels)
235    }
236}