diff --git a/crates/gpui3/src/elements.rs b/crates/gpui3/src/elements.rs index 931fa51308b660af70eeb353a2998c4f00cffeec..e0ad68abfc1df6a0ef1a3345e4f15f8a1b0b9bd2 100644 --- a/crates/gpui3/src/elements.rs +++ b/crates/gpui3/src/elements.rs @@ -4,6 +4,7 @@ mod group; mod hoverable; mod identified; mod img; +mod nested; mod pressable; mod svg; mod text; diff --git a/crates/gpui3/src/elements/nested.rs b/crates/gpui3/src/elements/nested.rs new file mode 100644 index 0000000000000000000000000000000000000000..66a55b3a791e37d81ab15bfe49ad2d1513edbb2b --- /dev/null +++ b/crates/gpui3/src/elements/nested.rs @@ -0,0 +1,133 @@ +use crate::{AnyElement, Element, IntoAnyElement, Style, StyleCascade, StyleRefinement}; +use refineable::Refineable; +use smallvec::SmallVec; + +trait LayoutNode { + fn state(&mut self) -> &mut LayoutNodeState; + + fn child(mut self, child: impl IntoAnyElement) -> Self + where + Self: Sized, + { + self.state().children.push(child.into_any()); + self + } + + fn children(mut self, children: C) -> Self + where + C: IntoIterator, + E: IntoAnyElement, + Self: Sized, + { + for child in children { + self.state().children.push(child.into_any()); + } + self + } +} + +struct LayoutNodeState { + style_cascade: StyleCascade, + children: SmallVec<[AnyElement; 2]>, +} + +impl IntoAnyElement for LayoutNodeState +where + V: 'static + Send + Sync, +{ + fn into_any(self) -> AnyElement { + AnyElement::new(self) + } +} + +impl Element for LayoutNodeState { + type ViewState = V; + type ElementState = (); + + fn element_id(&self) -> Option { + None + } + + fn layout( + &mut self, + state: &mut Self::ViewState, + _: Option, + cx: &mut crate::ViewContext, + ) -> (crate::LayoutId, Self::ElementState) { + let layout_ids = self + .children + .iter_mut() + .map(|child| child.layout(state, cx)) + .collect::>(); + + // todo!("pass just the style cascade") + let style = Style::from_refinement(&self.style_cascade().merged()); + let layout_id = cx.request_layout(style, layout_ids); + (layout_id, ()) + } + + fn paint( + &mut self, + _: crate::Bounds, + state: &mut Self::ViewState, + _: &mut Self::ElementState, + cx: &mut crate::ViewContext, + ) { + for child in &mut self.children { + child.paint(state, None, cx); + } + } +} + +pub trait Styled { + fn style_cascade(&mut self) -> &mut StyleCascade; +} + +pub trait Hoverable { + fn hover_style(&mut self) -> &mut StyleRefinement; + + fn hover(mut self, f: impl FnOnce(&mut StyleRefinement) -> &mut StyleRefinement) -> Self + where + Self: Sized, + { + f(self.hover_style()); + self + } +} + +struct HoverableState { + hover_style: StyleRefinement, + child: Child, +} + +impl HoverableState { + fn hover_style(&mut self) -> &mut StyleRefinement { + &mut self.hover_style + } +} + +struct Div(HoverableState>); + +impl LayoutNode for Div { + fn state(&mut self) -> &mut LayoutNodeState { + &mut self.0.child + } +} + +impl Styled for LayoutNodeState { + fn style_cascade(&mut self) -> &mut StyleCascade { + &mut self.style_cascade + } +} + +impl Styled for Div { + fn style_cascade(&mut self) -> &mut StyleCascade { + &mut self.0.child.style_cascade + } +} + +impl Hoverable for Div { + fn hover_style(&mut self) -> &mut StyleRefinement { + self.0.hover_style() + } +} diff --git a/crates/gpui3/src/style.rs b/crates/gpui3/src/style.rs index d3d6b10e52dfbf420f9bd684f4e009b90f548540..24e0dfaa17ec29193fb5f658cfec61a9ab0ebf8d 100644 --- a/crates/gpui3/src/style.rs +++ b/crates/gpui3/src/style.rs @@ -4,13 +4,15 @@ use crate::{ FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rems, Result, RunStyle, SharedString, Size, SizeRefinement, ViewContext, WindowContext, }; -use refineable::Refineable; +use refineable::{Cascade, Refineable}; use smallvec::SmallVec; pub use taffy::style::{ AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent, Overflow, Position, }; +pub type StyleCascade = Cascade