window.rs

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