1use crate::PlatformWindow;
2
3use super::{
4 px, taffy::LayoutId, AppContext, Bounds, Context, EntityId, Handle, Pixels, Reference, Style,
5 TaffyLayoutEngine,
6};
7use anyhow::Result;
8use derive_more::{Deref, DerefMut};
9use std::{
10 any::{Any, TypeId},
11 marker::PhantomData,
12};
13
14pub struct AnyWindow {}
15
16pub struct Window {
17 id: WindowId,
18 platform_window: Box<dyn PlatformWindow>,
19 rem_size: Pixels,
20 layout_engine: TaffyLayoutEngine,
21 pub(crate) root_view: Option<Box<dyn Any>>,
22}
23
24impl Window {
25 pub fn new(id: WindowId, platform_window: Box<dyn PlatformWindow>) -> Window {
26 Window {
27 id,
28 platform_window,
29 rem_size: px(16.),
30 layout_engine: TaffyLayoutEngine::new(),
31 root_view: None,
32 }
33 }
34}
35
36#[derive(Deref, DerefMut)]
37pub struct WindowContext<'a, 'b> {
38 #[deref]
39 #[deref_mut]
40 app: Reference<'a, AppContext>,
41 window: Reference<'b, Window>,
42}
43
44impl<'a, 'w> WindowContext<'a, 'w> {
45 pub(crate) fn mutable(app: &'a mut AppContext, window: &'w mut Window) -> Self {
46 Self {
47 app: Reference::Mutable(app),
48 window: Reference::Mutable(window),
49 }
50 }
51
52 pub(crate) fn immutable(app: &'a AppContext, window: &'w Window) -> Self {
53 Self {
54 app: Reference::Immutable(app),
55 window: Reference::Immutable(window),
56 }
57 }
58
59 pub fn request_layout(
60 &mut self,
61 style: Style,
62 children: impl IntoIterator<Item = LayoutId>,
63 ) -> Result<LayoutId> {
64 self.app.layout_id_buffer.clear();
65 self.app.layout_id_buffer.extend(children.into_iter());
66 let rem_size = self.rem_size();
67
68 self.window
69 .layout_engine
70 .request_layout(style, rem_size, &self.app.layout_id_buffer)
71 }
72
73 pub fn layout(&mut self, layout_id: LayoutId) -> Result<Layout> {
74 Ok(self
75 .window
76 .layout_engine
77 .layout(layout_id)
78 .map(Into::into)?)
79 }
80
81 pub fn rem_size(&self) -> Pixels {
82 self.window.rem_size
83 }
84
85 fn update_window<R>(
86 &mut self,
87 window_id: WindowId,
88 update: impl FnOnce(&mut WindowContext) -> R,
89 ) -> Result<R> {
90 if window_id == self.window.id {
91 Ok(update(self))
92 } else {
93 self.app.update_window(window_id, update)
94 }
95 }
96}
97
98impl Context for WindowContext<'_, '_> {
99 type EntityContext<'a, 'w, T: 'static> = ViewContext<'a, 'w, T>;
100
101 fn entity<T: 'static>(
102 &mut self,
103 build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
104 ) -> Handle<T> {
105 let id = self.entities.insert(None);
106 let entity = Box::new(build_entity(&mut ViewContext::mutable(
107 &mut *self.app,
108 &mut self.window,
109 id,
110 )));
111 self.entities.get_mut(id).unwrap().replace(entity);
112
113 Handle {
114 id,
115 entity_type: PhantomData,
116 }
117 }
118
119 fn update_entity<T: 'static, R>(
120 &mut self,
121 handle: &Handle<T>,
122 update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
123 ) -> R {
124 let mut entity = self
125 .app
126 .entities
127 .get_mut(handle.id)
128 .unwrap()
129 .take()
130 .unwrap()
131 .downcast::<T>()
132 .unwrap();
133
134 let result = update(
135 &mut *entity,
136 &mut ViewContext::mutable(&mut *self.app, &mut *self.window, handle.id),
137 );
138
139 self.app
140 .entities
141 .get_mut(handle.id)
142 .unwrap()
143 .replace(entity);
144
145 result
146 }
147}
148
149#[derive(Deref, DerefMut)]
150pub struct ViewContext<'a, 'w, T> {
151 #[deref]
152 #[deref_mut]
153 window_cx: WindowContext<'a, 'w>,
154 entity_type: PhantomData<T>,
155 entity_id: EntityId,
156}
157
158impl<'a, 'w, T: 'static> ViewContext<'a, 'w, T> {
159 // fn update<R>(&mut self, update: impl FnOnce(&mut T, &mut Self) -> R) -> R {
160
161 // self.window_cx.update_entity(handle, update)
162
163 // let mut entity = self.window_cx.app.entities.remove(&self.entity_id).unwrap();
164 // let result = update(entity.downcast_mut::<T>().unwrap(), self);
165 // self.window_cx
166 // .app
167 // .entities
168 // .insert(self.entity_id, Box::new(entity));
169 // result
170 // }
171
172 fn mutable(app: &'a mut AppContext, window: &'w mut Window, entity_id: EntityId) -> Self {
173 Self {
174 window_cx: WindowContext::mutable(app, window),
175 entity_id,
176 entity_type: PhantomData,
177 }
178 }
179
180 fn immutable(app: &'a AppContext, window: &'w Window, entity_id: EntityId) -> Self {
181 Self {
182 window_cx: WindowContext::immutable(app, window),
183 entity_id,
184 entity_type: PhantomData,
185 }
186 }
187}
188
189impl<'a, 'w, T: 'static> Context for ViewContext<'a, 'w, T> {
190 type EntityContext<'b, 'c, U: 'static> = ViewContext<'b, 'c, U>;
191
192 fn entity<T2: 'static>(
193 &mut self,
194 build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T2>) -> T2,
195 ) -> Handle<T2> {
196 self.window_cx.entity(build_entity)
197 }
198
199 fn update_entity<U: 'static, R>(
200 &mut self,
201 handle: &Handle<U>,
202 update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R,
203 ) -> R {
204 self.window_cx.update_entity(handle, update)
205 }
206}
207
208// #[derive(Clone, Copy, Eq, PartialEq, Hash)]
209slotmap::new_key_type! { pub struct WindowId; }
210
211#[derive(PartialEq, Eq)]
212pub struct WindowHandle<S> {
213 id: WindowId,
214 state_type: PhantomData<S>,
215}
216
217impl<S> Copy for WindowHandle<S> {}
218
219impl<S> Clone for WindowHandle<S> {
220 fn clone(&self) -> Self {
221 WindowHandle {
222 id: self.id,
223 state_type: PhantomData,
224 }
225 }
226}
227
228impl<S> WindowHandle<S> {
229 pub fn new(id: WindowId) -> Self {
230 WindowHandle {
231 id,
232 state_type: PhantomData,
233 }
234 }
235}
236
237impl<S: 'static> Into<AnyWindowHandle> for WindowHandle<S> {
238 fn into(self) -> AnyWindowHandle {
239 AnyWindowHandle {
240 id: self.id,
241 state_type: TypeId::of::<S>(),
242 }
243 }
244}
245
246#[derive(Copy, Clone, PartialEq, Eq)]
247pub struct AnyWindowHandle {
248 id: WindowId,
249 state_type: TypeId,
250}
251
252#[derive(Clone)]
253pub struct Layout {
254 pub order: u32,
255 pub bounds: Bounds<Pixels>,
256}