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