@@ -506,6 +506,22 @@
"cmd-k cmd-down": [
"workspace::ActivatePaneInDirection",
"Down"
+ ],
+ "cmd-k shift-left": [
+ "workspace::SwapPaneInDirection",
+ "Left"
+ ],
+ "cmd-k shift-right": [
+ "workspace::SwapPaneInDirection",
+ "Right"
+ ],
+ "cmd-k shift-up": [
+ "workspace::SwapPaneInDirection",
+ "Up"
+ ],
+ "cmd-k shift-down": [
+ "workspace::SwapPaneInDirection",
+ "Down"
]
}
},
@@ -316,6 +316,38 @@
"workspace::ActivatePaneInDirection",
"Down"
],
+ "ctrl-w shift-left": [
+ "workspace::SwapPaneInDirection",
+ "Left"
+ ],
+ "ctrl-w shift-right": [
+ "workspace::SwapPaneInDirection",
+ "Right"
+ ],
+ "ctrl-w shift-up": [
+ "workspace::SwapPaneInDirection",
+ "Up"
+ ],
+ "ctrl-w shift-down": [
+ "workspace::SwapPaneInDirection",
+ "Down"
+ ],
+ "ctrl-w shift-h": [
+ "workspace::SwapPaneInDirection",
+ "Left"
+ ],
+ "ctrl-w shift-l": [
+ "workspace::SwapPaneInDirection",
+ "Right"
+ ],
+ "ctrl-w shift-k": [
+ "workspace::SwapPaneInDirection",
+ "Up"
+ ],
+ "ctrl-w shift-j": [
+ "workspace::SwapPaneInDirection",
+ "Down"
+ ],
"ctrl-w g t": "pane::ActivateNextItem",
"ctrl-w ctrl-g t": "pane::ActivateNextItem",
"ctrl-w g shift-t": "pane::ActivatePrevItem",
@@ -84,6 +84,13 @@ impl PaneGroup {
}
}
+ pub fn swap(&mut self, from: &ViewHandle<Pane>, to: &ViewHandle<Pane>) {
+ match &mut self.root {
+ Member::Pane(_) => {}
+ Member::Axis(axis) => axis.swap(from, to),
+ };
+ }
+
pub(crate) fn render(
&self,
project: &ModelHandle<Project>,
@@ -428,6 +435,21 @@ impl PaneAxis {
}
}
+ fn swap(&mut self, from: &ViewHandle<Pane>, to: &ViewHandle<Pane>) {
+ for member in self.members.iter_mut() {
+ match member {
+ Member::Axis(axis) => axis.swap(from, to),
+ Member::Pane(pane) => {
+ if pane == from {
+ *member = Member::Pane(to.clone());
+ } else if pane == to {
+ *member = Member::Pane(from.clone())
+ }
+ }
+ }
+ }
+ }
+
fn bounding_box_for_pane(&self, pane: &ViewHandle<Pane>) -> Option<RectF> {
debug_assert!(self.members.len() == self.bounding_boxes.borrow().len());
@@ -157,6 +157,9 @@ pub struct ActivatePane(pub usize);
#[derive(Clone, Deserialize, PartialEq)]
pub struct ActivatePaneInDirection(pub SplitDirection);
+#[derive(Clone, Deserialize, PartialEq)]
+pub struct SwapPaneInDirection(pub SplitDirection);
+
#[derive(Clone, Deserialize, PartialEq)]
pub struct NewFileInDirection(pub SplitDirection);
@@ -233,6 +236,7 @@ impl_actions!(
[
ActivatePane,
ActivatePaneInDirection,
+ SwapPaneInDirection,
NewFileInDirection,
Toast,
OpenTerminal,
@@ -318,6 +322,12 @@ pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
},
);
+ cx.add_action(
+ |workspace: &mut Workspace, action: &SwapPaneInDirection, cx| {
+ workspace.swap_pane_in_direction(action.0, cx)
+ },
+ );
+
cx.add_action(|workspace: &mut Workspace, _: &ToggleLeftDock, cx| {
workspace.toggle_dock(DockPosition::Left, cx);
});
@@ -2236,11 +2246,32 @@ impl Workspace {
direction: SplitDirection,
cx: &mut ViewContext<Self>,
) {
- let bounding_box = match self.center.bounding_box_for_pane(&self.active_pane) {
- Some(coordinates) => coordinates,
- None => {
- return;
- }
+ if let Some(pane) = self.find_pane_in_direction(direction, cx) {
+ cx.focus(pane);
+ }
+ }
+
+ pub fn swap_pane_in_direction(
+ &mut self,
+ direction: SplitDirection,
+ cx: &mut ViewContext<Self>,
+ ) {
+ if let Some(to) = self
+ .find_pane_in_direction(direction, cx)
+ .map(|pane| pane.clone())
+ {
+ self.center.swap(&self.active_pane.clone(), &to);
+ cx.notify();
+ }
+ }
+
+ fn find_pane_in_direction(
+ &mut self,
+ direction: SplitDirection,
+ cx: &mut ViewContext<Self>,
+ ) -> Option<&ViewHandle<Pane>> {
+ let Some(bounding_box) = self.center.bounding_box_for_pane(&self.active_pane) else {
+ return None;
};
let cursor = self.active_pane.read(cx).pixel_position_of_cursor(cx);
let center = match cursor {
@@ -2256,10 +2287,7 @@ impl Workspace {
SplitDirection::Up => vec2f(center.x(), bounding_box.origin_y() - distance_to_next),
SplitDirection::Down => vec2f(center.x(), bounding_box.max_y() + distance_to_next),
};
-
- if let Some(pane) = self.center.pane_at_pixel_position(target) {
- cx.focus(pane);
- }
+ self.center.pane_at_pixel_position(target)
}
fn handle_pane_focused(&mut self, pane: ViewHandle<Pane>, cx: &mut ViewContext<Self>) {