@@ -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::<DragAndDrop<Workspace>>()
- .currently_dragged::<Channel>(cx.window())
+ .currently_dragged::<DraggedChannel>(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::<DraggedChannel>(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<Workspace>| {
+ move |e, (channel, _), cx: &mut ViewContext<Workspace>| {
let theme = &theme::current(cx).collab_panel;
Flex::<Workspace>::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<Self>) -> bool {
+ if cx
+ .global::<DragAndDrop<Workspace>>()
+ .currently_dragged::<DraggedChannel>(cx.window())
+ .is_some()
+ {
+ cx.notify();
+ true
+ } else {
+ false
+ }
+ }
+
fn render(&mut self, cx: &mut gpui::ViewContext<'_, '_, Self>) -> gpui::AnyElement<Self> {
let theme = &theme::current(cx).collab_panel;
@@ -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<V> {
region: RectF,
},
Dragging {
+ modifiers: Modifiers,
window: AnyWindowHandle,
position: Vector2F,
region_offset: Vector2F,
region: RectF,
payload: Rc<dyn Any + 'static>,
- render: Rc<dyn Fn(Rc<dyn Any>, &mut ViewContext<V>) -> AnyElement<V>>,
+ render: Rc<dyn Fn(&Modifiers, Rc<dyn Any>, &mut ViewContext<V>) -> AnyElement<V>>,
},
Canceled,
}
@@ -49,6 +50,7 @@ impl<V> Clone for State<V> {
region,
},
State::Dragging {
+ modifiers,
window,
position,
region_offset,
@@ -62,6 +64,7 @@ impl<V> Clone for State<V> {
region: region.clone(),
payload: payload.clone(),
render: render.clone(),
+ modifiers: modifiers.clone(),
},
State::Canceled => State::Canceled,
}
@@ -111,6 +114,27 @@ impl<V: 'static> DragAndDrop<V> {
})
}
+ 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<V: 'static> DragAndDrop<V> {
event: MouseDrag,
payload: Rc<T>,
cx: &mut WindowContext,
- render: Rc<impl 'static + Fn(&T, &mut ViewContext<V>) -> AnyElement<V>>,
+ render: Rc<impl 'static + Fn(&Modifiers, &T, &mut ViewContext<V>) -> AnyElement<V>>,
) {
let window = cx.window();
cx.update_global(|this: &mut Self, cx| {
@@ -141,13 +165,14 @@ impl<V: 'static> DragAndDrop<V> {
}) => {
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::<T>().unwrap(), cx)
+ render: Rc::new(move |modifiers, payload, cx| {
+ render(modifiers, payload.downcast_ref::<T>().unwrap(), cx)
}),
});
} else {
@@ -163,13 +188,14 @@ impl<V: 'static> DragAndDrop<V> {
..
}) => {
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::<T>().unwrap(), cx)
+ render: Rc::new(move |modifiers, payload, cx| {
+ render(modifiers, payload.downcast_ref::<T>().unwrap(), cx)
}),
});
}
@@ -178,6 +204,19 @@ impl<V: 'static> DragAndDrop<V> {
});
}
+ pub fn update_modifiers(new_modifiers: Modifiers, cx: &mut ViewContext<V>) -> 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<V>) -> Option<AnyElement<V>> {
enum DraggedElementHandler {}
cx.global::<Self>()
@@ -188,6 +227,7 @@ impl<V: 'static> DragAndDrop<V> {
State::Down { .. } => None,
State::DeadZone { .. } => None,
State::Dragging {
+ modifiers,
window,
region_offset,
position,
@@ -205,7 +245,7 @@ impl<V: 'static> DragAndDrop<V> {
MouseEventHandler::new::<DraggedElementHandler, _>(
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<V> {
fn as_draggable<D: View, P: Any>(
self,
payload: P,
- render: impl 'static + Fn(&P, &mut ViewContext<D>) -> AnyElement<D>,
+ render: impl 'static + Fn(&Modifiers, &P, &mut ViewContext<D>) -> AnyElement<D>,
) -> Self
where
Self: Sized;
@@ -305,7 +345,7 @@ impl<V: 'static> Draggable<V> for MouseEventHandler<V> {
fn as_draggable<D: View, P: Any>(
self,
payload: P,
- render: impl 'static + Fn(&P, &mut ViewContext<D>) -> AnyElement<D>,
+ render: impl 'static + Fn(&Modifiers, &P, &mut ViewContext<D>) -> AnyElement<D>,
) -> Self
where
Self: Sized,
@@ -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<Self>) -> bool {
+ DragAndDrop::<Workspace>::update_modifiers(e.modifiers, cx)
+ }
}
impl ViewId {