window.rs

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