polyhorn_ios/raw/
builtin.rs1use polyhorn_ios_sys::polykit::{
2 PLYImageView, PLYKeyboardAvoidingView, PLYLabel, PLYScrollView, PLYTextInputView, PLYView,
3 PLYViewController, PLYWindow,
4};
5use polyhorn_ios_sys::uikit::UIApplication;
6use polyhorn_ui::geometry::{Dimension, Size};
7use polyhorn_ui::layout::{LayoutNode, MeasureFunc};
8use polyhorn_ui::styles::{FlexDirection, Position, Relative, ViewStyle};
9
10use super::{Container, Environment, OpaqueContainer, Platform};
11
12#[derive(Clone, Debug)]
14pub enum Builtin {
15 ImageView(ViewStyle),
17
18 KeyboardAvoidingView,
21
22 Label(MeasureFunc),
24
25 Modal,
27
28 ScrollView {
31 self_style: ViewStyle,
33
34 content_style: ViewStyle,
37 },
38
39 TextInput,
41
42 View(ViewStyle),
44
45 Window,
47}
48
49impl Container for UIApplication {
50 fn mount(&mut self, child: &mut OpaqueContainer) {
51 let container = child.container();
52 if let Some(mut window) = container.to_window() {
53 window.make_key_and_visible()
54 }
55 }
56
57 fn unmount(&mut self) {
58 unimplemented!("Applications cannot be unmounted.");
60 }
61}
62
63impl polyhorn_core::Builtin<Platform> for Builtin {
64 fn instantiate(
65 &self,
66 _parent: &mut OpaqueContainer,
67 environment: &mut Environment,
68 ) -> OpaqueContainer {
69 let layout = match self {
70 Builtin::Label(_) => LayoutNode::leaf(environment.layout_tree().clone()),
71 _ => LayoutNode::new(environment.layout_tree().clone()),
72 };
73
74 let mut container = match self {
75 &Builtin::ImageView(_) => OpaqueContainer::new(layout, None, PLYImageView::new()),
76 Builtin::KeyboardAvoidingView => {
77 layout.set_style(ViewStyle {
78 position: Position::Relative(Relative {
79 flex_grow: 1.0,
80 ..Default::default()
81 }),
82 ..Default::default()
83 });
84 OpaqueContainer::new(layout, None, PLYKeyboardAvoidingView::new())
85 }
86 Builtin::Label(_) => OpaqueContainer::new(layout, None, PLYLabel::new()),
87 Builtin::Modal => {
88 let view_controller = PLYViewController::new();
89
90 OpaqueContainer::new(layout, None, view_controller)
91 }
92 Builtin::ScrollView { .. } => {
93 let content_layout = LayoutNode::new(environment.layout_tree().clone());
94 OpaqueContainer::new(layout, Some(content_layout), PLYScrollView::new())
95 }
96 Builtin::TextInput => {
97 layout.set_style(ViewStyle {
98 size: Size {
99 width: Dimension::Percentage(1.0),
100 height: Dimension::Auto,
101 },
102 ..Default::default()
103 });
104 OpaqueContainer::new(layout, None, PLYTextInputView::new())
105 }
106 Builtin::View(_) => OpaqueContainer::new(layout, None, PLYView::new()),
107 Builtin::Window => {
108 let mut window = PLYWindow::new();
109 window.set_root_view_controller(PLYViewController::new());
110
111 layout
113 .layouter()
114 .write()
115 .unwrap()
116 .roots_mut()
117 .push(layout.node());
118
119 OpaqueContainer::new(layout, None, window)
120 }
121 };
122
123 self.update(&mut container, environment);
124
125 container
126 }
127
128 fn update(&self, container: &mut OpaqueContainer, _environment: &mut Environment) {
129 match self {
130 &Builtin::ImageView(style) => container.layout().unwrap().set_style(style),
131 Builtin::Label(measure) => container.layout().unwrap().set_measure(measure.clone()),
132 Builtin::Modal => {
133 let view_controller =
134 if let Some(view_controller) = container.downcast_mut::<PLYViewController>() {
135 view_controller
136 } else {
137 return;
138 };
139
140 let view = view_controller.view_mut();
141 view.set_needs_layout();
142 let frame = view.frame();
143
144 container.layout().unwrap().set_style(ViewStyle {
145 position: Position::Absolute(Default::default()),
146 flex_direction: FlexDirection::Column,
147 size: Size {
148 width: Dimension::Points(frame.size.width as _),
149 height: Dimension::Points(frame.size.height as _),
150 },
151 ..Default::default()
152 });
153 }
154 &Builtin::ScrollView {
155 self_style,
156 content_style,
157 } => {
158 container.layout().unwrap().set_style(self_style);
159 container.content_layout().unwrap().set_style(content_style);
160 }
161 &Builtin::View(style) => container.layout().unwrap().set_style(style),
162 Builtin::Window => {
163 let window = if let Some(window) = container.downcast_mut::<PLYWindow>() {
164 window
165 } else {
166 return;
167 };
168
169 let frame = window.root_view_controller().view_mut().frame();
170
171 container.layout().unwrap().set_style(ViewStyle {
172 position: Position::Relative(Relative {
173 flex_shrink: 0.0,
174 flex_grow: 0.0,
175 ..Default::default()
176 }),
177 flex_direction: FlexDirection::Column,
178 size: Size {
179 width: Dimension::Points(frame.size.width as _),
180 height: Dimension::Points(frame.size.height as _),
181 },
182 ..Default::default()
183 });
184 }
185 _ => {}
186 }
187 }
188}