diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index b4920175ca4cf356c256ed34744c449d3be06ca0..4e5c793ef3fbcec947d38de9c68976cb532c3a8d 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -33,7 +33,7 @@ use gpui::{ vector::{vec2f, Vector2F}, }, impl_actions, - platform::{CursorStyle, MouseButton, PromptLevel}, + platform::{CursorStyle, ModifiersChangedEvent, MouseButton, PromptLevel}, serde_json, AnyElement, AppContext, AsyncAppContext, Element, Entity, FontCache, ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; @@ -1669,7 +1669,7 @@ impl CollabPanel { let mut is_dragged_over = false; if cx .global::>() - .currently_dragged::(cx.window()) + .currently_dragged::(cx.window()) .is_some() && self .dragged_channel_target @@ -1771,7 +1771,9 @@ impl CollabPanel { ) }) .on_click(MouseButton::Left, move |_, this, cx| { - this.join_channel_chat(channel_id, cx); + if this.dragged_channel_target.take().is_none() { + this.join_channel_chat(channel_id, cx); + } }) .on_click(MouseButton::Right, { let path = path.clone(); @@ -1817,16 +1819,32 @@ impl CollabPanel { .currently_dragged::(cx.window()) .is_some() { - this.dragged_channel_target = Some((channel.clone(), path.clone())); + if let Some(dragged_channel_target) = &this.dragged_channel_target { + if dragged_channel_target.0 != channel || dragged_channel_target.1 != path { + this.dragged_channel_target = Some((channel.clone(), path.clone())); + cx.notify(); + } + } else { + this.dragged_channel_target = Some((channel.clone(), path.clone())); + cx.notify(); + } } } }) .as_draggable( (channel.clone(), path.parent_id()), - move |(channel, _), cx: &mut ViewContext| { + move |e, (channel, _), cx: &mut ViewContext| { let theme = &theme::current(cx).collab_panel; Flex::::row() + .with_children(e.alt.then(|| { + Svg::new("icons/plus.svg") + .with_color(theme.channel_hash.color) + .constrained() + .with_width(theme.channel_hash.width) + .aligned() + .left() + })) .with_child( Svg::new("icons/hash.svg") .with_color(theme.channel_hash.color) @@ -1840,11 +1858,17 @@ impl CollabPanel { .contained() .with_style(theme.channel_name.container) .aligned() - .left() - .flex(1., true), + .left(), ) .align_children_center() .contained() + .with_background_color( + theme + .container + .background_color + .unwrap_or(gpui::color::Color::transparent_black()), + ) + .contained() .with_padding_left( theme.channel_row.default_style().padding.left + theme.channel_indent * depth as f32, @@ -2816,6 +2840,19 @@ impl View for CollabPanel { self.has_focus = false; } + fn modifiers_changed(&mut self, _: &ModifiersChangedEvent, cx: &mut ViewContext) -> bool { + if cx + .global::>() + .currently_dragged::(cx.window()) + .is_some() + { + cx.notify(); + true + } else { + false + } + } + fn render(&mut self, cx: &mut gpui::ViewContext<'_, '_, Self>) -> gpui::AnyElement { let theme = &theme::current(cx).collab_panel; diff --git a/crates/drag_and_drop/src/drag_and_drop.rs b/crates/drag_and_drop/src/drag_and_drop.rs index 197c9918f54176e038efbd6e93887cc129c3f764..f58717a2cfa8fcf89da472f7f270ba7b9f140200 100644 --- a/crates/drag_and_drop/src/drag_and_drop.rs +++ b/crates/drag_and_drop/src/drag_and_drop.rs @@ -4,7 +4,7 @@ use collections::HashSet; use gpui::{ elements::{Empty, MouseEventHandler, Overlay}, geometry::{rect::RectF, vector::Vector2F}, - platform::{CursorStyle, MouseButton}, + platform::{CursorStyle, Modifiers, MouseButton}, scene::{MouseDown, MouseDrag}, AnyElement, AnyWindowHandle, Element, View, ViewContext, WeakViewHandle, WindowContext, }; @@ -21,12 +21,13 @@ enum State { region: RectF, }, Dragging { + modifiers: Modifiers, window: AnyWindowHandle, position: Vector2F, region_offset: Vector2F, region: RectF, payload: Rc, - render: Rc, &mut ViewContext) -> AnyElement>, + render: Rc, &mut ViewContext) -> AnyElement>, }, Canceled, } @@ -49,6 +50,7 @@ impl Clone for State { region, }, State::Dragging { + modifiers, window, position, region_offset, @@ -62,6 +64,7 @@ impl Clone for State { region: region.clone(), payload: payload.clone(), render: render.clone(), + modifiers: modifiers.clone(), }, State::Canceled => State::Canceled, } @@ -111,6 +114,27 @@ impl DragAndDrop { }) } + pub fn any_currently_dragged(&self, window: AnyWindowHandle) -> bool { + self.currently_dragged + .as_ref() + .map(|state| { + if let State::Dragging { + window: window_dragged_from, + .. + } = state + { + if &window != window_dragged_from { + return false; + } + + true + } else { + false + } + }) + .unwrap_or(false) + } + pub fn drag_started(event: MouseDown, cx: &mut WindowContext) { cx.update_global(|this: &mut Self, _| { this.currently_dragged = Some(State::Down { @@ -124,7 +148,7 @@ impl DragAndDrop { event: MouseDrag, payload: Rc, cx: &mut WindowContext, - render: Rc) -> AnyElement>, + render: Rc) -> AnyElement>, ) { let window = cx.window(); cx.update_global(|this: &mut Self, cx| { @@ -141,13 +165,14 @@ impl DragAndDrop { }) => { if (event.position - (region.origin() + region_offset)).length() > DEAD_ZONE { this.currently_dragged = Some(State::Dragging { + modifiers: event.modifiers, window, region_offset, region, position: event.position, payload, - render: Rc::new(move |payload, cx| { - render(payload.downcast_ref::().unwrap(), cx) + render: Rc::new(move |modifiers, payload, cx| { + render(modifiers, payload.downcast_ref::().unwrap(), cx) }), }); } else { @@ -163,13 +188,14 @@ impl DragAndDrop { .. }) => { this.currently_dragged = Some(State::Dragging { + modifiers: event.modifiers, window, region_offset, region, position: event.position, payload, - render: Rc::new(move |payload, cx| { - render(payload.downcast_ref::().unwrap(), cx) + render: Rc::new(move |modifiers, payload, cx| { + render(modifiers, payload.downcast_ref::().unwrap(), cx) }), }); } @@ -178,6 +204,19 @@ impl DragAndDrop { }); } + pub fn update_modifiers(new_modifiers: Modifiers, cx: &mut ViewContext) -> bool { + cx.update_global(|this: &mut Self, _| match &mut this.currently_dragged { + Some(state) => match state { + State::Dragging { modifiers, .. } => { + *modifiers = new_modifiers; + true + } + _ => false, + }, + None => false, + }) + } + pub fn render(cx: &mut ViewContext) -> Option> { enum DraggedElementHandler {} cx.global::() @@ -188,6 +227,7 @@ impl DragAndDrop { State::Down { .. } => None, State::DeadZone { .. } => None, State::Dragging { + modifiers, window, region_offset, position, @@ -205,7 +245,7 @@ impl DragAndDrop { MouseEventHandler::new::( 0, cx, - |_, cx| render(payload, cx), + |_, cx| render(&modifiers, payload, cx), ) .with_cursor_style(CursorStyle::Arrow) .on_up(MouseButton::Left, |_, _, cx| { @@ -295,7 +335,7 @@ pub trait Draggable { fn as_draggable( self, payload: P, - render: impl 'static + Fn(&P, &mut ViewContext) -> AnyElement, + render: impl 'static + Fn(&Modifiers, &P, &mut ViewContext) -> AnyElement, ) -> Self where Self: Sized; @@ -305,7 +345,7 @@ impl Draggable for MouseEventHandler { fn as_draggable( self, payload: P, - render: impl 'static + Fn(&P, &mut ViewContext) -> AnyElement, + render: impl 'static + Fn(&Modifiers, &P, &mut ViewContext) -> AnyElement, ) -> Self where Self: Sized, diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 617870fcb4674b981c35924aa3e7bbe656f429ee..726a07acee7fd05ae5502243cad626b765c4727c 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -1485,7 +1485,7 @@ impl ProjectPanel { .as_draggable(entry_id, { let row_container_style = theme.dragged_entry.container; - move |_, cx: &mut ViewContext| { + move |_, _, cx: &mut ViewContext| { let theme = theme::current(cx).clone(); Self::render_entry_visual_element( &details, diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 1b48275ee98d53d4668f8c91ebc1fd0a2664e4a7..a3e6a547ddfd73c1fd67c50c4b6c4df2d6ff51d1 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -1383,7 +1383,7 @@ impl Pane { let theme = theme::current(cx).clone(); let detail = detail.clone(); - move |dragged_item: &DraggedItem, cx: &mut ViewContext| { + move |_, dragged_item: &DraggedItem, cx: &mut ViewContext| { let tab_style = &theme.workspace.tab_bar.dragged_tab; Self::render_dragged_tab( &dragged_item.handle, diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 7d0f6db917f4d7024732f1fe37d9feffdc52e4fd..23c12722fbf8877abe9e517bbdbfa3e3fbf2cf30 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -33,8 +33,8 @@ use gpui::{ }, impl_actions, platform::{ - CursorStyle, MouseButton, PathPromptOptions, Platform, PromptLevel, WindowBounds, - WindowOptions, + CursorStyle, ModifiersChangedEvent, MouseButton, PathPromptOptions, Platform, PromptLevel, + WindowBounds, WindowOptions, }, AnyModelHandle, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle, @@ -3807,6 +3807,10 @@ impl View for Workspace { cx.focus(&self.active_pane); } } + + fn modifiers_changed(&mut self, e: &ModifiersChangedEvent, cx: &mut ViewContext) -> bool { + DragAndDrop::::update_modifiers(e.modifiers, cx) + } } impl ViewId {