1use crate::{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};
14use taffy::style::AvailableSpace;
15
16pub struct AnyWindow {}
17
18pub struct Window {
19 id: WindowId,
20 platform_window: 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>>,
25}
26
27impl Window {
28 pub fn new(id: WindowId, platform_window: Box<dyn PlatformWindow>) -> Window {
29 Window {
30 id,
31 platform_window,
32 rem_size: px(16.),
33 layout_engine: TaffyLayoutEngine::new(),
34 text_style_stack: Vec::new(),
35 root_view: None,
36 }
37 }
38}
39
40#[derive(Deref, DerefMut)]
41pub struct WindowContext<'a, 'b> {
42 #[deref]
43 #[deref_mut]
44 app: Reference<'a, AppContext>,
45 window: Reference<'b, Window>,
46}
47
48impl<'a, 'w> WindowContext<'a, 'w> {
49 pub(crate) fn mutable(app: &'a mut AppContext, window: &'w mut Window) -> Self {
50 Self {
51 app: Reference::Mutable(app),
52 window: Reference::Mutable(window),
53 }
54 }
55
56 pub(crate) fn immutable(app: &'a AppContext, window: &'w Window) -> Self {
57 Self {
58 app: Reference::Immutable(app),
59 window: Reference::Immutable(window),
60 }
61 }
62
63 pub fn request_layout(
64 &mut self,
65 style: Style,
66 children: impl IntoIterator<Item = LayoutId>,
67 ) -> Result<LayoutId> {
68 self.app.layout_id_buffer.clear();
69 self.app.layout_id_buffer.extend(children.into_iter());
70 let rem_size = self.rem_size();
71
72 self.window
73 .layout_engine
74 .request_layout(style, rem_size, &self.app.layout_id_buffer)
75 }
76
77 pub fn request_measured_layout<
78 F: FnOnce(Size<Option<Pixels>>, Size<AvailableSpace>) + 'static,
79 >(
80 &mut self,
81 style: Style,
82 rem_size: Pixels,
83 measure: F,
84 ) -> Result<LayoutId> {
85 self.window
86 .layout_engine
87 .request_measured_layout(style, rem_size, measure)
88 }
89
90 pub fn layout(&mut self, layout_id: LayoutId) -> Result<Layout> {
91 Ok(self
92 .window
93 .layout_engine
94 .layout(layout_id)
95 .map(Into::into)?)
96 }
97
98 pub fn rem_size(&self) -> Pixels {
99 self.window.rem_size
100 }
101
102 pub fn push_text_style(&mut self, text_style: TextStyleRefinement) {
103 self.window.text_style_stack.push(text_style);
104 }
105
106 pub fn pop_text_style(&mut self) {
107 self.window.text_style_stack.pop();
108 }
109
110 pub fn text_style(&self) -> &Vec<TextStyle> {
111 let style = TextStyleRefinement::default();
112 for refinement in &self.window.text_style_stack {
113 style.refine(refinement);
114 }
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}