Add group_active

Nathan Sobo created

Change summary

crates/gpui3/src/elements/group.rs     |  2 +-
crates/gpui3/src/elements/hoverable.rs | 16 ++++++++--------
crates/gpui3/src/elements/pressable.rs | 19 ++++++++++++++-----
crates/gpui3/src/styled.rs             | 11 ++++++++++-
crates/storybook2/src/collab_panel.rs  |  5 ++++-
5 files changed, 37 insertions(+), 16 deletions(-)

Detailed changes

crates/gpui3/src/elements/group.rs 🔗

@@ -9,7 +9,7 @@ use smallvec::SmallVec;
 #[derive(Default)]
 struct GroupBounds(HashMap<SharedString, SmallVec<[Bounds<Pixels>; 1]>>);
 
-pub fn element_group_bounds(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
+pub fn group_bounds(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
     cx.default_global::<GroupBounds>()
         .0
         .get(name)

crates/gpui3/src/elements/hoverable.rs 🔗

@@ -1,5 +1,5 @@
 use crate::{
-    element_group_bounds, AnyElement, Bounds, DispatchPhase, Element, ElementId, IdentifiedElement,
+    group_bounds, AnyElement, Bounds, DispatchPhase, Element, ElementId, IdentifiedElement,
     Interactive, MouseEventListeners, MouseMoveEvent, ParentElement, Pixels, SharedString, Styled,
     ViewContext,
 };
@@ -11,7 +11,7 @@ use std::sync::{
 };
 
 pub struct Hoverable<E: Styled> {
-    hover_group: Option<SharedString>,
+    group: Option<SharedString>,
     hovered: Arc<AtomicBool>,
     cascade_slot: CascadeSlot,
     hovered_style: <E::Style as Refineable>::Refinement,
@@ -21,7 +21,7 @@ pub struct Hoverable<E: Styled> {
 impl<E: Styled> Hoverable<E> {
     pub fn new(mut child: E, hover_group: Option<SharedString>) -> Self {
         Self {
-            hover_group,
+            group: hover_group,
             hovered: Arc::new(AtomicBool::new(false)),
             cascade_slot: child.style_cascade().reserve(),
             hovered_style: Default::default(),
@@ -80,13 +80,13 @@ where
         element_state: &mut Self::ElementState,
         cx: &mut ViewContext<Self::ViewState>,
     ) {
-        let hover_bounds = self
-            .hover_group
+        let target_bounds = self
+            .group
             .as_ref()
-            .and_then(|group| element_group_bounds(group, cx))
+            .and_then(|group| group_bounds(group, cx))
             .unwrap_or(bounds);
 
-        let hovered = hover_bounds.contains_point(cx.mouse_position());
+        let hovered = target_bounds.contains_point(cx.mouse_position());
 
         let slot = self.cascade_slot;
         let style = hovered.then_some(self.hovered_style.clone());
@@ -98,7 +98,7 @@ where
 
             move |_, event: &MouseMoveEvent, phase, cx| {
                 if phase == DispatchPhase::Capture {
-                    if hover_bounds.contains_point(event.position) != hovered.load(SeqCst) {
+                    if target_bounds.contains_point(event.position) != hovered.load(SeqCst) {
                         cx.notify();
                     }
                 }

crates/gpui3/src/elements/pressable.rs 🔗

@@ -1,6 +1,7 @@
 use crate::{
-    AnyElement, Bounds, DispatchPhase, Element, IdentifiedElement, Interactive, MouseDownEvent,
-    MouseEventListeners, MouseUpEvent, ParentElement, Pixels, Styled, ViewContext,
+    group_bounds, AnyElement, Bounds, DispatchPhase, Element, IdentifiedElement, Interactive,
+    MouseDownEvent, MouseEventListeners, MouseUpEvent, ParentElement, Pixels, SharedString, Styled,
+    ViewContext,
 };
 use refineable::{Cascade, CascadeSlot, Refineable};
 use smallvec::SmallVec;
@@ -10,6 +11,7 @@ use std::sync::{
 };
 
 pub struct Pressable<E: Styled> {
+    group: Option<SharedString>,
     cascade_slot: CascadeSlot,
     pressed_style: <E::Style as Refineable>::Refinement,
     child: E,
@@ -21,8 +23,9 @@ pub struct PressableState<S> {
 }
 
 impl<E: Styled> Pressable<E> {
-    pub fn new(mut child: E) -> Self {
+    pub fn new(mut child: E, group: Option<SharedString>) -> Self {
         Self {
+            group,
             cascade_slot: child.style_cascade().reserve(),
             pressed_style: Default::default(),
             child,
@@ -96,6 +99,12 @@ where
         element_state: &mut Self::ElementState,
         cx: &mut ViewContext<Self::ViewState>,
     ) {
+        let target_bounds = self
+            .group
+            .as_ref()
+            .and_then(|group| group_bounds(group, cx))
+            .unwrap_or(bounds);
+
         let style = element_state
             .pressed
             .load(SeqCst)
@@ -105,8 +114,8 @@ where
 
         let pressed = element_state.pressed.clone();
         cx.on_mouse_event(move |_, event: &MouseDownEvent, phase, cx| {
-            if phase == DispatchPhase::Capture {
-                if bounds.contains_point(event.position) {
+            if phase == DispatchPhase::Bubble {
+                if target_bounds.contains_point(event.position) {
                     pressed.store(true, SeqCst);
                     cx.notify();
                 }

crates/gpui3/src/styled.rs 🔗

@@ -34,6 +34,15 @@ pub trait Styled {
         Self::Style: 'static + Refineable + Default + Send + Sync,
         <Self::Style as Refineable>::Refinement: 'static + Default + Send + Sync,
     {
-        Pressable::new(self)
+        Pressable::new(self, None)
+    }
+
+    fn group_active(self, group_name: impl Into<SharedString>) -> Pressable<Self>
+    where
+        Self: 'static + Sized + Send + Sync,
+        Self::Style: 'static + Refineable + Default + Send + Sync,
+        <Self::Style as Refineable>::Refinement: 'static + Default + Send + Sync,
+    {
+        Pressable::new(self, Some(group_name.into()))
     }
 }

crates/storybook2/src/collab_panel.rs 🔗

@@ -175,6 +175,7 @@ impl CollabPanel {
                     .text_sm()
                     .child(
                         div()
+                            .id(0)
                             // .uri(avatar_uri)
                             .size_3p5()
                             .rounded_full()
@@ -183,7 +184,9 @@ impl CollabPanel {
                             .group_hover("")
                             .fill(theme.middle.negative.default.foreground)
                             .hover()
-                            .fill(theme.middle.warning.default.foreground),
+                            .fill(theme.middle.warning.default.foreground)
+                            .group_active("")
+                            .fill(theme.middle.accent.default.foreground),
                     )
                     .child(label),
             )