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}