Skip to main content

dc_layout/
styles.rs

1// Copyright 2024 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::into_taffy::TryIntoTaffy;
16use ::taffy::style_helpers::TaffyZero;
17use dc_bundle::{
18    positioning::{
19        item_spacing, AlignContent, AlignItems, AlignSelf, FlexDirection, ItemSpacing,
20        JustifyContent, PositionType,
21    },
22    Error,
23};
24use protobuf::MessageField;
25use taffy::prelude as taffy;
26
27impl TryIntoTaffy<taffy::AlignItems> for AlignItems {
28    type Error = dc_bundle::Error;
29    fn try_into_taffy(self) -> Result<taffy::AlignItems, Self::Error> {
30        match self {
31            AlignItems::ALIGN_ITEMS_CENTER => Ok(taffy::AlignItems::Center),
32            AlignItems::ALIGN_ITEMS_FLEX_START => Ok(taffy::AlignItems::FlexStart),
33            AlignItems::ALIGN_ITEMS_FLEX_END => Ok(taffy::AlignItems::FlexEnd),
34            AlignItems::ALIGN_ITEMS_BASELINE => Ok(taffy::AlignItems::Baseline),
35            AlignItems::ALIGN_ITEMS_STRETCH => Ok(taffy::AlignItems::Stretch),
36            AlignItems::ALIGN_ITEMS_UNSPECIFIED => {
37                Err(Error::UnknownEnumVariant { enum_name: "AlignItems".to_string() })
38            }
39        }
40    }
41}
42
43impl TryIntoTaffy<Option<taffy::AlignItems>> for AlignSelf {
44    type Error = dc_bundle::Error;
45    fn try_into_taffy(self) -> Result<Option<taffy::AlignItems>, Self::Error> {
46        match self {
47            AlignSelf::ALIGN_SELF_AUTO => Ok(None),
48            AlignSelf::ALIGN_SELF_FLEX_START => Ok(Some(taffy::AlignItems::FlexStart)),
49            AlignSelf::ALIGN_SELF_FLEX_END => Ok(Some(taffy::AlignItems::FlexEnd)),
50            AlignSelf::ALIGN_SELF_CENTER => Ok(Some(taffy::AlignItems::Center)),
51            AlignSelf::ALIGN_SELF_BASELINE => Ok(Some(taffy::AlignItems::Baseline)),
52            AlignSelf::ALIGN_SELF_STRETCH => Ok(Some(taffy::AlignItems::Stretch)),
53            AlignSelf::ALIGN_SELF_UNSPECIFIED => {
54                Err(Error::UnknownEnumVariant { enum_name: "AlignSelf".to_string() })
55            }
56        }
57    }
58}
59
60impl TryIntoTaffy<taffy::AlignContent> for AlignContent {
61    type Error = dc_bundle::Error;
62    fn try_into_taffy(self) -> Result<taffy::AlignContent, Self::Error> {
63        match self {
64            AlignContent::ALIGN_CONTENT_CENTER => Ok(taffy::AlignContent::Center),
65            AlignContent::ALIGN_CONTENT_FLEX_START => Ok(taffy::AlignContent::FlexStart),
66            AlignContent::ALIGN_CONTENT_FLEX_END => Ok(taffy::AlignContent::FlexEnd),
67            AlignContent::ALIGN_CONTENT_SPACE_AROUND => Ok(taffy::AlignContent::SpaceAround),
68            AlignContent::ALIGN_CONTENT_SPACE_BETWEEN => Ok(taffy::AlignContent::SpaceBetween),
69            AlignContent::ALIGN_CONTENT_STRETCH => Ok(taffy::AlignContent::Stretch),
70            AlignContent::ALIGN_CONTENT_UNSPECIFIED => {
71                Err(Error::UnknownEnumVariant { enum_name: "AlignContent".to_string() })
72            }
73        }
74    }
75}
76
77impl TryIntoTaffy<taffy::FlexDirection> for FlexDirection {
78    type Error = dc_bundle::Error;
79    fn try_into_taffy(self) -> Result<taffy::FlexDirection, Self::Error> {
80        match self {
81            FlexDirection::FLEX_DIRECTION_ROW => Ok(taffy::FlexDirection::Row),
82            FlexDirection::FLEX_DIRECTION_COLUMN => Ok(taffy::FlexDirection::Column),
83            FlexDirection::FLEX_DIRECTION_ROW_REVERSE => Ok(taffy::FlexDirection::RowReverse),
84            FlexDirection::FLEX_DIRECTION_COLUMN_REVERSE => Ok(taffy::FlexDirection::ColumnReverse),
85            FlexDirection::FLEX_DIRECTION_NONE => Ok(taffy::FlexDirection::Row),
86            FlexDirection::FLEX_DIRECTION_UNSPECIFIED => {
87                Err(Error::UnknownEnumVariant { enum_name: "FlexDirection".to_string() })
88            }
89        }
90    }
91}
92
93impl TryIntoTaffy<taffy::JustifyContent> for JustifyContent {
94    type Error = dc_bundle::Error;
95    fn try_into_taffy(self) -> Result<taffy::JustifyContent, Self::Error> {
96        match self {
97            JustifyContent::JUSTIFY_CONTENT_CENTER => Ok(taffy::JustifyContent::Center),
98            JustifyContent::JUSTIFY_CONTENT_FLEX_START => Ok(taffy::JustifyContent::FlexStart),
99            JustifyContent::JUSTIFY_CONTENT_FLEX_END => Ok(taffy::JustifyContent::FlexEnd),
100            JustifyContent::JUSTIFY_CONTENT_SPACE_AROUND => Ok(taffy::JustifyContent::SpaceAround),
101            JustifyContent::JUSTIFY_CONTENT_SPACE_BETWEEN => {
102                Ok(taffy::JustifyContent::SpaceBetween)
103            }
104            JustifyContent::JUSTIFY_CONTENT_SPACE_EVENLY => Ok(taffy::JustifyContent::SpaceEvenly),
105            JustifyContent::JUSTIFY_CONTENT_UNSPECIFIED => {
106                Err(Error::UnknownEnumVariant { enum_name: "JustifyContent".to_string() })
107            }
108        }
109    }
110}
111
112impl TryIntoTaffy<taffy::Position> for PositionType {
113    type Error = dc_bundle::Error;
114    fn try_into_taffy(self) -> Result<taffy::Position, Self::Error> {
115        match self {
116            PositionType::POSITION_TYPE_ABSOLUTE => Ok(taffy::Position::Absolute),
117            PositionType::POSITION_TYPE_RELATIVE => Ok(taffy::Position::Relative),
118            PositionType::POSITION_TYPE_UNSPECIFIED => {
119                Err(Error::UnknownEnumVariant { enum_name: "PositionType".to_string() })
120            }
121        }
122    }
123}
124impl TryIntoTaffy<taffy::LengthPercentage> for &MessageField<ItemSpacing> {
125    type Error = dc_bundle::Error;
126    fn try_into_taffy(self) -> Result<taffy::LengthPercentage, Self::Error> {
127        match self.as_ref() {
128            Some(spacing) => match spacing.ItemSpacingType {
129                Some(item_spacing::ItemSpacingType::Fixed(s)) => {
130                    Ok(taffy::LengthPercentage::Length(s as f32))
131                }
132                Some(item_spacing::ItemSpacingType::Auto(..)) => Ok(taffy::LengthPercentage::ZERO),
133                Some(_) => Err(dc_bundle::Error::UnknownEnumVariant {
134                    enum_name: "ItemSpacing".to_string(),
135                }),
136                None => Err(dc_bundle::Error::UnknownEnumVariant {
137                    enum_name: "ItemSpacing".to_string(),
138                }),
139            },
140            None => Err(Error::MissingFieldError { field: "ItemSpacing".to_string() }),
141        }
142    }
143}
144
145#[cfg(test)]
146mod tests {
147    use super::*;
148
149    #[test]
150    fn test_align_items_try_into_taffy() {
151        assert_eq!(
152            AlignItems::ALIGN_ITEMS_FLEX_START.try_into_taffy().unwrap(),
153            taffy::AlignItems::FlexStart
154        );
155        assert_eq!(
156            AlignItems::ALIGN_ITEMS_FLEX_END.try_into_taffy().unwrap(),
157            taffy::AlignItems::FlexEnd
158        );
159        assert_eq!(
160            AlignItems::ALIGN_ITEMS_CENTER.try_into_taffy().unwrap(),
161            taffy::AlignItems::Center
162        );
163        assert_eq!(
164            AlignItems::ALIGN_ITEMS_BASELINE.try_into_taffy().unwrap(),
165            taffy::AlignItems::Baseline
166        );
167        assert_eq!(
168            AlignItems::ALIGN_ITEMS_STRETCH.try_into_taffy().unwrap(),
169            taffy::AlignItems::Stretch
170        );
171        assert!(AlignItems::ALIGN_ITEMS_UNSPECIFIED.try_into_taffy().is_err());
172    }
173
174    #[test]
175    fn test_align_self_try_into_taffy() {
176        assert_eq!(AlignSelf::ALIGN_SELF_AUTO.try_into_taffy().unwrap(), None);
177        assert_eq!(
178            AlignSelf::ALIGN_SELF_FLEX_START.try_into_taffy().unwrap(),
179            Some(taffy::AlignItems::FlexStart)
180        );
181        assert_eq!(
182            AlignSelf::ALIGN_SELF_FLEX_END.try_into_taffy().unwrap(),
183            Some(taffy::AlignItems::FlexEnd)
184        );
185        assert_eq!(
186            AlignSelf::ALIGN_SELF_CENTER.try_into_taffy().unwrap(),
187            Some(taffy::AlignItems::Center)
188        );
189        assert_eq!(
190            AlignSelf::ALIGN_SELF_BASELINE.try_into_taffy().unwrap(),
191            Some(taffy::AlignItems::Baseline)
192        );
193        assert_eq!(
194            AlignSelf::ALIGN_SELF_STRETCH.try_into_taffy().unwrap(),
195            Some(taffy::AlignItems::Stretch)
196        );
197        assert!(AlignSelf::ALIGN_SELF_UNSPECIFIED.try_into_taffy().is_err());
198    }
199
200    #[test]
201    fn test_align_content_try_into_taffy() {
202        assert_eq!(
203            AlignContent::ALIGN_CONTENT_FLEX_START.try_into_taffy().unwrap(),
204            taffy::AlignContent::FlexStart
205        );
206        assert_eq!(
207            AlignContent::ALIGN_CONTENT_FLEX_END.try_into_taffy().unwrap(),
208            taffy::AlignContent::FlexEnd
209        );
210        assert_eq!(
211            AlignContent::ALIGN_CONTENT_CENTER.try_into_taffy().unwrap(),
212            taffy::AlignContent::Center
213        );
214        assert_eq!(
215            AlignContent::ALIGN_CONTENT_STRETCH.try_into_taffy().unwrap(),
216            taffy::AlignContent::Stretch
217        );
218        assert_eq!(
219            AlignContent::ALIGN_CONTENT_SPACE_BETWEEN.try_into_taffy().unwrap(),
220            taffy::AlignContent::SpaceBetween
221        );
222        assert_eq!(
223            AlignContent::ALIGN_CONTENT_SPACE_AROUND.try_into_taffy().unwrap(),
224            taffy::AlignContent::SpaceAround
225        );
226        assert!(AlignContent::ALIGN_CONTENT_UNSPECIFIED.try_into_taffy().is_err());
227    }
228
229    #[test]
230    fn test_flex_direction_try_into_taffy() {
231        assert_eq!(
232            FlexDirection::FLEX_DIRECTION_ROW.try_into_taffy().unwrap(),
233            taffy::FlexDirection::Row
234        );
235        assert_eq!(
236            FlexDirection::FLEX_DIRECTION_COLUMN.try_into_taffy().unwrap(),
237            taffy::FlexDirection::Column
238        );
239        assert_eq!(
240            FlexDirection::FLEX_DIRECTION_ROW_REVERSE.try_into_taffy().unwrap(),
241            taffy::FlexDirection::RowReverse
242        );
243        assert_eq!(
244            FlexDirection::FLEX_DIRECTION_COLUMN_REVERSE.try_into_taffy().unwrap(),
245            taffy::FlexDirection::ColumnReverse
246        );
247        assert!(FlexDirection::FLEX_DIRECTION_UNSPECIFIED.try_into_taffy().is_err());
248    }
249
250    #[test]
251    fn test_justify_content_try_into_taffy() {
252        assert_eq!(
253            JustifyContent::JUSTIFY_CONTENT_FLEX_START.try_into_taffy().unwrap(),
254            taffy::JustifyContent::FlexStart
255        );
256        assert_eq!(
257            JustifyContent::JUSTIFY_CONTENT_FLEX_END.try_into_taffy().unwrap(),
258            taffy::JustifyContent::FlexEnd
259        );
260        assert_eq!(
261            JustifyContent::JUSTIFY_CONTENT_CENTER.try_into_taffy().unwrap(),
262            taffy::JustifyContent::Center
263        );
264        assert_eq!(
265            JustifyContent::JUSTIFY_CONTENT_SPACE_BETWEEN.try_into_taffy().unwrap(),
266            taffy::JustifyContent::SpaceBetween
267        );
268        assert_eq!(
269            JustifyContent::JUSTIFY_CONTENT_SPACE_AROUND.try_into_taffy().unwrap(),
270            taffy::JustifyContent::SpaceAround
271        );
272        assert_eq!(
273            JustifyContent::JUSTIFY_CONTENT_SPACE_EVENLY.try_into_taffy().unwrap(),
274            taffy::JustifyContent::SpaceEvenly
275        );
276        assert!(JustifyContent::JUSTIFY_CONTENT_UNSPECIFIED.try_into_taffy().is_err());
277    }
278
279    #[test]
280    fn test_position_type_try_into_taffy() {
281        assert_eq!(
282            PositionType::POSITION_TYPE_RELATIVE.try_into_taffy().unwrap(),
283            taffy::Position::Relative
284        );
285        assert_eq!(
286            PositionType::POSITION_TYPE_ABSOLUTE.try_into_taffy().unwrap(),
287            taffy::Position::Absolute
288        );
289        assert!(PositionType::POSITION_TYPE_UNSPECIFIED.try_into_taffy().is_err());
290    }
291
292    #[test]
293    fn test_item_spacing_try_into_taffy() {
294        let fixed_spacing = ItemSpacing {
295            ItemSpacingType: Some(item_spacing::ItemSpacingType::Fixed(10)),
296            ..Default::default()
297        };
298        let fixed_spacing_field: MessageField<ItemSpacing> = Some(fixed_spacing).into();
299        assert_eq!(
300            (&fixed_spacing_field).try_into_taffy().unwrap(),
301            taffy::LengthPercentage::Length(10.0)
302        );
303
304        let auto_spacing = ItemSpacing {
305            ItemSpacingType: Some(item_spacing::ItemSpacingType::Auto(item_spacing::Auto::new())),
306            ..Default::default()
307        };
308        let auto_spacing_field: MessageField<ItemSpacing> = Some(auto_spacing).into();
309        assert_eq!((&auto_spacing_field).try_into_taffy().unwrap(), taffy::LengthPercentage::ZERO);
310
311        let none_spacing: MessageField<ItemSpacing> = None.into();
312        assert!((&none_spacing).try_into_taffy().is_err());
313    }
314}