Prepare for external file drop in pane

This commit is contained in:
Kirill Bulatov 2024-01-07 01:17:49 +02:00
parent dc7f9bbc54
commit 8ff05c6a72
8 changed files with 63 additions and 28 deletions

View file

@ -1099,12 +1099,6 @@ impl AppContext {
pub fn has_active_drag(&self) -> bool { pub fn has_active_drag(&self) -> bool {
self.active_drag.is_some() self.active_drag.is_some()
} }
pub fn active_drag<T: 'static>(&self) -> Option<&T> {
self.active_drag
.as_ref()
.and_then(|drag| drag.value.downcast_ref())
}
} }
impl Context for AppContext { impl Context for AppContext {

View file

@ -214,7 +214,7 @@ impl Render for ExternalPaths {
pub enum FileDropEvent { pub enum FileDropEvent {
Entered { Entered {
position: Point<Pixels>, position: Point<Pixels>,
files: ExternalPaths, paths: ExternalPaths,
}, },
Pending { Pending {
position: Point<Pixels>, position: Point<Pixels>,

View file

@ -1673,10 +1673,7 @@ extern "C" fn dragging_entered(this: &Object, _: Sel, dragging_info: id) -> NSDr
if send_new_event(&window_state, { if send_new_event(&window_state, {
let position = drag_event_position(&window_state, dragging_info); let position = drag_event_position(&window_state, dragging_info);
let paths = external_paths_from_event(dragging_info); let paths = external_paths_from_event(dragging_info);
InputEvent::FileDrop(FileDropEvent::Entered { InputEvent::FileDrop(FileDropEvent::Entered { position, paths })
position,
files: paths,
})
}) { }) {
NSDragOperationCopy NSDragOperationCopy
} else { } else {

View file

@ -1462,12 +1462,12 @@ impl<'a> WindowContext<'a> {
// Translate dragging and dropping of external files from the operating system // Translate dragging and dropping of external files from the operating system
// to internal drag and drop events. // to internal drag and drop events.
InputEvent::FileDrop(file_drop) => match file_drop { InputEvent::FileDrop(file_drop) => match file_drop {
FileDropEvent::Entered { position, files } => { FileDropEvent::Entered { position, paths } => {
self.window.mouse_position = position; self.window.mouse_position = position;
if self.active_drag.is_none() { if self.active_drag.is_none() {
self.active_drag = Some(AnyDrag { self.active_drag = Some(AnyDrag {
value: Box::new(files.clone()), value: Box::new(paths.clone()),
view: self.new_view(|_| files).into(), view: self.new_view(|_| paths).into(),
cursor_offset: position, cursor_offset: position,
}); });
} }

View file

@ -693,9 +693,9 @@ impl TerminalElement {
.join(""); .join("");
new_text.push(' '); new_text.push(' ');
terminal.update(cx, |terminal, _| { terminal.update(cx, |terminal, _| {
// todo!() long paths are not displayed properly albeit the text is there
terminal.paste(&new_text); terminal.paste(&new_text);
}); });
cx.stop_propagation();
} }
}); });

View file

@ -65,11 +65,8 @@ impl TerminalPanel {
return item.downcast::<TerminalView>().is_some(); return item.downcast::<TerminalView>().is_some();
} }
} }
if a.downcast_ref::<ExternalPaths>().is_some() {
return true;
}
false a.downcast_ref::<ExternalPaths>().is_some()
})), })),
cx, cx,
); );

View file

