mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 02:47:34 +03:00
Some terminal bugs (#3767)
Fixes: - drag and drop into terminal element does not change its style - drag and drop terminal tab into main pane then back panics - can drop non-terminal items into the terminal pane Release Notes: - N/A
This commit is contained in:
commit
051bad734e
@ -297,6 +297,10 @@ impl Interactivity {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn can_drop(&mut self, predicate: impl Fn(&dyn Any, &mut WindowContext) -> bool + 'static) {
|
||||||
|
self.can_drop_predicate = Some(Box::new(predicate));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn on_click(&mut self, listener: impl Fn(&ClickEvent, &mut WindowContext) + 'static)
|
pub fn on_click(&mut self, listener: impl Fn(&ClickEvent, &mut WindowContext) + 'static)
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
@ -569,6 +573,14 @@ pub trait InteractiveElement: Sized {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn can_drop(
|
||||||
|
mut self,
|
||||||
|
predicate: impl Fn(&dyn Any, &mut WindowContext) -> bool + 'static,
|
||||||
|
) -> Self {
|
||||||
|
self.interactivity().can_drop(predicate);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn block_mouse(mut self) -> Self {
|
fn block_mouse(mut self) -> Self {
|
||||||
self.interactivity().block_mouse();
|
self.interactivity().block_mouse();
|
||||||
self
|
self
|
||||||
@ -699,6 +711,8 @@ pub type DragListener = Box<dyn Fn(&dyn Any, &mut WindowContext) -> AnyView + 's
|
|||||||
|
|
||||||
type DropListener = Box<dyn Fn(&dyn Any, &mut WindowContext) + 'static>;
|
type DropListener = Box<dyn Fn(&dyn Any, &mut WindowContext) + 'static>;
|
||||||
|
|
||||||
|
type CanDropPredicate = Box<dyn Fn(&dyn Any, &mut WindowContext) -> bool + 'static>;
|
||||||
|
|
||||||
pub type TooltipBuilder = Rc<dyn Fn(&mut WindowContext) -> AnyView + 'static>;
|
pub type TooltipBuilder = Rc<dyn Fn(&mut WindowContext) -> AnyView + 'static>;
|
||||||
|
|
||||||
pub type KeyDownListener = Box<dyn Fn(&KeyDownEvent, DispatchPhase, &mut WindowContext) + 'static>;
|
pub type KeyDownListener = Box<dyn Fn(&KeyDownEvent, DispatchPhase, &mut WindowContext) + 'static>;
|
||||||
@ -887,6 +901,7 @@ pub struct Interactivity {
|
|||||||
pub key_up_listeners: Vec<KeyUpListener>,
|
pub key_up_listeners: Vec<KeyUpListener>,
|
||||||
pub action_listeners: Vec<(TypeId, ActionListener)>,
|
pub action_listeners: Vec<(TypeId, ActionListener)>,
|
||||||
pub drop_listeners: Vec<(TypeId, DropListener)>,
|
pub drop_listeners: Vec<(TypeId, DropListener)>,
|
||||||
|
pub can_drop_predicate: Option<CanDropPredicate>,
|
||||||
pub click_listeners: Vec<ClickListener>,
|
pub click_listeners: Vec<ClickListener>,
|
||||||
pub drag_listener: Option<(Box<dyn Any>, DragListener)>,
|
pub drag_listener: Option<(Box<dyn Any>, DragListener)>,
|
||||||
pub hover_listener: Option<Box<dyn Fn(&bool, &mut WindowContext)>>,
|
pub hover_listener: Option<Box<dyn Fn(&bool, &mut WindowContext)>>,
|
||||||
@ -1198,6 +1213,7 @@ impl Interactivity {
|
|||||||
let mut drag_listener = mem::take(&mut self.drag_listener);
|
let mut drag_listener = mem::take(&mut self.drag_listener);
|
||||||
let drop_listeners = mem::take(&mut self.drop_listeners);
|
let drop_listeners = mem::take(&mut self.drop_listeners);
|
||||||
let click_listeners = mem::take(&mut self.click_listeners);
|
let click_listeners = mem::take(&mut self.click_listeners);
|
||||||
|
let can_drop_predicate = mem::take(&mut self.can_drop_predicate);
|
||||||
|
|
||||||
if !drop_listeners.is_empty() {
|
if !drop_listeners.is_empty() {
|
||||||
cx.on_mouse_event({
|
cx.on_mouse_event({
|
||||||
@ -1215,9 +1231,17 @@ impl Interactivity {
|
|||||||
"checked for type drag state type above",
|
"checked for type drag state type above",
|
||||||
);
|
);
|
||||||
|
|
||||||
listener(drag.value.as_ref(), cx);
|
let mut can_drop = true;
|
||||||
cx.notify();
|
if let Some(predicate) = &can_drop_predicate {
|
||||||
cx.stop_propagation();
|
can_drop =
|
||||||
|
predicate(drag.value.as_ref(), cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if can_drop {
|
||||||
|
listener(drag.value.as_ref(), cx);
|
||||||
|
cx.notify();
|
||||||
|
cx.stop_propagation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1596,27 +1620,36 @@ impl Interactivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(drag) = cx.active_drag.take() {
|
if let Some(drag) = cx.active_drag.take() {
|
||||||
for (state_type, group_drag_style) in &self.group_drag_over_styles {
|
let mut can_drop = true;
|
||||||
if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) {
|
if let Some(can_drop_predicate) = &self.can_drop_predicate {
|
||||||
if *state_type == drag.value.as_ref().type_id()
|
can_drop = can_drop_predicate(drag.value.as_ref(), cx);
|
||||||
&& group_bounds.contains(&mouse_position)
|
|
||||||
{
|
|
||||||
style.refine(&group_drag_style.style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (state_type, drag_over_style) in &self.drag_over_styles {
|
if can_drop {
|
||||||
if *state_type == drag.value.as_ref().type_id()
|
for (state_type, group_drag_style) in &self.group_drag_over_styles {
|
||||||
&& bounds
|
if let Some(group_bounds) =
|
||||||
.intersect(&cx.content_mask().bounds)
|
GroupBounds::get(&group_drag_style.group, cx)
|
||||||
.contains(&mouse_position)
|
{
|
||||||
&& cx.was_top_layer_under_active_drag(
|
if *state_type == drag.value.as_ref().type_id()
|
||||||
&mouse_position,
|
&& group_bounds.contains(&mouse_position)
|
||||||
cx.stacking_order(),
|
{
|
||||||
)
|
style.refine(&group_drag_style.style);
|
||||||
{
|
}
|
||||||
style.refine(drag_over_style);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (state_type, drag_over_style) in &self.drag_over_styles {
|
||||||
|
if *state_type == drag.value.as_ref().type_id()
|
||||||
|
&& bounds
|
||||||
|
.intersect(&cx.content_mask().bounds)
|
||||||
|
.contains(&mouse_position)
|
||||||
|
&& cx.was_top_layer_under_active_drag(
|
||||||
|
&mouse_position,
|
||||||
|
cx.stacking_order(),
|
||||||
|
)
|
||||||
|
{
|
||||||
|
style.refine(drag_over_style);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1672,6 +1705,7 @@ impl Default for Interactivity {
|
|||||||
key_up_listeners: Vec::new(),
|
key_up_listeners: Vec::new(),
|
||||||
action_listeners: Vec::new(),
|
action_listeners: Vec::new(),
|
||||||
drop_listeners: Vec::new(),
|
drop_listeners: Vec::new(),
|
||||||
|
can_drop_predicate: None,
|
||||||
click_listeners: Vec::new(),
|
click_listeners: Vec::new(),
|
||||||
drag_listener: None,
|
drag_listener: None,
|
||||||
hover_listener: None,
|
hover_listener: None,
|
||||||
|
@ -58,6 +58,15 @@ impl TerminalPanel {
|
|||||||
workspace.weak_handle(),
|
workspace.weak_handle(),
|
||||||
workspace.project().clone(),
|
workspace.project().clone(),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
|
Some(Arc::new(|a, cx| {
|
||||||
|
if let Some(tab) = a.downcast_ref::<workspace::pane::DraggedTab>() {
|
||||||
|
if let Some(item) = tab.pane.read(cx).item_for_index(tab.ix) {
|
||||||
|
return item.downcast::<TerminalView>().is_some();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
})),
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
pane.set_can_split(false, cx);
|
pane.set_can_split(false, cx);
|
||||||
|
@ -181,7 +181,7 @@ pub struct Pane {
|
|||||||
workspace: WeakView<Workspace>,
|
workspace: WeakView<Workspace>,
|
||||||
project: Model<Project>,
|
project: Model<Project>,
|
||||||
drag_split_direction: Option<SplitDirection>,
|
drag_split_direction: Option<SplitDirection>,
|
||||||
// can_drop: Rc<dyn Fn(&DragAndDrop<Workspace>, &WindowContext) -> bool>,
|
can_drop_predicate: Option<Arc<dyn Fn(&dyn Any, &mut WindowContext) -> bool>>,
|
||||||
can_split: bool,
|
can_split: bool,
|
||||||
// render_tab_bar_buttons: Rc<dyn Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement<Pane>>,
|
// render_tab_bar_buttons: Rc<dyn Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement<Pane>>,
|
||||||
_subscriptions: Vec<Subscription>,
|
_subscriptions: Vec<Subscription>,
|
||||||
@ -229,7 +229,7 @@ pub struct NavigationEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct DraggedTab {
|
pub struct DraggedTab {
|
||||||
pub pane: View<Pane>,
|
pub pane: View<Pane>,
|
||||||
pub ix: usize,
|
pub ix: usize,
|
||||||
pub item_id: EntityId,
|
pub item_id: EntityId,
|
||||||
@ -325,6 +325,7 @@ impl Pane {
|
|||||||
workspace: WeakView<Workspace>,
|
workspace: WeakView<Workspace>,
|
||||||
project: Model<Project>,
|
project: Model<Project>,
|
||||||
next_timestamp: Arc<AtomicUsize>,
|
next_timestamp: Arc<AtomicUsize>,
|
||||||
|
can_drop_predicate: Option<Arc<dyn Fn(&dyn Any, &mut WindowContext) -> bool + 'static>>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
// todo!("context menu")
|
// todo!("context menu")
|
||||||
@ -371,7 +372,7 @@ impl Pane {
|
|||||||
// tab_context_menu: cx.build_view(|_| ContextMenu::new(pane_view_id, cx)),
|
// tab_context_menu: cx.build_view(|_| ContextMenu::new(pane_view_id, cx)),
|
||||||
workspace,
|
workspace,
|
||||||
project,
|
project,
|
||||||
// can_drop: Rc::new(|_, _| true),
|
can_drop_predicate,
|
||||||
can_split: true,
|
can_split: true,
|
||||||
// render_tab_bar_buttons: Rc::new(move |pane, cx| {
|
// render_tab_bar_buttons: Rc::new(move |pane, cx| {
|
||||||
// Flex::row()
|
// Flex::row()
|
||||||
@ -746,6 +747,10 @@ impl Pane {
|
|||||||
.position(|i| i.item_id() == item.item_id())
|
.position(|i| i.item_id() == item.item_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn item_for_index(&self, ix: usize) -> Option<&dyn ItemHandle> {
|
||||||
|
self.items.get(ix).map(|i| i.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toggle_zoom(&mut self, _: &ToggleZoom, cx: &mut ViewContext<Self>) {
|
pub fn toggle_zoom(&mut self, _: &ToggleZoom, cx: &mut ViewContext<Self>) {
|
||||||
if self.zoomed {
|
if self.zoomed {
|
||||||
cx.emit(Event::ZoomOut);
|
cx.emit(Event::ZoomOut);
|
||||||
@ -1530,6 +1535,9 @@ impl Pane {
|
|||||||
)
|
)
|
||||||
.drag_over::<DraggedTab>(|tab| tab.bg(cx.theme().colors().drop_target_background))
|
.drag_over::<DraggedTab>(|tab| tab.bg(cx.theme().colors().drop_target_background))
|
||||||
.drag_over::<ProjectEntryId>(|tab| tab.bg(cx.theme().colors().drop_target_background))
|
.drag_over::<ProjectEntryId>(|tab| tab.bg(cx.theme().colors().drop_target_background))
|
||||||
|
.when_some(self.can_drop_predicate.clone(), |this, p| {
|
||||||
|
this.can_drop(move |a, cx| p(a, cx))
|
||||||
|
})
|
||||||
.on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| {
|
.on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| {
|
||||||
this.drag_split_direction = None;
|
this.drag_split_direction = None;
|
||||||
this.handle_tab_drop(dragged_tab, ix, cx)
|
this.handle_tab_drop(dragged_tab, ix, cx)
|
||||||
@ -1754,6 +1762,10 @@ impl Pane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_drag_move<T>(&mut self, event: &DragMoveEvent<T>, cx: &mut ViewContext<Self>) {
|
fn handle_drag_move<T>(&mut self, event: &DragMoveEvent<T>, cx: &mut ViewContext<Self>) {
|
||||||
|
if !self.can_split {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let edge_width = cx.rem_size() * 8;
|
let edge_width = cx.rem_size() * 8;
|
||||||
let cursor = event.event.position;
|
let cursor = event.event.position;
|
||||||
let direction = if cursor.x < event.bounds.left() + edge_width {
|
let direction = if cursor.x < event.bounds.left() + edge_width {
|
||||||
@ -1767,9 +1779,9 @@ impl Pane {
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
if direction != self.drag_split_direction {
|
if direction != self.drag_split_direction {
|
||||||
self.drag_split_direction = direction;
|
self.drag_split_direction = direction;
|
||||||
cx.notify();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1934,6 +1946,7 @@ impl Render for Pane {
|
|||||||
.child(
|
.child(
|
||||||
// drag target
|
// drag target
|
||||||
div()
|
div()
|
||||||
|
.z_index(1)
|
||||||
.invisible()
|
.invisible()
|
||||||
.absolute()
|
.absolute()
|
||||||
.bg(theme::color_alpha(
|
.bg(theme::color_alpha(
|
||||||
@ -1942,6 +1955,9 @@ 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())
|
||||||
|
.when_some(self.can_drop_predicate.clone(), |this, p| {
|
||||||
|
this.can_drop(move |a, cx| p(a, cx))
|
||||||
|
})
|
||||||
.on_drop(cx.listener(move |this, dragged_tab, cx| {
|
.on_drop(cx.listener(move |this, dragged_tab, cx| {
|
||||||
this.handle_tab_drop(dragged_tab, this.active_item_index(), cx)
|
this.handle_tab_drop(dragged_tab, this.active_item_index(), cx)
|
||||||
}))
|
}))
|
||||||
|
@ -542,6 +542,7 @@ impl Workspace {
|
|||||||
weak_handle.clone(),
|
weak_handle.clone(),
|
||||||
project.clone(),
|
project.clone(),
|
||||||
pane_history_timestamp.clone(),
|
pane_history_timestamp.clone(),
|
||||||
|
None,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@ -1724,6 +1725,7 @@ impl Workspace {
|
|||||||
self.weak_handle(),
|
self.weak_handle(),
|
||||||
self.project.clone(),
|
self.project.clone(),
|
||||||
self.pane_history_timestamp.clone(),
|
self.pane_history_timestamp.clone(),
|
||||||
|
None,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user