Checkpoint

Antonio Scandurra created

Change summary

crates/gpui3/src/elements/div.rs |  82 +++--------------------
crates/gpui3/src/elements/img.rs |   6 
crates/gpui3/src/elements/svg.rs |   8 +-
crates/gpui3/src/interactive.rs  | 113 ++++++++++++++++++++++++++-------
4 files changed, 108 insertions(+), 101 deletions(-)

Detailed changes

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

@@ -1,10 +1,9 @@
 use crate::{
     Active, Anonymous, AnyElement, AppContext, BorrowWindow, Bounds, Click, DispatchPhase, Element,
     ElementFocusability, ElementId, ElementIdentity, Focus, FocusHandle, FocusListeners, Focusable,
-    GlobalElementId, Hover, Identified, Interactive, InteractiveState, IntoAnyElement,
-    KeyDownEvent, KeyMatch, LayoutId, MouseClickEvent, MouseDownEvent, MouseMoveEvent,
-    MouseUpEvent, NonFocusable, Overflow, ParentElement, Pixels, Point, ScrollWheelEvent,
-    SharedString, Style, StyleRefinement, Styled, ViewContext,
+    GlobalElementId, Hover, Identified, Interactive, Interactivity, IntoAnyElement, KeyDownEvent,
+    KeyMatch, LayoutId, MouseDownEvent, MouseMoveEvent, MouseUpEvent, NonFocusable, Overflow,
+    ParentElement, Pixels, Point, SharedString, Style, StyleRefinement, Styled, ViewContext,
 };
 use collections::HashMap;
 use parking_lot::Mutex;
@@ -68,6 +67,7 @@ pub struct Div<
 > {
     identity: I,
     focusability: F,
+    interactivity: Interactivity<V>,
     children: SmallVec<[AnyElement<V>; 2]>,
     group: Option<SharedString>,
     base_style: StyleRefinement,
@@ -75,7 +75,6 @@ pub struct Div<
     group_hover: Option<GroupStyle>,
     active_style: StyleRefinement,
     group_active: Option<GroupStyle>,
-    interactive_state: InteractiveState<V>,
 }
 
 pub fn div<V>() -> Div<V, Anonymous, NonFocusable>
@@ -85,6 +84,7 @@ where
     Div {
         identity: Anonymous,
         focusability: NonFocusable,
+        interactivity: Interactivity::default(),
         children: SmallVec::new(),
         group: None,
         base_style: StyleRefinement::default(),
@@ -92,7 +92,6 @@ where
         group_hover: None,
         active_style: StyleRefinement::default(),
         group_active: None,
-        interactive_state: InteractiveState::default(),
     }
 }
 
@@ -110,6 +109,7 @@ where
         Div {
             identity: Identified(id.into()),
             focusability: self.focusability,
+            interactivity: self.interactivity,
             children: self.children,
             group: self.group,
             base_style: self.base_style,
@@ -117,7 +117,6 @@ where
             group_hover: self.group_hover,
             active_style: self.active_style,
             group_active: self.group_active,
-            interactive_state: self.interactive_state,
         }
     }
 }
@@ -268,62 +267,6 @@ where
             });
         }
     }
