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 refineable::Refineable;
use crate::{
group_bounds, AnyElement, DispatchPhase, Element, IntoAnyElement, MouseMoveEvent, SharedString,
Style, StyleCascade, StyleRefinement,
};
use refineable::CascadeSlot;
use smallvec::SmallVec;
use std::sync::{
atomic::{AtomicBool, Ordering::SeqCst},
Arc,
};
trait LayoutNode<V: 'static + Send + Sync> {
fn state(&mut self) -> &mut LayoutNodeState<V>;
@ -28,6 +35,7 @@ trait LayoutNode<V: 'static + Send + Sync> {
struct LayoutNodeState<V: 'static + Send + Sync> {
style_cascade: StyleCascade,
computed_style: Option<Style>,
children: SmallVec<[AnyElement<V>; 2]>,
}
@ -61,7 +69,7 @@ impl<V: 'static + Send + Sync> Element for LayoutNodeState<V> {
.collect::<Vec<_>>();
// 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);
(layout_id, ())
}
@ -81,6 +89,49 @@ impl<V: 'static + Send + Sync> Element for LayoutNodeState<V> {
pub trait Styled {
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 {
@ -95,18 +146,83 @@ pub trait Hoverable {
}
}
struct HoverableState<Child: Styled + Element> {
struct HoverableElement<Child> {
hover_style: StyleRefinement,
group: Option<SharedString>,
cascade_slot: CascadeSlot,
hovered: Arc<AtomicBool>,
child: Child,
}
impl<Child: Styled + Element> HoverableState<Child> {
impl<Child: Styled + Element> HoverableElement<Child> {
fn hover_style(&mut self) -> &mut StyleRefinement {
&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> {
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 {
&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> {
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)]
#[refineable(debug)]
#[repr(C)]
pub struct Bounds<T: Clone + Debug> {
pub struct Bounds<T: Clone + Debug + Default> {
pub origin: Point<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 {
let origin = Point {
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 {
let my_lower_right = self.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 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>

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()
.map(|field| {
let name = &field.ident;
@ -106,7 +110,34 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
})
.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()
.map(|field| {
let name = &field.ident;
@ -126,6 +157,49 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
})
.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 refinement_field_debugs: Vec<TokenStream2> = fields
.iter()
@ -173,7 +247,12 @@ pub fn derive_refineable(input: TokenStream) -> TokenStream {
type Refinement = #refinement_ident #ty_generics;
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;
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;
fn refine(&mut self, refinement: &Self::Refinement);
fn refined(mut 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 refined(self, refinement: Self::Refinement) -> Self;
fn from_cascade(cascade: &Cascade<Self>) -> Self
where
Self: Default + Sized,
{
Self::default().refined(&cascade.merged())
Self::default().refined(cascade.merged())
}
}