Skip to main content

polyhorn_ios/raw/
convert.rs

1use polyhorn_ios_sys::polykit::{
2    PLYByEdge, PLYCornerRadii, PLYDimension, PLYDimensionKind, PLYLayoutAxisX, PLYLayoutAxisY,
3    PLYPoint,
4};
5use polyhorn_ios_sys::quartzcore::CATransform3D;
6use polyhorn_ios_sys::uikit::{UIColor, UIFont, UIScrollViewIndicatorStyle};
7use polyhorn_ui::color::Color;
8use polyhorn_ui::font::{Font, FontFamily, FontSize, FontStyle, FontWeight, GenericFontFamily};
9use polyhorn_ui::geometry::{ByCorner, ByDirection, ByEdge, Dimension};
10use polyhorn_ui::layout::{LayoutAxisX, LayoutAxisY, LayoutDirection};
11use polyhorn_ui::linalg::Transform3D;
12use polyhorn_ui::styles::ScrollbarColor;
13
14/// Implemented by Polyhorn types that can be trivially converted into native
15/// Objective-C types.
16pub trait Convert<T> {
17    /// This function should perform the conversion to a native Objective-C
18    /// type.
19    fn convert(self) -> T;
20}
21
22impl Convert<UIColor> for Color {
23    fn convert(self) -> UIColor {
24        let rgb = self.to_srgb();
25        UIColor::new(rgb.red as _, rgb.green as _, rgb.blue as _, rgb.alpha as _)
26    }
27}
28
29impl Convert<PLYPoint> for ByDirection<Dimension<f32>> {
30    fn convert(self) -> PLYPoint {
31        PLYPoint {
32            x: self.horizontal.convert(),
33            y: self.vertical.convert(),
34        }
35    }
36}
37
38impl<T1, T2> Convert<PLYLayoutAxisX<T2>> for LayoutAxisX<T1>
39where
40    T1: Convert<T2>,
41{
42    fn convert(self) -> PLYLayoutAxisX<T2> {
43        match self {
44            LayoutAxisX::DirectionDependent { leading, trailing } => PLYLayoutAxisX {
45                independent: false,
46                start: leading.convert(),
47                end: trailing.convert(),
48            },
49            LayoutAxisX::DirectionIndependent { left, right } => PLYLayoutAxisX {
50                independent: true,
51                start: left.convert(),
52                end: right.convert(),
53            },
54        }
55    }
56}
57
58impl<T1, T2> Convert<PLYLayoutAxisY<T2>> for LayoutAxisY<T1>
59where
60    T1: Convert<T2>,
61{
62    fn convert(self) -> PLYLayoutAxisY<T2> {
63        PLYLayoutAxisY {
64            top: self.top.convert(),
65            bottom: self.bottom.convert(),
66        }
67    }
68}
69
70impl<T1, T2> Convert<PLYByEdge<T2>> for ByEdge<T1>
71where
72    T1: Convert<T2>,
73{
74    fn convert(self) -> PLYByEdge<T2> {
75        PLYByEdge {
76            horizontal: self.horizontal.convert(),
77            vertical: self.vertical.convert(),
78        }
79    }
80}
81
82impl Convert<PLYCornerRadii> for ByCorner<ByDirection<Dimension<f32>>> {
83    fn convert(self) -> PLYCornerRadii {
84        let direction = LayoutDirection::LTR;
85
86        let top_left = self.top.left(direction).convert();
87        let top_right = self.top.right(direction).convert();
88        let bottom_right = self.bottom.right(direction).convert();
89        let bottom_left = self.bottom.left(direction).convert();
90
91        PLYCornerRadii {
92            top_left,
93            top_right,
94            bottom_right,
95            bottom_left,
96        }
97    }
98}
99
100impl Convert<PLYDimension> for Dimension<f32> {
101    fn convert(self) -> PLYDimension {
102        match self {
103            Dimension::Points(pixels) => PLYDimension {
104                kind: PLYDimensionKind::Pixels,
105                value: pixels as _,
106            },
107            Dimension::Percentage(percent) => PLYDimension {
108                kind: PLYDimensionKind::Percentage,
109                value: percent as _,
110            },
111            _ => PLYDimension {
112                kind: PLYDimensionKind::Pixels,
113                value: 0.0,
114            },
115        }
116    }
117}
118
119impl Convert<UIScrollViewIndicatorStyle> for ScrollbarColor {
120    fn convert(self) -> UIScrollViewIndicatorStyle {
121        match self {
122            ScrollbarColor::Auto => UIScrollViewIndicatorStyle::Default,
123            ScrollbarColor::Dark => UIScrollViewIndicatorStyle::Black,
124            ScrollbarColor::Light => UIScrollViewIndicatorStyle::White,
125        }
126    }
127}
128
129impl Convert<CATransform3D> for Transform3D<f32> {
130    fn convert(self) -> CATransform3D {
131        // Polyhorn uses `y = Ax` (pre-multiply transform).
132        // CoreAnimation uses `y = xA` (post-multiply transform).
133        // That's why `m23` refers to the second column and third row of our
134        // pre-multiply transformation matrix.
135        CATransform3D {
136            m11: self.columns[0][0] as _,
137            m12: self.columns[0][1] as _,
138            m13: self.columns[0][2] as _,
139            m14: self.columns[0][3] as _,
140            m21: self.columns[1][0] as _,
141            m22: self.columns[1][1] as _,
142            m23: self.columns[1][2] as _,
143            m24: self.columns[1][3] as _,
144            m31: self.columns[2][0] as _,
145            m32: self.columns[2][1] as _,
146            m33: self.columns[2][2] as _,
147            m34: self.columns[2][3] as _,
148            m41: self.columns[3][0] as _,
149            m42: self.columns[3][1] as _,
150            m43: self.columns[3][2] as _,
151            m44: self.columns[3][3] as _,
152        }
153    }
154}
155
156impl Convert<UIFont> for Font {
157    fn convert(self) -> UIFont {
158        let size = match self.size {
159            FontSize::Medium => 16.0,
160            FontSize::Dimension(dimension) => match dimension {
161                Dimension::Points(size) => size,
162                _ => unimplemented!("Non-points font sizes have not yet been implemented."),
163            },
164            _ => unimplemented!("Not all named font sizes have yet been implemented."),
165        };
166
167        match self.family {
168            FontFamily::Generic(generic) => match generic {
169                GenericFontFamily::SansSerif => match self.style {
170                    FontStyle::Normal => match self.weight {
171                        FontWeight::Normal => UIFont::system_font_of_size(size as _),
172                        FontWeight::Bold => UIFont::bold_system_font_of_size(size as _),
173                        _ => {
174                            unimplemented!("Not all named font weights have yet been implemented.")
175                        }
176                    },
177                    _ => unimplemented!("Oblique font styles have not yet been implemented."),
178                },
179                _ => unimplemented!("Not all generic font families have yet been implemented."),
180            },
181            _ => unimplemented!("Custom fonts have not yet been implemented."),
182        }
183    }
184}