@ -8,9 +8,10 @@ use anyhow::Result;
use collections::{HashMap, HashSet, VecDeque}; use collections::{HashMap, HashSet, VecDeque};
use gpui::{ use gpui::{
actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AnyElement, AppContext, actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AnyElement, AppContext,
AsyncWindowContext, DismissEvent, Div, DragMoveEvent, EntityId, EventEmitter, FocusHandle, AsyncWindowContext, DismissEvent, Div, DragMoveEvent, EntityId, EventEmitter, ExternalPaths,
FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, Render, FocusHandle, FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point,
ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, PromptLevel, Render, ScrollHandle, Subscription, Task, View, ViewContext, VisualContext,
WeakView, WindowContext,
}; };
use parking_lot::Mutex; use parking_lot::Mutex;
use project::{Project, ProjectEntryId, ProjectPath}; use project::{Project, ProjectEntryId, ProjectPath};
@ -1555,6 +1556,10 @@ impl Pane {
this.drag_split_direction = None; this.drag_split_direction = None;
this.handle_project_entry_drop(entry_id, cx) this.handle_project_entry_drop(entry_id, cx)
})) }))
.on_drop(cx.listener(move |this, paths, cx| {
this.drag_split_direction = None;
this.handle_external_paths_drop(paths, cx)
}))
.when_some(item.tab_tooltip_text(cx), |tab, text| { .when_some(item.tab_tooltip_text(cx), |tab, text| {
tab.tooltip(move |cx| Tooltip::text(text.clone(), cx)) tab.tooltip(move |cx| Tooltip::text(text.clone(), cx))
}) })
@ -1721,6 +1726,10 @@ impl Pane {
.on_drop(cx.listener(move |this, entry_id: &ProjectEntryId, cx| { .on_drop(cx.listener(move |this, entry_id: &ProjectEntryId, cx| {
this.drag_split_direction = None; this.drag_split_direction = None;
this.handle_project_entry_drop(entry_id, cx) this.handle_project_entry_drop(entry_id, cx)
}))
.on_drop(cx.listener(move |this, paths, cx| {
this.drag_split_direction = None;
this.handle_external_paths_drop(paths, cx)
})), })),
) )
} }
@ -1855,6 +1864,35 @@ impl Pane {
.log_err(); .log_err();
} }
fn handle_external_paths_drop(
&mut self,
paths: &ExternalPaths,
cx: &mut ViewContext<'_, Pane>,
) {
// let mut to_pane = cx.view().clone();
// let split_direction = self.drag_split_direction;
// let project_entry_id = *project_entry_id;
// self.workspace
// .update(cx, |_, cx| {
// cx.defer(move |workspace, cx| {
// if let Some(path) = workspace
// .project()
// .read(cx)
// .path_for_entry(project_entry_id, cx)
// {
// if let Some(split_direction) = split_direction {
// to_pane = workspace.split_pane(to_pane, split_direction, cx);
// }
// workspace
// .open_path(path, Some(to_pane.downgrade()), true, cx)
// .detach_and_log_err(cx);
// }
// });
// })
// .log_err();
dbg!("@@@@@@@@@@@@@@", paths);
}
pub fn display_nav_history_buttons(&mut self, display: bool) { pub fn display_nav_history_buttons(&mut self, display: bool) {
self.display_nav_history_buttons = display; self.display_nav_history_buttons = display;
} }
@ -1956,6 +1994,7 @@ impl Render for Pane {
.group("") .group("")
.on_drag_move::<DraggedTab>(cx.listener(Self::handle_drag_move)) .on_drag_move::<DraggedTab>(cx.listener(Self::handle_drag_move))
.on_drag_move::<ProjectEntryId>(cx.listener(Self::handle_drag_move)) .on_drag_move::<ProjectEntryId>(cx.listener(Self::handle_drag_move))
.on_drag_move::<ExternalPaths>(cx.listener(Self::handle_drag_move))
.map(|div| { .map(|div| {
if let Some(item) = self.active_item() { if let Some(item) = self.active_item() {
div.v_flex() div.v_flex()
@ -1985,6 +2024,7 @@ impl Render for Pane {
)) ))
.group_drag_over::<DraggedTab>("", |style| style.visible()) .group_drag_over::<DraggedTab>("", |style| style.visible())
.group_drag_over::<ProjectEntryId>("", |style| style.visible()) .group_drag_over::<ProjectEntryId>("", |style| style.visible())
.group_drag_over::<ExternalPaths>("", |style| style.visible())
.when_some(self.can_drop_predicate.clone(), |this, p| { .when_some(self.can_drop_predicate.clone(), |this, p| {
this.can_drop(move |a, cx| p(a, cx)) this.can_drop(move |a, cx| p(a, cx))
}) })
@ -1994,6 +2034,9 @@ impl Render for Pane {
.on_drop(cx.listener(move |this, entry_id, cx| { .on_drop(cx.listener(move |this, entry_id, cx| {
this.handle_project_entry_drop(entry_id, cx) this.handle_project_entry_drop(entry_id, cx)
})) }))
.on_drop(cx.listener(move |this, paths, cx| {
this.handle_external_paths_drop(paths, cx)
}))
.map(|div| match self.drag_split_direction { .map(|div| match self.drag_split_direction {
None => div.top_0().left_0().right_0().bottom_0(), None => div.top_0().left_0().right_0().bottom_0(),
Some(SplitDirection::Up) => div.top_0().left_0().right_0().h_32(), Some(SplitDirection::Up) => div.top_0().left_0().right_0().h_32(),

View file

@ -27,11 +27,11 @@ use futures::{
use gpui::{ use gpui::{
actions, canvas, div, impl_actions, point, size, Action, AnyElement, AnyModel, AnyView, actions, canvas, div, impl_actions, point, size, Action, AnyElement, AnyModel, AnyView,
AnyWeakView, AnyWindowHandle, AppContext, AsyncAppContext, AsyncWindowContext, BorrowWindow, AnyWeakView, AnyWindowHandle, AppContext, AsyncAppContext, AsyncWindowContext, BorrowWindow,
Bounds, Context, Div, DragMoveEvent, Element, Entity, EntityId, EventEmitter, FocusHandle, Bounds, Context, Div, DragMoveEvent, Element, Entity, EntityId, EventEmitter, ExternalPaths,
FocusableView, GlobalPixels, InteractiveElement, IntoElement, KeyContext, LayoutId, FocusHandle, FocusableView, GlobalPixels, InteractiveElement, IntoElement, KeyContext,
ManagedView, Model, ModelContext, ParentElement, PathPromptOptions, Pixels, Point, PromptLevel, LayoutId, ManagedView, Model, ModelContext, ParentElement, PathPromptOptions, Pixels, Point,
Render, Size, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, PromptLevel, Render, Size, Styled, Subscription, Task, View, ViewContext, VisualContext,
WindowBounds, WindowContext, WindowHandle, WindowOptions, WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
}; };
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem}; use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
use itertools::Itertools; use itertools::Itertools;
@ -544,7 +544,11 @@ impl Workspace {
weak_handle.clone(), weak_handle.clone(),
project.clone(), project.clone(),
pane_history_timestamp.clone(), pane_history_timestamp.clone(),
None, Some(Arc::new(|a, _| {
a.downcast_ref::<ExternalPaths>().is_some()
|| a.downcast_ref::<DraggedTab>().is_some()
|| a.downcast_ref::<ProjectEntryId>().is_some()
})),
cx, cx,
) )
}); });