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:
parent
bf6d3ad02d
commit
67a585cdfa
3 changed files with 40 additions and 21 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
1
styles/package-lock.json
generated
1
styles/package-lock.json
generated
|
@ -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": {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue