From afff46b335e51f031bc1da784af61c2108c64324 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 19 Aug 2023 21:24:28 -0600 Subject: [PATCH] Checkpoint --- crates/gpui/playground/src/div.rs | 123 ++++++++++++------- crates/gpui/playground/src/layout_context.rs | 11 +- crates/gpui/playground/src/paint_context.rs | 22 +++- crates/gpui/src/scene.rs | 21 +++- 4 files changed, 123 insertions(+), 54 deletions(-) diff --git a/crates/gpui/playground/src/div.rs b/crates/gpui/playground/src/div.rs index 946d77e1f1..1cc1d1761e 100644 --- a/crates/gpui/playground/src/div.rs +++ b/crates/gpui/playground/src/div.rs @@ -1,3 +1,4 @@ +use std::cell::Cell; use std::{marker::PhantomData, rc::Rc}; use crate::element::{AnyElement, PaintContext}; @@ -15,20 +16,22 @@ use util::ResultExt; type LayoutId = gpui::LayoutId; #[derive(Deref, DerefMut)] -pub struct Layout> { +pub struct Layout { id: LayoutId, engine_layout: Option, #[deref] #[deref_mut] - element_data: E::Layout, + element_data: D, + view_type: PhantomData, } -impl> Layout { - pub fn new(id: LayoutId, engine_layout: Option, element_data: E::Layout) -> Self { +impl Layout { + pub fn new(id: LayoutId, engine_layout: Option, element_data: D) -> Self { Self { id, engine_layout, element_data, + view_type: PhantomData, } } @@ -36,6 +39,10 @@ impl> Layout { self.engine_layout(cx).bounds } + pub fn order(&mut self, cx: &mut PaintContext) -> u32 { + self.engine_layout(cx).order + } + fn engine_layout(&mut self, cx: &mut PaintContext<'_, '_, '_, '_, V>) -> &mut EngineLayout { self.engine_layout .get_or_insert_with(|| cx.computed_layout(self.id).log_err().unwrap_or_default()) @@ -45,12 +52,20 @@ impl> Layout { pub trait Element { type Layout; - fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result> + fn layout( + &mut self, + view: &mut V, + cx: &mut LayoutContext, + ) -> Result> where Self: Sized; - fn paint(&mut self, view: &mut V, cx: &mut PaintContext) - where + fn paint( + &mut self, + view: &mut V, + layout: &mut Layout, + cx: &mut PaintContext, + ) where Self: Sized; /// ## Helpers @@ -106,7 +121,7 @@ pub fn div() -> Div { impl Element for Div { type Layout = (); - fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result> + fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result> where Self: Sized, { @@ -119,7 +134,7 @@ impl Element for Div { cx.add_layout_node(self.style(), (), children) } - fn paint(&mut self, view: &mut V, cx: &mut PaintContext) + fn paint(&mut self, view: &mut V, layout: &mut Layout, cx: &mut PaintContext) where Self: Sized, { @@ -128,12 +143,65 @@ impl Element for Div { } pub struct Hoverable + Styleable> { - default_style: Style, + hovered: Cell, + child_style: StyleRefinement, hovered_style: StyleRefinement, child: E, view_type: PhantomData, } +pub fn hoverable + Styleable>(mut child: E) -> Hoverable { + Hoverable { + hovered: Cell::new(false), + child_style: child.declared_style().clone(), + hovered_style: Default::default(), + child, + view_type: PhantomData, + } +} + +impl + Styleable> Styleable for Hoverable { + type Style = E::Style; + + fn declared_style(&mut self) -> &mut playground::style::StyleRefinement { + self.child.declared_style() + } +} + +impl + Styleable> Element for Hoverable { + type Layout = E::Layout; + + fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result> + where + Self: Sized, + { + if self.hovered.get() { + // If hovered, refine the child's style with this element's style. + self.child.declared_style().refine(&self.hovered_style); + } else { + // Otherwise, set the child's style back to its original style. + *self.child.declared_style() = self.child_style.clone(); + } + + self.child.layout(view, cx) + } + + fn paint( + &mut self, + view: &mut V, + layout: &mut Layout, + cx: &mut PaintContext, + ) where + Self: Sized, + { + let bounds = layout.bounds(cx); + let order = layout.order(cx); + self.hovered.set(bounds.contains_point(cx.mouse_position())); + let hovered = self.hovered.clone(); + cx.on_event(order, move |view, event: &MouseMovedEvent, cx| {}); + } +} + pub trait Interactive { fn declared_interactions(&mut self) -> &mut Interactions; @@ -154,41 +222,6 @@ pub struct Interactions { mouse_moved: Option) -> bool>>, } -pub fn hoverable + Styleable>(mut child: E) -> Hoverable { - Hoverable { - default_style: child.style(), - hovered_style: Default::default(), - child, - view_type: PhantomData, - } -} - -impl + Styleable> Styleable for Hoverable { - type Style = E::Style; - - fn declared_style(&mut self) -> &mut playground::style::StyleRefinement { - self.child.declared_style() - } -} - -impl + Styleable> Element for Hoverable { - type Layout = E::Layout; - - fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result> - where - Self: Sized, - { - todo!() - } - - fn paint(&mut self, view: &mut V, cx: &mut PaintContext) - where - Self: Sized, - { - todo!() - } -} - #[test] fn test() { // let elt = div().w_auto(); diff --git a/crates/gpui/playground/src/layout_context.rs b/crates/gpui/playground/src/layout_context.rs index a424e561b3..32155de338 100644 --- a/crates/gpui/playground/src/layout_context.rs +++ b/crates/gpui/playground/src/layout_context.rs @@ -4,10 +4,7 @@ pub use gpui::LayoutContext as LegacyLayoutContext; use gpui::{RenderContext, ViewContext}; pub use taffy::tree::NodeId; -use crate::{ - div::{Element, Layout}, - style::Style, -}; +use crate::{div::Layout, style::Style}; #[derive(Deref, DerefMut)] pub struct LayoutContext<'a, 'b, 'c, 'd, V> { @@ -43,12 +40,12 @@ impl<'a, 'b, 'c, 'd, V: 'static> LayoutContext<'a, 'b, 'c, 'd, V> { Self { legacy_cx, scene } } - pub fn add_layout_node>( + pub fn add_layout_node( &mut self, style: Style, - element_data: E::Layout, + element_data: D, children: impl IntoIterator, - ) -> Result> { + ) -> Result> { let rem_size = self.rem_pixels(); let id = self .legacy_cx diff --git a/crates/gpui/playground/src/paint_context.rs b/crates/gpui/playground/src/paint_context.rs index b849c3f131..59e728b6f7 100644 --- a/crates/gpui/playground/src/paint_context.rs +++ b/crates/gpui/playground/src/paint_context.rs @@ -1,7 +1,8 @@ use anyhow::{anyhow, Result}; use derive_more::{Deref, DerefMut}; use gpui::{ - geometry::rect::RectF, EngineLayout, EventContext, LayoutId, RenderContext, ViewContext, + geometry::rect::RectF, scene::EventHandler, EngineLayout, EventContext, LayoutId, + RenderContext, ViewContext, }; pub use gpui::{LayoutContext, PaintContext as LegacyPaintContext}; use std::{any::TypeId, rc::Rc}; @@ -41,6 +42,25 @@ impl<'a, 'b, 'c, 'd, V: 'static> PaintContext<'a, 'b, 'c, 'd, V> { Self { legacy_cx, scene } } + pub fn on_event( + &mut self, + order: u32, + handler: impl Fn(&mut V, &E, &mut ViewContext) + 'static, + ) { + self.scene.event_handlers.push(EventHandler { + order, + handler: Rc::new(move |view, event, window_cx, view_id| { + let mut view_context = ViewContext::mutable(window_cx, view_id); + handler( + view.downcast_mut().unwrap(), + event.downcast_ref().unwrap(), + &mut view_context, + ); + }), + event_type: TypeId::of::(), + }) + } + pub fn draw_interactive_region( &mut self, order: u32, diff --git a/crates/gpui/src/scene.rs b/crates/gpui/src/scene.rs index 7b6c98d8e7..830ffa857e 100644 --- a/crates/gpui/src/scene.rs +++ b/crates/gpui/src/scene.rs @@ -31,8 +31,10 @@ pub struct SceneBuilder { scale_factor: f32, stacking_contexts: Vec, active_stacking_context_stack: Vec, - /// Used by the playground crate. + /// Used by the playground crate. I hope to replace it with event_handlers. pub interactive_regions: Vec, + /// Used by the playground crate. + pub event_handlers: Vec, #[cfg(debug_assertions)] mouse_region_ids: HashSet, } @@ -41,6 +43,7 @@ pub struct Scene { scale_factor: f32, stacking_contexts: Vec, interactive_regions: Vec, + event_handlers: Vec, } struct StackingContext { @@ -282,11 +285,17 @@ impl Scene { .collect() } + /// TODO: Hoping to replace this with take_event_handlers pub fn take_interactive_regions(&mut self) -> Vec { self.interactive_regions .sort_by(|a, b| a.order.cmp(&b.order)); std::mem::take(&mut self.interactive_regions) } + + pub fn take_event_handlers(&mut self) -> Vec { + self.event_handlers.sort_by(|a, b| a.order.cmp(&b.order)); + std::mem::take(&mut self.event_handlers) + } } impl SceneBuilder { @@ -299,6 +308,7 @@ impl SceneBuilder { #[cfg(debug_assertions)] mouse_region_ids: Default::default(), interactive_regions: Vec::new(), + event_handlers: Vec::new(), } } @@ -309,6 +319,7 @@ impl SceneBuilder { scale_factor: self.scale_factor, stacking_contexts: self.stacking_contexts, interactive_regions: self.interactive_regions, + event_handlers: self.event_handlers, } } @@ -717,6 +728,14 @@ pub struct InteractiveRegion { pub view_id: usize, } +pub struct EventHandler { + pub order: u32, + // First param is a dynamic view reference + // Second param is a dynamic event reference + pub handler: Rc, + pub event_type: TypeId, +} + fn can_draw(bounds: RectF) -> bool { let size = bounds.size(); size.x() > 0. && size.y() > 0.