@@ -212,7 +212,6 @@ pub enum Event {
entry_id: ProjectEntryId,
focus_opened_item: bool,
allow_preview: bool,
- mark_selected: bool,
},
SplitEntry {
entry_id: ProjectEntryId,
@@ -352,24 +351,12 @@ impl ProjectPanel {
entry_id,
focus_opened_item,
allow_preview,
- mark_selected
} => {
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) {
let file_path = entry.path.clone();
let worktree_id = worktree.read(cx).id();
let entry_id = entry.id;
-
- project_panel.update(cx, |this, _| {
- if !mark_selected {
- this.marked_entries.clear();
- }
- this.marked_entries.insert(SelectedEntry {
- worktree_id,
- entry_id
- });
- }).ok();
-
let is_via_ssh = project.read(cx).is_via_ssh();
workspace
@@ -399,12 +386,12 @@ impl ProjectPanel {
});
if let Some(project_panel) = project_panel.upgrade() {
- // Always select the entry, regardless of whether it is opened or not.
+ // Always select and mark the entry, regardless of whether it is opened or not.
project_panel.update(cx, |project_panel, _| {
- project_panel.selection = Some(SelectedEntry {
- worktree_id,
- entry_id
- });
+ let entry = SelectedEntry { worktree_id, entry_id };
+ project_panel.marked_entries.clear();
+ project_panel.marked_entries.insert(entry);
+ project_panel.selection = Some(entry);
});
if !focus_opened_item {
let focus_handle = project_panel.read(cx).focus_handle.clone();
@@ -793,29 +780,22 @@ impl ProjectPanel {
fn open(&mut self, _: &Open, cx: &mut ViewContext<Self>) {
let preview_tabs_enabled = PreviewTabsSettings::get_global(cx).enabled;
- self.open_internal(false, true, !preview_tabs_enabled, cx);
+ self.open_internal(true, !preview_tabs_enabled, cx);
}
fn open_permanent(&mut self, _: &OpenPermanent, cx: &mut ViewContext<Self>) {
- self.open_internal(true, false, true, cx);
+ self.open_internal(false, true, cx);
}
fn open_internal(
&mut self,
- mark_selected: bool,
allow_preview: bool,
focus_opened_item: bool,
cx: &mut ViewContext<Self>,
) {
if let Some((_, entry)) = self.selected_entry(cx) {
if entry.is_file() {
- self.open_entry(
- entry.id,
- mark_selected,
- focus_opened_item,
- allow_preview,
- cx,
- );
+ self.open_entry(entry.id, focus_opened_item, allow_preview, cx);
} else {
self.toggle_expanded(entry.id, cx);
}
@@ -897,7 +877,7 @@ impl ProjectPanel {
}
project_panel.update_visible_entries(None, cx);
if is_new_entry && !is_dir {
- project_panel.open_entry(new_entry.id, false, true, false, cx);
+ project_panel.open_entry(new_entry.id, true, false, cx);
}
cx.notify();
})?;
@@ -955,7 +935,6 @@ impl ProjectPanel {
fn open_entry(
&mut self,
entry_id: ProjectEntryId,
- mark_selected: bool,
focus_opened_item: bool,
allow_preview: bool,
cx: &mut ViewContext<Self>,
@@ -964,7 +943,6 @@ impl ProjectPanel {
entry_id,
focus_opened_item,
allow_preview,
- mark_selected,
});
}
@@ -2172,7 +2150,7 @@ impl ProjectPanel {
let opened_entries = task.await?;
this.update(&mut cx, |this, cx| {
if open_file_after_drop && !opened_entries.is_empty() {
- this.open_entry(opened_entries[0], true, true, false, cx);
+ this.open_entry(opened_entries[0], true, false, cx);
}
})
}
@@ -2605,70 +2583,60 @@ impl ProjectPanel {
this.drag_onto(selections, entry_id, kind.is_file(), cx);
}))
.on_click(cx.listener(move |this, event: &gpui::ClickEvent, cx| {
- if event.down.button == MouseButton::Right || event.down.first_mouse {
+ if event.down.button == MouseButton::Right || event.down.first_mouse || show_editor
+ {
return;
}
- if !show_editor {
- cx.stop_propagation();
- if let Some(selection) = this.selection.filter(|_| event.down.modifiers.shift) {
- let current_selection = this.index_for_selection(selection);
- let target_selection = this.index_for_selection(SelectedEntry {
- entry_id,
- worktree_id,
- });
- if let Some(((_, _, source_index), (_, _, target_index))) =
- current_selection.zip(target_selection)
- {
- let range_start = source_index.min(target_index);
- let range_end = source_index.max(target_index) + 1; // Make the range inclusive.
- let mut new_selections = BTreeSet::new();
- this.for_each_visible_entry(
- range_start..range_end,
- cx,
- |entry_id, details, _| {
- new_selections.insert(SelectedEntry {
- entry_id,
- worktree_id: details.worktree_id,
- });
- },
- );
-
- this.marked_entries = this
- .marked_entries
- .union(&new_selections)
- .cloned()
- .collect();
+ cx.stop_propagation();
- this.selection = Some(SelectedEntry {
- entry_id,
- worktree_id,
- });
- // Ensure that the current entry is selected.
- this.marked_entries.insert(SelectedEntry {
- entry_id,
- worktree_id,
- });
- }
- } else if event.down.modifiers.secondary() {
- if event.down.click_count > 1 {
- this.split_entry(entry_id, cx);
- } else if !this.marked_entries.insert(selection) {
- this.marked_entries.remove(&selection);
- }
- } else if kind.is_dir() {
- this.toggle_expanded(entry_id, cx);
- } else {
- let preview_tabs_enabled = PreviewTabsSettings::get_global(cx).enabled;
- let click_count = event.up.click_count;
- this.open_entry(
- entry_id,
- cx.modifiers().secondary(),
- !preview_tabs_enabled || click_count > 1,
- preview_tabs_enabled && click_count == 1,
+ if let Some(selection) = this.selection.filter(|_| event.down.modifiers.shift) {
+ let current_selection = this.index_for_selection(selection);
+ let clicked_entry = SelectedEntry {
+ entry_id,
+ worktree_id,
+ };
+ let target_selection = this.index_for_selection(clicked_entry);
+ if let Some(((_, _, source_index), (_, _, target_index))) =
+ current_selection.zip(target_selection)
+ {
+ let range_start = source_index.min(target_index);
+ let range_end = source_index.max(target_index) + 1; // Make the range inclusive.
+ let mut new_selections = BTreeSet::new();
+ this.for_each_visible_entry(
+ range_start..range_end,
cx,
+ |entry_id, details, _| {
+ new_selections.insert(SelectedEntry {
+ entry_id,
+ worktree_id: details.worktree_id,
+ });
+ },
);
+
+ this.marked_entries = this
+ .marked_entries
+ .union(&new_selections)
+ .cloned()
+ .collect();
+
+ this.selection = Some(clicked_entry);
+ this.marked_entries.insert(clicked_entry);
}
+ } else if event.down.modifiers.secondary() {
+ if event.down.click_count > 1 {
+ this.split_entry(entry_id, cx);
+ } else if !this.marked_entries.insert(selection) {
+ this.marked_entries.remove(&selection);
+ }
+ } else if kind.is_dir() {
+ this.toggle_expanded(entry_id, cx);
+ } else {
+ let preview_tabs_enabled = PreviewTabsSettings::get_global(cx).enabled;
+ let click_count = event.up.click_count;
+ let focus_opened_item = !preview_tabs_enabled || click_count > 1;
+ let allow_preview = preview_tabs_enabled && click_count == 1;
+ this.open_entry(entry_id, focus_opened_item, allow_preview, cx);
}
}))
.cursor_pointer()
@@ -2996,9 +2964,18 @@ impl ProjectPanel {
}
let worktree_id = worktree.id();
- self.marked_entries.clear();
self.expand_entry(worktree_id, entry_id, cx);
self.update_visible_entries(Some((worktree_id, entry_id)), cx);
+
+ if self.marked_entries.len() == 1
+ && self
+ .marked_entries
+ .first()
+ .filter(|entry| entry.entry_id == entry_id)
+ .is_none()
+ {
+ self.marked_entries.clear();
+ }
self.autoscroll(cx);
cx.notify();
}
@@ -3629,6 +3606,60 @@ mod tests {
);
}
+ #[gpui::test]
+ async fn test_opening_file(cx: &mut gpui::TestAppContext) {
+ init_test_with_editor(cx);
+
+ let fs = FakeFs::new(cx.executor().clone());
+ fs.insert_tree(
+ "/src",
+ json!({
+ "test": {
+ "first.rs": "// First Rust file",
+ "second.rs": "// Second Rust file",
+ "third.rs": "// Third Rust file",
+ }
+ }),
+ )
+ .await;
+
+ let project = Project::test(fs.clone(), ["/src".as_ref()], cx).await;
+ let workspace = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
+ let cx = &mut VisualTestContext::from_window(*workspace, cx);
+ let panel = workspace.update(cx, ProjectPanel::new).unwrap();
+
+ toggle_expand_dir(&panel, "src/test", cx);
+ select_path(&panel, "src/test/first.rs", cx);
+ panel.update(cx, |panel, cx| panel.open(&Open, cx));
+ cx.executor().run_until_parked();
+ assert_eq!(
+ visible_entries_as_strings(&panel, 0..10, cx),
+ &[
+ "v src",
+ " v test",
+ " first.rs <== selected <== marked",
+ " second.rs",
+ " third.rs"
+ ]
+ );
+ ensure_single_file_is_opened(&workspace, "test/first.rs", cx);
+
+ select_path(&panel, "src/test/second.rs", cx);
+ panel.update(cx, |panel, cx| panel.open(&Open, cx));
+ cx.executor().run_until_parked();
+ assert_eq!(
+ visible_entries_as_strings(&panel, 0..10, cx),
+ &[
+ "v src",
+ " v test",
+ " first.rs",
+ " second.rs <== selected <== marked",
+ " third.rs"
+ ]
+ );
+ ensure_single_file_is_opened(&workspace, "test/second.rs", cx);
+ }
+
#[gpui::test]
async fn test_exclusions_in_visible_list(cx: &mut gpui::TestAppContext) {
init_test(cx);
@@ -4853,7 +4884,7 @@ mod tests {
&[
"v src",
" v test",
- " first.rs <== selected",
+ " first.rs <== selected <== marked",
" second.rs",
" third.rs"
]
@@ -4881,7 +4912,7 @@ mod tests {
&[
"v src",
" v test",
- " second.rs <== selected",
+ " second.rs <== selected <== marked",
" third.rs"
]
);