window.rs

  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}