Unify on drag types

Anthony Eid created

Change summary

crates/ui/src/components/data_table.rs              | 49 ++++++++------
crates/ui/src/components/redistributable_columns.rs | 37 +++++++---
2 files changed, 53 insertions(+), 33 deletions(-)

Detailed changes

crates/ui/src/components/data_table.rs 🔗

@@ -2,13 +2,13 @@ use std::{ops::Range, rc::Rc};
 
 use crate::{
     ActiveTheme as _, AnyElement, App, Button, ButtonCommon as _, ButtonStyle, Color, Component,
-    ComponentScope, Context, Div, ElementId, FixedWidth as _, FluentBuilder as _, HeaderResizeInfo,
-    Indicator, InteractiveElement, IntoElement, ParentElement, Pixels, RESIZE_COLUMN_WIDTH,
-    RESIZE_DIVIDER_WIDTH, RedistributableColumnsState, RegisterComponent, RenderOnce, ScrollAxes,
-    ScrollableHandle, Scrollbars, SharedString, StatefulInteractiveElement, Styled, StyledExt as _,
-    StyledTypography, TableResizeBehavior, Window, WithScrollbar, bind_redistributable_columns,
-    div, example_group_with_title, h_flex, px, render_redistributable_columns_resize_handles,
-    single_example,
+    ComponentScope, Context, Div, DraggedColumn, ElementId, FixedWidth as _, FluentBuilder as _,
+    HeaderResizeInfo, Indicator, InteractiveElement, IntoElement, ParentElement, Pixels,
+    RESIZE_COLUMN_WIDTH, RESIZE_DIVIDER_WIDTH, RedistributableColumnsState, RegisterComponent,
+    RenderOnce, ScrollAxes, ScrollableHandle, Scrollbars, SharedString, StatefulInteractiveElement,
+    Styled, StyledExt as _, StyledTypography, TableResizeBehavior, Window, WithScrollbar,
+    bind_redistributable_columns, div, example_group_with_title, h_flex, px,
+    render_redistributable_columns_resize_handles, single_example,
     table_row::{IntoTableRow as _, TableRow},
     v_flex,
 };
@@ -23,10 +23,6 @@ pub mod table_row;
 #[cfg(test)]
 mod tests;
 
-/// Used as the drag payload when resizing columns in `Resizable` mode.
-#[derive(Debug)]
-pub(crate) struct DraggedResizableColumn(pub(crate) usize);
-
 /// Represents an unchecked table row, which is a vector of elements.
 /// Will be converted into `TableRow<T>` internally
 pub type UncheckedTableRow<T> = Vec<T>;
@@ -69,11 +65,11 @@ impl ResizableColumnsState {
 
     pub(crate) fn on_drag_move(
         &mut self,
-        drag_event: &DragMoveEvent<DraggedResizableColumn>,
+        drag_event: &DragMoveEvent<DraggedColumn>,
         window: &mut Window,
         cx: &mut Context<Self>,
     ) {
-        let col_idx = drag_event.drag(cx).0;
+        let col_idx = drag_event.drag(cx).col_idx;
         let rem_size = window.rem_size();
         let drag_x = drag_event.event.position.x - drag_event.bounds.left();
 
@@ -755,14 +751,20 @@ fn render_resize_handles_resizable(
                                 cx.stop_propagation();
                             }
                         })
