This commit is contained in:
Antonio Scandurra 2023-10-13 19:05:51 +02:00
parent 90f226193c
commit fedb787b4f
5 changed files with 239 additions and 29 deletions

View file

@ -1,6 +1,13 @@
use crate::{AnyElement, Element, IntoAnyElement, Style, StyleCascade, StyleRefinement}; use crate::{
use refineable::Refineable; group_bounds, AnyElement, DispatchPhase, Element, IntoAnyElement, MouseMoveEvent, SharedString,
Style, StyleCascade, StyleRefinement,
};
use refineable::CascadeSlot;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::sync::{
atomic::{AtomicBool, Ordering::SeqCst},
Arc,
};
trait LayoutNode<V: 'static + Send + Sync> { trait LayoutNode<V: 'static + Send + Sync> {
fn state(&mut self) -> &mut LayoutNodeState<V>; fn state(&mut self) -> &mut LayoutNodeState<V>;
@ -28,6 +35,7 @@ trait LayoutNode<V: 'static + Send + Sync> {
struct LayoutNodeState<V: 'static + Send + Sync> { struct LayoutNodeState<V: 'static + Send + Sync> {
style_cascade: StyleCascade, style_cascade: StyleCascade,
computed_style: Option<Style>,
children: SmallVec<[AnyElement<V>; 2]>, children: SmallVec<[AnyElement<V>; 2]>,
} }
@ -61,7 +69,7 @@ impl<V: 'static + Send + Sync> Element for LayoutNodeState<V> {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// todo!("pass just the style cascade") // todo!("pass just the style cascade")
let style = Style::from_refinement(&self.style_cascade().merged()); let style = self.computed_style().clone();
let layout_id = cx.request_layout(style, layout_ids); let layout_id = cx.request_layout(style, layout_ids);
(layout_id, ()) (layout_id, ())
} }
@ -81,6 +89,49 @@ impl<V: 'static + Send + Sync> Element for LayoutNodeState<V> {
pub trait Styled { pub trait Styled {
fn style_cascade(&mut self) -> &mut StyleCascade; fn style_cascade(&mut self) -> &mut StyleCascade;
fn computed_style(&mut self) -> &Style;
}
pub struct StyledElement<E> {
child: E,
}
impl<E> IntoAnyElement<E::ViewState> for StyledElement<E>
where
E: Element + Styled,
{
fn into_any(self) -> AnyElement<E::ViewState> {
AnyElement::new(self)
}
}
impl<E: Element + Styled> Element for StyledElement<E> {
type ViewState = E::ViewState;
type ElementState = E::ElementState;
fn element_id(&self) -> Option<crate::ElementId> {
self.child.element_id()
}
fn layout(
&mut self,
state: &mut Self::ViewState,
element_state: Option<Self::ElementState>,
cx: &mut crate::ViewContext<Self::ViewState>,
) -> (crate::LayoutId, Self::ElementState) {
self.child.layout(state, element_state, cx)
}
fn paint(
&mut self,
bounds: crate::Bounds<crate::Pixels>,
state: &mut Self::ViewState,
element_state: &mut Self::ElementState,
cx: &mut crate::ViewContext<Self::ViewState>,
) {
self.child.computed_style().paint(bounds, cx);
self.child.paint(bounds, state, element_state, cx);
}
} }
pub trait Hoverable { pub trait Hoverable {
@ -95,18 +146,83 @@ pub trait Hoverable {
} }
} }
struct HoverableState<Child: Styled + Element> { struct HoverableElement<Child> {
hover_style: StyleRefinement, hover_style: StyleRefinement,
group: Option<SharedString>,
cascade_slot: CascadeSlot,
hovered: Arc<AtomicBool>,
child: Child, child: Child,
} }
impl<Child: Styled + Element> HoverableState<Child> { impl<Child: Styled + Element> HoverableElement<Child> {
fn hover_style(&mut self) -> &mut StyleRefinement { fn hover_style(&mut self) -> &mut StyleRefinement {
&mut self.hover_style &mut self.hover_style
} }
} }
struct Div<V: 'static + Send + Sync>(HoverableState<LayoutNodeState<V>>); impl<E> IntoAnyElement<E::ViewState> for HoverableElement<E>
where
E: Element + Styled,
{
fn into_any(self) -> AnyElement<E::ViewState> {
AnyElement::new(self)
}
}
impl<E> Element for HoverableElement<E>
where
E: Element + Styled,
{
type ViewState = E::ViewState;
type ElementState = E::ElementState;
fn element_id(&self) -> Option<crate::ElementId> {
self.child.element_id()
}
fn layout(
&mut self,
state: &mut Self::ViewState,
element_state: Option<Self::ElementState>,
cx: &mut crate::ViewContext<Self::ViewState>,
) -> (crate::LayoutId, Self::ElementState) {
self.child.layout(state, element_state, cx)
}
fn paint(
&mut self,
bounds: crate::Bounds<crate::Pixels>,
state: &mut Self::ViewState,
element_state: &mut Self::ElementState,
cx: &mut crate::ViewContext<Self::ViewState>,
) {
let target_bounds = self
.group
.as_ref()
.and_then(|group| group_bounds(group, cx))
.unwrap_or(bounds);
let hovered = target_bounds.contains_point(cx.mouse_position());
let slot = self.cascade_slot;
let style = hovered.then_some(self.hover_style.clone());
self.child.style_cascade().set(slot, style);
self.hovered.store(hovered, SeqCst);
let hovered = self.hovered.clone();
cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
if phase == DispatchPhase::Capture {
if target_bounds.contains_point(event.position) != hovered.load(SeqCst) {
cx.notify();
}
}
});
self.child.paint(bounds, state, element_state, cx);
}
}
struct Div<V: 'static + Send + Sync>(HoverableElement<LayoutNodeState<V>>);
impl<V: 'static + Send + Sync> LayoutNode<V> for Div<V> { impl<V: 'static + Send + Sync> LayoutNode<V> for Div<V> {
fn state(&mut self) -> &mut LayoutNodeState<V> { fn state(&mut self) -> &mut LayoutNodeState<V> {
@ -118,11 +234,20 @@ impl<V: 'static + Send + Sync> Styled for LayoutNodeState<V> {
fn style_cascade(&mut self) -> &mut StyleCascade { fn style_cascade(&mut self) -> &mut StyleCascade {
&mut self.style_cascade &mut self.style_cascade
} }
fn computed_style(&mut self) -> &Style {
self.computed_style
.get_or_insert_with(|| Style::from(self.style_cascade.merged()))
}
} }
impl<V: 'static + Send + Sync> Styled for Div<V> { impl<V: 'static + Send + Sync> Styled for Div<V> {
fn style_cascade(&mut self) -> &mut StyleCascade { fn style_cascade(&mut self) -> &mut StyleCascade {
&mut self.0.child.style_cascade self.0.child.style_cascade()
}
fn computed_style(&mut self) -> &Style {
self.0.child.computed_style()
} }
} }

