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