diff --git a/crates/gpui3/src/app.rs b/crates/gpui3/src/app.rs index 7a79f53a5a53a10c13cfd347dbb21feb090a3e8f..3ec994503521eebc5ed2f21bf86a9ba5f3dd0421 100644 --- a/crates/gpui3/src/app.rs +++ b/crates/gpui3/src/app.rs @@ -23,10 +23,7 @@ use std::{ mem, sync::{Arc, Weak}, }; -use util::{ - http::{self, HttpClient}, - ResultExt, -}; +use util::http::{self, HttpClient}; #[derive(Clone)] pub struct App(Arc>); @@ -169,9 +166,7 @@ impl AppContext { .collect::>(); for dirty_window_id in dirty_window_ids { - self.update_window(dirty_window_id, |cx| cx.draw()) - .unwrap() - .log_err(); + self.update_window(dirty_window_id, |cx| cx.draw()).unwrap(); } } diff --git a/crates/gpui3/src/element.rs b/crates/gpui3/src/element.rs index 3eb2af914ef7b177d8a131d9e856c538aa1b2073..60d8d5d5076c803f803ab54d13c5a965cb8690c5 100644 --- a/crates/gpui3/src/element.rs +++ b/crates/gpui3/src/element.rs @@ -1,11 +1,10 @@ -use crate::{Bounds, Identified, LayoutId, Pixels, Point, Result, ViewContext}; +use crate::{BorrowWindow, Bounds, ElementId, Identified, LayoutId, Pixels, Point, ViewContext}; use derive_more::{Deref, DerefMut}; pub(crate) use smallvec::SmallVec; -use util::arc_cow::ArcCow; -pub trait Element: 'static { - type State; - type FrameState; +pub trait Element: 'static + Send + Sync { + type ViewState: 'static + Send + Sync; + type ElementState: 'static + Send + Sync; fn element_id(&self) -> Option { None @@ -13,17 +12,18 @@ pub trait Element: 'static { fn layout( &mut self, - state: &mut Self::State, - cx: &mut ViewContext, - ) -> Result<(LayoutId, Self::FrameState)>; + state: &mut Self::ViewState, + element_state: Option, + cx: &mut ViewContext, + ) -> (LayoutId, Self::ElementState); fn paint( &mut self, bounds: Bounds, - state: &mut Self::State, - frame_state: &mut Self::FrameState, - cx: &mut ViewContext, - ) -> Result<()>; + state: &mut Self::ViewState, + element_state: &mut Self::ElementState, + cx: &mut ViewContext, + ); fn id(self, id: ElementId) -> Identified where @@ -39,10 +39,7 @@ pub trait StatefulElement: Element { } } -#[derive(Clone, Debug, Eq, PartialEq, Hash)] -pub struct ElementId(ArcCow<'static, [u8]>); - -#[derive(Deref, DerefMut, Default, Clone, Debug)] +#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)] pub(crate) struct GlobalElementId(SmallVec<[ElementId; 8]>); pub trait ParentElement { @@ -68,19 +65,14 @@ pub trait ParentElement { } } -trait ElementObject { - fn layout(&mut self, state: &mut S, cx: &mut ViewContext) -> Result; - fn paint( - &mut self, - state: &mut S, - offset: Option>, - cx: &mut ViewContext, - ) -> Result<()>; +trait ElementObject: 'static + Send + Sync { + fn layout(&mut self, state: &mut S, cx: &mut ViewContext) -> LayoutId; + fn paint(&mut self, state: &mut S, offset: Option>, cx: &mut ViewContext); } struct RenderedElement { element: E, - phase: ElementRenderPhase, + phase: ElementRenderPhase, } #[derive(Default)] @@ -89,15 +81,15 @@ enum ElementRenderPhase { Rendered, LayoutRequested { layout_id: LayoutId, - frame_state: S, + frame_state: Option, }, Painted { bounds: Bounds, - frame_state: S, + frame_state: Option, }, } -/// Internal struct that wraps an element to store Layout and FrameState after the element is rendered. +/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered. /// It's allocated as a trait object to erase the element type and wrapped in AnyElement for /// improved usability. impl RenderedElement { @@ -107,24 +99,58 @@ impl RenderedElement { phase: ElementRenderPhase::Rendered, } } + + fn paint_with_element_state( + &mut self, + bounds: Bounds, + view_state: &mut E::ViewState, + frame_state: &mut Option, + cx: &mut ViewContext, + ) { + if let Some(id) = self.element.element_id() { + cx.with_element_state(id, |element_state, cx| { + let mut element_state = element_state.unwrap(); + self.element + .paint(bounds, view_state, &mut element_state, cx); + ((), element_state) + }); + } else { + self.element + .paint(bounds, view_state, frame_state.as_mut().unwrap(), cx); + } + } } -impl ElementObject for RenderedElement { - fn layout(&mut self, state: &mut E::State, cx: &mut ViewContext) -> Result { - let (layout_id, frame_state) = self.element.layout(state, cx)?; +impl ElementObject for RenderedElement +where + E: Element, + S: 'static + Send + Sync, +{ + fn layout(&mut self, state: &mut E::ViewState, cx: &mut ViewContext) -> LayoutId { + let (layout_id, frame_state) = if let Some(id) = self.element.element_id() { + let layout_id = cx.with_element_state(id, |element_state, cx| { + self.element.layout(state, element_state, cx) + }); + (layout_id, None) + } else { + let (layout_id, frame_state) = self.element.layout(state, None, cx); + (layout_id, Some(frame_state)) + }; + self.phase = ElementRenderPhase::LayoutRequested { layout_id, frame_state, }; - Ok(layout_id) + + layout_id } fn paint( &mut self, - state: &mut E::State, + view_state: &mut E::ViewState, offset: Option>, - cx: &mut ViewContext, - ) -> Result<()> { + cx: &mut ViewContext, + ) { self.phase = match std::mem::take(&mut self.phase) { ElementRenderPhase::Rendered => panic!("must call layout before paint"), @@ -132,9 +158,9 @@ impl ElementObject for RenderedElement { layout_id, mut frame_state, } => { - let mut bounds = cx.layout_bounds(layout_id)?.clone(); + let mut bounds = cx.layout_bounds(layout_id); offset.map(|offset| bounds.origin += offset); - self.element.paint(bounds, state, &mut frame_state, cx)?; + self.paint_with_element_state(bounds, view_state, &mut frame_state, cx); ElementRenderPhase::Painted { bounds, frame_state, @@ -145,32 +171,24 @@ impl ElementObject for RenderedElement { bounds, mut frame_state, } => { - self.element - .paint(bounds.clone(), state, &mut frame_state, cx)?; + self.paint_with_element_state(bounds, view_state, &mut frame_state, cx); ElementRenderPhase::Painted { bounds, frame_state, } } }; - - Ok(()) } } pub struct AnyElement(Box>); -impl AnyElement { - pub fn layout(&mut self, state: &mut S, cx: &mut ViewContext) -> Result { +impl AnyElement { + pub fn layout(&mut self, state: &mut S, cx: &mut ViewContext) -> LayoutId { self.0.layout(state, cx) } - pub fn paint( - &mut self, - state: &mut S, - offset: Option>, - cx: &mut ViewContext, - ) -> Result<()> { + pub fn paint(&mut self, state: &mut S, offset: Option>, cx: &mut ViewContext) { self.0.paint(state, offset, cx) } } @@ -179,8 +197,8 @@ pub trait IntoAnyElement { fn into_any(self) -> AnyElement; } -impl IntoAnyElement for E { - fn into_any(self) -> AnyElement { +impl IntoAnyElement for E { + fn into_any(self) -> AnyElement { AnyElement(Box::new(RenderedElement::new(self))) } } diff --git a/crates/gpui3/src/elements/div.rs b/crates/gpui3/src/elements/div.rs index 5fd4b0b243e52cc02befffcec37e72e08073fbcd..db25370c30613fbffaef4459226185c5226adf34 100644 --- a/crates/gpui3/src/elements/div.rs +++ b/crates/gpui3/src/elements/div.rs @@ -1,12 +1,10 @@ use crate::{ AnyElement, Bounds, Element, Interactive, LayoutId, MouseEventListeners, Overflow, - ParentElement, Pixels, Point, Refineable, RefinementCascade, Result, Style, Styled, - ViewContext, + ParentElement, Pixels, Point, Refineable, RefinementCascade, Style, Styled, ViewContext, }; use parking_lot::Mutex; use smallvec::SmallVec; use std::sync::Arc; -use util::ResultExt; pub struct Div { styles: RefinementCascade