-                        .on_drag(DraggedResizableColumn(col_idx), {
-                            let is_highlighted = is_highlighted.clone();
-                            move |_, _offset, _window, cx| {
-                                is_highlighted.write(cx, true);
-                                cx.new(|_cx| Empty)
-                            }
-                        })
-                        .on_drop::<DraggedResizableColumn>(move |_, _, cx| {
+                        .on_drag(
+                            DraggedColumn {
+                                col_idx,
+                                state_id: columns_state.entity_id(),
+                            },
+                            {
+                                let is_highlighted = is_highlighted.clone();
+                                move |_, _offset, _window, cx| {
+                                    is_highlighted.write(cx, true);
+                                    cx.new(|_cx| Empty)
+                                }
+                            },
+                        )
+                        .on_drop::<DraggedColumn>(move |_, _, cx| {
                             is_highlighted.write(cx, false);
                         });
                 }
@@ -851,7 +853,10 @@ impl RenderOnce for Table {
                 bind_redistributable_columns(this, widths)
             })
             .when_some(resizable_entity, |this, entity| {
-                this.on_drag_move::<DraggedResizableColumn>(move |event, window, cx| {
+                this.on_drag_move::<DraggedColumn>(move |event, window, cx| {
+                    if event.drag(cx).state_id != entity.entity_id() {
+                        return;
+                    }
                     entity.update(cx, |state, cx| state.on_drag_move(event, window, cx));
                 })
             })

crates/ui/src/components/redistributable_columns.rs 🔗

@@ -1,8 +1,8 @@
 use std::rc::Rc;
 
 use gpui::{
-    AbsoluteLength, AppContext as _, Bounds, DefiniteLength, DragMoveEvent, Empty, Entity, Length,
-    WeakEntity,
+    AbsoluteLength, AppContext as _, Bounds, DefiniteLength, DragMoveEvent, Empty, Entity,
+    EntityId, Length, WeakEntity,
 };
 use itertools::intersperse_with;
 
@@ -19,8 +19,14 @@ use crate::{
 pub(crate) const RESIZE_COLUMN_WIDTH: f32 = 8.0;
 pub(crate) const RESIZE_DIVIDER_WIDTH: f32 = 1.0;
 
+/// Drag payload for column resize handles.
+/// Includes the `EntityId` of the owning column state so that
+/// `on_drag_move` handlers on unrelated tables ignore the event.
 #[derive(Debug)]
-struct DraggedColumn(usize);
+pub(crate) struct DraggedColumn {
+    pub(crate) col_idx: usize,
+    pub(crate) state_id: EntityId,
+}
 
 #[derive(Debug, Copy, Clone, PartialEq)]
 pub enum TableResizeBehavior {
@@ -276,7 +282,7 @@ impl RedistributableColumnsState {
 
         let mut col_position = 0.0;
         let rem_size = window.rem_size();
-        let col_idx = drag_event.drag(cx).0;
+        let col_idx = drag_event.drag(cx).col_idx;
 
         let divider_width = Self::get_fraction(
             &DefiniteLength::Absolute(AbsoluteLength::Pixels(px(RESIZE_DIVIDER_WIDTH))),
@@ -387,6 +393,9 @@ pub fn bind_redistributable_columns(
         .on_drag_move::<DraggedColumn>({
             let columns_state = columns_state.clone();
             move |event, window, cx| {
+                if event.drag(cx).state_id != columns_state.entity_id() {
+                    return;
+                }
                 columns_state.update(cx, |columns, cx| {
                     columns.on_drag_move(event, window, cx);
                 });
@@ -478,13 +487,19 @@ pub fn render_redistributable_columns_resize_handles(
                                 cx.stop_propagation();
                             }
                         })
-                        .on_drag(DraggedColumn(current_column_ix), {
-                            let is_highlighted = is_highlighted.clone();
-                            move |_, _offset, _window, cx| {
-                                is_highlighted.write(cx, true);
-                                cx.new(|_cx| Empty)
-                            }
-                        })
+                        .on_drag(
+                            DraggedColumn {
+                                col_idx: current_column_ix,
+                                state_id: columns_state.entity_id(),
+                            },
+                            {
+                                let is_highlighted = is_highlighted.clone();
+                                move |_, _offset, _window, cx| {
+                                    is_highlighted.write(cx, true);
+                                    cx.new(|_cx| Empty)
+                                }
+                            },
+                        )
                         .on_drop::<DraggedColumn>(move |_, _, cx| {
                             is_highlighted.write(cx, false);
                             columns_state.update(cx, |state, _| {