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;
Antonio Scandurra created
crates/gpui3/src/elements.rs | 1
crates/gpui3/src/elements/nested.rs | 133 +++++++++++++++++++++++++++++++
crates/gpui3/src/style.rs | 4
crates/gpui3/src/taffy.rs | 6 +
crates/gpui3/src/view.rs | 2
5 files changed, 144 insertions(+), 2 deletions(-)
@@ -4,6 +4,7 @@ mod group;
mod hoverable;
mod identified;
mod img;
+mod nested;
mod pressable;
mod svg;
mod text;
@@ -0,0 +1,133 @@
+use crate::{AnyElement, Element, IntoAnyElement, Style, StyleCascade, StyleRefinement};
+use refineable::Refineable;
+use smallvec::SmallVec;
+
+trait LayoutNode<V: 'static + Send + Sync> {
+ fn state(&mut self) -> &mut LayoutNodeState<V>;
+
+ fn child(mut self, child: impl IntoAnyElement<V>) -> Self
+ where
+ Self: Sized,
+ {
+ self.state().children.push(child.into_any());
+ self
+ }
+
+ fn children<C, E>(mut self, children: C) -> Self
+ where
+ C: IntoIterator<Item = E>,
+ E: IntoAnyElement<V>,
+ Self: Sized,
+ {
+ for child in children {
+ self.state().children.push(child.into_any());
+ }
+ self
+ }
+}
+
+struct LayoutNodeState<V: 'static + Send + Sync> {
+ style_cascade: StyleCascade,
+ children: SmallVec<[AnyElement<V>; 2]>,
+}
+
+impl<V> IntoAnyElement<V> for LayoutNodeState<V>
+where
+ V: 'static + Send + Sync,
+{
+ fn into_any(self) -> AnyElement<V> {
+ AnyElement::new(self)
+ }
+}
+
+impl<V: 'static + Send + Sync> Element for LayoutNodeState<V> {
+ type ViewState = V;
+ type ElementState = ();
+
+ fn element_id(&self) -> Option<crate::ElementId> {
+ None
+ }
+
+ fn layout(
+ &mut self,
+ state: &mut Self::ViewState,
+ _: Option<Self::ElementState>,
+ cx: &mut crate::ViewContext<Self::ViewState>,
+ ) -> (crate::LayoutId, Self::ElementState) {
+ let layout_ids = self
+ .children
+ .iter_mut()
+ .map(|child| child.layout(state, cx))
+ .collect::<Vec<_>>();
+
+ // 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<crate::Pixels>,
+ state: &mut Self::ViewState,
+ _: &mut Self::ElementState,
+ cx: &mut crate::ViewContext<Self::ViewState>,
+ ) {
+ 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<Child: Styled + Element> {
+ hover_style: StyleRefinement,
+ child: Child,
+}
+
+impl<Child: Styled + Element> HoverableState<Child> {
+ fn hover_style(&mut self) -> &mut StyleRefinement {
+ &mut self.hover_style
+ }
+}
+
+struct Div<V: 'static + Send + Sync>(HoverableState<LayoutNodeState<V>>);
+
+impl<V: 'static + Send + Sync> LayoutNode<V> for Div<V> {
+ fn state(&mut self) -> &mut LayoutNodeState<V> {
+ &mut self.0.child
+ }
+}
+
+impl<V: 'static + Send + Sync> Styled for LayoutNodeState<V> {
+ fn style_cascade(&mut self) -> &mut StyleCascade {
+ &mut self.style_cascade
+ }
+}
+
+impl<V: 'static + Send + Sync> Styled for Div<V> {
+ fn style_cascade(&mut self) -> &mut StyleCascade {
+ &mut self.0.child.style_cascade
+ }
+}
+
+impl<V: 'static + Send + Sync> Hoverable for Div<V> {
+ fn hover_style(&mut self) -> &mut StyleRefinement {
+ self.0.hover_style()
+ }
+}
@@ -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<Style>;
+
#[derive(Clone, Refineable, Debug)]
#[refineable(debug)]
pub struct Style {
@@ -67,6 +67,8 @@ impl TaffyLayoutEngine {
.into()
}
+ // Used to understand performance
+ #[allow(dead_code)]
fn count_all_children(&self, parent: LayoutId) -> anyhow::Result<u32> {
let mut count = 0;
@@ -81,6 +83,8 @@ impl TaffyLayoutEngine {
Ok(count)
}
+ // Used to understand performance
+ #[allow(dead_code)]
fn max_depth(&self, depth: u32, parent: LayoutId) -> anyhow::Result<u32> {
println!(
"{parent:?} at depth {depth} has {} children",
@@ -96,6 +100,8 @@ impl TaffyLayoutEngine {
Ok(depth + 1 + max_child_depth)
}
+ // Used to understand performance
+ #[allow(dead_code)]
fn get_edges(&self, parent: LayoutId) -> anyhow::Result<Vec<(LayoutId, LayoutId)>> {
let mut edges = Vec::new();
@@ -4,7 +4,7 @@ use crate::{
AnyBox, AnyElement, BorrowWindow, Bounds, Element, ElementId, EntityId, Handle,
IdentifiedElement, IntoAnyElement, LayoutId, Pixels, ViewContext, WindowContext,
};
-use std::{any::Any, marker::PhantomData, sync::Arc};
+use std::{marker::PhantomData, sync::Arc};
pub struct View<S: Send + Sync> {
state: Handle<S>,