diff --git a/crates/gpui3/src/elements/div.rs b/crates/gpui3/src/elements/div.rs index 7a0b550007df6b1839e69d853e7b99bf19f35150..9582ad769d8cd4cc7299c0a548ebe252dd909010 100644 --- a/crates/gpui3/src/elements/div.rs +++ b/crates/gpui3/src/elements/div.rs @@ -23,7 +23,7 @@ pub fn div() -> Div { } } -impl Element for Div { +impl Element for Div { type State = S; type FrameState = Vec; @@ -33,22 +33,16 @@ impl Element for Div { cx: &mut ViewContext, ) -> Result<(LayoutId, Self::FrameState)> { let style = self.computed_style(); - let pop_text_style = style - .text_style(cx) - .map(|style| cx.push_text_style(style.clone())) - .is_some(); - - let children = self - .children - .iter_mut() - .map(|child| child.layout(view, cx)) - .collect::>>()?; - - if pop_text_style { - cx.pop_text_style(); - } - - Ok((cx.request_layout(style.into(), children.clone())?, children)) + let child_layout_ids = if let Some(text_style) = style.text_style(cx) { + cx.with_text_style(text_style.clone(), |cx| self.layout_children(view, cx))? + } else { + self.layout_children(view, cx)? + }; + + Ok(( + cx.request_layout(style.into(), child_layout_ids.clone())?, + child_layout_ids, + )) } fn paint( @@ -61,36 +55,25 @@ impl Element for Div { let Layout { order, bounds } = layout; let style = self.computed_style(); - let pop_text_style = style - .text_style(cx) - .map(|style| cx.push_text_style(style.clone())) - .is_some(); style.paint_background(bounds, cx); - // self.interaction_handlers().paint(order, bounds, cx); - - // // TODO: Support only one dimension being hidden - // let mut pop_layer = false; + let overflow = &style.overflow; + // // todo!("support only one dimension being hidden") // if style.overflow.y != Overflow::Visible || style.overflow.x != Overflow::Visible { // cx.scene().push_layer(Some(bounds)); // pop_layer = true; // } - - let scroll_offset = self.scroll_offset(&style.overflow); - for child in &mut self.children { - child.paint(state, Some(scroll_offset), cx)?; + if let Some(text_style) = style.text_style(cx) { + cx.with_text_style(text_style.clone(), |cx| { + self.paint_children(overflow, state, cx) + })?; + } else { + self.paint_children(overflow, state, cx)?; } - - // if pop_layer { - // cx.scene().pop_layer(); - // } - style.paint_foreground(bounds, cx); - if pop_text_style { - cx.pop_text_style(); - } self.handle_scroll(order, bounds, style.overflow.clone(), child_layouts, cx); + // todo!("enable inspector") // if cx.is_inspector_enabled() { // self.paint_inspector(parent_origin, layout, cx); // } @@ -99,7 +82,7 @@ impl Element for Div { } } -impl Div { +impl Div { pub fn overflow_hidden(mut self) -> Self { self.declared_style().overflow.x = Some(Overflow::Hidden); self.declared_style().overflow.y = Some(Overflow::Hidden); @@ -147,13 +130,33 @@ impl Div { offset } + fn layout_children(&mut self, view: &mut S, cx: &mut ViewContext) -> Result> { + self.children + .iter_mut() + .map(|child| child.layout(view, cx)) + .collect::>>() + } + + fn paint_children( + &mut self, + overflow: &Point, + state: &mut S, + cx: &mut ViewContext, + ) -> Result<()> { + let scroll_offset = self.scroll_offset(overflow); + for child in &mut self.children { + child.paint(state, Some(scroll_offset), cx)?; + } + Ok(()) + } + fn handle_scroll( &mut self, _order: u32, bounds: Bounds, overflow: Point, child_layout_ids: &[LayoutId], - cx: &mut ViewContext, + cx: &mut ViewContext, ) { if overflow.y == Overflow::Scroll || overflow.x == Overflow::Scroll { let mut scroll_max = Point::default(); @@ -244,6 +247,7 @@ impl Div { // // } // // }); // } + // } impl Styled for Div { diff --git a/crates/gpui3/src/window.rs b/crates/gpui3/src/window.rs index bdbb69d0b9eaff484281ff07d01ef4d7756d40bb..a0f880f47dc8d4360b40d582de009cfa3dcc99d6 100644 --- a/crates/gpui3/src/window.rs +++ b/crates/gpui3/src/window.rs @@ -158,14 +158,6 @@ impl<'a, 'w> WindowContext<'a, 'w> { self.window.rem_size } - pub fn push_text_style(&mut self, text_style: TextStyleRefinement) { - self.window.text_style_stack.push(text_style); - } - - pub fn pop_text_style(&mut self) { - self.window.text_style_stack.pop(); - } - pub fn push_cascading_state(&mut self, theme: T) { self.window .state_stacks_by_type @@ -239,15 +231,15 @@ impl Context for WindowContext<'_, '_> { } #[derive(Deref, DerefMut)] -pub struct ViewContext<'a, 'w, T> { +pub struct ViewContext<'a, 'w, S> { #[deref] #[deref_mut] window_cx: WindowContext<'a, 'w>, - entity_type: PhantomData, + entity_type: PhantomData, entity_id: EntityId, } -impl<'a, 'w, T: Send + Sync + 'static> ViewContext<'a, 'w, T> { +impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> { fn mutable(app: &'a mut AppContext, window: &'w mut Window, entity_id: EntityId) -> Self { Self { window_cx: WindowContext::mutable(app, window), @@ -256,32 +248,25 @@ impl<'a, 'w, T: Send + Sync + 'static> ViewContext<'a, 'w, T> { } } - // fn immutable(app: &'a AppContext, window: &'w Window, entity_id: EntityId) -> Self { - // Self { - // window_cx: WindowContext::immutable(app, window), - // entity_id, - // entity_type: PhantomData, - // } - // } - - pub fn erase_state(&mut self, f: impl FnOnce(&mut ViewContext<()>) -> R) -> R { - let entity_id = self.unit_entity.id; - let mut cx = ViewContext::mutable( - &mut *self.window_cx.app, - &mut *self.window_cx.window, - entity_id, - ); - f(&mut cx) + pub fn handle(&self) -> WeakHandle { + self.entities.weak_handle(self.entity_id) } - pub fn handle(&self) -> WeakHandle { - self.entities.weak_handle(self.entity_id) + pub fn with_text_style( + &mut self, + style: TextStyleRefinement, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + self.window.text_style_stack.push(style); + let result = f(self); + self.window.text_style_stack.pop(); + result } pub fn observe( &mut self, handle: &Handle, - on_notify: impl Fn(&mut T, Handle, &mut ViewContext<'_, '_, T>) + Send + Sync + 'static, + on_notify: impl Fn(&mut S, Handle, &mut ViewContext<'_, '_, S>) + Send + Sync + 'static, ) { let this = self.handle(); let handle = handle.downgrade(); @@ -310,9 +295,19 @@ impl<'a, 'w, T: Send + Sync + 'static> ViewContext<'a, 'w, T> { .push_back(Effect::Notify(entity_id)); self.window.dirty = true; } + + pub(crate) fn erase_state(&mut self, f: impl FnOnce(&mut ViewContext<()>) -> R) -> R { + let entity_id = self.unit_entity.id; + let mut cx = ViewContext::mutable( + &mut *self.window_cx.app, + &mut *self.window_cx.window, + entity_id, + ); + f(&mut cx) + } } -impl<'a, 'w, T: 'static> Context for ViewContext<'a, 'w, T> { +impl<'a, 'w, S: 'static> Context for ViewContext<'a, 'w, S> { type EntityContext<'b, 'c, U: Send + Sync + 'static> = ViewContext<'b, 'c, U>; type Result = U;