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