Allow accessing workspace after adding item to pane
This commit is contained in:
parent
10e6d82c3e
commit
3d81eb9ddf
2 changed files with 116 additions and 74 deletions
|
@ -107,12 +107,6 @@ pub struct Pane {
|
||||||
active_toolbar_visible: bool,
|
active_toolbar_visible: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct FollowerState {
|
|
||||||
pub(crate) leader_id: PeerId,
|
|
||||||
pub(crate) current_view_id: Option<usize>,
|
|
||||||
pub(crate) items_by_leader_view_id: HashMap<usize, Box<dyn ItemHandle>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Toolbar: View {
|
pub trait Toolbar: View {
|
||||||
fn active_item_changed(
|
fn active_item_changed(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -266,7 +260,17 @@ impl Pane {
|
||||||
if let Some((project_entry_id, build_item)) = task.log_err() {
|
if let Some((project_entry_id, build_item)) = task.log_err() {
|
||||||
pane.update(&mut cx, |pane, cx| {
|
pane.update(&mut cx, |pane, cx| {
|
||||||
pane.nav_history.borrow_mut().set_mode(mode);
|
pane.nav_history.borrow_mut().set_mode(mode);
|
||||||
let item = pane.open_item(project_entry_id, cx, build_item);
|
});
|
||||||
|
let item = workspace.update(&mut cx, |workspace, cx| {
|
||||||
|
Self::open_item(
|
||||||
|
workspace,
|
||||||
|
pane.clone(),
|
||||||
|
project_entry_id,
|
||||||
|
cx,
|
||||||
|
build_item,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
pane.update(&mut cx, |pane, cx| {
|
||||||
pane.nav_history
|
pane.nav_history
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.set_mode(NavigationMode::Normal);
|
.set_mode(NavigationMode::Normal);
|
||||||
|
@ -289,52 +293,50 @@ impl Pane {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn open_item(
|
pub(crate) fn open_item(
|
||||||
&mut self,
|
workspace: &mut Workspace,
|
||||||
|
pane: ViewHandle<Pane>,
|
||||||
project_entry_id: ProjectEntryId,
|
project_entry_id: ProjectEntryId,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
build_item: impl FnOnce(&mut MutableAppContext) -> Box<dyn ItemHandle>,
|
build_item: impl FnOnce(&mut MutableAppContext) -> Box<dyn ItemHandle>,
|
||||||
) -> Box<dyn ItemHandle> {
|
) -> Box<dyn ItemHandle> {
|
||||||
for (ix, item) in self.items.iter().enumerate() {
|
let existing_item = pane.update(cx, |pane, cx| {
|
||||||
if item.project_entry_id(cx) == Some(project_entry_id) {
|
for (ix, item) in pane.items.iter().enumerate() {
|
||||||
let item = item.boxed_clone();
|
if item.project_entry_id(cx) == Some(project_entry_id) {
|
||||||
self.activate_item(ix, cx);
|
let item = item.boxed_clone();
|
||||||
return item;
|
pane.activate_item(ix, cx);
|
||||||
|
return Some(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
None
|
||||||
|
});
|
||||||
|
if let Some(existing_item) = existing_item {
|
||||||
|
existing_item
|
||||||
|
} else {
|
||||||
|
let item = build_item(cx);
|
||||||
|
Self::add_item(workspace, pane, item.boxed_clone(), cx);
|
||||||
|
item
|
||||||
}
|
}
|
||||||
|
|
||||||
let item = build_item(cx);
|
|
||||||
self.add_item(item.boxed_clone(), cx);
|
|
||||||
item
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_item(&mut self, mut item: Box<dyn ItemHandle>, cx: &mut ViewContext<Self>) {
|
pub(crate) fn add_item(
|
||||||
|
workspace: &mut Workspace,
|
||||||
|
pane: ViewHandle<Pane>,
|
||||||
|
mut item: Box<dyn ItemHandle>,
|
||||||
|
cx: &mut ViewContext<Workspace>,
|
||||||
|
) {
|
||||||
// Prevent adding the same item to the pane more than once.
|
// Prevent adding the same item to the pane more than once.
|
||||||
if self.items.iter().any(|i| i.id() == item.id()) {
|
if pane.read(cx).items.iter().any(|i| i.id() == item.id()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.set_nav_history(self.nav_history.clone(), cx);
|
item.set_nav_history(pane.read(cx).nav_history.clone(), cx);
|
||||||
item.added_to_pane(cx);
|
item.added_to_pane(workspace, pane.clone(), cx);
|
||||||
let item_idx = cmp::min(self.active_item_index + 1, self.items.len());
|
pane.update(cx, |pane, cx| {
|
||||||
self.items.insert(item_idx, item);
|
let item_idx = cmp::min(pane.active_item_index + 1, pane.items.len());
|
||||||
self.activate_item(item_idx, cx);
|
pane.items.insert(item_idx, item);
|
||||||
cx.notify();
|
pane.activate_item(item_idx, cx);
|
||||||
}
|
cx.notify();
|
||||||
|
});
|
||||||
pub(crate) fn set_follow_state(
|
|
||||||
&mut self,
|
|
||||||
follower_state: FollowerState,
|
|
||||||
cx: &mut ViewContext<Self>,
|
|
||||||
) -> Result<()> {
|
|
||||||
if let Some(current_view_id) = follower_state.current_view_id {
|
|
||||||
let item = follower_state
|
|
||||||
.items_by_leader_view_id
|
|
||||||
.get(¤t_view_id)
|
|
||||||
.ok_or_else(|| anyhow!("invalid current view id"))?
|
|
||||||
.clone();
|
|
||||||
self.add_item(item, cx);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn items(&self) -> impl Iterator<Item = &Box<dyn ItemHandle>> {
|
pub fn items(&self) -> impl Iterator<Item = &Box<dyn ItemHandle>> {
|
||||||
|
|
|
@ -284,7 +284,12 @@ pub trait ItemHandle: 'static {
|
||||||
fn boxed_clone(&self) -> Box<dyn ItemHandle>;
|
fn boxed_clone(&self) -> Box<dyn ItemHandle>;
|
||||||
fn set_nav_history(&self, nav_history: Rc<RefCell<NavHistory>>, cx: &mut MutableAppContext);
|
fn set_nav_history(&self, nav_history: Rc<RefCell<NavHistory>>, cx: &mut MutableAppContext);
|
||||||
fn clone_on_split(&self, cx: &mut MutableAppContext) -> Option<Box<dyn ItemHandle>>;
|
fn clone_on_split(&self, cx: &mut MutableAppContext) -> Option<Box<dyn ItemHandle>>;
|
||||||
fn added_to_pane(&mut self, cx: &mut ViewContext<Pane>);
|
fn added_to_pane(
|
||||||
|
&self,
|
||||||
|
workspace: &mut Workspace,
|
||||||
|
pane: ViewHandle<Pane>,
|
||||||
|
cx: &mut ViewContext<Workspace>,
|
||||||
|
);
|
||||||
fn deactivated(&self, cx: &mut MutableAppContext);
|
fn deactivated(&self, cx: &mut MutableAppContext);
|
||||||
fn navigate(&self, data: Box<dyn Any>, cx: &mut MutableAppContext);
|
fn navigate(&self, data: Box<dyn Any>, cx: &mut MutableAppContext);
|
||||||
fn id(&self) -> usize;
|
fn id(&self) -> usize;
|
||||||
|
@ -350,22 +355,37 @@ impl<T: Item> ItemHandle for ViewHandle<T> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn added_to_pane(&mut self, cx: &mut ViewContext<Pane>) {
|
fn added_to_pane(
|
||||||
cx.subscribe(self, |pane, item, event, cx| {
|
&self,
|
||||||
|
workspace: &mut Workspace,
|
||||||
|
pane: ViewHandle<Pane>,
|
||||||
|
cx: &mut ViewContext<Workspace>,
|
||||||
|
) {
|
||||||
|
let pane = pane.downgrade();
|
||||||
|
cx.subscribe(self, move |workspace, item, event, cx| {
|
||||||
|
let pane = if let Some(pane) = pane.upgrade(cx) {
|
||||||
|
pane
|
||||||
|
} else {
|
||||||
|
log::error!("unexpected item event after pane was dropped");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
if T::should_close_item_on_event(event) {
|
if T::should_close_item_on_event(event) {
|
||||||
pane.close_item(item.id(), cx);
|
pane.update(cx, |pane, cx| pane.close_item(item.id(), cx));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if T::should_activate_item_on_event(event) {
|
if T::should_activate_item_on_event(event) {
|
||||||
if let Some(ix) = pane.index_for_item(&item) {
|
pane.update(cx, |pane, cx| {
|
||||||
pane.activate_item(ix, cx);
|
if let Some(ix) = pane.index_for_item(&item) {
|
||||||
pane.activate(cx);
|
pane.activate_item(ix, cx);
|
||||||
}
|
pane.activate(cx);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if T::should_update_tab_on_event(event) {
|
if T::should_update_tab_on_event(event) {
|
||||||
cx.notify()
|
pane.update(cx, |_, cx| cx.notify());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(message) = item
|
if let Some(message) = item
|
||||||
|
@ -533,6 +553,7 @@ pub struct Workspace {
|
||||||
status_bar: ViewHandle<StatusBar>,
|
status_bar: ViewHandle<StatusBar>,
|
||||||
project: ModelHandle<Project>,
|
project: ModelHandle<Project>,
|
||||||
leader_state: LeaderState,
|
leader_state: LeaderState,
|
||||||
|
follower_states_by_leader: HashMap<PeerId, FollowerState>,
|
||||||
_observe_current_user: Task<()>,
|
_observe_current_user: Task<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,6 +563,11 @@ struct LeaderState {
|
||||||
subscriptions: Vec<Subscription>,
|
subscriptions: Vec<Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct FollowerState {
|
||||||
|
current_view_id: Option<usize>,
|
||||||
|
items_by_leader_view_id: HashMap<usize, Box<dyn ItemHandle>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Workspace {
|
impl Workspace {
|
||||||
pub fn new(params: &WorkspaceParams, cx: &mut ViewContext<Self>) -> Self {
|
pub fn new(params: &WorkspaceParams, cx: &mut ViewContext<Self>) -> Self {
|
||||||
cx.observe(¶ms.project, |_, project, cx| {
|
cx.observe(¶ms.project, |_, project, cx| {
|
||||||
|
@ -614,6 +640,7 @@ impl Workspace {
|
||||||
right_sidebar: Sidebar::new(Side::Right),
|
right_sidebar: Sidebar::new(Side::Right),
|
||||||
project: params.project.clone(),
|
project: params.project.clone(),
|
||||||
leader_state: Default::default(),
|
leader_state: Default::default(),
|
||||||
|
follower_states_by_leader: Default::default(),
|
||||||
_observe_current_user,
|
_observe_current_user,
|
||||||
};
|
};
|
||||||
this.project_remote_id_changed(this.project.read(cx).remote_id(), cx);
|
this.project_remote_id_changed(this.project.read(cx).remote_id(), cx);
|
||||||
|
@ -910,8 +937,8 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_item(&mut self, item: Box<dyn ItemHandle>, cx: &mut ViewContext<Self>) {
|
pub fn add_item(&mut self, item: Box<dyn ItemHandle>, cx: &mut ViewContext<Self>) {
|
||||||
self.active_pane()
|
let pane = self.active_pane().clone();
|
||||||
.update(cx, |pane, cx| pane.add_item(item, cx))
|
Pane::add_item(self, pane, item, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_path(
|
pub fn open_path(
|
||||||
|
@ -926,10 +953,14 @@ impl Workspace {
|
||||||
let pane = pane
|
let pane = pane
|
||||||
.upgrade(&cx)
|
.upgrade(&cx)
|
||||||
.ok_or_else(|| anyhow!("pane was closed"))?;
|
.ok_or_else(|| anyhow!("pane was closed"))?;
|
||||||
this.update(&mut cx, |_, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
pane.update(cx, |pane, cx| {
|
Ok(Pane::open_item(
|
||||||
Ok(pane.open_item(project_entry_id, cx, build_item))
|
this,
|
||||||
})
|
pane,
|
||||||
|
project_entry_id,
|
||||||
|
cx,
|
||||||
|
build_item,
|
||||||
|
))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1057,9 +1088,7 @@ impl Workspace {
|
||||||
self.activate_pane(new_pane.clone(), cx);
|
self.activate_pane(new_pane.clone(), cx);
|
||||||
if let Some(item) = pane.read(cx).active_item() {
|
if let Some(item) = pane.read(cx).active_item() {
|
||||||
if let Some(clone) = item.clone_on_split(cx.as_mut()) {
|
if let Some(clone) = item.clone_on_split(cx.as_mut()) {
|
||||||
new_pane.update(cx, |new_pane, cx| {
|
Pane::add_item(self, new_pane.clone(), clone, cx);
|
||||||
new_pane.add_item(clone, cx);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.center.split(&pane, &new_pane, direction).unwrap();
|
self.center.split(&pane, &new_pane, direction).unwrap();
|
||||||
|
@ -1149,21 +1178,32 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
|
|
||||||
let items = futures::future::try_join_all(item_tasks).await?;
|
let items = futures::future::try_join_all(item_tasks).await?;
|
||||||
let mut items_by_leader_view_id = HashMap::default();
|
let follower_state = FollowerState {
|
||||||
for (view, item) in response.views.into_iter().zip(items) {
|
current_view_id: response.current_view_id.map(|id| id as usize),
|
||||||
items_by_leader_view_id.insert(view.id as usize, item);
|
items_by_leader_view_id: response
|
||||||
}
|
.views
|
||||||
|
.iter()
|
||||||
pane.update(&mut cx, |pane, cx| {
|
.map(|v| v.id as usize)
|
||||||
pane.set_follow_state(
|
.zip(items)
|
||||||
FollowerState {
|
.collect(),
|
||||||
leader_id,
|
};
|
||||||
current_view_id: response.current_view_id.map(|id| id as usize),
|
let current_item = if let Some(current_view_id) = follower_state.current_view_id
|
||||||
items_by_leader_view_id,
|
{
|
||||||
},
|
Some(
|
||||||
cx,
|
follower_state
|
||||||
|
.items_by_leader_view_id
|
||||||
|
.get(¤t_view_id)
|
||||||
|
.ok_or_else(|| anyhow!("invalid current view id"))?
|
||||||
|
.clone(),
|
||||||
)
|
)
|
||||||
})?;
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
this.update(&mut cx, |this, cx| {
|
||||||
|
if let Some(item) = current_item {
|
||||||
|
Pane::add_item(this, pane, item, cx);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue