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