@@ -177,7 +177,7 @@ pub struct Pane {
toolbar: View<Toolbar>,
new_item_menu: Option<View<ContextMenu>>,
split_item_menu: Option<View<ContextMenu>>,
- // tab_context_menu: ViewHandle<ContextMenu>,
+ // tab_context_menu: View<ContextMenu>,
workspace: WeakView<Workspace>,
project: Model<Project>,
drag_split_direction: Option<SplitDirection>,
@@ -256,11 +256,11 @@ struct DraggedTab {
// struct TabBarContextMenu {
// kind: TabBarContextMenuKind,
-// handle: ViewHandle<ContextMenu>,
+// handle: View<ContextMenu>,
// }
// impl TabBarContextMenu {
-// fn handle_if_kind(&self, kind: TabBarContextMenuKind) -> Option<ViewHandle<ContextMenu>> {
+// fn handle_if_kind(&self, kind: TabBarContextMenuKind) -> Option<View<ContextMenu>> {
// if self.kind == kind {
// return Some(self.handle.clone());
// }
@@ -329,7 +329,7 @@ impl Pane {
) -> Self {
// todo!("context menu")
// let pane_view_id = cx.view_id();
- // let context_menu = cx.add_view(|cx| ContextMenu::new(pane_view_id, cx));
+ // let context_menu = cx.build_view(|cx| ContextMenu::new(pane_view_id, cx));
// context_menu.update(cx, |menu, _| {
// menu.set_position_mode(OverlayPositionMode::Local)
// });
@@ -368,7 +368,7 @@ impl Pane {
// kind: TabBarContextMenuKind::New,
// handle: context_menu,
// },
- // tab_context_menu: cx.add_view(|cx| ContextMenu::new(pane_view_id, cx)),
+ // tab_context_menu: cx.build_view(|_| ContextMenu::new(pane_view_id, cx)),
workspace,
project,
// can_drop: Rc::new(|_, _| true),
@@ -1968,52 +1968,6 @@ impl Render for Pane {
}),
)
}
-
- // fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
- // if !self.has_focus {
- // self.has_focus = true;
- // cx.emit(Event::Focus);
- // cx.notify();
- // }
-
- // self.toolbar.update(cx, |toolbar, cx| {
- // toolbar.focus_changed(true, cx);
- // });
-
- // if let Some(active_item) = self.active_item() {
- // if cx.is_self_focused() {
- // // Pane was focused directly. We need to either focus a view inside the active item,
- // // or focus the active item itself
- // if let Some(weak_last_focused_view) =
- // self.last_focused_view_by_item.get(&active_item.id())
- // {
- // if let Some(last_focused_view) = weak_last_focused_view.upgrade(cx) {
- // cx.focus(&last_focused_view);
- // return;
- // } else {
- // self.last_focused_view_by_item.remove(&active_item.id());
- // }
- // }
-
- // cx.focus(active_item.as_any());
- // } else if focused != self.tab_bar_context_menu.handle {
- // self.last_focused_view_by_item
- // .insert(active_item.id(), focused.downgrade());
- // }
- // }
- // }
-
- // fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
- // self.has_focus = false;
- // self.toolbar.update(cx, |toolbar, cx| {
- // toolbar.focus_changed(false, cx);
- // });
- // cx.notify();
- // }
-
- // fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
- // Self::reset_to_default_keymap_context(keymap);
- // }
}
impl ItemNavHistory {
@@ -2171,98 +2125,6 @@ impl NavHistoryState {
}
}
-// pub struct PaneBackdrop<V> {
-// child_view: usize,
-// child: AnyElement<V>,
-// }
-
-// impl<V> PaneBackdrop<V> {
-// pub fn new(pane_item_view: usize, child: AnyElement<V>) -> Self {
-// PaneBackdrop {
-// child,
-// child_view: pane_item_view,
-// }
-// }
-// }
-
-// impl<V: 'static> Element<V> for PaneBackdrop<V> {
-// type LayoutState = ();
-
-// type PaintState = ();
-
-// fn layout(
-// &mut self,
-// constraint: gpui::SizeConstraint,
-// view: &mut V,
-// cx: &mut ViewContext<V>,
-// ) -> (Vector2F, Self::LayoutState) {
-// let size = self.child.layout(constraint, view, cx);
-// (size, ())
-// }
-
-// fn paint(
-// &mut self,
-// bounds: RectF,
-// visible_bounds: RectF,
-// _: &mut Self::LayoutState,
-// view: &mut V,
-// cx: &mut ViewContext<V>,
-// ) -> Self::PaintState {
-// let background = theme::current(cx).editor.background;
-
-// let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
-
-// cx.scene().push_quad(gpui::Quad {
-// bounds: RectF::new(bounds.origin(), bounds.size()),
-// background: Some(background),
-// ..Default::default()
-// });
-
-// let child_view_id = self.child_view;
-// cx.scene().push_mouse_region(
-// MouseRegion::new::<Self>(child_view_id, 0, visible_bounds).on_down(
-// gpui::platform::MouseButton::Left,
-// move |_, _: &mut V, cx| {
-// let window = cx.window();
-// cx.app_context().focus(window, Some(child_view_id))
-// },
-// ),
-// );
-
-// cx.scene().push_layer(Some(bounds));
-// self.child.paint(bounds.origin(), visible_bounds, view, cx);
-// cx.scene().pop_layer();
-// }
-
-// fn rect_for_text_range(
-// &self,
-// range_utf16: std::ops::Range<usize>,
-// _bounds: RectF,
-// _visible_bounds: RectF,
-// _layout: &Self::LayoutState,
-// _paint: &Self::PaintState,
-// view: &V,
-// cx: &gpui::ViewContext<V>,
-// ) -> Option<RectF> {
-// self.child.rect_for_text_range(range_utf16, view, cx)
-// }
-
-// fn debug(
-// &self,
-// _bounds: RectF,
-// _layout: &Self::LayoutState,
-// _paint: &Self::PaintState,
-// view: &V,
-// cx: &gpui::ViewContext<V>,
-// ) -> serde_json::Value {
-// gpui::json::json!({
-// "type": "Pane Back Drop",
-// "view": self.child_view,
-// "child": self.child.debug(view, cx),
-// })
-// }
-// }
-
fn dirty_message_for(buffer_path: Option<ProjectPath>) -> String {
let path = buffer_path
.as_ref()
@@ -2272,528 +2134,549 @@ fn dirty_message_for(buffer_path: Option<ProjectPath>) -> String {
format!("{path} contains unsaved edits. Do you want to save it?")
}
-// todo!("uncomment tests")
-// #[cfg(test)]
-// mod tests {
-// use super::*;
-// use crate::item::test::{TestItem, TestProjectItem};
-// use gpui::TestAppContext;
-// use project::FakeFs;
-// use settings::SettingsStore;
-
-// #[gpui::test]
-// async fn test_remove_active_empty(cx: &mut TestAppContext) {
-// init_test(cx);
-// let fs = FakeFs::new(cx.background());
-
-// let project = Project::test(fs, None, cx).await;
-// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
-// let workspace = window.root(cx);
-// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
-
-// pane.update(cx, |pane, cx| {
-// assert!(pane
-// .close_active_item(&CloseActiveItem { save_intent: None }, cx)
-// .is_none())
-// });
-// }
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::item::test::{TestItem, TestProjectItem};
+ use gpui::{TestAppContext, VisualTestContext};
+ use project::FakeFs;
+ use settings::SettingsStore;
+ use theme::LoadThemes;
+
+ #[gpui::test]
+ async fn test_remove_active_empty(cx: &mut TestAppContext) {
+ init_test(cx);
+ let fs = FakeFs::new(cx.executor());
+
+ let project = Project::test(fs, None, cx).await;
+ let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());
+
+ pane.update(cx, |pane, cx| {
+ assert!(pane
+ .close_active_item(&CloseActiveItem { save_intent: None }, cx)
+ .is_none())
+ });
+ }
-// #[gpui::test]
-// async fn test_add_item_with_new_item(cx: &mut TestAppContext) {
-// cx.foreground().forbid_parking();
-// init_test(cx);
-// let fs = FakeFs::new(cx.background());
-
-// let project = Project::test(fs, None, cx).await;
-// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
-// let workspace = window.root(cx);
-// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
-
-// // 1. Add with a destination index
-// // a. Add before the active item
-// set_labeled_items(&pane, ["A", "B*", "C"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(
-// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))),
-// false,
-// false,
-// Some(0),
-// cx,
-// );
-// });
-// assert_item_labels(&pane, ["D*", "A", "B", "C"], cx);
-
-// // b. Add after the active item
-// set_labeled_items(&pane, ["A", "B*", "C"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(
-// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))),
-// false,
-// false,
-// Some(2),
-// cx,
-// );
-// });
-// assert_item_labels(&pane, ["A", "B", "D*", "C"], cx);
-
-// // c. Add at the end of the item list (including off the length)
-// set_labeled_items(&pane, ["A", "B*", "C"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(
-// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))),
-// false,
-// false,
-// Some(5),
-// cx,
-// );
-// });
-// assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);
-
-// // 2. Add without a destination index
-// // a. Add with active item at the start of the item list
-// set_labeled_items(&pane, ["A*", "B", "C"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(
-// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))),
-// false,
-// false,
-// None,
-// cx,
-// );
-// });
-// set_labeled_items(&pane, ["A", "D*", "B", "C"], cx);
-
-// // b. Add with active item at the end of the item list
-// set_labeled_items(&pane, ["A", "B", "C*"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(
-// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))),
-// false,
-// false,
-// None,
-// cx,
-// );
-// });
-// assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);
-// }
+ #[gpui::test]
+ async fn test_add_item_with_new_item(cx: &mut TestAppContext) {
+ init_test(cx);
+ let fs = FakeFs::new(cx.executor());
+
+ let project = Project::test(fs, None, cx).await;
+ let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());
+
+ // 1. Add with a destination index
+ // a. Add before the active item
+ set_labeled_items(&pane, ["A", "B*", "C"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(
+ Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))),
+ false,
+ false,
+ Some(0),
+ cx,
+ );
+ });
+ assert_item_labels(&pane, ["D*", "A", "B", "C"], cx);
+
+ // b. Add after the active item
+ set_labeled_items(&pane, ["A", "B*", "C"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(
+ Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))),
+ false,
+ false,
+ Some(2),
+ cx,
+ );
+ });
+ assert_item_labels(&pane, ["A", "B", "D*", "C"], cx);
+
+ // c. Add at the end of the item list (including off the length)
+ set_labeled_items(&pane, ["A", "B*", "C"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(
+ Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))),
+ false,
+ false,
+ Some(5),
+ cx,
+ );
+ });
+ assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);
+
+ // 2. Add without a destination index
+ // a. Add with active item at the start of the item list
+ set_labeled_items(&pane, ["A*", "B", "C"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(
+ Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))),
+ false,
+ false,
+ None,
+ cx,
+ );
+ });
+ set_labeled_items(&pane, ["A", "D*", "B", "C"], cx);
+
+ // b. Add with active item at the end of the item list
+ set_labeled_items(&pane, ["A", "B", "C*"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(
+ Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))),
+ false,
+ false,
+ None,
+ cx,
+ );
+ });
+ assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);
+ }
-// #[gpui::test]
-// async fn test_add_item_with_existing_item(cx: &mut TestAppContext) {
-// cx.foreground().forbid_parking();
-// init_test(cx);
-// let fs = FakeFs::new(cx.background());
-
-// let project = Project::test(fs, None, cx).await;
-// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
-// let workspace = window.root(cx);
-// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
-
-// // 1. Add with a destination index
-// // 1a. Add before the active item
-// let [_, _, _, d] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(d, false, false, Some(0), cx);
-// });
-// assert_item_labels(&pane, ["D*", "A", "B", "C"], cx);
-
-// // 1b. Add after the active item
-// let [_, _, _, d] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(d, false, false, Some(2), cx);
-// });
-// assert_item_labels(&pane, ["A", "B", "D*", "C"], cx);
-
-// // 1c. Add at the end of the item list (including off the length)
-// let [a, _, _, _] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(a, false, false, Some(5), cx);
-// });
-// assert_item_labels(&pane, ["B", "C", "D", "A*"], cx);
-
-// // 1d. Add same item to active index
-// let [_, b, _] = set_labeled_items(&pane, ["A", "B*", "C"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(b, false, false, Some(1), cx);
-// });
-// assert_item_labels(&pane, ["A", "B*", "C"], cx);
-
-// // 1e. Add item to index after same item in last position
-// let [_, _, c] = set_labeled_items(&pane, ["A", "B*", "C"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(c, false, false, Some(2), cx);
-// });
-// assert_item_labels(&pane, ["A", "B", "C*"], cx);
-
-// // 2. Add without a destination index
-// // 2a. Add with active item at the start of the item list
-// let [_, _, _, d] = set_labeled_items(&pane, ["A*", "B", "C", "D"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(d, false, false, None, cx);
-// });
-// assert_item_labels(&pane, ["A", "D*", "B", "C"], cx);
-
-// // 2b. Add with active item at the end of the item list
-// let [a, _, _, _] = set_labeled_items(&pane, ["A", "B", "C", "D*"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(a, false, false, None, cx);
-// });
-// assert_item_labels(&pane, ["B", "C", "D", "A*"], cx);
-
-// // 2c. Add active item to active item at end of list
-// let [_, _, c] = set_labeled_items(&pane, ["A", "B", "C*"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(c, false, false, None, cx);
-// });
-// assert_item_labels(&pane, ["A", "B", "C*"], cx);
-
-// // 2d. Add active item to active item at start of list
-// let [a, _, _] = set_labeled_items(&pane, ["A*", "B", "C"], cx);
-// pane.update(cx, |pane, cx| {
-// pane.add_item(a, false, false, None, cx);
-// });
-// assert_item_labels(&pane, ["A*", "B", "C"], cx);
-// }
+ #[gpui::test]
+ async fn test_add_item_with_existing_item(cx: &mut TestAppContext) {
+ init_test(cx);
+ let fs = FakeFs::new(cx.executor());
-// #[gpui::test]
-// async fn test_add_item_with_same_project_entries(cx: &mut TestAppContext) {
-// cx.foreground().forbid_parking();
-// init_test(cx);
-// let fs = FakeFs::new(cx.background());
-
-// let project = Project::test(fs, None, cx).await;
-// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
-// let workspace = window.root(cx);
-// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
-
-// // singleton view
-// pane.update(cx, |pane, cx| {
-// let item = TestItem::new()
-// .with_singleton(true)
-// .with_label("buffer 1")
-// .with_project_items(&[TestProjectItem::new(1, "one.txt", cx)]);
-
-// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx);
-// });
-// assert_item_labels(&pane, ["buffer 1*"], cx);
-
-// // new singleton view with the same project entry
-// pane.update(cx, |pane, cx| {
-// let item = TestItem::new()
-// .with_singleton(true)
-// .with_label("buffer 1")
-// .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]);
-
-// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx);
-// });
-// assert_item_labels(&pane, ["buffer 1*"], cx);
-
-// // new singleton view with different project entry
-// pane.update(cx, |pane, cx| {
-// let item = TestItem::new()
-// .with_singleton(true)
-// .with_label("buffer 2")
-// .with_project_items(&[TestProjectItem::new(2, "2.txt", cx)]);
-// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx);
-// });
-// assert_item_labels(&pane, ["buffer 1", "buffer 2*"], cx);
-
-// // new multibuffer view with the same project entry
-// pane.update(cx, |pane, cx| {
-// let item = TestItem::new()
-// .with_singleton(false)
-// .with_label("multibuffer 1")
-// .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]);
-
-// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx);
-// });
-// assert_item_labels(&pane, ["buffer 1", "buffer 2", "multibuffer 1*"], cx);
-
-// // another multibuffer view with the same project entry
-// pane.update(cx, |pane, cx| {
-// let item = TestItem::new()
-// .with_singleton(false)
-// .with_label("multibuffer 1b")
-// .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]);
-
-// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx);
-// });
-// assert_item_labels(
-// &pane,
-// ["buffer 1", "buffer 2", "multibuffer 1", "multibuffer 1b*"],
-// cx,
-// );
-// }
+ let project = Project::test(fs, None, cx).await;
+ let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());
-// #[gpui::test]
-// async fn test_remove_item_ordering(cx: &mut TestAppContext) {
-// init_test(cx);
-// let fs = FakeFs::new(cx.background());
-
-// let project = Project::test(fs, None, cx).await;
-// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
-// let workspace = window.root(cx);
-// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
-
-// add_labeled_item(&pane, "A", false, cx);
-// add_labeled_item(&pane, "B", false, cx);
-// add_labeled_item(&pane, "C", false, cx);
-// add_labeled_item(&pane, "D", false, cx);
-// assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);
-
-// pane.update(cx, |pane, cx| pane.activate_item(1, false, false, cx));
-// add_labeled_item(&pane, "1", false, cx);
-// assert_item_labels(&pane, ["A", "B", "1*", "C", "D"], cx);
-
-// pane.update(cx, |pane, cx| {
-// pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
-// })
-// .unwrap()
-// .await
-// .unwrap();
-// assert_item_labels(&pane, ["A", "B*", "C", "D"], cx);
-
-// pane.update(cx, |pane, cx| pane.activate_item(3, false, false, cx));
-// assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);
-
-// pane.update(cx, |pane, cx| {
-// pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
-// })
-// .unwrap()
-// .await
-// .unwrap();
-// assert_item_labels(&pane, ["A", "B*", "C"], cx);
-
-// pane.update(cx, |pane, cx| {
-// pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
-// })
-// .unwrap()
-// .await
-// .unwrap();
-// assert_item_labels(&pane, ["A", "C*"], cx);
-
-// pane.update(cx, |pane, cx| {
-// pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
-// })
-// .unwrap()
-// .await
-// .unwrap();
-// assert_item_labels(&pane, ["A*"], cx);
-// }
+ // 1. Add with a destination index
+ // 1a. Add before the active item
+ let [_, _, _, d] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(d, false, false, Some(0), cx);
+ });
+ assert_item_labels(&pane, ["D*", "A", "B", "C"], cx);
-// #[gpui::test]
-// async fn test_close_inactive_items(cx: &mut TestAppContext) {
-// init_test(cx);
-// let fs = FakeFs::new(cx.background());
-
-// let project = Project::test(fs, None, cx).await;
-// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
-// let workspace = window.root(cx);
-// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
-
-// set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx);
-
-// pane.update(cx, |pane, cx| {
-// pane.close_inactive_items(&CloseInactiveItems, cx)
-// })
-// .unwrap()
-// .await
-// .unwrap();
-// assert_item_labels(&pane, ["C*"], cx);
-// }
+ // 1b. Add after the active item
+ let [_, _, _, d] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(d, false, false, Some(2), cx);
+ });
+ assert_item_labels(&pane, ["A", "B", "D*", "C"], cx);
-// #[gpui::test]
-// async fn test_close_clean_items(cx: &mut TestAppContext) {
-// init_test(cx);
-// let fs = FakeFs::new(cx.background());
-
-// let project = Project::test(fs, None, cx).await;
-// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
-// let workspace = window.root(cx);
-// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
-
-// add_labeled_item(&pane, "A", true, cx);
-// add_labeled_item(&pane, "B", false, cx);
-// add_labeled_item(&pane, "C", true, cx);
-// add_labeled_item(&pane, "D", false, cx);
-// add_labeled_item(&pane, "E", false, cx);
-// assert_item_labels(&pane, ["A^", "B", "C^", "D", "E*"], cx);
-
-// pane.update(cx, |pane, cx| pane.close_clean_items(&CloseCleanItems, cx))
-// .unwrap()
-// .await
-// .unwrap();
-// assert_item_labels(&pane, ["A^", "C*^"], cx);
-// }
+ // 1c. Add at the end of the item list (including off the length)
+ let [a, _, _, _] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(a, false, false, Some(5), cx);
+ });
+ assert_item_labels(&pane, ["B", "C", "D", "A*"], cx);
-// #[gpui::test]
-// async fn test_close_items_to_the_left(cx: &mut TestAppContext) {
-// init_test(cx);
-// let fs = FakeFs::new(cx.background());
-
-// let project = Project::test(fs, None, cx).await;
-// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
-// let workspace = window.root(cx);
-// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
-
-// set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx);
-
-// pane.update(cx, |pane, cx| {
-// pane.close_items_to_the_left(&CloseItemsToTheLeft, cx)
-// })
-// .unwrap()
-// .await
-// .unwrap();
-// assert_item_labels(&pane, ["C*", "D", "E"], cx);
-// }
+ // 1d. Add same item to active index
+ let [_, b, _] = set_labeled_items(&pane, ["A", "B*", "C"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(b, false, false, Some(1), cx);
+ });
+ assert_item_labels(&pane, ["A", "B*", "C"], cx);
-// #[gpui::test]
-// async fn test_close_items_to_the_right(cx: &mut TestAppContext) {
-// init_test(cx);
-// let fs = FakeFs::new(cx.background());
-
-// let project = Project::test(fs, None, cx).await;
-// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
-// let workspace = window.root(cx);
-// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
-
-// set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx);
-
-// pane.update(cx, |pane, cx| {
-// pane.close_items_to_the_right(&CloseItemsToTheRight, cx)
-// })
-// .unwrap()
-// .await
-// .unwrap();
-// assert_item_labels(&pane, ["A", "B", "C*"], cx);
-// }
+ // 1e. Add item to index after same item in last position
+ let [_, _, c] = set_labeled_items(&pane, ["A", "B*", "C"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(c, false, false, Some(2), cx);
+ });
+ assert_item_labels(&pane, ["A", "B", "C*"], cx);
-// #[gpui::test]
-// async fn test_close_all_items(cx: &mut TestAppContext) {
-// init_test(cx);
-// let fs = FakeFs::new(cx.background());
-
-// let project = Project::test(fs, None, cx).await;
-// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx));
-// let workspace = window.root(cx);
-// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone());
-
-// add_labeled_item(&pane, "A", false, cx);
-// add_labeled_item(&pane, "B", false, cx);
-// add_labeled_item(&pane, "C", false, cx);
-// assert_item_labels(&pane, ["A", "B", "C*"], cx);
-
-// pane.update(cx, |pane, cx| {
-// pane.close_all_items(&CloseAllItems { save_intent: None }, cx)
-// })
-// .unwrap()
-// .await
-// .unwrap();
-// assert_item_labels(&pane, [], cx);
-
-// add_labeled_item(&pane, "A", true, cx);
-// add_labeled_item(&pane, "B", true, cx);
-// add_labeled_item(&pane, "C", true, cx);
-// assert_item_labels(&pane, ["A^", "B^", "C*^"], cx);
-
-// let save = pane
-// .update(cx, |pane, cx| {
-// pane.close_all_items(&CloseAllItems { save_intent: None }, cx)
-// })
-// .unwrap();
-
-// cx.foreground().run_until_parked();
-// window.simulate_prompt_answer(2, cx);
-// save.await.unwrap();
-// assert_item_labels(&pane, [], cx);
-// }
+ // 2. Add without a destination index
+ // 2a. Add with active item at the start of the item list
+ let [_, _, _, d] = set_labeled_items(&pane, ["A*", "B", "C", "D"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(d, false, false, None, cx);
+ });
+ assert_item_labels(&pane, ["A", "D*", "B", "C"], cx);
-// fn init_test(cx: &mut TestAppContext) {
-// cx.update(|cx| {
-// cx.set_global(SettingsStore::test(cx));
-// theme::init((), cx);
-// crate::init_settings(cx);
-// Project::init_settings(cx);
-// });
-// }
+ // 2b. Add with active item at the end of the item list
+ let [a, _, _, _] = set_labeled_items(&pane, ["A", "B", "C", "D*"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(a, false, false, None, cx);
+ });
+ assert_item_labels(&pane, ["B", "C", "D", "A*"], cx);
-// fn add_labeled_item(
-// pane: &ViewHandle<Pane>,
-// label: &str,
-// is_dirty: bool,
-// cx: &mut TestAppContext,
-// ) -> Box<ViewHandle<TestItem>> {
-// pane.update(cx, |pane, cx| {
-// let labeled_item =
-// Box::new(cx.add_view(|_| TestItem::new().with_label(label).with_dirty(is_dirty)));
-// pane.add_item(labeled_item.clone(), false, false, None, cx);
-// labeled_item
-// })
-// }
+ // 2c. Add active item to active item at end of list
+ let [_, _, c] = set_labeled_items(&pane, ["A", "B", "C*"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(c, false, false, None, cx);
+ });
+ assert_item_labels(&pane, ["A", "B", "C*"], cx);
-// fn set_labeled_items<const COUNT: usize>(
-// pane: &ViewHandle<Pane>,
-// labels: [&str; COUNT],
-// cx: &mut TestAppContext,
-// ) -> [Box<ViewHandle<TestItem>>; COUNT] {
-// pane.update(cx, |pane, cx| {
-// pane.items.clear();
-// let mut active_item_index = 0;
-
-// let mut index = 0;
-// let items = labels.map(|mut label| {
-// if label.ends_with("*") {
-// label = label.trim_end_matches("*");
-// active_item_index = index;
-// }
-
-// let labeled_item = Box::new(cx.add_view(|_| TestItem::new().with_label(label)));
-// pane.add_item(labeled_item.clone(), false, false, None, cx);
-// index += 1;
-// labeled_item
-// });
-
-// pane.activate_item(active_item_index, false, false, cx);
-
-// items
-// })
-// }
+ // 2d. Add active item to active item at start of list
+ let [a, _, _] = set_labeled_items(&pane, ["A*", "B", "C"], cx);
+ pane.update(cx, |pane, cx| {
+ pane.add_item(a, false, false, None, cx);
+ });
+ assert_item_labels(&pane, ["A*", "B", "C"], cx);
+ }
+
+ #[gpui::test]
+ async fn test_add_item_with_same_project_entries(cx: &mut TestAppContext) {
+ init_test(cx);
+ let fs = FakeFs::new(cx.executor());
+
+ let project = Project::test(fs, None, cx).await;
+ let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());
+
+ // singleton view
+ pane.update(cx, |pane, cx| {
+ pane.add_item(
+ Box::new(cx.build_view(|cx| {
+ TestItem::new(cx)
+ .with_singleton(true)
+ .with_label("buffer 1")
+ .with_project_items(&[TestProjectItem::new(1, "one.txt", cx)])
+ })),
+ false,
+ false,
+ None,
+ cx,
+ );
+ });
+ assert_item_labels(&pane, ["buffer 1*"], cx);
+
+ // new singleton view with the same project entry
+ pane.update(cx, |pane, cx| {
+ pane.add_item(
+ Box::new(cx.build_view(|cx| {
+ TestItem::new(cx)
+ .with_singleton(true)
+ .with_label("buffer 1")
+ .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)])
+ })),
+ false,
+ false,
+ None,
+ cx,
+ );
+ });
+ assert_item_labels(&pane, ["buffer 1*"], cx);
+
+ // new singleton view with different project entry
+ pane.update(cx, |pane, cx| {
+ pane.add_item(
+ Box::new(cx.build_view(|cx| {
+ TestItem::new(cx)
+ .with_singleton(true)
+ .with_label("buffer 2")
+ .with_project_items(&[TestProjectItem::new(2, "2.txt", cx)])
+ })),
+ false,
+ false,
+ None,
+ cx,
+ );
+ });
+ assert_item_labels(&pane, ["buffer 1", "buffer 2*"], cx);
+
+ // new multibuffer view with the same project entry
+ pane.update(cx, |pane, cx| {
+ pane.add_item(
+ Box::new(cx.build_view(|cx| {
+ TestItem::new(cx)
+ .with_singleton(false)
+ .with_label("multibuffer 1")
+ .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)])
+ })),
+ false,
+ false,
+ None,
+ cx,
+ );
+ });
+ assert_item_labels(&pane, ["buffer 1", "buffer 2", "multibuffer 1*"], cx);
+
+ // another multibuffer view with the same project entry
+ pane.update(cx, |pane, cx| {
+ pane.add_item(
+ Box::new(cx.build_view(|cx| {
+ TestItem::new(cx)
+ .with_singleton(false)
+ .with_label("multibuffer 1b")
+ .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)])
+ })),
+ false,
+ false,
+ None,
+ cx,
+ );
+ });
+ assert_item_labels(
+ &pane,
+ ["buffer 1", "buffer 2", "multibuffer 1", "multibuffer 1b*"],
+ cx,
+ );
+ }
-// // Assert the item label, with the active item label suffixed with a '*'
-// fn assert_item_labels<const COUNT: usize>(
-// pane: &ViewHandle<Pane>,
-// expected_states: [&str; COUNT],
-// cx: &mut TestAppContext,
-// ) {
-// pane.read_with(cx, |pane, cx| {
-// let actual_states = pane
-// .items
-// .iter()
-// .enumerate()
-// .map(|(ix, item)| {
-// let mut state = item
-// .as_any()
-// .downcast_ref::<TestItem>()
-// .unwrap()
-// .read(cx)
-// .label
-// .clone();
-// if ix == pane.active_item_index {
-// state.push('*');
-// }
-// if item.is_dirty(cx) {
-// state.push('^');
-// }
-// state
-// })
-// .collect::<Vec<_>>();
-
-// assert_eq!(
-// actual_states, expected_states,
-// "pane items do not match expectation"
-// );
-// })
-// }
-// }
+ #[gpui::test]
+ async fn test_remove_item_ordering(cx: &mut TestAppContext) {
+ init_test(cx);
+ let fs = FakeFs::new(cx.executor());
+
+ let project = Project::test(fs, None, cx).await;
+ let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());
+
+ add_labeled_item(&pane, "A", false, cx);
+ add_labeled_item(&pane, "B", false, cx);
+ add_labeled_item(&pane, "C", false, cx);
+ add_labeled_item(&pane, "D", false, cx);
+ assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);
+
+ pane.update(cx, |pane, cx| pane.activate_item(1, false, false, cx));
+ add_labeled_item(&pane, "1", false, cx);
+ assert_item_labels(&pane, ["A", "B", "1*", "C", "D"], cx);
+
+ pane.update(cx, |pane, cx| {
+ pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
+ })
+ .unwrap()
+ .await
+ .unwrap();
+ assert_item_labels(&pane, ["A", "B*", "C", "D"], cx);
+
+ pane.update(cx, |pane, cx| pane.activate_item(3, false, false, cx));
+ assert_item_labels(&pane, ["A", "B", "C", "D*"], cx);
+
+ pane.update(cx, |pane, cx| {
+ pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
+ })
+ .unwrap()
+ .await
+ .unwrap();
+ assert_item_labels(&pane, ["A", "B*", "C"], cx);
+
+ pane.update(cx, |pane, cx| {
+ pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
+ })
+ .unwrap()
+ .await
+ .unwrap();
+ assert_item_labels(&pane, ["A", "C*"], cx);
+
+ pane.update(cx, |pane, cx| {
+ pane.close_active_item(&CloseActiveItem { save_intent: None }, cx)
+ })
+ .unwrap()
+ .await
+ .unwrap();
+ assert_item_labels(&pane, ["A*"], cx);
+ }
+
+ #[gpui::test]
+ async fn test_close_inactive_items(cx: &mut TestAppContext) {
+ init_test(cx);
+ let fs = FakeFs::new(cx.executor());
+
+ let project = Project::test(fs, None, cx).await;
+ let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());
+
+ set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx);
+
+ pane.update(cx, |pane, cx| {
+ pane.close_inactive_items(&CloseInactiveItems, cx)
+ })
+ .unwrap()
+ .await
+ .unwrap();
+ assert_item_labels(&pane, ["C*"], cx);
+ }
+
+ #[gpui::test]
+ async fn test_close_clean_items(cx: &mut TestAppContext) {
+ init_test(cx);
+ let fs = FakeFs::new(cx.executor());
+
+ let project = Project::test(fs, None, cx).await;
+ let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());
+
+ add_labeled_item(&pane, "A", true, cx);
+ add_labeled_item(&pane, "B", false, cx);
+ add_labeled_item(&pane, "C", true, cx);
+ add_labeled_item(&pane, "D", false, cx);
+ add_labeled_item(&pane, "E", false, cx);
+ assert_item_labels(&pane, ["A^", "B", "C^", "D", "E*"], cx);
+
+ pane.update(cx, |pane, cx| pane.close_clean_items(&CloseCleanItems, cx))
+ .unwrap()
+ .await
+ .unwrap();
+ assert_item_labels(&pane, ["A^", "C*^"], cx);
+ }
+
+ #[gpui::test]
+ async fn test_close_items_to_the_left(cx: &mut TestAppContext) {
+ init_test(cx);
+ let fs = FakeFs::new(cx.executor());
+
+ let project = Project::test(fs, None, cx).await;
+ let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());
+
+ set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx);
+
+ pane.update(cx, |pane, cx| {
+ pane.close_items_to_the_left(&CloseItemsToTheLeft, cx)
+ })
+ .unwrap()
+ .await
+ .unwrap();
+ assert_item_labels(&pane, ["C*", "D", "E"], cx);
+ }
+
+ #[gpui::test]
+ async fn test_close_items_to_the_right(cx: &mut TestAppContext) {
+ init_test(cx);
+ let fs = FakeFs::new(cx.executor());
+
+ let project = Project::test(fs, None, cx).await;
+ let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());
+
+ set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx);
+
+ pane.update(cx, |pane, cx| {
+ pane.close_items_to_the_right(&CloseItemsToTheRight, cx)
+ })
+ .unwrap()
+ .await
+ .unwrap();
+ assert_item_labels(&pane, ["A", "B", "C*"], cx);
+ }
+
+ #[gpui::test]
+ async fn test_close_all_items(cx: &mut TestAppContext) {
+ init_test(cx);
+ let fs = FakeFs::new(cx.executor());
+
+ let project = Project::test(fs, None, cx).await;
+ let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx));
+ let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone());
+
+ add_labeled_item(&pane, "A", false, cx);
+ add_labeled_item(&pane, "B", false, cx);
+ add_labeled_item(&pane, "C", false, cx);
+ assert_item_labels(&pane, ["A", "B", "C*"], cx);
+
+ pane.update(cx, |pane, cx| {
+ pane.close_all_items(&CloseAllItems { save_intent: None }, cx)
+ })
+ .unwrap()
+ .await
+ .unwrap();
+ assert_item_labels(&pane, [], cx);
+
+ add_labeled_item(&pane, "A", true, cx);
+ add_labeled_item(&pane, "B", true, cx);
+ add_labeled_item(&pane, "C", true, cx);
+ assert_item_labels(&pane, ["A^", "B^", "C*^"], cx);
+
+ let save = pane
+ .update(cx, |pane, cx| {
+ pane.close_all_items(&CloseAllItems { save_intent: None }, cx)
+ })
+ .unwrap();
+
+ cx.executor().run_until_parked();
+ cx.simulate_prompt_answer(2);
+ save.await.unwrap();
+ assert_item_labels(&pane, [], cx);
+ }
+
+ fn init_test(cx: &mut TestAppContext) {
+ cx.update(|cx| {
+ let settings_store = SettingsStore::test(cx);
+ cx.set_global(settings_store);
+ theme::init(LoadThemes::JustBase, cx);
+ crate::init_settings(cx);
+ Project::init_settings(cx);
+ });
+ }
+
+ fn add_labeled_item(
+ pane: &View<Pane>,
+ label: &str,
+ is_dirty: bool,
+ cx: &mut VisualTestContext,
+ ) -> Box<View<TestItem>> {
+ pane.update(cx, |pane, cx| {
+ let labeled_item = Box::new(
+ cx.build_view(|cx| TestItem::new(cx).with_label(label).with_dirty(is_dirty)),
+ );
+ pane.add_item(labeled_item.clone(), false, false, None, cx);
+ labeled_item
+ })
+ }
+
+ fn set_labeled_items<const COUNT: usize>(
+ pane: &View<Pane>,
+ labels: [&str; COUNT],
+ cx: &mut VisualTestContext,
+ ) -> [Box<View<TestItem>>; COUNT] {
+ pane.update(cx, |pane, cx| {
+ pane.items.clear();
+ let mut active_item_index = 0;
+
+ let mut index = 0;
+ let items = labels.map(|mut label| {
+ if label.ends_with("*") {
+ label = label.trim_end_matches("*");
+ active_item_index = index;
+ }
+
+ let labeled_item =
+ Box::new(cx.build_view(|cx| TestItem::new(cx).with_label(label)));
+ pane.add_item(labeled_item.clone(), false, false, None, cx);
+ index += 1;
+ labeled_item
+ });
+
+ pane.activate_item(active_item_index, false, false, cx);
+
+ items
+ })
+ }
+
+ // Assert the item label, with the active item label suffixed with a '*'
+ fn assert_item_labels<const COUNT: usize>(
+ pane: &View<Pane>,
+ expected_states: [&str; COUNT],
+ cx: &mut VisualTestContext,
+ ) {
+ pane.update(cx, |pane, cx| {
+ let actual_states = pane
+ .items
+ .iter()
+ .enumerate()
+ .map(|(ix, item)| {
+ let mut state = item
+ .to_any()
+ .downcast::<TestItem>()
+ .unwrap()
+ .read(cx)
+ .label
+ .clone();
+ if ix == pane.active_item_index {
+ state.push('*');
+ }
+ if item.is_dirty(cx) {
+ state.push('^');
+ }
+ state
+ })
+ .collect::<Vec<_>>();
+
+ assert_eq!(
+ actual_states, expected_states,
+ "pane items do not match expectation"
+ );
+ })
+ }
+}
impl Render for DraggedTab {
type Element = <Tab as RenderOnce>::Rendered;