Impl default for drag and drop global. Make drag and drop global maintain a list of weak handles to the container.

Co-Authored-By: Max Brunsfeld <max@zed.dev>
This commit is contained in:
K Simmons 2022-09-01 12:10:20 -07:00
parent bf6d3ad02d
commit 67a585cdfa
3 changed files with 40 additions and 21 deletions

View file

@ -1,11 +1,12 @@
use std::{any::Any, rc::Rc}; use std::{any::Any, rc::Rc};
use collections::HashSet;
use gpui::{ use gpui::{
elements::{Container, MouseEventHandler}, elements::{Container, MouseEventHandler},
geometry::vector::Vector2F, geometry::vector::Vector2F,
scene::DragRegionEvent, scene::DragRegionEvent,
CursorStyle, Element, ElementBox, EventContext, MouseButton, RenderContext, View, ViewContext, CursorStyle, Element, ElementBox, EventContext, MouseButton, MutableAppContext, RenderContext,
WeakViewHandle, View, WeakViewHandle,
}; };
struct State<V: View> { struct State<V: View> {
@ -29,24 +30,23 @@ impl<V: View> Clone for State<V> {
} }
pub struct DragAndDrop<V: View> { pub struct DragAndDrop<V: View> {
parent: WeakViewHandle<V>, containers: HashSet<WeakViewHandle<V>>,
currently_dragged: Option<State<V>>, currently_dragged: Option<State<V>>,
} }
impl<V: View> DragAndDrop<V> { impl<V: View> Default for DragAndDrop<V> {
pub fn new(parent: WeakViewHandle<V>, cx: &mut ViewContext<V>) -> Self { fn default() -> Self {
cx.observe_global::<Self, _>(|cx| {
if let Some(parent) = cx.global::<Self>().parent.upgrade(cx) {
parent.update(cx, |_, cx| cx.notify())
}
})
.detach();
Self { Self {
parent, containers: Default::default(),
currently_dragged: None, currently_dragged: Default::default(),
} }
} }
}
impl<V: View> DragAndDrop<V> {
pub fn register_container(&mut self, handle: WeakViewHandle<V>) {
self.containers.insert(handle);
}
pub fn currently_dragged<T: Any>(&self, window_id: usize) -> Option<(Vector2F, Rc<T>)> { pub fn currently_dragged<T: Any>(&self, window_id: usize) -> Option<(Vector2F, Rc<T>)> {
self.currently_dragged.as_ref().and_then( self.currently_dragged.as_ref().and_then(
@ -93,9 +93,7 @@ impl<V: View> DragAndDrop<V> {
}), }),
}); });
if let Some(parent) = this.parent.upgrade(cx) { this.notify_containers_for_window(window_id, cx);
parent.update(cx, |_, cx| cx.notify())
}
}); });
} }
@ -129,13 +127,13 @@ impl<V: View> DragAndDrop<V> {
.with_cursor_style(CursorStyle::Arrow) .with_cursor_style(CursorStyle::Arrow)
.on_up(MouseButton::Left, |_, cx| { .on_up(MouseButton::Left, |_, cx| {
cx.defer(|cx| { cx.defer(|cx| {
cx.update_global::<Self, _, _>(|this, _| this.currently_dragged.take()); cx.update_global::<Self, _, _>(|this, cx| this.stop_dragging(cx));
}); });
cx.propogate_event(); cx.propogate_event();
}) })
.on_up_out(MouseButton::Left, |_, cx| { .on_up_out(MouseButton::Left, |_, cx| {
cx.defer(|cx| { cx.defer(|cx| {
cx.update_global::<Self, _, _>(|this, _| this.currently_dragged.take()); cx.update_global::<Self, _, _>(|this, cx| this.stop_dragging(cx));
}); });
}) })
// Don't block hover events or invalidations // Don't block hover events or invalidations
@ -145,6 +143,25 @@ impl<V: View> DragAndDrop<V> {
}, },
) )
} }
fn stop_dragging(&mut self, cx: &mut MutableAppContext) {
if let Some(State { window_id, .. }) = self.currently_dragged.take() {
self.notify_containers_for_window(window_id, cx);
}
}
fn notify_containers_for_window(&mut self, window_id: usize, cx: &mut MutableAppContext) {
self.containers.retain(|container| {
if let Some(container) = container.upgrade(cx) {
if container.window_id() == window_id {
container.update(cx, |_, cx| cx.notify());
}
true
} else {
false
}
});
}
} }
pub trait Draggable { pub trait Draggable {

View file

@ -949,8 +949,9 @@ impl Workspace {
status_bar status_bar
}); });
let drag_and_drop = DragAndDrop::new(cx.weak_handle(), cx); cx.update_default_global::<DragAndDrop<Workspace>, _, _>(|drag_and_drop, _| {
cx.set_global(drag_and_drop); drag_and_drop.register_container(weak_self.clone());
});
let mut this = Workspace { let mut this = Workspace {
modal: None, modal: None,

View file

@ -5,6 +5,7 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "styles",
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {