diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index 40d486c161..b4ce8c1b92 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -431,6 +431,12 @@ "shift-escape": "dock::HideDock" } }, + { + "context": "Pane", + "bindings": { + "cmd-escape": "dock::MoveActiveItemToDock" + } + }, { "context": "ProjectPanel", "bindings": { diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index 09f9cc91b4..aebb12727d 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -24,7 +24,8 @@ actions!( HideDock, AnchorDockRight, AnchorDockBottom, - ExpandDock + ExpandDock, + MoveActiveItemToDock, ] ); impl_internal_actions!(dock, [MoveDock, AddDefaultItemToDock]); @@ -48,6 +49,30 @@ pub fn init(cx: &mut MutableAppContext) { Dock::move_dock(workspace, &MoveDock(DockAnchor::Expanded), cx) }, ); + cx.add_action( + |workspace: &mut Workspace, _: &MoveActiveItemToDock, cx: &mut ViewContext| { + if let Some(active_item) = workspace.active_item(cx) { + let item_id = active_item.id(); + + let from = workspace.active_pane(); + let to = workspace.dock_pane(); + if from.id() == to.id() { + return; + } + + let destination_index = to.read(cx).items_len() + 1; + + Pane::move_item( + workspace, + from.clone(), + to.clone(), + item_id, + destination_index, + cx, + ); + } + }, + ); } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -338,7 +363,8 @@ impl View for ToggleDockButton { return Empty::new().boxed(); } - let dock_position = workspace.unwrap().read(cx).dock.position; + let workspace = workspace.unwrap(); + let dock_position = workspace.read(cx).dock.position; let theme = cx.global::().theme.clone(); let button = MouseEventHandler::::new(0, cx, { @@ -361,8 +387,12 @@ impl View for ToggleDockButton { .boxed() } }) - .with_cursor_style(CursorStyle::PointingHand); - .on_ + .with_cursor_style(CursorStyle::PointingHand) + .on_up(MouseButton::Left, move |_, cx| { + let dock_pane = workspace.read(cx.app).dock_pane(); + let drop_index = dock_pane.read(cx.app).items_len() + 1; + Pane::handle_dropped_item(&dock_pane.downgrade(), drop_index, cx); + }); if dock_position.is_visible() { button diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index cf5413c692..4865b0aa51 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -575,6 +575,10 @@ impl Pane { } } + pub fn items_len(&self) -> usize { + self.items.len() + } + pub fn items(&self) -> impl Iterator> { self.items.iter() } @@ -943,11 +947,11 @@ impl Pane { } } - fn move_item( + pub fn move_item( workspace: &mut Workspace, from: ViewHandle, to: ViewHandle, - item_to_move: usize, + item_id_to_move: usize, destination_index: usize, cx: &mut ViewContext, ) { @@ -955,7 +959,7 @@ impl Pane { .read(cx) .items() .enumerate() - .find(|(_, item_handle)| item_handle.id() == item_to_move); + .find(|(_, item_handle)| item_handle.id() == item_id_to_move); if item_to_move.is_none() { log::warn!("Tried to move item handle which was not in `from` pane. Maybe tab was closed during drop"); @@ -1321,7 +1325,7 @@ impl Pane { tab.constrained().with_height(tab_style.height).boxed() } - fn handle_dropped_item(pane: &WeakViewHandle, index: usize, cx: &mut EventContext) { + pub fn handle_dropped_item(pane: &WeakViewHandle, index: usize, cx: &mut EventContext) { if let Some((_, dragged_item)) = cx .global::>() .currently_dragged::(cx.window_id) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index e7752219c5..714325a699 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -3175,7 +3175,7 @@ mod tests { cx.foreground().run_until_parked(); pane.read_with(cx, |pane, _| { - assert_eq!(pane.items().count(), 4); + assert_eq!(pane.items_len(), 4); assert_eq!(pane.active_item().unwrap().id(), item1.id()); }); @@ -3185,7 +3185,7 @@ mod tests { assert_eq!(item1.read(cx).save_count, 1); assert_eq!(item1.read(cx).save_as_count, 0); assert_eq!(item1.read(cx).reload_count, 0); - assert_eq!(pane.items().count(), 3); + assert_eq!(pane.items_len(), 3); assert_eq!(pane.active_item().unwrap().id(), item3.id()); }); @@ -3195,7 +3195,7 @@ mod tests { assert_eq!(item3.read(cx).save_count, 0); assert_eq!(item3.read(cx).save_as_count, 0); assert_eq!(item3.read(cx).reload_count, 1); - assert_eq!(pane.items().count(), 2); + assert_eq!(pane.items_len(), 2); assert_eq!(pane.active_item().unwrap().id(), item4.id()); }); @@ -3207,7 +3207,7 @@ mod tests { assert_eq!(item4.read(cx).save_count, 0); assert_eq!(item4.read(cx).save_as_count, 1); assert_eq!(item4.read(cx).reload_count, 0); - assert_eq!(pane.items().count(), 1); + assert_eq!(pane.items_len(), 1); assert_eq!(pane.active_item().unwrap().id(), item2.id()); }); } @@ -3309,7 +3309,7 @@ mod tests { cx.foreground().run_until_parked(); close.await.unwrap(); left_pane.read_with(cx, |pane, _| { - assert_eq!(pane.items().count(), 0); + assert_eq!(pane.items_len(), 0); }); } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 3319aebd09..ef504026d5 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -811,7 +811,7 @@ mod tests { pane.active_item().unwrap().project_path(cx), Some(file1.clone()) ); - assert_eq!(pane.items().count(), 1); + assert_eq!(pane.items_len(), 1); }); // Open the second entry @@ -825,7 +825,7 @@ mod tests { pane.active_item().unwrap().project_path(cx), Some(file2.clone()) ); - assert_eq!(pane.items().count(), 2); + assert_eq!(pane.items_len(), 2); }); // Open the first entry again. The existing pane item is activated. @@ -841,7 +841,7 @@ mod tests { pane.active_item().unwrap().project_path(cx), Some(file1.clone()) ); - assert_eq!(pane.items().count(), 2); + assert_eq!(pane.items_len(), 2); }); // Split the pane with the first entry, then open the second entry again.