diff --git a/crates/gpui/src/fonts.rs b/crates/gpui/src/fonts.rs index 19ff468088f2ddaff43c69d3f81db440041f6f78..f360ef933f8f1213a50393d608c29592a57963d4 100644 --- a/crates/gpui/src/fonts.rs +++ b/crates/gpui/src/fonts.rs @@ -155,8 +155,9 @@ impl Refineable for TextStyleRefinement { } } - fn refined(self, refinement: Self::Refinement) -> Self { - todo!() + fn refined(mut self, refinement: Self::Refinement) -> Self { + self.refine(&refinement); + self } } diff --git a/crates/gpui3/src/active.rs b/crates/gpui3/src/active.rs new file mode 100644 index 0000000000000000000000000000000000000000..93cdb9d8bbd858874c22b97e71a1f4f18f56ac11 --- /dev/null +++ b/crates/gpui3/src/active.rs @@ -0,0 +1,25 @@ +use crate::{SharedString, StyleRefinement}; + +pub trait Active { + fn set_active_style(&mut self, group_name: Option, style: StyleRefinement); + + fn active(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self + where + Self: Sized, + { + self.set_active_style(None, f(StyleRefinement::default())); + self + } + + fn group_active( + mut self, + group_name: impl Into, + f: impl FnOnce(StyleRefinement) -> StyleRefinement, + ) -> Self + where + Self: Sized, + { + self.set_active_style(Some(group_name.into()), f(StyleRefinement::default())); + self + } +} diff --git a/crates/gpui3/src/element.rs b/crates/gpui3/src/element.rs index ad4cfa97bc036c3cac19ded2e8419e7595315c7f..b9c42721d17c7c24e3842ab5e48bc54edd5424f8 100644 --- a/crates/gpui3/src/element.rs +++ b/crates/gpui3/src/element.rs @@ -1,9 +1,4 @@ -use std::sync::Arc; - -use crate::{ - BorrowWindow, Bounds, Clickable, ElementId, Group, LayoutId, MouseDownEvent, MouseUpEvent, - Pixels, Point, SharedString, ViewContext, -}; +use crate::{BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, ViewContext}; use derive_more::{Deref, DerefMut}; pub(crate) use smallvec::SmallVec; @@ -11,7 +6,7 @@ pub trait Element: 'static + Send + Sync + IntoAnyElement { type ViewState: 'static + Send + Sync; type ElementState: 'static + Send + Sync; - fn element_id(&self) -> Option; + fn id(&self) -> Option; fn layout( &mut self, @@ -27,46 +22,34 @@ pub trait Element: 'static + Send + Sync + IntoAnyElement { element_state: &mut Self::ElementState, cx: &mut ViewContext, ); +} - fn group(self, name: impl Into) -> Group - where - Self: Sized, - { - Group::new(name.into(), self) - } +#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)] +pub(crate) struct GlobalElementId(SmallVec<[ElementId; 8]>); + +pub trait ElementIdentity: 'static + Send + Sync { + fn id(&self) -> Option; } -pub trait IdentifiedElement: Element { - fn element_id(&self) -> ElementId { - Element::element_id(self).unwrap() - } +pub struct IdentifiedElement(pub(crate) ElementId); +pub struct AnonymousElement; - fn on_click( - self, - listener: impl Fn( - &mut Self::ViewState, - (&MouseDownEvent, &MouseUpEvent), - &mut ViewContext, - ) + Send - + Sync - + 'static, - ) -> Clickable - where - Self: Sized, - { - Clickable::new(self, Arc::from(listener)) +impl ElementIdentity for IdentifiedElement { + fn id(&self) -> Option { + Some(self.0.clone()) } } -#[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)] -pub(crate) struct GlobalElementId(SmallVec<[ElementId; 8]>); - -pub trait ParentElement { - type State; +impl ElementIdentity for AnonymousElement { + fn id(&self) -> Option { + None + } +} - fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>; +pub trait ParentElement: Element { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>; - fn child(mut self, child: impl IntoAnyElement) -> Self + fn child(mut self, child: impl IntoAnyElement) -> Self where Self: Sized, { @@ -74,7 +57,10 @@ pub trait ParentElement { self } - fn children(mut self, iter: impl IntoIterator>) -> Self + fn children( + mut self, + iter: impl IntoIterator>, + ) -> Self where Self: Sized, { @@ -126,7 +112,7 @@ impl RenderedElement { frame_state: &mut Option, cx: &mut ViewContext, ) { - if let Some(id) = self.element.element_id() { + if let Some(id) = self.element.id() { cx.with_element_state(id, |element_state, cx| { let mut element_state = element_state.unwrap(); self.element @@ -146,7 +132,7 @@ where S: 'static + Send + Sync, { fn layout(&mut self, state: &mut E::ViewState, cx: &mut ViewContext) -> LayoutId { - let (layout_id, frame_state) = if let Some(id) = self.element.element_id() { + let (layout_id, frame_state) = if let Some(id) = self.element.id() { let layout_id = cx.with_element_state(id, |element_state, cx| { self.element.layout(state, element_state, cx) }); diff --git a/crates/gpui3/src/elements.rs b/crates/gpui3/src/elements.rs index e0ad68abfc1df6a0ef1a3345e4f15f8a1b0b9bd2..83c27b8a3b1a88e6dee517c485f5f99ea1df7a93 100644 --- a/crates/gpui3/src/elements.rs +++ b/crates/gpui3/src/elements.rs @@ -1,20 +1,9 @@ -mod clickable; mod div; -mod group; -mod hoverable; -mod identified; mod img; -mod nested; -mod pressable; mod svg; mod text; -pub use clickable::*; pub use div::*; -pub use group::*; -pub use hoverable::*; -pub use identified::*; pub use img::*; -pub use pressable::*; pub use svg::*; pub use text::*; diff --git a/crates/gpui3/src/elements/clickable.rs b/crates/gpui3/src/elements/clickable.rs deleted file mode 100644 index 861108a79ac3c08d88d077edc839596d26bfbe25..0000000000000000000000000000000000000000 --- a/crates/gpui3/src/elements/clickable.rs +++ /dev/null @@ -1,144 +0,0 @@ -use crate::{ - AnyElement, Bounds, DispatchPhase, Element, IdentifiedElement, Interactive, IntoAnyElement, - MouseDownEvent, MouseEventListeners, MouseUpEvent, ParentElement, Pixels, Styled, ViewContext, -}; -use parking_lot::Mutex; -use refineable::Cascade; -use smallvec::SmallVec; -use std::sync::Arc; - -pub type ClickListener = - dyn Fn(&mut S, (&MouseDownEvent, &MouseUpEvent), &mut ViewContext) + Send + Sync + 'static; - -pub struct Clickable { - child: E, - listener: Arc>, -} - -pub struct ClickableState { - last_mouse_down: Arc>>, - child_state: S, -} - -impl Clickable { - pub fn new(child: E, listener: Arc>) -> Self { - Self { child, listener } - } -} - -impl Styled for Clickable -where - E: Styled + IdentifiedElement, -{ - type Style = E::Style; - - fn style_cascade(&mut self) -> &mut Cascade { - self.child.style_cascade() - } - - fn declared_style(&mut self) -> &mut ::Refinement { - self.child.declared_style() - } -} - -impl Interactive for Clickable -where - S: 'static + Send + Sync, - E: IdentifiedElement + Interactive, -{ - fn listeners(&mut self) -> &mut MouseEventListeners { - self.child.listeners() - } -} - -impl IntoAnyElement for Clickable { - fn into_any(self) -> AnyElement { - AnyElement::new(self) - } -} - -impl Element for Clickable -where - E: IdentifiedElement, -{ - type ViewState = E::ViewState; - type ElementState = ClickableState; - - fn element_id(&self) -> Option { - Some(IdentifiedElement::element_id(&self.child)) - } - - fn layout( - &mut self, - state: &mut Self::ViewState, - element_state: Option, - cx: &mut ViewContext, - ) -> (crate::LayoutId, Self::ElementState) { - if let Some(element_state) = element_state { - let (layout_id, child_state) = - self.child - .layout(state, Some(element_state.child_state), cx); - - let element_state = ClickableState { - last_mouse_down: element_state.last_mouse_down, - child_state, - }; - (layout_id, element_state) - } else { - let (layout_id, child_state) = self.child.layout(state, None, cx); - let element_state = ClickableState { - last_mouse_down: Default::default(), - child_state, - }; - (layout_id, element_state) - } - } - - fn paint( - &mut self, - bounds: Bounds, - state: &mut Self::ViewState, - element_state: &mut Self::ElementState, - cx: &mut ViewContext, - ) { - let last_mouse_down = element_state.last_mouse_down.clone(); - let is_some = last_mouse_down.lock().is_some(); - - if is_some { - let listener = self.listener.clone(); - cx.on_mouse_event(move |view, up_event: &MouseUpEvent, phase, cx| { - if phase == DispatchPhase::Capture && !bounds.contains_point(up_event.position) { - *last_mouse_down.lock() = None; - } else if phase == DispatchPhase::Bubble && bounds.contains_point(up_event.position) - { - if let Some(down_event) = last_mouse_down.lock().take() { - listener(view, (&down_event, up_event), cx); - } else { - log::error!("No mouse down event found for click event"); - } - } - }) - } else { - cx.on_mouse_event(move |_, event: &MouseDownEvent, phase, _| { - if phase == DispatchPhase::Bubble { - if bounds.contains_point(event.position) { - *last_mouse_down.lock() = Some(event.clone()); - } - } - }) - } - - self.child - .paint(bounds, state, &mut element_state.child_state, cx); - } -} - -impl ParentElement for Clickable { - type State = E::State; - - fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { - self.child.children_mut() - } -} - -impl IdentifiedElement for Clickable where E: IdentifiedElement + Styled {} diff --git a/crates/gpui3/src/elements/div.rs b/crates/gpui3/src/elements/div.rs index 444e0956847a5c2252a07151afdff623b0816e1f..d110d811320e1b462259b3bb4e99209ea1deeec5 100644 --- a/crates/gpui3/src/elements/div.rs +++ b/crates/gpui3/src/elements/div.rs @@ -1,246 +1,494 @@ use crate::{ - AnyElement, BorrowWindow, Bounds, Cascade, Element, ElementId, IdentifiedElement, Interactive, - IntoAnyElement, LayoutId, MouseEventListeners, Overflow, ParentElement, Pixels, Point, - Refineable, Style, Styled, ViewContext, + Active, AnonymousElement, AnyElement, AppContext, BorrowWindow, Bounds, Click, DispatchPhase, + Element, ElementId, ElementIdentity, Hover, IdentifiedElement, Interactive, IntoAnyElement, + LayoutId, MouseClickEvent, MouseDownEvent, MouseEventListeners, MouseMoveEvent, MouseUpEvent, + Overflow, ParentElement, Pixels, Point, ScrollWheelEvent, SharedString, Style, StyleRefinement, + Styled, ViewContext, }; +use collections::HashMap; use parking_lot::Mutex; +use refineable::Refineable; use smallvec::SmallVec; -use std::{marker::PhantomData, sync::Arc}; +use std::sync::Arc; -pub enum HasId {} +#[derive(Default)] +pub struct DivState { + active_state: Arc>, + pending_click: Arc>>, +} -pub struct Div { - styles: Cascade