window.rs

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