use crate::{ element::{AnyElement, Element, IntoElement, Layout, ParentElement}, interactive::{InteractionHandlers, Interactive}, layout_context::LayoutContext, paint_context::PaintContext, style::{Style, StyleHelpers, Styleable}, }; use anyhow::Result; use gpui::{platform::MouseMovedEvent, LayoutId}; use refineable::{CascadeSlot, Refineable, RefinementCascade}; use smallvec::SmallVec; use std::{cell::Cell, rc::Rc}; pub struct Hoverable { hovered: Rc>, cascade_slot: CascadeSlot, hovered_style: ::Refinement, child: E, } pub fn hoverable(mut child: E) -> Hoverable { Hoverable { hovered: Rc::new(Cell::new(false)), cascade_slot: child.style_cascade().reserve(), hovered_style: Default::default(), child, } } impl Styleable for Hoverable { type Style = E::Style; fn style_cascade(&mut self) -> &mut RefinementCascade { self.child.style_cascade() } fn declared_style(&mut self) -> &mut ::Refinement { &mut self.hovered_style } } impl + Styleable> Element for Hoverable { type PaintState = E::PaintState; fn layout( &mut self, view: &mut V, cx: &mut LayoutContext, ) -> Result<(LayoutId, Self::PaintState)> where Self: Sized, { Ok(self.child.layout(view, cx)?) } fn paint( &mut self, view: &mut V, layout: &Layout, paint_state: &mut Self::PaintState, cx: &mut PaintContext, ) where Self: Sized, { self.hovered .set(layout.bounds.contains_point(cx.mouse_position())); let slot = self.cascade_slot; let style = self.hovered.get().then_some(self.hovered_style.clone()); self.style_cascade().set(slot, style); let hovered = self.hovered.clone(); let bounds = layout.bounds; cx.on_event(layout.order, move |view, event: &MouseMovedEvent, cx| { if bounds.contains_point(cx.mouse_position()) != hovered.get() { cx.repaint(); } }); self.child.paint(view, layout, paint_state, cx); } } impl> StyleHelpers for Hoverable {} impl + Styleable> Interactive for Hoverable { fn interaction_handlers(&mut self) -> &mut InteractionHandlers { self.child.interaction_handlers() } } impl + Styleable> ParentElement for Hoverable { fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { self.child.children_mut() } } impl + Styleable> IntoElement for Hoverable { type Element = Self; fn into_element(self) -> Self::Element { self } }