mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-07 20:39:04 +03:00
feat(workspace): allow alternative actions to open files and symbols in split
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
parent
369ccc725c
commit
c7669317ec
@ -9,6 +9,7 @@
|
|||||||
"context": "Editor",
|
"context": "Editor",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"cmd-b": "editor::GoToDefinition",
|
"cmd-b": "editor::GoToDefinition",
|
||||||
|
"alt-cmd-b": "editor::GoToDefinitionSplit",
|
||||||
"cmd-<": "editor::ScrollCursorCenter",
|
"cmd-<": "editor::ScrollCursorCenter",
|
||||||
"cmd-g": [
|
"cmd-g": [
|
||||||
"editor::SelectNext",
|
"editor::SelectNext",
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"cmd-up": "menu::SelectFirst",
|
"cmd-up": "menu::SelectFirst",
|
||||||
"cmd-down": "menu::SelectLast",
|
"cmd-down": "menu::SelectLast",
|
||||||
"enter": "menu::Confirm",
|
"enter": "menu::Confirm",
|
||||||
|
"cmd-enter": "menu::SecondaryConfirm",
|
||||||
"escape": "menu::Cancel",
|
"escape": "menu::Cancel",
|
||||||
"ctrl-c": "menu::Cancel",
|
"ctrl-c": "menu::Cancel",
|
||||||
"cmd-{": "pane::ActivatePrevItem",
|
"cmd-{": "pane::ActivatePrevItem",
|
||||||
@ -298,7 +299,9 @@
|
|||||||
"shift-f8": "editor::GoToPrevDiagnostic",
|
"shift-f8": "editor::GoToPrevDiagnostic",
|
||||||
"f2": "editor::Rename",
|
"f2": "editor::Rename",
|
||||||
"f12": "editor::GoToDefinition",
|
"f12": "editor::GoToDefinition",
|
||||||
|
"alt-f12": "editor::GoToDefinitionSplit",
|
||||||
"cmd-f12": "editor::GoToTypeDefinition",
|
"cmd-f12": "editor::GoToTypeDefinition",
|
||||||
|
"alt-cmd-f12": "editor::GoToTypeDefinitionSplit",
|
||||||
"alt-shift-f12": "editor::FindAllReferences",
|
"alt-shift-f12": "editor::FindAllReferences",
|
||||||
"ctrl-m": "editor::MoveToEnclosingBracket",
|
"ctrl-m": "editor::MoveToEnclosingBracket",
|
||||||
"alt-cmd-[": "editor::Fold",
|
"alt-cmd-[": "editor::Fold",
|
||||||
|
@ -46,8 +46,9 @@
|
|||||||
"alt-f7": "editor::FindAllReferences",
|
"alt-f7": "editor::FindAllReferences",
|
||||||
"cmd-alt-f7": "editor::FindAllReferences",
|
"cmd-alt-f7": "editor::FindAllReferences",
|
||||||
"cmd-b": "editor::GoToDefinition",
|
"cmd-b": "editor::GoToDefinition",
|
||||||
"cmd-alt-b": "editor::GoToDefinition",
|
"cmd-alt-b": "editor::GoToDefinitionSplit",
|
||||||
"cmd-shift-b": "editor::GoToTypeDefinition",
|
"cmd-shift-b": "editor::GoToTypeDefinition",
|
||||||
|
"cmd-alt-shift-b": "editor::GoToTypeDefinitionSplit",
|
||||||
"alt-enter": "editor::ToggleCodeActions",
|
"alt-enter": "editor::ToggleCodeActions",
|
||||||
"f2": "editor::GoToDiagnostic",
|
"f2": "editor::GoToDiagnostic",
|
||||||
"cmd-f2": "editor::GoToPrevDiagnostic",
|
"cmd-f2": "editor::GoToPrevDiagnostic",
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"cmd-shift-a": "editor::SelectLargerSyntaxNode",
|
"cmd-shift-a": "editor::SelectLargerSyntaxNode",
|
||||||
"shift-f12": "editor::FindAllReferences",
|
"shift-f12": "editor::FindAllReferences",
|
||||||
"alt-cmd-down": "editor::GoToDefinition",
|
"alt-cmd-down": "editor::GoToDefinition",
|
||||||
|
"ctrl-alt-cmd-down": "editor::GoToDefinitionSplit",
|
||||||
"alt-shift-cmd-down": "editor::FindAllReferences",
|
"alt-shift-cmd-down": "editor::FindAllReferences",
|
||||||
"ctrl-.": "editor::GoToHunk",
|
"ctrl-.": "editor::GoToHunk",
|
||||||
"ctrl-,": "editor::GoToPrevHunk",
|
"ctrl-,": "editor::GoToPrevHunk",
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"cmd-l": "go_to_line::Toggle",
|
"cmd-l": "go_to_line::Toggle",
|
||||||
"ctrl-shift-d": "editor::DuplicateLine",
|
"ctrl-shift-d": "editor::DuplicateLine",
|
||||||
"cmd-b": "editor::GoToDefinition",
|
"cmd-b": "editor::GoToDefinition",
|
||||||
|
"alt-cmd-b": "editor::GoToDefinition",
|
||||||
"cmd-j": "editor::ScrollCursorCenter",
|
"cmd-j": "editor::ScrollCursorCenter",
|
||||||
"cmd-shift-l": "editor::SelectLine",
|
"cmd-shift-l": "editor::SelectLine",
|
||||||
"cmd-shift-t": "outline::Toggle",
|
"cmd-shift-t": "outline::Toggle",
|
||||||
|
@ -7217,7 +7217,7 @@ async fn test_peers_following_each_other(
|
|||||||
|
|
||||||
// Clients A and B follow each other in split panes
|
// Clients A and B follow each other in split panes
|
||||||
workspace_a.update(cx_a, |workspace, cx| {
|
workspace_a.update(cx_a, |workspace, cx| {
|
||||||
workspace.split_pane(workspace.active_pane().clone(), SplitDirection::Right, cx);
|
workspace.split_and_clone(workspace.active_pane().clone(), SplitDirection::Right, cx);
|
||||||
});
|
});
|
||||||
workspace_a
|
workspace_a
|
||||||
.update(cx_a, |workspace, cx| {
|
.update(cx_a, |workspace, cx| {
|
||||||
@ -7228,7 +7228,7 @@ async fn test_peers_following_each_other(
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
workspace_b.update(cx_b, |workspace, cx| {
|
workspace_b.update(cx_b, |workspace, cx| {
|
||||||
workspace.split_pane(workspace.active_pane().clone(), SplitDirection::Right, cx);
|
workspace.split_and_clone(workspace.active_pane().clone(), SplitDirection::Right, cx);
|
||||||
});
|
});
|
||||||
workspace_b
|
workspace_b
|
||||||
.update(cx_b, |workspace, cx| {
|
.update(cx_b, |workspace, cx| {
|
||||||
@ -7455,7 +7455,7 @@ async fn test_auto_unfollowing(
|
|||||||
|
|
||||||
// When client B activates a different pane, it continues following client A in the original pane.
|
// When client B activates a different pane, it continues following client A in the original pane.
|
||||||
workspace_b.update(cx_b, |workspace, cx| {
|
workspace_b.update(cx_b, |workspace, cx| {
|
||||||
workspace.split_pane(pane_b.clone(), SplitDirection::Right, cx)
|
workspace.split_and_clone(pane_b.clone(), SplitDirection::Right, cx)
|
||||||
});
|
});
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
workspace_b.read_with(cx_b, |workspace, _| workspace.leader_for_pane(&pane_b)),
|
workspace_b.read_with(cx_b, |workspace, _| workspace.leader_for_pane(&pane_b)),
|
||||||
|
@ -67,7 +67,7 @@ impl PickerDelegate for ContactFinderDelegate {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
|
||||||
if let Some(user) = self.potential_contacts.get(self.selected_index) {
|
if let Some(user) = self.potential_contacts.get(self.selected_index) {
|
||||||
let user_store = self.user_store.read(cx);
|
let user_store = self.user_store.read(cx);
|
||||||
match user_store.contact_request_status(user) {
|
match user_store.contact_request_status(user) {
|
||||||
|
@ -160,7 +160,7 @@ impl PickerDelegate for CommandPaletteDelegate {
|
|||||||
|
|
||||||
fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
|
fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
|
||||||
|
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
|
||||||
if !self.matches.is_empty() {
|
if !self.matches.is_empty() {
|
||||||
let window_id = cx.window_id();
|
let window_id = cx.window_id();
|
||||||
let focused_view_id = self.focused_view_id;
|
let focused_view_id = self.focused_view_id;
|
||||||
|
@ -271,7 +271,9 @@ actions!(
|
|||||||
SelectLargerSyntaxNode,
|
SelectLargerSyntaxNode,
|
||||||
SelectSmallerSyntaxNode,
|
SelectSmallerSyntaxNode,
|
||||||
GoToDefinition,
|
GoToDefinition,
|
||||||
|
GoToDefinitionSplit,
|
||||||
GoToTypeDefinition,
|
GoToTypeDefinition,
|
||||||
|
GoToTypeDefinitionSplit,
|
||||||
MoveToEnclosingBracket,
|
MoveToEnclosingBracket,
|
||||||
UndoSelection,
|
UndoSelection,
|
||||||
RedoSelection,
|
RedoSelection,
|
||||||
@ -407,7 +409,9 @@ pub fn init(cx: &mut AppContext) {
|
|||||||
cx.add_action(Editor::go_to_hunk);
|
cx.add_action(Editor::go_to_hunk);
|
||||||
cx.add_action(Editor::go_to_prev_hunk);
|
cx.add_action(Editor::go_to_prev_hunk);
|
||||||
cx.add_action(Editor::go_to_definition);
|
cx.add_action(Editor::go_to_definition);
|
||||||
|
cx.add_action(Editor::go_to_definition_split);
|
||||||
cx.add_action(Editor::go_to_type_definition);
|
cx.add_action(Editor::go_to_type_definition);
|
||||||
|
cx.add_action(Editor::go_to_type_definition_split);
|
||||||
cx.add_action(Editor::fold);
|
cx.add_action(Editor::fold);
|
||||||
cx.add_action(Editor::fold_at);
|
cx.add_action(Editor::fold_at);
|
||||||
cx.add_action(Editor::unfold_lines);
|
cx.add_action(Editor::unfold_lines);
|
||||||
@ -6185,14 +6189,31 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
|
pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
|
||||||
self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, cx);
|
self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
|
pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
|
||||||
self.go_to_definition_of_kind(GotoDefinitionKind::Type, cx);
|
self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn go_to_definition_of_kind(&mut self, kind: GotoDefinitionKind, cx: &mut ViewContext<Self>) {
|
pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
|
||||||
|
self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn go_to_type_definition_split(
|
||||||
|
&mut self,
|
||||||
|
_: &GoToTypeDefinitionSplit,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
|
self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn go_to_definition_of_kind(
|
||||||
|
&mut self,
|
||||||
|
kind: GotoDefinitionKind,
|
||||||
|
split: bool,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
let Some(workspace) = self.workspace(cx) else { return };
|
let Some(workspace) = self.workspace(cx) else { return };
|
||||||
let buffer = self.buffer.read(cx);
|
let buffer = self.buffer.read(cx);
|
||||||
let head = self.selections.newest::<usize>(cx).head();
|
let head = self.selections.newest::<usize>(cx).head();
|
||||||
@ -6211,7 +6232,7 @@ impl Editor {
|
|||||||
cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
|
cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
|
||||||
let definitions = definitions.await?;
|
let definitions = definitions.await?;
|
||||||
editor.update(&mut cx, |editor, cx| {
|
editor.update(&mut cx, |editor, cx| {
|
||||||
editor.navigate_to_definitions(definitions, cx);
|
editor.navigate_to_definitions(definitions, split, cx);
|
||||||
})?;
|
})?;
|
||||||
Ok::<(), anyhow::Error>(())
|
Ok::<(), anyhow::Error>(())
|
||||||
})
|
})
|
||||||
@ -6221,6 +6242,7 @@ impl Editor {
|
|||||||
pub fn navigate_to_definitions(
|
pub fn navigate_to_definitions(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut definitions: Vec<LocationLink>,
|
mut definitions: Vec<LocationLink>,
|
||||||
|
split: bool,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) {
|
) {
|
||||||
let Some(workspace) = self.workspace(cx) else { return };
|
let Some(workspace) = self.workspace(cx) else { return };
|
||||||
@ -6240,7 +6262,11 @@ impl Editor {
|
|||||||
} else {
|
} else {
|
||||||
cx.window_context().defer(move |cx| {
|
cx.window_context().defer(move |cx| {
|
||||||
let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
|
let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
|
||||||
workspace.open_project_item(definition.target.buffer.clone(), cx)
|
if split {
|
||||||
|
workspace.split_project_item(definition.target.buffer.clone(), cx)
|
||||||
|
} else {
|
||||||
|
workspace.open_project_item(definition.target.buffer.clone(), cx)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
target_editor.update(cx, |target_editor, cx| {
|
target_editor.update(cx, |target_editor, cx| {
|
||||||
// When selecting a definition in a different buffer, disable the nav history
|
// When selecting a definition in a different buffer, disable the nav history
|
||||||
@ -6276,7 +6302,9 @@ impl Editor {
|
|||||||
.map(|definition| definition.target)
|
.map(|definition| definition.target)
|
||||||
.collect();
|
.collect();
|
||||||
workspace.update(cx, |workspace, cx| {
|
workspace.update(cx, |workspace, cx| {
|
||||||
Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
|
Self::open_locations_in_multibuffer(
|
||||||
|
workspace, locations, replica_id, title, split, cx,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -6321,7 +6349,7 @@ impl Editor {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Self::open_locations_in_multibuffer(
|
Self::open_locations_in_multibuffer(
|
||||||
workspace, locations, replica_id, title, cx,
|
workspace, locations, replica_id, title, false, cx,
|
||||||
);
|
);
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@ -6336,6 +6364,7 @@ impl Editor {
|
|||||||
mut locations: Vec<Location>,
|
mut locations: Vec<Location>,
|
||||||
replica_id: ReplicaId,
|
replica_id: ReplicaId,
|
||||||
title: String,
|
title: String,
|
||||||
|
split: bool,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) {
|
) {
|
||||||
// If there are multiple definitions, open them in a multibuffer
|
// If there are multiple definitions, open them in a multibuffer
|
||||||
@ -6382,7 +6411,11 @@ impl Editor {
|
|||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
workspace.add_item(Box::new(editor), cx);
|
if split {
|
||||||
|
workspace.split_item(Box::new(editor), cx);
|
||||||
|
} else {
|
||||||
|
workspace.add_item(Box::new(editor), cx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
|
pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
|
||||||
|
@ -156,6 +156,7 @@ impl EditorElement {
|
|||||||
event.position,
|
event.position,
|
||||||
event.cmd,
|
event.cmd,
|
||||||
event.shift,
|
event.shift,
|
||||||
|
event.alt,
|
||||||
position_map.as_ref(),
|
position_map.as_ref(),
|
||||||
text_bounds,
|
text_bounds,
|
||||||
cx,
|
cx,
|
||||||
@ -308,6 +309,7 @@ impl EditorElement {
|
|||||||
position: Vector2F,
|
position: Vector2F,
|
||||||
cmd: bool,
|
cmd: bool,
|
||||||
shift: bool,
|
shift: bool,
|
||||||
|
alt: bool,
|
||||||
position_map: &PositionMap,
|
position_map: &PositionMap,
|
||||||
text_bounds: RectF,
|
text_bounds: RectF,
|
||||||
cx: &mut EventContext<Editor>,
|
cx: &mut EventContext<Editor>,
|
||||||
@ -324,9 +326,9 @@ impl EditorElement {
|
|||||||
|
|
||||||
if point == target_point {
|
if point == target_point {
|
||||||
if shift {
|
if shift {
|
||||||
go_to_fetched_type_definition(editor, point, cx);
|
go_to_fetched_type_definition(editor, point, alt, cx);
|
||||||
} else {
|
} else {
|
||||||
go_to_fetched_definition(editor, point, cx);
|
go_to_fetched_definition(editor, point, alt, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -246,23 +246,26 @@ pub fn hide_link_definition(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
|
|||||||
pub fn go_to_fetched_definition(
|
pub fn go_to_fetched_definition(
|
||||||
editor: &mut Editor,
|
editor: &mut Editor,
|
||||||
point: DisplayPoint,
|
point: DisplayPoint,
|
||||||
|
split: bool,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) {
|
) {
|
||||||
go_to_fetched_definition_of_kind(LinkDefinitionKind::Symbol, editor, point, cx);
|
go_to_fetched_definition_of_kind(LinkDefinitionKind::Symbol, editor, point, split, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn go_to_fetched_type_definition(
|
pub fn go_to_fetched_type_definition(
|
||||||
editor: &mut Editor,
|
editor: &mut Editor,
|
||||||
point: DisplayPoint,
|
point: DisplayPoint,
|
||||||
|
split: bool,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) {
|
) {
|
||||||
go_to_fetched_definition_of_kind(LinkDefinitionKind::Type, editor, point, cx);
|
go_to_fetched_definition_of_kind(LinkDefinitionKind::Type, editor, point, split, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn go_to_fetched_definition_of_kind(
|
fn go_to_fetched_definition_of_kind(
|
||||||
kind: LinkDefinitionKind,
|
kind: LinkDefinitionKind,
|
||||||
editor: &mut Editor,
|
editor: &mut Editor,
|
||||||
point: DisplayPoint,
|
point: DisplayPoint,
|
||||||
|
split: bool,
|
||||||
cx: &mut ViewContext<Editor>,
|
cx: &mut ViewContext<Editor>,
|
||||||
) {
|
) {
|
||||||
let cached_definitions = editor.link_go_to_definition_state.definitions.clone();
|
let cached_definitions = editor.link_go_to_definition_state.definitions.clone();
|
||||||
@ -275,7 +278,7 @@ fn go_to_fetched_definition_of_kind(
|
|||||||
cx.focus_self();
|
cx.focus_self();
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.navigate_to_definitions(cached_definitions, cx);
|
editor.navigate_to_definitions(cached_definitions, split, cx);
|
||||||
} else {
|
} else {
|
||||||
editor.select(
|
editor.select(
|
||||||
SelectPhase::Begin {
|
SelectPhase::Begin {
|
||||||
@ -403,7 +406,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
cx.update_editor(|editor, cx| {
|
cx.update_editor(|editor, cx| {
|
||||||
go_to_fetched_type_definition(editor, hover_point, cx);
|
go_to_fetched_type_definition(editor, hover_point, false, cx);
|
||||||
});
|
});
|
||||||
requests.next().await;
|
requests.next().await;
|
||||||
cx.foreground().run_until_parked();
|
cx.foreground().run_until_parked();
|
||||||
@ -614,7 +617,7 @@ mod tests {
|
|||||||
|
|
||||||
// Cmd click with existing definition doesn't re-request and dismisses highlight
|
// Cmd click with existing definition doesn't re-request and dismisses highlight
|
||||||
cx.update_editor(|editor, cx| {
|
cx.update_editor(|editor, cx| {
|
||||||
go_to_fetched_definition(editor, hover_point, cx);
|
go_to_fetched_definition(editor, hover_point, false, cx);
|
||||||
});
|
});
|
||||||
// Assert selection moved to to definition
|
// Assert selection moved to to definition
|
||||||
cx.lsp
|
cx.lsp
|
||||||
@ -655,7 +658,7 @@ mod tests {
|
|||||||
])))
|
])))
|
||||||
});
|
});
|
||||||
cx.update_editor(|editor, cx| {
|
cx.update_editor(|editor, cx| {
|
||||||
go_to_fetched_definition(editor, hover_point, cx);
|
go_to_fetched_definition(editor, hover_point, false, cx);
|
||||||
});
|
});
|
||||||
requests.next().await;
|
requests.next().await;
|
||||||
cx.foreground().run_until_parked();
|
cx.foreground().run_until_parked();
|
||||||
|
@ -442,53 +442,71 @@ impl PickerDelegate for FileFinderDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<FileFinder>) {
|
fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<FileFinder>) {
|
||||||
if let Some(m) = self.matches.get(self.selected_index()) {
|
if let Some(m) = self.matches.get(self.selected_index()) {
|
||||||
if let Some(workspace) = self.workspace.upgrade(cx) {
|
if let Some(workspace) = self.workspace.upgrade(cx) {
|
||||||
let open_task = workspace.update(cx, |workspace, cx| match m {
|
let open_task = workspace.update(cx, move |workspace, cx| {
|
||||||
Match::History(history_match) => {
|
let split_or_open = |workspace: &mut Workspace, project_path, cx| {
|
||||||
let worktree_id = history_match.project.worktree_id;
|
if secondary {
|
||||||
if workspace
|
workspace.split_path(project_path, cx)
|
||||||
.project()
|
|
||||||
.read(cx)
|
|
||||||
.worktree_for_id(worktree_id, cx)
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
workspace.open_path(
|
|
||||||
ProjectPath {
|
|
||||||
worktree_id,
|
|
||||||
path: Arc::clone(&history_match.project.path),
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
true,
|
|
||||||
cx,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
match history_match.absolute.as_ref() {
|
workspace.open_path(project_path, None, true, cx)
|
||||||
Some(abs_path) => {
|
}
|
||||||
workspace.open_abs_path(abs_path.to_path_buf(), false, cx)
|
};
|
||||||
}
|
match m {
|
||||||
None => workspace.open_path(
|
Match::History(history_match) => {
|
||||||
|
let worktree_id = history_match.project.worktree_id;
|
||||||
|
if workspace
|
||||||
|
.project()
|
||||||
|
.read(cx)
|
||||||
|
.worktree_for_id(worktree_id, cx)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
split_or_open(
|
||||||
|
workspace,
|
||||||
ProjectPath {
|
ProjectPath {
|
||||||
worktree_id,
|
worktree_id,
|
||||||
path: Arc::clone(&history_match.project.path),
|
path: Arc::clone(&history_match.project.path),
|
||||||
},
|
},
|
||||||
None,
|
|
||||||
true,
|
|
||||||
cx,
|
cx,
|
||||||
),
|
)
|
||||||
|
} else {
|
||||||
|
match history_match.absolute.as_ref() {
|
||||||
|
Some(abs_path) => {
|
||||||
|
if secondary {
|
||||||
|
workspace.split_abs_path(
|
||||||
|
abs_path.to_path_buf(),
|
||||||
|
false,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
workspace.open_abs_path(
|
||||||
|
abs_path.to_path_buf(),
|
||||||
|
false,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => split_or_open(
|
||||||
|
workspace,
|
||||||
|
ProjectPath {
|
||||||
|
worktree_id,
|
||||||
|
path: Arc::clone(&history_match.project.path),
|
||||||
|
},
|
||||||
|
cx,
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Match::Search(m) => split_or_open(
|
||||||
|
workspace,
|
||||||
|
ProjectPath {
|
||||||
|
worktree_id: WorktreeId::from_usize(m.worktree_id),
|
||||||
|
path: m.path.clone(),
|
||||||
|
},
|
||||||
|
cx,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
Match::Search(m) => workspace.open_path(
|
|
||||||
ProjectPath {
|
|
||||||
worktree_id: WorktreeId::from_usize(m.worktree_id),
|
|
||||||
path: m.path.clone(),
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
true,
|
|
||||||
cx,
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let row = self
|
let row = self
|
||||||
|
@ -93,7 +93,7 @@ impl PickerDelegate for LanguageSelectorDelegate {
|
|||||||
self.matches.len()
|
self.matches.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
|
||||||
if let Some(mat) = self.matches.get(self.selected_index) {
|
if let Some(mat) = self.matches.get(self.selected_index) {
|
||||||
let language_name = &self.candidates[mat.candidate_id].string;
|
let language_name = &self.candidates[mat.candidate_id].string;
|
||||||
let language = self.language_registry.language_for_name(language_name);
|
let language = self.language_registry.language_for_name(language_name);
|
||||||
|
@ -3,6 +3,7 @@ gpui::actions!(
|
|||||||
[
|
[
|
||||||
Cancel,
|
Cancel,
|
||||||
Confirm,
|
Confirm,
|
||||||
|
SecondaryConfirm,
|
||||||
SelectPrev,
|
SelectPrev,
|
||||||
SelectNext,
|
SelectNext,
|
||||||
SelectFirst,
|
SelectFirst,
|
||||||
|
@ -177,7 +177,7 @@ impl PickerDelegate for OutlineViewDelegate {
|
|||||||
Task::ready(())
|
Task::ready(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<OutlineView>) {
|
fn confirm(&mut self, _: bool, cx: &mut ViewContext<OutlineView>) {
|
||||||
self.prev_scroll_position.take();
|
self.prev_scroll_position.take();
|
||||||
self.active_editor.update(cx, |active_editor, cx| {
|
self.active_editor.update(cx, |active_editor, cx| {
|
||||||
if let Some(rows) = active_editor.highlighted_rows() {
|
if let Some(rows) = active_editor.highlighted_rows() {
|
||||||
|
@ -7,7 +7,7 @@ use gpui::{
|
|||||||
AnyElement, AnyViewHandle, AppContext, Axis, Entity, MouseState, Task, View, ViewContext,
|
AnyElement, AnyViewHandle, AppContext, Axis, Entity, MouseState, Task, View, ViewContext,
|
||||||
ViewHandle,
|
ViewHandle,
|
||||||
};
|
};
|
||||||
use menu::{Cancel, Confirm, SelectFirst, SelectLast, SelectNext, SelectPrev};
|
use menu::{Cancel, Confirm, SecondaryConfirm, SelectFirst, SelectLast, SelectNext, SelectPrev};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{cmp, sync::Arc};
|
use std::{cmp, sync::Arc};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
@ -34,7 +34,7 @@ pub trait PickerDelegate: Sized + 'static {
|
|||||||
fn selected_index(&self) -> usize;
|
fn selected_index(&self) -> usize;
|
||||||
fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>);
|
fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext<Picker<Self>>);
|
||||||
fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()>;
|
fn update_matches(&mut self, query: String, cx: &mut ViewContext<Picker<Self>>) -> Task<()>;
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<Picker<Self>>);
|
fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<Self>>);
|
||||||
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>);
|
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>);
|
||||||
fn render_match(
|
fn render_match(
|
||||||
&self,
|
&self,
|
||||||
@ -118,8 +118,8 @@ impl<D: PickerDelegate> View for Picker<D> {
|
|||||||
// Capture mouse events
|
// Capture mouse events
|
||||||
.on_down(MouseButton::Left, |_, _, _| {})
|
.on_down(MouseButton::Left, |_, _, _| {})
|
||||||
.on_up(MouseButton::Left, |_, _, _| {})
|
.on_up(MouseButton::Left, |_, _, _| {})
|
||||||
.on_click(MouseButton::Left, move |_, picker, cx| {
|
.on_click(MouseButton::Left, move |click, picker, cx| {
|
||||||
picker.select_index(ix, cx);
|
picker.select_index(ix, click.cmd, cx);
|
||||||
})
|
})
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
.into_any()
|
.into_any()
|
||||||
@ -175,6 +175,7 @@ impl<D: PickerDelegate> Picker<D> {
|
|||||||
cx.add_action(Self::select_next);
|
cx.add_action(Self::select_next);
|
||||||
cx.add_action(Self::select_prev);
|
cx.add_action(Self::select_prev);
|
||||||
cx.add_action(Self::confirm);
|
cx.add_action(Self::confirm);
|
||||||
|
cx.add_action(Self::secondary_confirm);
|
||||||
cx.add_action(Self::cancel);
|
cx.add_action(Self::cancel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,11 +289,11 @@ impl<D: PickerDelegate> Picker<D> {
|
|||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_index(&mut self, index: usize, cx: &mut ViewContext<Self>) {
|
pub fn select_index(&mut self, index: usize, cmd: bool, cx: &mut ViewContext<Self>) {
|
||||||
if self.delegate.match_count() > 0 {
|
if self.delegate.match_count() > 0 {
|
||||||
self.confirmed = true;
|
self.confirmed = true;
|
||||||
self.delegate.set_selected_index(index, cx);
|
self.delegate.set_selected_index(index, cx);
|
||||||
self.delegate.confirm(cx);
|
self.delegate.confirm(cmd, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,7 +331,12 @@ impl<D: PickerDelegate> Picker<D> {
|
|||||||
|
|
||||||
pub fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
|
pub fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
|
||||||
self.confirmed = true;
|
self.confirmed = true;
|
||||||
self.delegate.confirm(cx);
|
self.delegate.confirm(false, cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn secondary_confirm(&mut self, _: &SecondaryConfirm, cx: &mut ViewContext<Self>) {
|
||||||
|
self.confirmed = true;
|
||||||
|
self.delegate.confirm(true, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
|
fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -159,6 +159,9 @@ pub enum Event {
|
|||||||
entry_id: ProjectEntryId,
|
entry_id: ProjectEntryId,
|
||||||
focus_opened_item: bool,
|
focus_opened_item: bool,
|
||||||
},
|
},
|
||||||
|
SplitEntry {
|
||||||
|
entry_id: ProjectEntryId,
|
||||||
|
},
|
||||||
DockPositionChanged,
|
DockPositionChanged,
|
||||||
Focus,
|
Focus,
|
||||||
}
|
}
|
||||||
@ -290,6 +293,21 @@ impl ProjectPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&Event::SplitEntry { entry_id } => {
|
||||||
|
if let Some(worktree) = project.read(cx).worktree_for_entry(entry_id, cx) {
|
||||||
|
if let Some(entry) = worktree.read(cx).entry_for_id(entry_id) {
|
||||||
|
workspace
|
||||||
|
.split_path(
|
||||||
|
ProjectPath {
|
||||||
|
worktree_id: worktree.read(cx).id(),
|
||||||
|
path: entry.path.clone(),
|
||||||
|
},
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.detach_and_log_err(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -620,6 +638,10 @@ impl ProjectPanel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn split_entry(&mut self, entry_id: ProjectEntryId, cx: &mut ViewContext<Self>) {
|
||||||
|
cx.emit(Event::SplitEntry { entry_id });
|
||||||
|
}
|
||||||
|
|
||||||
fn new_file(&mut self, _: &NewFile, cx: &mut ViewContext<Self>) {
|
fn new_file(&mut self, _: &NewFile, cx: &mut ViewContext<Self>) {
|
||||||
self.add_entry(false, cx)
|
self.add_entry(false, cx)
|
||||||
}
|
}
|
||||||
@ -1333,7 +1355,11 @@ impl ProjectPanel {
|
|||||||
if kind.is_dir() {
|
if kind.is_dir() {
|
||||||
this.toggle_expanded(entry_id, cx);
|
this.toggle_expanded(entry_id, cx);
|
||||||
} else {
|
} else {
|
||||||
this.open_entry(entry_id, event.click_count > 1, cx);
|
if event.cmd && event.click_count > 1 {
|
||||||
|
this.split_entry(entry_id, cx);
|
||||||
|
} else if !event.cmd {
|
||||||
|
this.open_entry(entry_id, event.click_count > 1, cx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -104,7 +104,7 @@ impl PickerDelegate for ProjectSymbolsDelegate {
|
|||||||
"Search project symbols...".into()
|
"Search project symbols...".into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<ProjectSymbols>) {
|
fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<ProjectSymbols>) {
|
||||||
if let Some(symbol) = self
|
if let Some(symbol) = self
|
||||||
.matches
|
.matches
|
||||||
.get(self.selected_match_index)
|
.get(self.selected_match_index)
|
||||||
@ -122,7 +122,12 @@ impl PickerDelegate for ProjectSymbolsDelegate {
|
|||||||
.read(cx)
|
.read(cx)
|
||||||
.clip_point_utf16(symbol.range.start, Bias::Left);
|
.clip_point_utf16(symbol.range.start, Bias::Left);
|
||||||
|
|
||||||
let editor = workspace.open_project_item::<Editor>(buffer, cx);
|
let editor = if secondary {
|
||||||
|
workspace.split_project_item::<Editor>(buffer, cx)
|
||||||
|
} else {
|
||||||
|
workspace.open_project_item::<Editor>(buffer, cx)
|
||||||
|
};
|
||||||
|
|
||||||
editor.update(cx, |editor, cx| {
|
editor.update(cx, |editor, cx| {
|
||||||
editor.change_selections(Some(Autoscroll::center()), cx, |s| {
|
editor.change_selections(Some(Autoscroll::center()), cx, |s| {
|
||||||
s.select_ranges([position..position])
|
s.select_ranges([position..position])
|
||||||
|
@ -161,7 +161,7 @@ impl PickerDelegate for RecentProjectsDelegate {
|
|||||||
Task::ready(())
|
Task::ready(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<RecentProjects>) {
|
fn confirm(&mut self, _: bool, cx: &mut ViewContext<RecentProjects>) {
|
||||||
if let Some((selected_match, workspace)) = self
|
if let Some((selected_match, workspace)) = self
|
||||||
.matches
|
.matches
|
||||||
.get(self.selected_index())
|
.get(self.selected_index())
|
||||||
|
@ -120,7 +120,7 @@ impl PickerDelegate for ThemeSelectorDelegate {
|
|||||||
self.matches.len()
|
self.matches.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<ThemeSelector>) {
|
fn confirm(&mut self, _: bool, cx: &mut ViewContext<ThemeSelector>) {
|
||||||
self.selection_completed = true;
|
self.selection_completed = true;
|
||||||
|
|
||||||
let theme_name = theme::current(cx).meta.name.clone();
|
let theme_name = theme::current(cx).meta.name.clone();
|
||||||
|
@ -182,7 +182,7 @@ impl PickerDelegate for BranchListDelegate {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<Picker<Self>>) {
|
fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
|
||||||
let current_pick = self.selected_index();
|
let current_pick = self.selected_index();
|
||||||
let Some(current_pick) = self.matches.get(current_pick).map(|pick| pick.string.clone()) else {
|
let Some(current_pick) = self.matches.get(current_pick).map(|pick| pick.string.clone()) else {
|
||||||
return;
|
return;
|
||||||
|
@ -51,7 +51,7 @@ impl PickerDelegate for SemanticSearchDelegate {
|
|||||||
"Search repository in natural language...".into()
|
"Search repository in natural language...".into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<SemanticSearch>) {
|
fn confirm(&mut self, _: bool, cx: &mut ViewContext<SemanticSearch>) {
|
||||||
if let Some(search_result) = self.matches.get(self.selected_match_index) {
|
if let Some(search_result) = self.matches.get(self.selected_match_index) {
|
||||||
// Open Buffer
|
// Open Buffer
|
||||||
let search_result = search_result.clone();
|
let search_result = search_result.clone();
|
||||||
|
@ -120,7 +120,7 @@ impl PickerDelegate for BaseKeymapSelectorDelegate {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, cx: &mut ViewContext<BaseKeymapSelector>) {
|
fn confirm(&mut self, _: bool, cx: &mut ViewContext<BaseKeymapSelector>) {
|
||||||
if let Some(selection) = self.matches.get(self.selected_index) {
|
if let Some(selection) = self.matches.get(self.selected_index) {
|
||||||
let base_keymap = BaseKeymap::from_names(&selection.string);
|
let base_keymap = BaseKeymap::from_names(&selection.string);
|
||||||
update_settings_file::<BaseKeymap>(self.fs.clone(), cx, move |setting| {
|
update_settings_file::<BaseKeymap>(self.fs.clone(), cx, move |setting| {
|
||||||
|
@ -1821,6 +1821,13 @@ impl Workspace {
|
|||||||
.update(cx, |pane, cx| pane.add_item(item, true, true, None, cx));
|
.update(cx, |pane, cx| pane.add_item(item, true, true, None, cx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn split_item(&mut self, item: Box<dyn ItemHandle>, cx: &mut ViewContext<Self>) {
|
||||||
|
let new_pane = self.split_pane(self.active_pane.clone(), SplitDirection::Right, cx);
|
||||||
|
new_pane.update(cx, move |new_pane, cx| {
|
||||||
|
new_pane.add_item(item, true, true, None, cx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn open_abs_path(
|
pub fn open_abs_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
abs_path: PathBuf,
|
abs_path: PathBuf,
|
||||||
@ -1851,6 +1858,21 @@ impl Workspace {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn split_abs_path(
|
||||||
|
&mut self,
|
||||||
|
abs_path: PathBuf,
|
||||||
|
visible: bool,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> Task<anyhow::Result<Box<dyn ItemHandle>>> {
|
||||||
|
let project_path_task =
|
||||||
|
Workspace::project_path_for_path(self.project.clone(), &abs_path, visible, cx);
|
||||||
|
cx.spawn(|this, mut cx| async move {
|
||||||
|
let (_, path) = project_path_task.await?;
|
||||||
|
this.update(&mut cx, |this, cx| this.split_path(path, cx))?
|
||||||
|
.await
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn open_path(
|
pub fn open_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: impl Into<ProjectPath>,
|
path: impl Into<ProjectPath>,
|
||||||
@ -1876,6 +1898,38 @@ impl Workspace {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn split_path(
|
||||||
|
&mut self,
|
||||||
|
path: impl Into<ProjectPath>,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> Task<Result<Box<dyn ItemHandle>, anyhow::Error>> {
|
||||||
|
let pane = self.last_active_center_pane.clone().unwrap_or_else(|| {
|
||||||
|
self.panes
|
||||||
|
.first()
|
||||||
|
.expect("There must be an active pane")
|
||||||
|
.downgrade()
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Member::Pane(center_pane) = &self.center.root {
|
||||||
|
if center_pane.read(cx).items_len() == 0 {
|
||||||
|
return self.open_path(path, Some(pane), true, cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let task = self.load_path(path.into(), cx);
|
||||||
|
cx.spawn(|this, mut cx| async move {
|
||||||
|
let (project_entry_id, build_item) = task.await?;
|
||||||
|
this.update(&mut cx, move |this, cx| -> Option<_> {
|
||||||
|
let pane = pane.upgrade(cx)?;
|
||||||
|
let new_pane = this.split_pane(pane, SplitDirection::Right, cx);
|
||||||
|
new_pane.update(cx, |new_pane, cx| {
|
||||||
|
Some(new_pane.open_item(project_entry_id, true, cx, build_item))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map(|option| option.ok_or_else(|| anyhow!("pane was dropped")))?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn load_path(
|
pub(crate) fn load_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
path: ProjectPath,
|
path: ProjectPath,
|
||||||
@ -1926,6 +1980,30 @@ impl Workspace {
|
|||||||
item
|
item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn split_project_item<T>(
|
||||||
|
&mut self,
|
||||||
|
project_item: ModelHandle<T::Item>,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> ViewHandle<T>
|
||||||
|
where
|
||||||
|
T: ProjectItem,
|
||||||
|
{
|
||||||
|
use project::Item as _;
|
||||||
|
|
||||||
|
let entry_id = project_item.read(cx).entry_id(cx);
|
||||||
|
if let Some(item) = entry_id
|
||||||
|
.and_then(|entry_id| self.active_pane().read(cx).item_for_entry(entry_id, cx))
|
||||||
|
.and_then(|item| item.downcast())
|
||||||
|
{
|
||||||
|
self.activate_item(&item, cx);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
let item = cx.add_view(|cx| T::for_project_item(self.project().clone(), project_item, cx));
|
||||||
|
self.split_item(Box::new(item.clone()), cx);
|
||||||
|
item
|
||||||
|
}
|
||||||
|
|
||||||
pub fn open_shared_screen(&mut self, peer_id: PeerId, cx: &mut ViewContext<Self>) {
|
pub fn open_shared_screen(&mut self, peer_id: PeerId, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(shared_screen) = self.shared_screen_for_peer(peer_id, &self.active_pane, cx) {
|
if let Some(shared_screen) = self.shared_screen_for_peer(peer_id, &self.active_pane, cx) {
|
||||||
self.active_pane.update(cx, |pane, cx| {
|
self.active_pane.update(cx, |pane, cx| {
|
||||||
@ -1953,7 +2031,7 @@ impl Workspace {
|
|||||||
if let Some(pane) = panes.get(action.0).map(|p| (*p).clone()) {
|
if let Some(pane) = panes.get(action.0).map(|p| (*p).clone()) {
|
||||||
cx.focus(&pane);
|
cx.focus(&pane);
|
||||||
} else {
|
} else {
|
||||||
self.split_pane(self.active_pane.clone(), SplitDirection::Right, cx);
|
self.split_and_clone(self.active_pane.clone(), SplitDirection::Right, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2006,7 +2084,7 @@ impl Workspace {
|
|||||||
match event {
|
match event {
|
||||||
pane::Event::AddItem { item } => item.added_to_pane(self, pane, cx),
|
pane::Event::AddItem { item } => item.added_to_pane(self, pane, cx),
|
||||||
pane::Event::Split(direction) => {
|
pane::Event::Split(direction) => {
|
||||||
self.split_pane(pane, *direction, cx);
|
self.split_and_clone(pane, *direction, cx);
|
||||||
}
|
}
|
||||||
pane::Event::Remove => self.remove_pane(pane, cx),
|
pane::Event::Remove => self.remove_pane(pane, cx),
|
||||||
pane::Event::ActivateItem { local } => {
|
pane::Event::ActivateItem { local } => {
|
||||||
@ -2057,6 +2135,20 @@ impl Workspace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn split_pane(
|
pub fn split_pane(
|
||||||
|
&mut self,
|
||||||
|
pane_to_split: ViewHandle<Pane>,
|
||||||
|
split_direction: SplitDirection,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) -> ViewHandle<Pane> {
|
||||||
|
let new_pane = self.add_pane(cx);
|
||||||
|
self.center
|
||||||
|
.split(&pane_to_split, &new_pane, split_direction)
|
||||||
|
.unwrap();
|
||||||
|
cx.notify();
|
||||||
|
new_pane
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn split_and_clone(
|
||||||
&mut self,
|
&mut self,
|
||||||
pane: ViewHandle<Pane>,
|
pane: ViewHandle<Pane>,
|
||||||
direction: SplitDirection,
|
direction: SplitDirection,
|
||||||
@ -4246,7 +4338,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
|
|
||||||
workspace
|
workspace
|
||||||
.split_pane(left_pane.clone(), SplitDirection::Right, cx)
|
.split_and_clone(left_pane.clone(), SplitDirection::Right, cx)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
left_pane
|
left_pane
|
||||||
|
@ -1021,7 +1021,7 @@ mod tests {
|
|||||||
// Split the pane with the first entry, then open the second entry again.
|
// Split the pane with the first entry, then open the second entry again.
|
||||||
workspace
|
workspace
|
||||||
.update(cx, |w, cx| {
|
.update(cx, |w, cx| {
|
||||||
w.split_pane(w.active_pane().clone(), SplitDirection::Right, cx);
|
w.split_and_clone(w.active_pane().clone(), SplitDirection::Right, cx);
|
||||||
w.open_path(file2.clone(), None, true, cx)
|
w.open_path(file2.clone(), None, true, cx)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
@ -1344,7 +1344,11 @@ mod tests {
|
|||||||
cx.dispatch_action(window_id, NewFile);
|
cx.dispatch_action(window_id, NewFile);
|
||||||
workspace
|
workspace
|
||||||
.update(cx, |workspace, cx| {
|
.update(cx, |workspace, cx| {
|
||||||
workspace.split_pane(workspace.active_pane().clone(), SplitDirection::Right, cx);
|
workspace.split_and_clone(
|
||||||
|
workspace.active_pane().clone(),
|
||||||
|
SplitDirection::Right,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
workspace.open_path((worktree.read(cx).id(), "the-new-name.rs"), None, true, cx)
|
workspace.open_path((worktree.read(cx).id(), "the-new-name.rs"), None, true, cx)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
Loading…
Reference in New Issue
Block a user