-
-    fn paint_event_listeners(
-        &mut self,
-        bounds: Bounds<Pixels>,
-        pending_click: Arc<Mutex<Option<MouseDownEvent>>>,
-        cx: &mut ViewContext<V>,
-    ) {
-        let click_listeners = mem::take(&mut self.interactive_state.mouse_click);
-
-        let mouse_down = pending_click.lock().clone();
-        if let Some(mouse_down) = mouse_down {
-            cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
-                if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
-                    let mouse_click = MouseClickEvent {
-                        down: mouse_down.clone(),
-                        up: event.clone(),
-                    };
-                    for listener in &click_listeners {
-                        listener(state, &mouse_click, cx);
-                    }
-                }
-
-                *pending_click.lock() = None;
-            });
-        } else {
-            cx.on_mouse_event(move |_state, event: &MouseDownEvent, phase, _cx| {
-                if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
-                    *pending_click.lock() = Some(event.clone());
-                }
-            });
-        }
-
-        for listener in mem::take(&mut self.interactive_state.mouse_down) {
-            cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
-                listener(state, event, &bounds, phase, cx);
-            })
-        }
-
-        for listener in mem::take(&mut self.interactive_state.mouse_up) {
-            cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
-                listener(state, event, &bounds, phase, cx);
-            })
-        }
-
-        for listener in mem::take(&mut self.interactive_state.mouse_move) {
-            cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| {
-                listener(state, event, &bounds, phase, cx);
-            })
-        }
-
-        for listener in mem::take(&mut self.interactive_state.scroll_wheel) {
-            cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| {
-                listener(state, event, &bounds, phase, cx);
-            })
-        }
-    }
 }
 
 impl<V, I> Div<V, I, NonFocusable>
@@ -342,7 +285,7 @@ where
             group_hover: self.group_hover,
             active_style: self.active_style,
             group_active: self.group_active,
-            interactive_state: self.interactive_state,
+            interactivity: self.interactivity,
         }
     }
 }
@@ -395,7 +338,7 @@ where
         self.with_element_id(cx, |this, global_id, cx| {
             let element_state = element_state.unwrap_or_default();
 
-            let mut key_listeners = mem::take(&mut this.interactive_state.key);
+            let mut key_listeners = mem::take(&mut this.interactivity.key);
             if let Some(global_id) = global_id {
                 key_listeners.push((
                     TypeId::of::<KeyDownEvent>(),
@@ -421,7 +364,7 @@ where
                     }
                 });
             });
-            this.interactive_state.key = key_listeners;
+            this.interactivity.key = key_listeners;
 
             element_state
         })
@@ -485,7 +428,8 @@ where
                         cx,
                     );
                     this.focusability.paint(bounds, cx);
