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