From 4855b8f3dea4f765d7684899955fe1756a22fcd6 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 10 Oct 2023 20:02:23 +0200 Subject: [PATCH] WIP --- crates/gpui3/src/elements.rs | 2 + crates/gpui3/src/elements/pressable.rs | 229 ++++++++++++++++++------- 2 files changed, 169 insertions(+), 62 deletions(-) diff --git a/crates/gpui3/src/elements.rs b/crates/gpui3/src/elements.rs index 5c8381ad77d9ee1467abbe5c312f860e7daef77f..b2653b22a3231aae904dbc39ea405cb0296e3ccd 100644 --- a/crates/gpui3/src/elements.rs +++ b/crates/gpui3/src/elements.rs @@ -2,6 +2,7 @@ mod div; mod hoverable; mod identified; mod img; +mod pressable; mod stateless; mod svg; mod text; @@ -10,6 +11,7 @@ pub use div::*; pub use hoverable::*; pub use identified::*; pub use img::*; +pub use pressable::*; pub use stateless::*; pub use svg::*; pub use text::*; diff --git a/crates/gpui3/src/elements/pressable.rs b/crates/gpui3/src/elements/pressable.rs index 6e9b031edae0905541d14bcd6b232589936bb3cd..9390785ba853092ec9f573142ea64ba6f83af49a 100644 --- a/crates/gpui3/src/elements/pressable.rs +++ b/crates/gpui3/src/elements/pressable.rs @@ -1,106 +1,211 @@ use crate::{ - element::{AnyElement, Element, IntoElement, Layout, ParentElement}, - interactive::{InteractionHandlers, Interactive}, - style::{Style, StyleHelpers, Styleable}, - ViewContext, + AnyElement, Bounds, DispatchPhase, Element, Identified, Interactive, MouseDownEvent, + MouseEventListeners, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Styled, ViewContext, }; use anyhow::Result; -use gpui::{geometry::vector::Vector2F, platform::MouseButtonEvent, LayoutId}; use refineable::{CascadeSlot, Refineable, RefinementCascade}; use smallvec::SmallVec; -use std::{cell::Cell, rc::Rc}; +use std::sync::{ + atomic::{AtomicBool, Ordering::SeqCst}, + Arc, +}; -pub struct Pressable { - pressed: Rc>, - pressed_style: ::Refinement, +pub struct Pressable { + pressed: Arc, cascade_slot: CascadeSlot, + pressed_style: ::Refinement, child: E, } -pub fn pressable(mut child: E) -> Pressable { - Pressable { - pressed: Rc::new(Cell::new(false)), - pressed_style: Default::default(), - cascade_slot: child.style_cascade().reserve(), - child, +impl Pressable { + pub fn new(mut child: E) -> Self { + Self { + pressed: Arc::new(AtomicBool::new(false)), + cascade_slot: child.style_cascade().reserve(), + pressed_style: Default::default(), + child, + } } } -impl Styleable for Pressable { +impl Styled for Pressable +where + E: Styled, +{ type Style = E::Style; - fn declared_style(&mut self) -> &mut ::Refinement { + fn style_cascade(&mut self) -> &mut RefinementCascade { + self.child.style_cascade() + } + + fn declared_style(&mut self) -> &mut ::Refinement { &mut self.pressed_style } +} - fn style_cascade(&mut self) -> &mut RefinementCascade { - self.child.style_cascade() +impl + Styled> Interactive for Pressable { + fn listeners(&mut self) -> &mut MouseEventListeners { + self.child.listeners() } } -impl + Styleable> Element for Pressable { - type PaintState = E::PaintState; +impl Element for Pressable { + type State = E::State; + type FrameState = E::FrameState; fn layout( &mut self, - view: &mut V, - cx: &mut ViewContext, - ) -> Result<(LayoutId, Self::PaintState)> - where - Self: Sized, - { - self.child.layout(view, cx) + state: &mut Self::State, + cx: &mut ViewContext, + ) -> Result<(crate::LayoutId, Self::FrameState)> { + Ok(self.child.layout(state, cx)?) } fn paint( &mut self, - view: &mut V, - parent_origin: Vector2F, - layout: &Layout, - paint_state: &mut Self::PaintState, - cx: &mut ViewContext, - ) where - Self: Sized, - { + bounds: Bounds, + state: &mut Self::State, + frame_state: &mut Self::FrameState, + cx: &mut ViewContext, + ) -> Result<()> { + let pressed = bounds.contains_point(cx.mouse_position()); let slot = self.cascade_slot; - let style = self.pressed.get().then_some(self.pressed_style.clone()); + let style = pressed.then_some(self.pressed_style.clone()); self.style_cascade().set(slot, style); + self.pressed.store(pressed, SeqCst); - let pressed = self.pressed.clone(); - let bounds = layout.bounds + parent_origin; - cx.on_event(layout.order, move |_view, event: &MouseButtonEvent, cx| { - if event.is_down { - if bounds.contains_point(event.position) { - pressed.set(true); - cx.repaint(); + let hovered = self.pressed.clone(); + cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { + if phase == DispatchPhase::Capture { + if bounds.contains_point(event.position) != hovered.load(SeqCst) { + cx.notify(); + } + } + }); + cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { + if phase == DispatchPhase::Capture { + if bounds.contains_point(event.position) != hovered.load(SeqCst) { + cx.notify(); } - } else if pressed.get() { - pressed.set(false); - cx.repaint(); } }); - self.child - .paint(view, parent_origin, layout, paint_state, cx); + self.child.paint(bounds, state, frame_state, cx)?; + Ok(()) } } -impl + Styleable> Interactive for Pressable { - fn interaction_handlers(&mut self) -> &mut InteractionHandlers { - self.child.interaction_handlers() - } -} +impl ParentElement for Pressable { + type State = E::State; -impl + Styleable> ParentElement for Pressable { - fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { self.child.children_mut() } } -impl + Styleable> IntoElement for Pressable { - type Element = Self; +// use crate::{ +// element::{AnyElement, Element, IntoElement, Layout, ParentElement}, +// interactive::{InteractionHandlers, Interactive}, +// style::{Style, StyleHelpers, Styleable}, +// ViewContext, +// }; +// use anyhow::Result; +// use gpui::{geometry::vector::Vector2F, platform::MouseButtonEvent, LayoutId}; +// use refineable::{CascadeSlot, Refineable, RefinementCascade}; +// use smallvec::SmallVec; +// use std::{cell::Cell, rc::Rc}; - fn into_element(self) -> Self::Element { - self - } -} +// pub struct Pressable { +// pressed: Rc>, +// pressed_style: ::Refinement, +// cascade_slot: CascadeSlot, +// child: E, +// } + +// pub fn pressable(mut child: E) -> Pressable { +// Pressable { +// pressed: Rc::new(Cell::new(false)), +// pressed_style: Default::default(), +// cascade_slot: child.style_cascade().reserve(), +// child, +// } +// } + +// impl Styleable for Pressable { +// type Style = E::Style; + +// fn declared_style(&mut self) -> &mut ::Refinement { +// &mut self.pressed_style +// } + +// fn style_cascade(&mut self) -> &mut RefinementCascade { +// self.child.style_cascade() +// } +// } + +// impl + Styleable> Element for Pressable { +// type PaintState = E::PaintState; + +// fn layout( +// &mut self, +// view: &mut V, +// cx: &mut ViewContext, +// ) -> Result<(LayoutId, Self::PaintState)> +// where +// Self: Sized, +// { +// self.child.layout(view, cx) +// } + +// fn paint( +// &mut self, +// view: &mut V, +// parent_origin: Vector2F, +// layout: &Layout, +// paint_state: &mut Self::PaintState, +// cx: &mut ViewContext, +// ) where +// Self: Sized, +// { +// let slot = self.cascade_slot; +// let style = self.pressed.get().then_some(self.pressed_style.clone()); +// self.style_cascade().set(slot, style); + +// let pressed = self.pressed.clone(); +// let bounds = layout.bounds + parent_origin; +// cx.on_event(layout.order, move |_view, event: &MouseButtonEvent, cx| { +// if event.is_down { +// if bounds.contains_point(event.position) { +// pressed.set(true); +// cx.repaint(); +// } +// } else if pressed.get() { +// pressed.set(false); +// cx.repaint(); +// } +// }); + +// self.child +// .paint(view, parent_origin, layout, paint_state, cx); +// } +// } + +// impl + Styleable> Interactive for Pressable { +// fn interaction_handlers(&mut self) -> &mut InteractionHandlers { +// self.child.interaction_handlers() +// } +// } + +// impl + Styleable> ParentElement for Pressable { +// fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { +// self.child.children_mut() +// } +// } + +// impl + Styleable> IntoElement for Pressable { +// type Element = Self; + +// fn into_element(self) -> Self::Element { +// self +// } +// }