Allow SplitAndMove on panes (#38034)
Updates #19350 Release Notes: - Add `pane::SplitAndMove{Up,Down,Left,Right}` to allow creating a split without cloning the current buffer.
This commit is contained in:
@@ -385,19 +385,44 @@ impl TerminalPanel {
|
||||
}
|
||||
self.serialize(cx);
|
||||
}
|
||||
&pane::Event::Split(direction) => {
|
||||
let fut = self.new_pane_with_cloned_active_terminal(window, cx);
|
||||
let pane = pane.clone();
|
||||
cx.spawn_in(window, async move |panel, cx| {
|
||||
let Some(new_pane) = fut.await else {
|
||||
&pane::Event::Split {
|
||||
direction,
|
||||
clone_active_item,
|
||||
} => {
|
||||
if clone_active_item {
|
||||
let fut = self.new_pane_with_cloned_active_terminal(window, cx);
|
||||
let pane = pane.clone();
|
||||
cx.spawn_in(window, async move |panel, cx| {
|
||||
let Some(new_pane) = fut.await else {
|
||||
return;
|
||||
};
|
||||
panel
|
||||
.update_in(cx, |panel, window, cx| {
|
||||
panel.center.split(&pane, &new_pane, direction).log_err();
|
||||
window.focus(&new_pane.focus_handle(cx));
|
||||
})
|
||||
.ok();
|
||||
})
|
||||
.detach();
|
||||
} else {
|
||||
let Some(item) = pane.update(cx, |pane, cx| pane.take_active_item(window, cx))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
_ = panel.update_in(cx, |panel, window, cx| {
|
||||
panel.center.split(&pane, &new_pane, direction).log_err();
|
||||
window.focus(&new_pane.focus_handle(cx));
|
||||
let Ok(project) = self
|
||||
.workspace
|
||||
.update(cx, |workspace, _| workspace.project().clone())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let new_pane =
|
||||
new_terminal_pane(self.workspace.clone(), project, false, window, cx);
|
||||
new_pane.update(cx, |pane, cx| {
|
||||
pane.add_item(item, true, true, None, window, cx);
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
self.center.split(&pane, &new_pane, direction).log_err();
|
||||
window.focus(&new_pane.focus_handle(cx));
|
||||
}
|
||||
}
|
||||
pane::Event::Focus => {
|
||||
self.active_pane = pane.clone();
|
||||
|
||||
@@ -206,14 +206,22 @@ actions!(
|
||||
JoinAll,
|
||||
/// Reopens the most recently closed item.
|
||||
ReopenClosedItem,
|
||||
/// Splits the pane to the left.
|
||||
/// Splits the pane to the left, cloning the current item.
|
||||
SplitLeft,
|
||||
/// Splits the pane upward.
|
||||
/// Splits the pane upward, cloning the current item.
|
||||
SplitUp,
|
||||
/// Splits the pane to the right.
|
||||
/// Splits the pane to the right, cloning the current item.
|
||||
SplitRight,
|
||||
/// Splits the pane downward.
|
||||
/// Splits the pane downward, cloning the current item.
|
||||
SplitDown,
|
||||
/// Splits the pane to the left, moving the current item.
|
||||
SplitAndMoveLeft,
|
||||
/// Splits the pane upward, moving the current item.
|
||||
SplitAndMoveUp,
|
||||
/// Splits the pane to the right, moving the current item.
|
||||
SplitAndMoveRight,
|
||||
/// Splits the pane downward, moving the current item.
|
||||
SplitAndMoveDown,
|
||||
/// Splits the pane horizontally.
|
||||
SplitHorizontal,
|
||||
/// Splits the pane vertically.
|
||||
@@ -257,7 +265,10 @@ pub enum Event {
|
||||
RemovedItem {
|
||||
item: Box<dyn ItemHandle>,
|
||||
},
|
||||
Split(SplitDirection),
|
||||
Split {
|
||||
direction: SplitDirection,
|
||||
clone_active_item: bool,
|
||||
},
|
||||
ItemPinned,
|
||||
ItemUnpinned,
|
||||
JoinAll,
|
||||
@@ -288,9 +299,13 @@ impl fmt::Debug for Event {
|
||||
.debug_struct("RemovedItem")
|
||||
.field("item", &item.item_id())
|
||||
.finish(),
|
||||
Event::Split(direction) => f
|
||||
Event::Split {
|
||||
direction,
|
||||
clone_active_item,
|
||||
} => f
|
||||
.debug_struct("Split")
|
||||
.field("direction", direction)
|
||||
.field("clone_active_item", clone_active_item)
|
||||
.finish(),
|
||||
Event::JoinAll => f.write_str("JoinAll"),
|
||||
Event::JoinIntoNext => f.write_str("JoinIntoNext"),
|
||||
@@ -1776,6 +1791,16 @@ impl Pane {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn take_active_item(
|
||||
&mut self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<Box<dyn ItemHandle>> {
|
||||
let item = self.active_item()?;
|
||||
self.remove_item(item.item_id(), false, false, window, cx);
|
||||
Some(item)
|
||||
}
|
||||
|
||||
pub fn remove_item(
|
||||
&mut self,
|
||||
item_id: EntityId,
|
||||
@@ -2222,7 +2247,19 @@ impl Pane {
|
||||
}
|
||||
|
||||
pub fn split(&mut self, direction: SplitDirection, cx: &mut Context<Self>) {
|
||||
cx.emit(Event::Split(direction));
|
||||
cx.emit(Event::Split {
|
||||
direction,
|
||||
clone_active_item: true,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn split_and_move(&mut self, direction: SplitDirection, cx: &mut Context<Self>) {
|
||||
if self.items.len() > 1 {
|
||||
cx.emit(Event::Split {
|
||||
direction,
|
||||
clone_active_item: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toolbar(&self) -> &Entity<Toolbar> {
|
||||
@@ -3566,6 +3603,18 @@ impl Render for Pane {
|
||||
.on_action(
|
||||
cx.listener(|pane, _: &SplitDown, _, cx| pane.split(SplitDirection::Down, cx)),
|
||||
)
|
||||
.on_action(cx.listener(|pane, _: &SplitAndMoveUp, _, cx| {
|
||||
pane.split_and_move(SplitDirection::Up, cx)
|
||||
}))
|
||||
.on_action(cx.listener(|pane, _: &SplitAndMoveDown, _, cx| {
|
||||
pane.split_and_move(SplitDirection::Down, cx)
|
||||
}))
|
||||
.on_action(cx.listener(|pane, _: &SplitAndMoveLeft, _, cx| {
|
||||
pane.split_and_move(SplitDirection::Left, cx)
|
||||
}))
|
||||
.on_action(cx.listener(|pane, _: &SplitAndMoveRight, _, cx| {
|
||||
pane.split_and_move(SplitDirection::Right, cx)
|
||||
}))
|
||||
.on_action(cx.listener(|_, _: &JoinIntoNext, _, cx| {
|
||||
cx.emit(Event::JoinIntoNext);
|
||||
}))
|
||||
|
||||
@@ -3929,8 +3929,15 @@ impl Workspace {
|
||||
item: item.boxed_clone(),
|
||||
});
|
||||
}
|
||||
pane::Event::Split(direction) => {
|
||||
self.split_and_clone(pane.clone(), *direction, window, cx);
|
||||
pane::Event::Split {
|
||||
direction,
|
||||
clone_active_item,
|
||||
} => {
|
||||
if *clone_active_item {
|
||||
self.split_and_clone(pane.clone(), *direction, window, cx);
|
||||
} else {
|
||||
self.split_and_move(pane.clone(), *direction, window, cx);
|
||||
}
|
||||
}
|
||||
pane::Event::JoinIntoNext => {
|
||||
self.join_pane_into_next(pane.clone(), window, cx);
|
||||
@@ -4044,6 +4051,24 @@ impl Workspace {
|
||||
new_pane
|
||||
}
|
||||
|
||||
pub fn split_and_move(
|
||||
&mut self,
|
||||
pane: Entity<Pane>,
|
||||
direction: SplitDirection,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let Some(item) = pane.update(cx, |pane, cx| pane.take_active_item(window, cx)) else {
|
||||
return;
|
||||
};
|
||||
let new_pane = self.add_pane(window, cx);
|
||||
new_pane.update(cx, |pane, cx| {
|
||||
pane.add_item(item, true, true, None, window, cx)
|
||||
});
|
||||
self.center.split(&pane, &new_pane, direction).unwrap();
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn split_and_clone(
|
||||
&mut self,
|
||||
pane: Entity<Pane>,
|
||||
|
||||
Reference in New Issue
Block a user