@@ -1,6 +1,7 @@
use crate::{
project::{self, Project},
theme,
+ workspace::Workspace,
worktree::{self, Worktree},
Settings,
};
@@ -14,7 +15,7 @@ use gpui::{
},
platform::CursorStyle,
AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, ReadModel, View,
- ViewContext, WeakViewHandle,
+ ViewContext, ViewHandle, WeakViewHandle,
};
use postage::watch;
use std::{
@@ -51,7 +52,7 @@ struct EntryDetails {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ProjectEntry {
- pub worktree_ix: usize,
+ pub worktree_id: usize,
pub entry_id: usize,
}
@@ -66,51 +67,73 @@ pub fn init(cx: &mut MutableAppContext) {
cx.add_action(ProjectPanel::toggle_expanded);
cx.add_action(ProjectPanel::select_prev);
cx.add_action(ProjectPanel::select_next);
+ cx.add_action(ProjectPanel::open_entry);
cx.add_bindings([
Binding::new("right", ExpandSelectedEntry, None),
Binding::new("left", CollapseSelectedEntry, None),
]);
}
-pub enum Event {}
+pub enum Event {
+ OpenedEntry { worktree_id: usize, entry_id: usize },
+}
impl ProjectPanel {
pub fn new(
project: ModelHandle<Project>,
settings: watch::Receiver<Settings>,
- cx: &mut ViewContext<Self>,
- ) -> Self {
- cx.observe(&project, |this, _, cx| {
- this.update_visible_entries(None, cx);
- cx.notify();
- })
- .detach();
- cx.subscribe(&project, |this, _, event, cx| match event {
- project::Event::ActiveEntryChanged(Some((worktree_id, entry_id))) => {
- this.expand_entry(*worktree_id, *entry_id, cx);
- this.update_visible_entries(Some((*worktree_id, *entry_id)), cx);
- cx.notify();
- }
- project::Event::WorktreeRemoved(id) => {
- this.expanded_dir_ids.remove(id);
+ cx: &mut ViewContext<Workspace>,
+ ) -> ViewHandle<Self> {
+ let project_panel = cx.add_view(|cx: &mut ViewContext<Self>| {
+ cx.observe(&project, |this, _, cx| {
this.update_visible_entries(None, cx);
cx.notify();
+ })
+ .detach();
+ cx.subscribe(&project, |this, _, event, cx| match event {
+ project::Event::ActiveEntryChanged(Some((worktree_id, entry_id))) => {
+ this.expand_entry(*worktree_id, *entry_id, cx);
+ this.update_visible_entries(Some((*worktree_id, *entry_id)), cx);
+ cx.notify();
+ }
+ project::Event::WorktreeRemoved(id) => {
+ this.expanded_dir_ids.remove(id);
+ this.update_visible_entries(None, cx);
+ cx.notify();
+ }
+ _ => {}
+ })
+ .detach();
+
+ let mut this = Self {
+ project: project.clone(),
+ settings,
+ list: Default::default(),
+ visible_entries: Default::default(),
+ expanded_dir_ids: Default::default(),
+ selection: None,
+ handle: cx.handle().downgrade(),
+ };
+ this.update_visible_entries(None, cx);
+ this
+ });
+ cx.subscribe(&project_panel, move |workspace, _, event, cx| match event {
+ Event::OpenedEntry {
+ worktree_id,
+ entry_id,
+ } => {
+ if let Some(worktree) = project.read(cx).worktree_for_id(*worktree_id) {
+ if let Some(entry) = worktree.read(cx).entry_for_id(*entry_id) {
+ workspace
+ .open_entry((worktree.id(), entry.path.clone()), cx)
+ .map(|t| t.detach());
+ }
+ }
}
- _ => {}
})
.detach();
- let mut this = Self {
- project,
- settings,
- list: Default::default(),
- visible_entries: Default::default(),
- expanded_dir_ids: Default::default(),
- selection: None,
- handle: cx.handle().downgrade(),
- };
- this.update_visible_entries(None, cx);
- this
+ project_panel
}
fn expand_selected_entry(&mut self, _: &ExpandSelectedEntry, cx: &mut ViewContext<Self>) {
@@ -132,6 +155,11 @@ impl ProjectPanel {
}
}
} else {
+ let event = Event::OpenedEntry {
+ worktree_id: worktree.id(),
+ entry_id: entry.id,
+ };
+ cx.emit(event);
}
}
}
@@ -169,10 +197,10 @@ impl ProjectPanel {
fn toggle_expanded(&mut self, action: &ToggleExpanded, cx: &mut ViewContext<Self>) {
let ProjectEntry {
- worktree_ix,
+ worktree_id,
entry_id,
} = action.0;
- let worktree_id = self.project.read(cx).worktrees()[worktree_ix].id();
+
if let Some(expanded_dir_ids) = self.expanded_dir_ids.get_mut(&worktree_id) {
match expanded_dir_ids.binary_search(&entry_id) {
Ok(ix) => {
@@ -203,6 +231,13 @@ impl ProjectPanel {
}
}
+ fn open_entry(&mut self, action: &Open, cx: &mut ViewContext<Self>) {
+ cx.emit(Event::OpenedEntry {
+ worktree_id: action.0.worktree_id,
+ entry_id: action.0.entry_id,
+ });
+ }
+
fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext<Self>) {
if let Some(selection) = self.selection {
let next_ix = selection.index + 1;
@@ -411,7 +446,7 @@ impl ProjectPanel {
}),
};
let entry = ProjectEntry {
- worktree_ix,
+ worktree_id: worktree.id(),
entry_id: entry.id,
};
callback(entry, details, cx);
@@ -429,7 +464,7 @@ impl ProjectPanel {
) -> ElementBox {
let is_dir = details.is_dir;
MouseEventHandler::new::<Self, _, _, _>(
- (entry.worktree_ix, entry.entry_id),
+ (entry.worktree_id, entry.entry_id),
cx,
|state, _| {
let style = if details.is_selected {
@@ -568,7 +603,8 @@ mod tests {
.read_with(&cx, |t, _| t.as_local().unwrap().scan_complete())
.await;
- let (_, panel) = cx.add_window(|cx| ProjectPanel::new(project, settings, cx));
+ let (_, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx));
+ let panel = workspace.update(&mut cx, |_, cx| ProjectPanel::new(project, settings, cx));
assert_eq!(
visible_entry_details(&panel, 0..50, &mut cx),
&[
@@ -742,14 +778,13 @@ mod tests {
) {
let path = path.as_ref();
panel.update(cx, |panel, cx| {
- for (worktree_ix, worktree) in panel.project.read(cx).worktrees().iter().enumerate()
- {
+ for worktree in panel.project.read(cx).worktrees() {
let worktree = worktree.read(cx);
if let Ok(relative_path) = path.strip_prefix(worktree.root_name()) {
let entry_id = worktree.entry_for_path(relative_path).unwrap().id;
panel.toggle_expanded(
&ToggleExpanded(ProjectEntry {
- worktree_ix,
+ worktree_id: worktree.id(),
entry_id,
}),
cx,
@@ -8,7 +8,7 @@ use crate::{
fs::Fs,
people_panel::{JoinWorktree, LeaveWorktree, PeoplePanel, ShareWorktree, UnshareWorktree},
project::Project,
- project_panel::{self, ProjectPanel},
+ project_panel::ProjectPanel,
rpc,
settings::Settings,
user,
@@ -54,14 +54,6 @@ pub fn init(cx: &mut MutableAppContext) {
cx.add_action(Workspace::save_active_item);
cx.add_action(Workspace::debug_elements);
cx.add_action(Workspace::open_new_file);
- cx.add_action(|this: &mut Workspace, action: &project_panel::Open, cx| {
- if let Some(worktree) = this.worktrees(cx).get(action.0.worktree_ix) {
- if let Some(entry) = worktree.read(cx).entry_for_id(action.0.entry_id) {
- this.open_entry((worktree.id(), entry.path.clone()), cx)
- .map(|task| task.detach());
- }
- }
- });
cx.add_action(Workspace::toggle_sidebar_item);
cx.add_action(Workspace::share_worktree);
cx.add_action(Workspace::unshare_worktree);
@@ -386,8 +378,7 @@ impl Workspace {
let mut left_sidebar = Sidebar::new(Side::Left);
left_sidebar.add_item(
"icons/folder-tree-16.svg",
- cx.add_view(|cx| ProjectPanel::new(project.clone(), app_state.settings.clone(), cx))
- .into(),
+ ProjectPanel::new(project.clone(), app_state.settings.clone(), cx).into(),
);
let mut right_sidebar = Sidebar::new(Side::Right);