From 2e6cf2011d842dd89ba80b6dcc85c109b7e1d9ff Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 5 May 2022 15:27:27 +0200 Subject: [PATCH] When opening items via project panel, only focus them on double-click Co-Authored-By: Nathan Sobo --- crates/collab/src/rpc.rs | 22 +++++----- crates/file_finder/src/file_finder.rs | 2 +- crates/project_panel/src/project_panel.rs | 51 ++++++++++++++++------- crates/vim/src/vim_test_context.rs | 2 +- crates/workspace/src/pane.rs | 47 ++++++++++++++------- crates/workspace/src/workspace.rs | 14 ++++--- crates/zed/src/zed.rs | 21 +++++----- 7 files changed, 98 insertions(+), 61 deletions(-) diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 4a4985c470..827ac564f8 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -3898,7 +3898,7 @@ mod tests { let (_window_b, workspace_b) = cx_b.add_window(|cx| Workspace::new(¶ms, cx)); let editor_b = workspace_b .update(cx_b, |workspace, cx| { - workspace.open_path((worktree_id, "main.rs"), cx) + workspace.open_path((worktree_id, "main.rs"), true, cx) }) .await .unwrap() @@ -4146,7 +4146,7 @@ mod tests { let (_window_b, workspace_b) = cx_b.add_window(|cx| Workspace::new(¶ms, cx)); let editor_b = workspace_b .update(cx_b, |workspace, cx| { - workspace.open_path((worktree_id, "one.rs"), cx) + workspace.open_path((worktree_id, "one.rs"), true, cx) }) .await .unwrap() @@ -4898,7 +4898,7 @@ mod tests { let pane_a = workspace_a.read_with(cx_a, |workspace, _| workspace.active_pane().clone()); let editor_a1 = workspace_a .update(cx_a, |workspace, cx| { - workspace.open_path((worktree_id, "1.txt"), cx) + workspace.open_path((worktree_id, "1.txt"), true, cx) }) .await .unwrap() @@ -4906,7 +4906,7 @@ mod tests { .unwrap(); let editor_a2 = workspace_a .update(cx_a, |workspace, cx| { - workspace.open_path((worktree_id, "2.txt"), cx) + workspace.open_path((worktree_id, "2.txt"), true, cx) }) .await .unwrap() @@ -4917,7 +4917,7 @@ mod tests { let workspace_b = client_b.build_workspace(&project_b, cx_b); let editor_b1 = workspace_b .update(cx_b, |workspace, cx| { - workspace.open_path((worktree_id, "1.txt"), cx) + workspace.open_path((worktree_id, "1.txt"), true, cx) }) .await .unwrap() @@ -5110,7 +5110,7 @@ mod tests { let pane_a1 = workspace_a.read_with(cx_a, |workspace, _| workspace.active_pane().clone()); let _editor_a1 = workspace_a .update(cx_a, |workspace, cx| { - workspace.open_path((worktree_id, "1.txt"), cx) + workspace.open_path((worktree_id, "1.txt"), true, cx) }) .await .unwrap() @@ -5122,7 +5122,7 @@ mod tests { let pane_b1 = workspace_b.read_with(cx_b, |workspace, _| workspace.active_pane().clone()); let _editor_b1 = workspace_b .update(cx_b, |workspace, cx| { - workspace.open_path((worktree_id, "2.txt"), cx) + workspace.open_path((worktree_id, "2.txt"), true, cx) }) .await .unwrap() @@ -5157,7 +5157,7 @@ mod tests { .update(cx_a, |workspace, cx| { workspace.activate_next_pane(cx); assert_eq!(*workspace.active_pane(), pane_a1); - workspace.open_path((worktree_id, "3.txt"), cx) + workspace.open_path((worktree_id, "3.txt"), true, cx) }) .await .unwrap(); @@ -5165,7 +5165,7 @@ mod tests { .update(cx_b, |workspace, cx| { workspace.activate_next_pane(cx); assert_eq!(*workspace.active_pane(), pane_b1); - workspace.open_path((worktree_id, "4.txt"), cx) + workspace.open_path((worktree_id, "4.txt"), true, cx) }) .await .unwrap(); @@ -5254,7 +5254,7 @@ mod tests { let workspace_a = client_a.build_workspace(&project_a, cx_a); let _editor_a1 = workspace_a .update(cx_a, |workspace, cx| { - workspace.open_path((worktree_id, "1.txt"), cx) + workspace.open_path((worktree_id, "1.txt"), true, cx) }) .await .unwrap() @@ -5367,7 +5367,7 @@ mod tests { // When client B activates a different item in the original pane, it automatically stops following client A. workspace_b .update(cx_b, |workspace, cx| { - workspace.open_path((worktree_id, "2.txt"), cx) + workspace.open_path((worktree_id, "2.txt"), true, cx) }) .await .unwrap(); diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index ae176dccaa..a63ff7b0bd 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -102,7 +102,7 @@ impl FileFinder { match event { Event::Selected(project_path) => { workspace - .open_path(project_path.clone(), cx) + .open_path(project_path.clone(), true, cx) .detach_and_log_err(cx); workspace.dismiss_modal(cx); } diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 220278fd1d..9530b2c2e2 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -103,7 +103,10 @@ pub fn init(cx: &mut MutableAppContext) { } pub enum Event { - OpenedEntry(ProjectEntryId), + OpenedEntry { + entry_id: ProjectEntryId, + focus_opened_item: bool, + }, } impl ProjectPanel { @@ -157,19 +160,29 @@ impl ProjectPanel { this.update_visible_entries(None, cx); this }); - cx.subscribe(&project_panel, move |workspace, _, event, cx| match event { - &Event::OpenedEntry(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 - .open_path( - ProjectPath { - worktree_id: worktree.read(cx).id(), - path: entry.path.clone(), - }, - cx, - ) - .detach_and_log_err(cx); + cx.subscribe(&project_panel, { + let project_panel = project_panel.clone(); + move |workspace, _, event, cx| match event { + &Event::OpenedEntry { + entry_id, + focus_opened_item, + } => { + 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 + .open_path( + ProjectPath { + worktree_id: worktree.read(cx).id(), + path: entry.path.clone(), + }, + focus_opened_item, + cx, + ) + .detach_and_log_err(cx); + if !focus_opened_item { + cx.focus(&project_panel); + } + } } } } @@ -198,7 +211,10 @@ impl ProjectPanel { } } } else { - let event = Event::OpenedEntry(entry.id); + let event = Event::OpenedEntry { + entry_id: entry.id, + focus_opened_item: true, + }; cx.emit(event); } } @@ -342,7 +358,10 @@ impl ProjectPanel { } fn open_entry(&mut self, action: &Open, cx: &mut ViewContext) { - cx.emit(Event::OpenedEntry(action.entry_id)); + cx.emit(Event::OpenedEntry { + entry_id: action.entry_id, + focus_opened_item: action.change_focus, + }); } fn add_file(&mut self, _: &AddFile, cx: &mut ViewContext) { diff --git a/crates/vim/src/vim_test_context.rs b/crates/vim/src/vim_test_context.rs index 400a8e467a..f99fceef3a 100644 --- a/crates/vim/src/vim_test_context.rs +++ b/crates/vim/src/vim_test_context.rs @@ -50,7 +50,7 @@ impl<'a> VimTestContext<'a> { let file = cx.read(|cx| workspace.file_project_paths(cx)[0].clone()); let item = workspace - .update(cx, |workspace, cx| workspace.open_path(file, cx)) + .update(cx, |workspace, cx| workspace.open_path(file, true, cx)) .await .expect("Could not open test file"); diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 94fe7c3a42..e963ca7e02 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -59,7 +59,7 @@ const MAX_NAVIGATION_HISTORY_LEN: usize = 1024; pub fn init(cx: &mut MutableAppContext) { cx.add_action(|pane: &mut Pane, action: &ActivateItem, cx| { - pane.activate_item(action.0, true, cx); + pane.activate_item(action.0, true, true, cx); }); cx.add_action(|pane: &mut Pane, _: &ActivatePrevItem, cx| { pane.activate_prev_item(cx); @@ -213,7 +213,7 @@ impl Pane { { let prev_active_item_index = pane.active_item_index; pane.nav_history.borrow_mut().set_mode(mode); - pane.activate_item(index, true, cx); + pane.activate_item(index, true, true, cx); pane.nav_history .borrow_mut() .set_mode(NavigationMode::Normal); @@ -257,6 +257,7 @@ impl Pane { workspace, pane.clone(), project_entry_id, + true, cx, build_item, ) @@ -287,6 +288,7 @@ impl Pane { workspace: &mut Workspace, pane: ViewHandle, project_entry_id: ProjectEntryId, + focus_item: bool, cx: &mut ViewContext, build_item: impl FnOnce(&mut MutableAppContext) -> Box, ) -> Box { @@ -294,7 +296,7 @@ impl Pane { for (ix, item) in pane.items.iter().enumerate() { if item.project_entry_id(cx) == Some(project_entry_id) { let item = item.boxed_clone(); - pane.activate_item(ix, true, cx); + pane.activate_item(ix, true, focus_item, cx); return Some(item); } } @@ -304,7 +306,7 @@ impl Pane { existing_item } else { let item = build_item(cx); - Self::add_item(workspace, pane, item.boxed_clone(), true, cx); + Self::add_item(workspace, pane, item.boxed_clone(), true, focus_item, cx); item } } @@ -313,12 +315,15 @@ impl Pane { workspace: &mut Workspace, pane: ViewHandle, item: Box, - local: bool, + activate_pane: bool, + focus_item: bool, cx: &mut ViewContext, ) { // Prevent adding the same item to the pane more than once. if let Some(item_ix) = pane.read(cx).items.iter().position(|i| i.id() == item.id()) { - pane.update(cx, |pane, cx| pane.activate_item(item_ix, local, cx)); + pane.update(cx, |pane, cx| { + pane.activate_item(item_ix, activate_pane, focus_item, cx) + }); return; } @@ -327,7 +332,7 @@ impl Pane { pane.update(cx, |pane, cx| { let item_idx = cmp::min(pane.active_item_index + 1, pane.items.len()); pane.items.insert(item_idx, item); - pane.activate_item(item_idx, local, cx); + pane.activate_item(item_idx, activate_pane, focus_item, cx); cx.notify(); }); } @@ -378,7 +383,13 @@ impl Pane { self.items.iter().position(|i| i.id() == item.id()) } - pub fn activate_item(&mut self, index: usize, local: bool, cx: &mut ViewContext) { + pub fn activate_item( + &mut self, + index: usize, + activate_pane: bool, + focus_item: bool, + cx: &mut ViewContext, + ) { use NavigationMode::{GoingBack, GoingForward}; if index < self.items.len() { let prev_active_item_ix = mem::replace(&mut self.active_item_index, index); @@ -387,11 +398,15 @@ impl Pane { && prev_active_item_ix < self.items.len()) { self.items[prev_active_item_ix].deactivated(cx); - cx.emit(Event::ActivateItem { local }); + cx.emit(Event::ActivateItem { + local: activate_pane, + }); } self.update_toolbar(cx); - if local { + if focus_item { self.focus_active_item(cx); + } + if activate_pane { self.activate(cx); } self.autoscroll = true; @@ -406,7 +421,7 @@ impl Pane { } else if self.items.len() > 0 { index = self.items.len() - 1; } - self.activate_item(index, true, cx); + self.activate_item(index, true, true, cx); } pub fn activate_next_item(&mut self, cx: &mut ViewContext) { @@ -416,7 +431,7 @@ impl Pane { } else { index = 0; } - self.activate_item(index, true, cx); + self.activate_item(index, true, true, cx); } fn close_active_item( @@ -498,7 +513,7 @@ impl Pane { if is_last_item_for_entry { if cx.read(|cx| item.has_conflict(cx) && item.can_save(cx)) { let mut answer = pane.update(&mut cx, |pane, cx| { - pane.activate_item(item_to_close_ix, true, cx); + pane.activate_item(item_to_close_ix, true, true, cx); cx.prompt( PromptLevel::Warning, CONFLICT_MESSAGE, @@ -518,7 +533,7 @@ impl Pane { } else if cx.read(|cx| item.is_dirty(cx)) { if cx.read(|cx| item.can_save(cx)) { let mut answer = pane.update(&mut cx, |pane, cx| { - pane.activate_item(item_to_close_ix, true, cx); + pane.activate_item(item_to_close_ix, true, true, cx); cx.prompt( PromptLevel::Warning, DIRTY_MESSAGE, @@ -535,7 +550,7 @@ impl Pane { } } else if cx.read(|cx| item.can_save_as(cx)) { let mut answer = pane.update(&mut cx, |pane, cx| { - pane.activate_item(item_to_close_ix, true, cx); + pane.activate_item(item_to_close_ix, true, true, cx); cx.prompt( PromptLevel::Warning, DIRTY_MESSAGE, @@ -949,7 +964,7 @@ mod tests { let close_items = workspace.update(cx, |workspace, cx| { pane.update(cx, |pane, cx| { - pane.activate_item(1, true, cx); + pane.activate_item(1, true, true, cx); assert_eq!(pane.active_item().unwrap().id(), item2.id()); }); diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index fe18fcb95a..499ae037c5 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -493,7 +493,7 @@ impl ItemHandle for ViewHandle { if T::should_activate_item_on_event(event) { pane.update(cx, |pane, cx| { if let Some(ix) = pane.index_for_item(&item) { - pane.activate_item(ix, true, cx); + pane.activate_item(ix, true, true, cx); pane.activate(cx); } }); @@ -898,7 +898,7 @@ impl Workspace { if fs.is_file(&abs_path).await { Some( this.update(&mut cx, |this, cx| { - this.open_path(project_path, cx) + this.open_path(project_path, true, cx) }) .await, ) @@ -1099,12 +1099,13 @@ impl Workspace { pub fn add_item(&mut self, item: Box, cx: &mut ViewContext) { let pane = self.active_pane().clone(); - Pane::add_item(self, pane, item, true, cx); + Pane::add_item(self, pane, item, true, true, cx); } pub fn open_path( &mut self, path: impl Into, + focus_item: bool, cx: &mut ViewContext, ) -> Task, Arc>> { let pane = self.active_pane().downgrade(); @@ -1119,6 +1120,7 @@ impl Workspace { this, pane, project_entry_id, + focus_item, cx, build_item, )) @@ -1187,7 +1189,7 @@ impl Workspace { }); if let Some((pane, ix)) = result { self.activate_pane(pane.clone(), cx); - pane.update(cx, |pane, cx| pane.activate_item(ix, true, cx)); + pane.update(cx, |pane, cx| pane.activate_item(ix, true, true, cx)); true } else { false @@ -1277,7 +1279,7 @@ impl Workspace { self.activate_pane(new_pane.clone(), cx); if let Some(item) = pane.read(cx).active_item() { if let Some(clone) = item.clone_on_split(cx.as_mut()) { - Pane::add_item(self, new_pane.clone(), clone, true, cx); + Pane::add_item(self, new_pane.clone(), clone, true, true, cx); } } self.center.split(&pane, &new_pane, direction).unwrap(); @@ -1961,7 +1963,7 @@ impl Workspace { } for (pane, item) in items_to_add { - Pane::add_item(self, pane.clone(), item.boxed_clone(), false, cx); + Pane::add_item(self, pane.clone(), item.boxed_clone(), false, false, cx); if pane == self.active_pane { pane.update(cx, |pane, cx| pane.focus_active_item(cx)); } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 20b5626834..77e400e02f 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -446,7 +446,7 @@ mod tests { // Open the first entry let entry_1 = workspace - .update(cx, |w, cx| w.open_path(file1.clone(), cx)) + .update(cx, |w, cx| w.open_path(file1.clone(), true, cx)) .await .unwrap(); cx.read(|cx| { @@ -460,7 +460,7 @@ mod tests { // Open the second entry workspace - .update(cx, |w, cx| w.open_path(file2.clone(), cx)) + .update(cx, |w, cx| w.open_path(file2.clone(), true, cx)) .await .unwrap(); cx.read(|cx| { @@ -474,7 +474,7 @@ mod tests { // Open the first entry again. The existing pane item is activated. let entry_1b = workspace - .update(cx, |w, cx| w.open_path(file1.clone(), cx)) + .update(cx, |w, cx| w.open_path(file1.clone(), true, cx)) .await .unwrap(); assert_eq!(entry_1.id(), entry_1b.id()); @@ -492,7 +492,7 @@ mod tests { workspace .update(cx, |w, cx| { w.split_pane(w.active_pane().clone(), SplitDirection::Right, cx); - w.open_path(file2.clone(), cx) + w.open_path(file2.clone(), true, cx) }) .await .unwrap(); @@ -511,8 +511,8 @@ mod tests { // Open the third entry twice concurrently. Only one pane item is added. let (t1, t2) = workspace.update(cx, |w, cx| { ( - w.open_path(file3.clone(), cx), - w.open_path(file3.clone(), cx), + w.open_path(file3.clone(), true, cx), + w.open_path(file3.clone(), true, cx), ) }); t1.await.unwrap(); @@ -780,6 +780,7 @@ mod tests { worktree_id: worktree.read(cx).id(), path: Path::new("the-new-name.rs").into(), }, + true, cx, ) }) @@ -875,7 +876,7 @@ mod tests { let pane_1 = cx.read(|cx| workspace.read(cx).active_pane().clone()); workspace - .update(cx, |w, cx| w.open_path(file1.clone(), cx)) + .update(cx, |w, cx| w.open_path(file1.clone(), true, cx)) .await .unwrap(); @@ -955,7 +956,7 @@ mod tests { let file3 = entries[2].clone(); let editor1 = workspace - .update(cx, |w, cx| w.open_path(file1.clone(), cx)) + .update(cx, |w, cx| w.open_path(file1.clone(), true, cx)) .await .unwrap() .downcast::() @@ -964,13 +965,13 @@ mod tests { editor.select_display_ranges(&[DisplayPoint::new(10, 0)..DisplayPoint::new(10, 0)], cx); }); let editor2 = workspace - .update(cx, |w, cx| w.open_path(file2.clone(), cx)) + .update(cx, |w, cx| w.open_path(file2.clone(), true, cx)) .await .unwrap() .downcast::() .unwrap(); let editor3 = workspace - .update(cx, |w, cx| w.open_path(file3.clone(), cx)) + .update(cx, |w, cx| w.open_path(file3.clone(), true, cx)) .await .unwrap() .downcast::()