diff --git a/crates/gpui3/src/element.rs b/crates/gpui3/src/element.rs index 445739017188fe1ed4049fc6d7c067761c05f2d9..e96f5e6b28969ddee66fcde9c5234deb21e0347b 100644 --- a/crates/gpui3/src/element.rs +++ b/crates/gpui3/src/element.rs @@ -81,11 +81,17 @@ pub trait ElementInteractivity: 'static + Send + Sync } } - fn refine_style(&self, style: &mut Style, bounds: Bounds, cx: &mut ViewContext) { + fn refine_style( + &self, + style: &mut Style, + bounds: Bounds, + active_state: &Mutex, + cx: &mut ViewContext, + ) { let mouse_position = cx.mouse_position(); let stateless = self.as_stateless(); - if let Some(group_hover) = stateless.group_hover.as_ref() { - if let Some(group_bounds) = group_bounds(&group_hover.group, cx) { + if let Some(group_hover) = stateless.group_hover_style.as_ref() { + if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) { if group_bounds.contains_point(&mouse_position) { style.refine(&group_hover.style); } @@ -94,12 +100,25 @@ pub trait ElementInteractivity: 'static + Send + Sync if bounds.contains_point(&mouse_position) { style.refine(&stateless.hover_style); } + + if let Some(stateful) = self.as_stateful() { + let active_state = active_state.lock(); + if active_state.group { + if let Some(group_style) = stateful.group_active_style.as_ref() { + style.refine(&group_style.style); + } + } + if active_state.element { + style.refine(&stateful.active_style); + } + } } fn paint( &mut self, bounds: Bounds, pending_click: Arc>>, + interactive_state: Arc>, cx: &mut ViewContext, ) { let stateless = self.as_stateless(); @@ -128,7 +147,7 @@ pub trait ElementInteractivity: 'static + Send + Sync } let hover_group_bounds = stateless - .group_hover + .group_hover_style .as_ref() .and_then(|group_hover| GroupBounds::get(&group_hover.group, cx)); @@ -164,7 +183,32 @@ pub trait ElementInteractivity: 'static + Send + Sync *pending_click.lock() = Some(event.clone()); } }); - }; + } + + if interactive_state.lock().is_none() { + let active_group_bounds = stateful + .group_active_style + .as_ref() + .and_then(|group_active| GroupBounds::get(&group_active.group, cx)); + cx.on_mouse_event(move |_view, down: &MouseDownEvent, phase, cx| { + if phase == DispatchPhase::Bubble { + let group = active_group_bounds + .map_or(false, |bounds| bounds.contains_point(&down.position)); + let element = bounds.contains_point(&down.position); + if group || element { + *interactive_state.lock() = InteractiveElementState { group, element }; + cx.notify(); + } + } + }); + } else { + cx.on_mouse_event(move |_, _: &MouseUpEvent, phase, cx| { + if phase == DispatchPhase::Capture { + *interactive_state.lock() = InteractiveElementState::default(); + cx.notify(); + } + }); + } } } } @@ -190,6 +234,8 @@ pub struct StatefulInteractivity { #[deref_mut] stateless: StatelessInteractivity, pub mouse_click_listeners: SmallVec<[MouseClickListener; 2]>, + pub active_style: StyleRefinement, + pub group_active_style: Option, } impl ElementInteractivity for StatefulInteractivity @@ -222,6 +268,8 @@ where id, stateless: StatelessInteractivity::default(), mouse_click_listeners: SmallVec::new(), + active_style: StyleRefinement::default(), + group_active_style: None, } } } @@ -233,7 +281,7 @@ pub struct StatelessInteractivity { pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>, pub key_listeners: SmallVec<[(TypeId, KeyListener); 32]>, pub hover_style: StyleRefinement, - pub group_hover: Option, + pub group_hover_style: Option, } pub struct GroupStyle { @@ -270,11 +318,16 @@ impl GroupBounds { } } -pub fn group_bounds(name: &SharedString, cx: &mut AppContext) -> Option> { - cx.default_global::() - .0 - .get(name) - .and_then(|bounds_stack| bounds_stack.last().cloned()) +#[derive(Copy, Clone, Default, Eq, PartialEq)] +pub struct InteractiveElementState { + pub group: bool, + pub element: bool, +} + +impl InteractiveElementState { + pub fn is_none(&self) -> bool { + !self.group && !self.element + } } impl Default for StatelessInteractivity { @@ -286,7 +339,7 @@ impl Default for StatelessInteractivity { scroll_wheel_listeners: SmallVec::new(), key_listeners: SmallVec::new(), hover_style: StyleRefinement::default(), - group_hover: None, + group_hover_style: None, } } } diff --git a/crates/gpui3/src/elements/div.rs b/crates/gpui3/src/elements/div.rs index 8a4b29cea7b41074503b53c71cecd93a364b966b..7df9a58bf929842596f4bc17624ea433bd01d5ec 100644 --- a/crates/gpui3/src/elements/div.rs +++ b/crates/gpui3/src/elements/div.rs @@ -1,8 +1,8 @@ use crate::{ - Active, AnyElement, BorrowWindow, Bounds, DispatchPhase, Element, ElementFocusability, - ElementId, ElementInteractivity, Focus, FocusHandle, FocusListeners, Focusable, - GlobalElementId, GroupBounds, GroupStyle, Hover, IntoAnyElement, LayoutId, MouseDownEvent, - MouseUpEvent, NonFocusable, Overflow, ParentElement, Pixels, Point, SharedString, + Active, AnyElement, BorrowWindow, Bounds, Element, ElementFocusability, ElementId, + ElementInteractivity, Focus, FocusHandle, FocusListeners, Focusable, GlobalElementId, + GroupBounds, GroupStyle, Hover, InteractiveElementState, IntoAnyElement, LayoutId, + MouseDownEvent, NonFocusable, Overflow, ParentElement, Pixels, Point, SharedString, StatefulInteractivity, StatefullyInteractive, StatelessInteractivity, StatelesslyInteractive, Style, StyleRefinement, Styled, ViewContext, }; @@ -13,22 +13,10 @@ use std::sync::Arc; #[derive(Default)] pub struct DivState { - active_state: Arc>, + active_state: Arc>, pending_click: Arc>>, } -#[derive(Copy, Clone, Default, Eq, PartialEq)] -struct ActiveState { - group: bool, - element: bool, -} - -impl ActiveState { - pub fn is_none(&self) -> bool { - !self.group && !self.element - } -} - #[derive(Default, Clone)] pub struct ScrollState(Arc>>); @@ -60,8 +48,6 @@ pub struct Div< children: SmallVec<[AnyElement; 2]>, group: Option, base_style: StyleRefinement, - active_style: StyleRefinement, - group_active: Option, } pub fn div() -> Div, NonFocusable> @@ -74,8 +60,6 @@ where children: SmallVec::new(), group: None, base_style: StyleRefinement::default(), - active_style: StyleRefinement::default(), - group_active: None, } } @@ -91,8 +75,6 @@ where children: self.children, group: self.group, base_style: self.base_style, - active_style: self.active_style, - group_active: self.group_active, } } } @@ -171,52 +153,11 @@ where ) -> Style { let mut computed_style = Style::default(); computed_style.refine(&self.base_style); - self.focusability.refine_style(&mut computed_style, cx); self.interactivity - .refine_style(&mut computed_style, bounds, cx); - - let active_state = *state.active_state.lock(); - if active_state.group { - if let Some(GroupStyle { style, .. }) = self.group_active.as_ref() { - computed_style.refine(style); - } - } - if active_state.element { - computed_style.refine(&self.active_style); - } - + .refine_style(&mut computed_style, bounds, &state.active_state, cx); computed_style } - - fn paint_active_listener( - &self, - bounds: Bounds, - group_bounds: Option>, - active_state: Arc>, - cx: &mut ViewContext, - ) { - if active_state.lock().is_none() { - cx.on_mouse_event(move |_view, down: &MouseDownEvent, phase, cx| { - if phase == DispatchPhase::Bubble { - let group = - group_bounds.map_or(false, |bounds| bounds.contains_point(&down.position)); - let element = bounds.contains_point(&down.position); - if group || element { - *active_state.lock() = ActiveState { group, element }; - cx.notify(); - } - } - }); - } else { - cx.on_mouse_event(move |_, _: &MouseUpEvent, phase, cx| { - if phase == DispatchPhase::Capture { - *active_state.lock() = ActiveState::default(); - cx.notify(); - } - }); - } - } } impl Div @@ -231,8 +172,6 @@ where children: self.children, group: self.group, base_style: self.base_style, - active_style: self.active_style, - group_active: self.group_active, } } } @@ -325,10 +264,6 @@ where GroupBounds::push(group, bounds, cx); } - let active_group_bounds = this - .group_active - .as_ref() - .and_then(|group_active| GroupBounds::get(&group_active.group, cx)); let style = this.compute_style(bounds, element_state, cx); let z_index = style.z_index.unwrap_or(0); @@ -336,15 +271,14 @@ where cx.stack(z_index, |cx| { cx.stack(0, |cx| { style.paint(bounds, cx); - this.paint_active_listener( + + this.focusability.paint(bounds, cx); + this.interactivity.paint( bounds, - active_group_bounds, + element_state.pending_click.clone(), element_state.active_state.clone(), cx, ); - this.focusability.paint(bounds, cx); - this.interactivity - .paint(bounds, element_state.pending_click.clone(), cx); }); cx.stack(1, |cx| { @@ -418,7 +352,7 @@ where fn set_hover_style(&mut self, group: Option, style: StyleRefinement) { let stateless = self.interactivity.as_stateless_mut(); if let Some(group) = group { - stateless.group_hover = Some(GroupStyle { group, style }); + stateless.group_hover_style = Some(GroupStyle { group, style }); } else { stateless.hover_style = style; } @@ -442,9 +376,9 @@ where { fn set_active_style(&mut self, group: Option, style: StyleRefinement) { if let Some(group) = group { - self.group_active = Some(GroupStyle { group, style }); + self.interactivity.group_active_style = Some(GroupStyle { group, style }); } else { - self.active_style = style; + self.interactivity.active_style = style; } } }