-                    this.paint_event_listeners(bounds, element_state.pending_click.clone(), cx);
+                    this.interactivity
+                        .paint(bounds, element_state.pending_click.clone(), cx);
                 });
 
                 cx.stack(1, |cx| {
@@ -549,8 +493,8 @@ where
     F: ElementFocusability<V>,
     V: 'static + Send + Sync,
 {
-    fn interactive_state(&mut self) -> &mut InteractiveState<V> {
-        &mut self.interactive_state
+    fn interactivity(&mut self) -> &mut Interactivity<V> {
+        &mut self.interactivity
     }
 }
 

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

@@ -1,7 +1,7 @@
 use crate::{
     div, Active, Anonymous, AnyElement, BorrowWindow, Bounds, Click, Div, DivState, Element,
     ElementFocusability, ElementId, ElementIdentity, Focus, FocusListeners, Focusable, Hover,
-    Identified, Interactive, InteractiveState, IntoAnyElement, LayoutId, NonFocusable, Pixels,
+    Identified, Interactive, Interactivity, IntoAnyElement, LayoutId, NonFocusable, Pixels,
     SharedString, StyleRefinement, Styled, ViewContext,
 };
 use futures::FutureExt;
@@ -156,8 +156,8 @@ where
     I: ElementIdentity,
     F: ElementFocusability<V>,
 {
-    fn interactive_state(&mut self) -> &mut InteractiveState<V> {
-        self.base.interactive_state()
+    fn interactivity(&mut self) -> &mut Interactivity<V> {
+        self.base.interactivity()
     }
 }
 

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

@@ -1,8 +1,8 @@
 use crate::{
     div, Active, Anonymous, AnyElement, Bounds, Click, Div, DivState, Element, ElementFocusability,
     ElementId, ElementIdentity, Focus, FocusListeners, Focusable, Hover, Identified, Interactive,
-    InteractiveState, IntoAnyElement, LayoutId, NonFocusable, Pixels, SharedString,
-    StyleRefinement, Styled, ViewContext,
+    Interactivity, IntoAnyElement, LayoutId, NonFocusable, Pixels, SharedString, StyleRefinement,
+    Styled, ViewContext,
 };
 use util::ResultExt;
 
@@ -130,8 +130,8 @@ where
     I: ElementIdentity,
     F: ElementFocusability<V>,
 {
-    fn interactive_state(&mut self) -> &mut InteractiveState<V> {
-        self.base.interactive_state()
+    fn interactivity(&mut self) -> &mut Interactivity<V> {
+        self.base.interactivity()
     }
 }
 

crates/gpui3/src/interactive.rs 🔗

@@ -1,3 +1,4 @@
+use parking_lot::Mutex;
 use smallvec::SmallVec;
 
 use crate::{
@@ -6,12 +7,13 @@ use crate::{
 };
 use std::{
     any::{Any, TypeId},
+    mem,
     ops::Deref,
     sync::Arc,
 };
 
 pub trait Interactive: Element {
-    fn interactive_state(&mut self) -> &mut InteractiveState<Self::ViewState>;
+    fn interactivity(&mut self) -> &mut Interactivity<Self::ViewState>;
 
     fn on_mouse_down(
         mut self,
@@ -24,16 +26,16 @@ pub trait Interactive: Element {
     where
         Self: Sized,
     {
-        self.interactive_state().mouse_down.push(Arc::new(
-            move |view, event, bounds, phase, cx| {
+        self.interactivity()
+            .mouse_down
+            .push(Arc::new(move |view, event, bounds, phase, cx| {
                 if phase == DispatchPhase::Bubble
                     && event.button == button
                     && bounds.contains_point(&event.position)
                 {
                     handler(view, event, cx)
                 }
-            },
-        ));
+            }));
         self
     }
 
@@ -48,7 +50,7 @@ pub trait Interactive: Element {
     where
         Self: Sized,
     {
-        self.interactive_state()
+        self.interactivity()
             .mouse_up
             .push(Arc::new(move |view, event, bounds, phase, cx| {
                 if phase == DispatchPhase::Bubble
@@ -72,16 +74,16 @@ pub trait Interactive: Element {
     where
         Self: Sized,
     {
-        self.interactive_state().mouse_down.push(Arc::new(
-            move |view, event, bounds, phase, cx| {
+        self.interactivity()
+            .mouse_down
+            .push(Arc::new(move |view, event, bounds, phase, cx| {
                 if phase == DispatchPhase::Capture
                     && event.button == button
                     && !bounds.contains_point(&event.position)
                 {
                     handler(view, event, cx)
                 }
-            },
-        ));
+            }));
         self
     }
 
@@ -96,7 +98,7 @@ pub trait Interactive: Element {
     where
         Self: Sized,
     {
-        self.interactive_state()
+        self.interactivity()
             .mouse_up
             .push(Arc::new(move |view, event, bounds, phase, cx| {
                 if phase == DispatchPhase::Capture
@@ -119,13 +121,13 @@ pub trait Interactive: Element {
     where
         Self: Sized,
     {
-        self.interactive_state().mouse_move.push(Arc::new(
-            move |view, event, bounds, phase, cx| {
+        self.interactivity()
+            .mouse_move
+            .push(Arc::new(move |view, event, bounds, phase, cx| {
                 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
                     handler(view, event, cx);
                 }
-            },
-        ));
+            }));
         self
     }
 
@@ -139,13 +141,13 @@ pub trait Interactive: Element {
     where
         Self: Sized,
     {
-        self.interactive_state().scroll_wheel.push(Arc::new(
-            move |view, event, bounds, phase, cx| {
+        self.interactivity()
+            .scroll_wheel
+            .push(Arc::new(move |view, event, bounds, phase, cx| {
                 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
                     handler(view, event, cx);
                 }
-            },
-        ));
+            }));
         self
     }
 
@@ -163,7 +165,7 @@ pub trait Interactive: Element {
     where
         Self: Sized,
     {
-        self.interactive_state().key.push((
+        self.interactivity().key.push((
             TypeId::of::<KeyDownEvent>(),
             Arc::new(move |view, event, _, phase, cx| {
                 let event = event.downcast_ref().unwrap();
@@ -184,7 +186,7 @@ pub trait Interactive: Element {
     where
         Self: Sized,
     {
-        self.interactive_state().key.push((
+        self.interactivity().key.push((
             TypeId::of::<KeyUpEvent>(),
             Arc::new(move |view, event, _, phase, cx| {
                 let event = event.downcast_ref().unwrap();
@@ -205,7 +207,7 @@ pub trait Interactive: Element {
     where
         Self: Sized,
     {
-        self.interactive_state().key.push((
+        self.interactivity().key.push((
             TypeId::of::<A>(),
             Arc::new(move |view, event, _, phase, cx| {
                 let event = event.downcast_ref().unwrap();
@@ -228,7 +230,7 @@ pub trait Click: Interactive {
     where
         Self: Sized,
     {
-        self.interactive_state()
+        self.interactivity()
             .mouse_click
             .push(Arc::new(move |view, event, cx| handler(view, event, cx)));
         self
@@ -494,7 +496,7 @@ pub type KeyListener<V> = Arc<
         + 'static,
 >;
 
-pub struct InteractiveState<V: 'static> {
+pub struct Interactivity<V> {
     pub mouse_down: SmallVec<[MouseDownListener<V>; 2]>,
     pub mouse_up: SmallVec<[MouseUpListener<V>; 2]>,
     pub mouse_click: SmallVec<[MouseClickListener<V>; 2]>,
@@ -503,7 +505,7 @@ pub struct InteractiveState<V: 'static> {
     pub key: SmallVec<[(TypeId, KeyListener<V>); 32]>,
 }
 
-impl<V> Default for InteractiveState<V> {
+impl<V> Default for Interactivity<V> {
     fn default() -> Self {
         Self {
             mouse_down: SmallVec::new(),
@@ -515,3 +517,64 @@ impl<V> Default for InteractiveState<V> {
         }
     }
 }
+
+impl<V> Interactivity<V>
+where
+    V: 'static + Send + Sync,
+{
+    pub fn paint(
+        &mut self,
+        bounds: Bounds<Pixels>,
+        pending_click: Arc<Mutex<Option<MouseDownEvent>>>,
+        cx: &mut ViewContext<V>,
+    ) {
+        let click_listeners = mem::take(&mut self.mouse_click);
+
+        let mouse_down = pending_click.lock().clone();
+        if let Some(mouse_down) = mouse_down {
+            cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
+                if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
+                    let mouse_click = MouseClickEvent {
+                        down: mouse_down.clone(),
+                        up: event.clone(),
+                    };
+                    for listener in &click_listeners {
+                        listener(state, &mouse_click, cx);
+                    }
+                }
+
+                *pending_click.lock() = None;
+            });
+        } else {
+            cx.on_mouse_event(move |_state, event: &MouseDownEvent, phase, _cx| {
+                if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
+                    *pending_click.lock() = Some(event.clone());
+                }
+            });
+        }
+
+        for listener in mem::take(&mut self.mouse_down) {
+            cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
+                listener(state, event, &bounds, phase, cx);
+            })
+        }
+
+        for listener in mem::take(&mut self.mouse_up) {
+            cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
+                listener(state, event, &bounds, phase, cx);
+            })
+        }
+
+        for listener in mem::take(&mut self.mouse_move) {
+            cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| {
+                listener(state, event, &bounds, phase, cx);
+            })
+        }
+
+        for listener in mem::take(&mut self.scroll_wheel) {
+            cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| {
+                listener(state, event, &bounds, phase, cx);
+            })
+        }
+    }
+}