polyhorn_ios/raw/
container.rs1use as_any::AsAny;
2use polyhorn_ios_sys::polykit::{PLYView, PLYViewController, PLYWindow};
3use polyhorn_ios_sys::uikit::UIApplication;
4use polyhorn_ui::layout::LayoutNode;
5
6use super::{Environment, Platform};
7
8pub trait Container: AsAny + 'static {
10 fn mount(&mut self, child: &mut OpaqueContainer);
12
13 fn unmount(&mut self);
15
16 fn to_view(&self) -> Option<PLYView> {
19 None
20 }
21
22 fn to_view_controller(&self) -> Option<PLYViewController> {
25 None
26 }
27
28 fn to_window(&self) -> Option<PLYWindow> {
31 None
32 }
33}
34
35pub struct OpaqueContainer(Option<LayoutNode>, Option<LayoutNode>, Box<dyn Container>);
41
42impl OpaqueContainer {
43 pub fn new<T>(
46 layout: LayoutNode,
47 content_layout: Option<LayoutNode>,
48 view: T,
49 ) -> OpaqueContainer
50 where
51 T: Container,
52 {
53 OpaqueContainer(Some(layout), content_layout, Box::new(view))
54 }
55
56 pub fn root() -> OpaqueContainer {
59 OpaqueContainer(None, None, Box::new(UIApplication::shared()))
60 }
61
62 pub fn layout(&self) -> Option<&LayoutNode> {
64 self.0.as_ref()
65 }
66
67 pub fn content_layout(&self) -> Option<&LayoutNode> {
70 self.1.as_ref()
71 }
72
73 pub fn container(&self) -> &dyn Container {
75 self.2.as_ref()
76 }
77
78 pub fn downcast_mut<T>(&mut self) -> Option<&mut T>
81 where
82 T: 'static,
83 {
84 self.2.as_mut().as_any_mut().downcast_mut::<T>()
85 }
86}
87
88impl polyhorn_core::Container<Platform> for OpaqueContainer {
89 fn mount(&mut self, container: &mut OpaqueContainer, _environment: &mut Environment) {
90 if let (Some(child), Some(content)) = (container.layout(), container.content_layout()) {
91 let mut layouter = child.layouter().write().unwrap();
92 layouter.add_child(child.node(), content.node());
93 }
94
95 if let (Some(parent), Some(child)) = (
96 self.content_layout().or_else(|| self.layout()),
97 container.layout(),
98 ) {
99 let mut layouter = parent.layouter().write().unwrap();
100 layouter.add_child(parent.node(), child.node());
101 }
102
103 self.2.mount(container);
104 }
105
106 fn unmount(&mut self) {
107 if let Some(layout) = self.content_layout() {
108 let mut layouter = layout.layouter().write().unwrap();
109 layouter.remove(layout.node());
110 }
111
112 if let Some(layout) = self.layout() {
113 let mut layouter = layout.layouter().write().unwrap();
114 layouter.remove(layout.node());
115 }
116
117 self.2.unmount();
118 }
119}