view_context.rs

  1use std::{any::TypeId, rc::Rc};
  2
  3use crate::{element::LayoutId, style::Style};
  4use anyhow::{anyhow, Result};
  5use derive_more::{Deref, DerefMut};
  6use gpui::{
  7    geometry::Size, scene::EventHandler, AnyWindowHandle, BorrowWindowContext, EventContext,
  8    Layout, MeasureParams, WindowContext,
  9};
 10pub use gpui::{taffy::tree::NodeId, ViewContext as LegacyViewContext};
 11
 12#[derive(Deref, DerefMut)]
 13pub struct ViewContext<'a, 'b, 'c, V> {
 14    #[deref]
 15    #[deref_mut]
 16    pub(crate) legacy_cx: &'c mut LegacyViewContext<'a, 'b, V>,
 17}
 18
 19impl<'a, 'b, 'c, V: 'static> ViewContext<'a, 'b, 'c, V> {
 20    pub fn new(legacy_cx: &'c mut LegacyViewContext<'a, 'b, V>) -> Self {
 21        Self { legacy_cx }
 22    }
 23
 24    pub fn add_layout_node(
 25        &mut self,
 26        style: Style,
 27        children: impl IntoIterator<Item = NodeId>,
 28    ) -> Result<LayoutId> {
 29        let rem_size = self.rem_size();
 30        let style = style.to_taffy(rem_size);
 31        let id = self
 32            .legacy_cx
 33            .layout_engine()
 34            .ok_or_else(|| anyhow!("no layout engine"))?
 35            .add_node(style, children)?;
 36
 37        Ok(id)
 38    }
 39
 40    pub fn add_measured_layout_node<F>(&mut self, style: Style, measure: F) -> Result<LayoutId>
 41    where
 42        F: Fn(MeasureParams) -> Size<f32> + Sync + Send + 'static,
 43    {
 44        let rem_size = self.rem_size();
 45        let layout_id = self
 46            .layout_engine()
 47            .ok_or_else(|| anyhow!("no layout engine"))?
 48            .add_measured_node(style.to_taffy(rem_size), measure)?;
 49
 50        Ok(layout_id)
 51    }
 52
 53    pub fn on_event<E: 'static>(
 54        &mut self,
 55        order: u32,
 56        handler: impl Fn(&mut V, &E, &mut EventContext<V>) + 'static,
 57    ) {
 58        let view = self.weak_handle();
 59
 60        self.scene().event_handlers.push(EventHandler {
 61            order,
 62            handler: Rc::new(move |event, window_cx| {
 63                if let Some(view) = view.upgrade(window_cx) {
 64                    view.update(window_cx, |view, view_cx| {
 65                        let mut event_cx = EventContext::new(view_cx);
 66                        handler(view, event.downcast_ref().unwrap(), &mut event_cx);
 67                        event_cx.bubble
 68                    })
 69                } else {
 70                    true
 71                }
 72            }),
 73            event_type: TypeId::of::<E>(),
 74        })
 75    }
 76
 77    pub(crate) fn computed_layout(&mut self, layout_id: LayoutId) -> Result<Layout> {
 78        self.layout_engine()
 79            .ok_or_else(|| anyhow!("no layout engine present"))?
 80            .computed_layout(layout_id)
 81    }
 82}
 83
 84impl<'a, 'b, 'c, V: 'static> BorrowWindowContext for ViewContext<'a, 'b, 'c, V> {
 85    type Result<T> = T;
 86
 87    fn read_window<T, F>(&self, window: AnyWindowHandle, f: F) -> Self::Result<T>
 88    where
 89        F: FnOnce(&WindowContext) -> T,
 90    {
 91        self.legacy_cx.read_window(window, f)
 92    }
 93
 94    fn read_window_optional<T, F>(&self, window: AnyWindowHandle, f: F) -> Option<T>
 95    where
 96        F: FnOnce(&WindowContext) -> Option<T>,
 97    {
 98        self.legacy_cx.read_window_optional(window, f)
 99    }
100
101    fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Self::Result<T>
102    where
103        F: FnOnce(&mut WindowContext) -> T,
104    {
105        self.legacy_cx.update_window(window, f)
106    }
107
108    fn update_window_optional<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Option<T>
109    where
110        F: FnOnce(&mut WindowContext) -> Option<T>,
111    {
112        self.legacy_cx.update_window_optional(window, f)
113    }
114}