View file

@ -244,12 +244,12 @@ impl Size<Length> {
#[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)] #[derive(Refineable, Clone, Default, Debug, Eq, PartialEq)]
#[refineable(debug)] #[refineable(debug)]
#[repr(C)] #[repr(C)]
pub struct Bounds<T: Clone + Debug> { pub struct Bounds<T: Clone + Debug + Default> {
pub origin: Point<T>, pub origin: Point<T>,
pub size: Size<T>, pub size: Size<T>,
} }
impl<T: Clone + Debug + Sub<Output = T>> Bounds<T> { impl<T: Clone + Debug + Sub<Output = T> + Default> Bounds<T> {
pub fn from_corners(upper_left: Point<T>, lower_right: Point<T>) -> Self { pub fn from_corners(upper_left: Point<T>, lower_right: Point<T>) -> Self {
let origin = Point { let origin = Point {
x: upper_left.x.clone(), x: upper_left.x.clone(),
@ -263,7 +263,7 @@ impl<T: Clone + Debug + Sub<Output = T>> Bounds<T> {
} }
} }
impl<T: Clone + Debug + PartialOrd + Add<T, Output = T> + Sub<Output = T>> Bounds<T> { impl<T: Clone + Debug + PartialOrd + Add<T, Output = T> + Sub<Output = T> + Default> Bounds<T> {
pub fn intersects(&self, other: &Bounds<T>) -> bool { pub fn intersects(&self, other: &Bounds<T>) -> bool {
let my_lower_right = self.lower_right(); let my_lower_right = self.lower_right();
let their_lower_right = other.lower_right(); let their_lower_right = other.lower_right();

View file

@ -7,7 +7,10 @@ pub trait Styled {
fn declared_style(&mut self) -> &mut <Self::Style as Refineable>::Refinement; fn declared_style(&mut self) -> &mut <Self::Style as Refineable>::Refinement;
fn computed_style(&mut self) -> Self::Style { fn computed_style(&mut self) -> Self::Style {
Self::Style::from_refinement(&self.style_cascade().merged()) todo!()
// let x: StyleRefinement = self.style_cascade().merged();
// x.into();
} }
fn hover(self) -> Hoverable<Self> fn hover(self) -> Hoverable<Self>

View file

@ -79,7 +79,11 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
}, },
}; };
let field_assignments: Vec<TokenStream2> = fields // refinable_refine_assignments
// refinable_refined_assignments
// refinement_refine_assignments
let refineable_refine_assignments: Vec<TokenStream2> = fields
.iter() .iter()
.map(|field| { .map(|field| {
let name = &field.ident; let name = &field.ident;
@ -106,7 +110,34 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
}) })
.collect(); .collect();
let refinement_field_assignments: Vec<TokenStream2> = fields let refineable_refined_assignments: Vec<TokenStream2> = fields
.iter()
.map(|field| {
let name = &field.ident;
let is_refineable = is_refineable_field(field);
let is_optional = is_optional_field(field);
if is_refineable {
quote! {
self.#name = self.#name.refined(refinement.#name);
}
} else if is_optional {
quote! {
if let Some(value) = refinement.#name {
self.#name = Some(value);
}
}
} else {
quote! {
if let Some(value) = refinement.#name {
self.#name = value;
}
}
}
})
.collect();
let refinement_refine_assigments: Vec<TokenStream2> = fields
.iter() .iter()
.map(|field| { .map(|field| {
let name = &field.ident; let name = &field.ident;
@ -126,6 +157,49 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
}) })
.collect(); .collect();
let refinement_refined_assigments: Vec<TokenStream2> = fields
.iter()
.map(|field| {
let name = &field.ident;
let is_refineable = is_refineable_field(field);
if is_refineable {
quote! {
self.#name = self.#name.refined(refinement.#name);
}
} else {
quote! {
if let Some(value) = refinement.#name {
self.#name = Some(value);
}
}
}
})
.collect();
let from_refinement_assigments: Vec<TokenStream2> = fields
.iter()
.map(|field| {
let name = &field.ident;
let is_refineable = is_refineable_field(field);
let is_optional = is_optional_field(field);
if is_refineable {
quote! {
#name: value.#name.into(),
}
} else if is_optional {
quote! {
#name: value.#name.map(|v| v.into()),
}
} else {
quote! {
#name: value.#name.map(|v| v.into()).unwrap_or_default(),
}
}
})
.collect();
let debug_impl = if impl_debug_on_refinement { let debug_impl = if impl_debug_on_refinement {
let refinement_field_debugs: Vec<TokenStream2> = fields let refinement_field_debugs: Vec<TokenStream2> = fields
.iter() .iter()
@ -173,7 +247,12 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
type Refinement = #refinement_ident #ty_generics; type Refinement = #refinement_ident #ty_generics;
fn refine(&mut self, refinement: &Self::Refinement) { fn refine(&mut self, refinement: &Self::Refinement) {
#( #field_assignments )* #( #refineable_refine_assignments )*
}
fn refined(mut self, refinement: Self::Refinement) -> Self {
#( #refineable_refined_assignments )*
self
} }
} }
@ -183,7 +262,22 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
type Refinement = #refinement_ident #ty_generics; type Refinement = #refinement_ident #ty_generics;
fn refine(&mut self, refinement: &Self::Refinement) { fn refine(&mut self, refinement: &Self::Refinement) {
#( #refinement_field_assignments )* #( #refinement_refine_assigments )*
}
fn refined(mut self, refinement: Self::Refinement) -> Self {
#( #refinement_refined_assigments )*
self
}
}
impl #impl_generics From<#refinement_ident #ty_generics> for #ident #ty_generics
#where_clause
{
fn from(value: #refinement_ident #ty_generics) -> Self {
Self {
#( #from_refinement_assigments )*
}
} }
} }

View file

@ -4,24 +4,12 @@ pub trait Refineable: Clone {
type Refinement: Refineable<Refinement = Self::Refinement> + Default; type Refinement: Refineable<Refinement = Self::Refinement> + Default;
fn refine(&mut self, refinement: &Self::Refinement); fn refine(&mut self, refinement: &Self::Refinement);
fn refined(mut self, refinement: &Self::Refinement) -> Self fn refined(self, refinement: Self::Refinement) -> Self;
where
Self: Sized,
{
self.refine(refinement);
self
}
fn from_refinement(refinement: &Self::Refinement) -> Self
where
Self: Default + Sized,
{
Self::default().refined(refinement)
}
fn from_cascade(cascade: &Cascade<Self>) -> Self fn from_cascade(cascade: &Cascade<Self>) -> Self
where where
Self: Default + Sized, Self: Default + Sized,
{ {
Self::default().refined(&cascade.merged()) Self::default().refined(cascade.merged())
} }
} }