| @@ -177,7 +177,7 @@ pub struct Pane { · 176 unmodified lines |
| 177 | 177 | toolbar: View<Toolbar>, |
| 178 | 178 | new_item_menu: Option<View<ContextMenu>>, |
| 179 | 179 | split_item_menu: Option<View<ContextMenu>>, |
| 180 | | − // tab_context_menu: ViewHandle<ContextMenu>, |
| 180 | + // tab_context_menu: View<ContextMenu>, |
| 181 | 181 | workspace: WeakView<Workspace>, |
| 182 | 182 | project: Model<Project>, |
| 183 | 183 | drag_split_direction: Option<SplitDirection>, |
| @@ -256,11 +256,11 @@ struct DraggedTab { · 72 unmodified lines |
| 256 | 256 | |
| 257 | 257 | // struct TabBarContextMenu { |
| 258 | 258 | // kind: TabBarContextMenuKind, |
| 259 | | −// handle: ViewHandle<ContextMenu>, |
| 259 | +// handle: View<ContextMenu>, |
| 260 | 260 | // } |
| 261 | 261 | |
| 262 | 262 | // impl TabBarContextMenu { |
| 263 | | −// fn handle_if_kind(&self, kind: TabBarContextMenuKind) -> Option<ViewHandle<ContextMenu>> { |
| 263 | +// fn handle_if_kind(&self, kind: TabBarContextMenuKind) -> Option<View<ContextMenu>> { |
| 264 | 264 | // if self.kind == kind { |
| 265 | 265 | // return Some(self.handle.clone()); |
| 266 | 266 | // } |
| @@ -329,7 +329,7 @@ impl Pane { · 62 unmodified lines |
| 329 | 329 | ) -> Self { |
| 330 | 330 | // todo!("context menu") |
| 331 | 331 | // let pane_view_id = cx.view_id(); |
| 332 | | − // let context_menu = cx.add_view(|cx| ContextMenu::new(pane_view_id, cx)); |
| 332 | + // let context_menu = cx.build_view(|cx| ContextMenu::new(pane_view_id, cx)); |
| 333 | 333 | // context_menu.update(cx, |menu, _| { |
| 334 | 334 | // menu.set_position_mode(OverlayPositionMode::Local) |
| 335 | 335 | // }); |
| @@ -368,7 +368,7 @@ impl Pane { · 32 unmodified lines |
| 368 | 368 | // kind: TabBarContextMenuKind::New, |
| 369 | 369 | // handle: context_menu, |
| 370 | 370 | // }, |
| 371 | | − // tab_context_menu: cx.add_view(|cx| ContextMenu::new(pane_view_id, cx)), |
| 371 | + // tab_context_menu: cx.build_view(|_| ContextMenu::new(pane_view_id, cx)), |
| 372 | 372 | workspace, |
| 373 | 373 | project, |
| 374 | 374 | // can_drop: Rc::new(|_, _| true), |
| @@ -1963,52 +1963,6 @@ impl Render for Pane { · 1588 unmodified lines |
| 1963 | 1963 | }), |
| 1964 | 1964 | ) |
| 1965 | 1965 | } |
| 1966 | | − |
| 1967 | | − // fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) { |
| 1968 | | − // if !self.has_focus { |
| 1969 | | − // self.has_focus = true; |
| 1970 | | − // cx.emit(Event::Focus); |
| 1971 | | − // cx.notify(); |
| 1972 | | − // } |
| 1973 | | − |
| 1974 | | − // self.toolbar.update(cx, |toolbar, cx| { |
| 1975 | | − // toolbar.focus_changed(true, cx); |
| 1976 | | − // }); |
| 1977 | | − |
| 1978 | | − // if let Some(active_item) = self.active_item() { |
| 1979 | | − // if cx.is_self_focused() { |
| 1980 | | − // // Pane was focused directly. We need to either focus a view inside the active item, |
| 1981 | | − // // or focus the active item itself |
| 1982 | | − // if let Some(weak_last_focused_view) = |
| 1983 | | − // self.last_focused_view_by_item.get(&active_item.id()) |
| 1984 | | − // { |
| 1985 | | − // if let Some(last_focused_view) = weak_last_focused_view.upgrade(cx) { |
| 1986 | | − // cx.focus(&last_focused_view); |
| 1987 | | − // return; |
| 1988 | | − // } else { |
| 1989 | | − // self.last_focused_view_by_item.remove(&active_item.id()); |
| 1990 | | − // } |
| 1991 | | − // } |
| 1992 | | − |
| 1993 | | − // cx.focus(active_item.as_any()); |
| 1994 | | − // } else if focused != self.tab_bar_context_menu.handle { |
| 1995 | | − // self.last_focused_view_by_item |
| 1996 | | − // .insert(active_item.id(), focused.downgrade()); |
| 1997 | | − // } |
| 1998 | | − // } |
| 1999 | | − // } |
| 2000 | | − |
| 2001 | | − // fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) { |
| 2002 | | − // self.has_focus = false; |
| 2003 | | − // self.toolbar.update(cx, |toolbar, cx| { |
| 2004 | | − // toolbar.focus_changed(false, cx); |
| 2005 | | − // }); |
| 2006 | | − // cx.notify(); |
| 2007 | | − // } |
| 2008 | | − |
| 2009 | | − // fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) { |
| 2010 | | − // Self::reset_to_default_keymap_context(keymap); |
| 2011 | | − // } |
| 2012 | 1966 | } |
| 2013 | 1967 | |
| 2014 | 1968 | impl ItemNavHistory { |
| @@ -2166,98 +2120,6 @@ impl NavHistoryState { · 151 unmodified lines |
| 2166 | 2120 | } |
| 2167 | 2121 | } |
| 2168 | 2122 | |
| 2169 | | −// pub struct PaneBackdrop<V> { |
| 2170 | | −// child_view: usize, |
| 2171 | | −// child: AnyElement<V>, |
| 2172 | | −// } |
| 2173 | | − |
| 2174 | | −// impl<V> PaneBackdrop<V> { |
| 2175 | | −// pub fn new(pane_item_view: usize, child: AnyElement<V>) -> Self { |
| 2176 | | −// PaneBackdrop { |
| 2177 | | −// child, |
| 2178 | | −// child_view: pane_item_view, |
| 2179 | | −// } |
| 2180 | | −// } |
| 2181 | | −// } |
| 2182 | | − |
| 2183 | | −// impl<V: 'static> Element<V> for PaneBackdrop<V> { |
| 2184 | | −// type LayoutState = (); |
| 2185 | | − |
| 2186 | | −// type PaintState = (); |
| 2187 | | − |
| 2188 | | −// fn layout( |
| 2189 | | −// &mut self, |
| 2190 | | −// constraint: gpui::SizeConstraint, |
| 2191 | | −// view: &mut V, |
| 2192 | | −// cx: &mut ViewContext<V>, |
| 2193 | | −// ) -> (Vector2F, Self::LayoutState) { |
| 2194 | | −// let size = self.child.layout(constraint, view, cx); |
| 2195 | | −// (size, ()) |
| 2196 | | −// } |
| 2197 | | − |
| 2198 | | −// fn paint( |
| 2199 | | −// &mut self, |
| 2200 | | −// bounds: RectF, |
| 2201 | | −// visible_bounds: RectF, |
| 2202 | | −// _: &mut Self::LayoutState, |
| 2203 | | −// view: &mut V, |
| 2204 | | −// cx: &mut ViewContext<V>, |
| 2205 | | −// ) -> Self::PaintState { |
| 2206 | | −// let background = theme::current(cx).editor.background; |
| 2207 | | − |
| 2208 | | −// let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); |
| 2209 | | − |
| 2210 | | −// cx.scene().push_quad(gpui::Quad { |
| 2211 | | −// bounds: RectF::new(bounds.origin(), bounds.size()), |
| 2212 | | −// background: Some(background), |
| 2213 | | −// ..Default::default() |
| 2214 | | −// }); |
| 2215 | | − |
| 2216 | | −// let child_view_id = self.child_view; |
| 2217 | | −// cx.scene().push_mouse_region( |
| 2218 | | −// MouseRegion::new::<Self>(child_view_id, 0, visible_bounds).on_down( |
| 2219 | | −// gpui::platform::MouseButton::Left, |
| 2220 | | −// move |_, _: &mut V, cx| { |
| 2221 | | −// let window = cx.window(); |
| 2222 | | −// cx.app_context().focus(window, Some(child_view_id)) |
| 2223 | | −// }, |
| 2224 | | −// ), |
| 2225 | | −// ); |
| 2226 | | − |
| 2227 | | −// cx.scene().push_layer(Some(bounds)); |
| 2228 | | −// self.child.paint(bounds.origin(), visible_bounds, view, cx); |
| 2229 | | −// cx.scene().pop_layer(); |
| 2230 | | −// } |
| 2231 | | − |
| 2232 | | −// fn rect_for_text_range( |
| 2233 | | −// &self, |
| 2234 | | −// range_utf16: std::ops::Range<usize>, |
| 2235 | | −// _bounds: RectF, |
| 2236 | | −// _visible_bounds: RectF, |
| 2237 | | −// _layout: &Self::LayoutState, |
| 2238 | | −// _paint: &Self::PaintState, |
| 2239 | | −// view: &V, |
| 2240 | | −// cx: &gpui::ViewContext<V>, |
| 2241 | | −// ) -> Option<RectF> { |
| 2242 | | −// self.child.rect_for_text_range(range_utf16, view, cx) |
| 2243 | | −// } |
| 2244 | | − |
| 2245 | | −// fn debug( |
| 2246 | | −// &self, |
| 2247 | | −// _bounds: RectF, |
| 2248 | | −// _layout: &Self::LayoutState, |
| 2249 | | −// _paint: &Self::PaintState, |
| 2250 | | −// view: &V, |
| 2251 | | −// cx: &gpui::ViewContext<V>, |
| 2252 | | −// ) -> serde_json::Value { |
| 2253 | | −// gpui::json::json!({ |
| 2254 | | −// "type": "Pane Back Drop", |
| 2255 | | −// "view": self.child_view, |
| 2256 | | −// "child": self.child.debug(view, cx), |
| 2257 | | −// }) |
| 2258 | | −// } |
| 2259 | | −// } |
| 2260 | | − |
| 2261 | 2123 | fn dirty_message_for(buffer_path: Option<ProjectPath>) -> String { |
| 2262 | 2124 | let path = buffer_path |
| 2263 | 2125 | .as_ref() |
| @@ -2267,528 +2129,549 @@ fn dirty_message_for(buffer_path: Option<ProjectPath>) -> String { · 3 unmodified lines |
| 2267 | 2129 | format!("{path} contains unsaved edits. Do you want to save it?") |
| 2268 | 2130 | } |
| 2269 | 2131 | |
| 2270 | | −// todo!("uncomment tests") |
| 2271 | | −// #[cfg(test)] |
| 2272 | | −// mod tests { |
| 2273 | | −// use super::*; |
| 2274 | | −// use crate::item::test::{TestItem, TestProjectItem}; |
| 2275 | | −// use gpui::TestAppContext; |
| 2276 | | −// use project::FakeFs; |
| 2277 | | −// use settings::SettingsStore; |
| 2278 | | − |
| 2279 | | −// #[gpui::test] |
| 2280 | | −// async fn test_remove_active_empty(cx: &mut TestAppContext) { |
| 2281 | | −// init_test(cx); |
| 2282 | | −// let fs = FakeFs::new(cx.background()); |
| 2283 | | − |
| 2284 | | −// let project = Project::test(fs, None, cx).await; |
| 2285 | | −// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); |
| 2286 | | −// let workspace = window.root(cx); |
| 2287 | | −// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); |
| 2288 | | − |
| 2289 | | −// pane.update(cx, |pane, cx| { |
| 2290 | | −// assert!(pane |
| 2291 | | −// .close_active_item(&CloseActiveItem { save_intent: None }, cx) |
| 2292 | | −// .is_none()) |
| 2293 | | −// }); |
| 2294 | | −// } |
| 2132 | +#[cfg(test)] |
| 2133 | +mod tests { |
| 2134 | + use super::*; |
| 2135 | + use crate::item::test::{TestItem, TestProjectItem}; |
| 2136 | + use gpui::{TestAppContext, VisualTestContext}; |
| 2137 | + use project::FakeFs; |
| 2138 | + use settings::SettingsStore; |
| 2139 | + use theme::LoadThemes; |
| 2140 | + |
| 2141 | + #[gpui::test] |
| 2142 | + async fn test_remove_active_empty(cx: &mut TestAppContext) { |
| 2143 | + init_test(cx); |
| 2144 | + let fs = FakeFs::new(cx.executor()); |
| 2145 | + |
| 2146 | + let project = Project::test(fs, None, cx).await; |
| 2147 | + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); |
| 2148 | + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); |
| 2149 | + |
| 2150 | + pane.update(cx, |pane, cx| { |
| 2151 | + assert!(pane |
| 2152 | + .close_active_item(&CloseActiveItem { save_intent: None }, cx) |
| 2153 | + .is_none()) |
| 2154 | + }); |
| 2155 | + } |
| 2295 | 2156 | |
| 2296 | | −// #[gpui::test] |
| 2297 | | −// async fn test_add_item_with_new_item(cx: &mut TestAppContext) { |
| 2298 | | −// cx.foreground().forbid_parking(); |
| 2299 | | −// init_test(cx); |
| 2300 | | −// let fs = FakeFs::new(cx.background()); |
| 2301 | | − |
| 2302 | | −// let project = Project::test(fs, None, cx).await; |
| 2303 | | −// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); |
| 2304 | | −// let workspace = window.root(cx); |
| 2305 | | −// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); |
| 2306 | | − |
| 2307 | | −// // 1. Add with a destination index |
| 2308 | | −// // a. Add before the active item |
| 2309 | | −// set_labeled_items(&pane, ["A", "B*", "C"], cx); |
| 2310 | | −// pane.update(cx, |pane, cx| { |
| 2311 | | −// pane.add_item( |
| 2312 | | −// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))), |
| 2313 | | −// false, |
| 2314 | | −// false, |
| 2315 | | −// Some(0), |
| 2316 | | −// cx, |
| 2317 | | −// ); |
| 2318 | | −// }); |
| 2319 | | −// assert_item_labels(&pane, ["D*", "A", "B", "C"], cx); |
| 2320 | | − |
| 2321 | | −// // b. Add after the active item |
| 2322 | | −// set_labeled_items(&pane, ["A", "B*", "C"], cx); |
| 2323 | | −// pane.update(cx, |pane, cx| { |
| 2324 | | −// pane.add_item( |
| 2325 | | −// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))), |
| 2326 | | −// false, |
| 2327 | | −// false, |
| 2328 | | −// Some(2), |
| 2329 | | −// cx, |
| 2330 | | −// ); |
| 2331 | | −// }); |
| 2332 | | −// assert_item_labels(&pane, ["A", "B", "D*", "C"], cx); |
| 2333 | | − |
| 2334 | | −// // c. Add at the end of the item list (including off the length) |
| 2335 | | −// set_labeled_items(&pane, ["A", "B*", "C"], cx); |
| 2336 | | −// pane.update(cx, |pane, cx| { |
| 2337 | | −// pane.add_item( |
| 2338 | | −// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))), |
| 2339 | | −// false, |
| 2340 | | −// false, |
| 2341 | | −// Some(5), |
| 2342 | | −// cx, |
| 2343 | | −// ); |
| 2344 | | −// }); |
| 2345 | | −// assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); |
| 2346 | | − |
| 2347 | | −// // 2. Add without a destination index |
| 2348 | | −// // a. Add with active item at the start of the item list |
| 2349 | | −// set_labeled_items(&pane, ["A*", "B", "C"], cx); |
| 2350 | | −// pane.update(cx, |pane, cx| { |
| 2351 | | −// pane.add_item( |
| 2352 | | −// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))), |
| 2353 | | −// false, |
| 2354 | | −// false, |
| 2355 | | −// None, |
| 2356 | | −// cx, |
| 2357 | | −// ); |
| 2358 | | −// }); |
| 2359 | | −// set_labeled_items(&pane, ["A", "D*", "B", "C"], cx); |
| 2360 | | − |
| 2361 | | −// // b. Add with active item at the end of the item list |
| 2362 | | −// set_labeled_items(&pane, ["A", "B", "C*"], cx); |
| 2363 | | −// pane.update(cx, |pane, cx| { |
| 2364 | | −// pane.add_item( |
| 2365 | | −// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))), |
| 2366 | | −// false, |
| 2367 | | −// false, |
| 2368 | | −// None, |
| 2369 | | −// cx, |
| 2370 | | −// ); |
| 2371 | | −// }); |
| 2372 | | −// assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); |
| 2373 | | −// } |
| 2157 | + #[gpui::test] |
| 2158 | + async fn test_add_item_with_new_item(cx: &mut TestAppContext) { |
| 2159 | + init_test(cx); |
| 2160 | + let fs = FakeFs::new(cx.executor()); |
| 2161 | + |
| 2162 | + let project = Project::test(fs, None, cx).await; |
| 2163 | + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); |
| 2164 | + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); |
| 2165 | + |
| 2166 | + // 1. Add with a destination index |
| 2167 | + // a. Add before the active item |
| 2168 | + set_labeled_items(&pane, ["A", "B*", "C"], cx); |
| 2169 | + pane.update(cx, |pane, cx| { |
| 2170 | + pane.add_item( |
| 2171 | + Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))), |
| 2172 | + false, |
| 2173 | + false, |
| 2174 | + Some(0), |
| 2175 | + cx, |
| 2176 | + ); |
| 2177 | + }); |
| 2178 | + assert_item_labels(&pane, ["D*", "A", "B", "C"], cx); |
| 2179 | + |
| 2180 | + // b. Add after the active item |
| 2181 | + set_labeled_items(&pane, ["A", "B*", "C"], cx); |
| 2182 | + pane.update(cx, |pane, cx| { |
| 2183 | + pane.add_item( |
| 2184 | + Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))), |
| 2185 | + false, |
| 2186 | + false, |
| 2187 | + Some(2), |
| 2188 | + cx, |
| 2189 | + ); |
| 2190 | + }); |
| 2191 | + assert_item_labels(&pane, ["A", "B", "D*", "C"], cx); |
| 2192 | + |
| 2193 | + // c. Add at the end of the item list (including off the length) |
| 2194 | + set_labeled_items(&pane, ["A", "B*", "C"], cx); |
| 2195 | + pane.update(cx, |pane, cx| { |
| 2196 | + pane.add_item( |
| 2197 | + Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))), |
| 2198 | + false, |
| 2199 | + false, |
| 2200 | + Some(5), |
| 2201 | + cx, |
| 2202 | + ); |
| 2203 | + }); |
| 2204 | + assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); |
| 2205 | + |
| 2206 | + // 2. Add without a destination index |
| 2207 | + // a. Add with active item at the start of the item list |
| 2208 | + set_labeled_items(&pane, ["A*", "B", "C"], cx); |
| 2209 | + pane.update(cx, |pane, cx| { |
| 2210 | + pane.add_item( |
| 2211 | + Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))), |
| 2212 | + false, |
| 2213 | + false, |
| 2214 | + None, |
| 2215 | + cx, |
| 2216 | + ); |
| 2217 | + }); |
| 2218 | + set_labeled_items(&pane, ["A", "D*", "B", "C"], cx); |
| 2219 | + |
| 2220 | + // b. Add with active item at the end of the item list |
| 2221 | + set_labeled_items(&pane, ["A", "B", "C*"], cx); |
| 2222 | + pane.update(cx, |pane, cx| { |
| 2223 | + pane.add_item( |
| 2224 | + Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))), |
| 2225 | + false, |
| 2226 | + false, |
| 2227 | + None, |
| 2228 | + cx, |
| 2229 | + ); |
| 2230 | + }); |
| 2231 | + assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); |
| 2232 | + } |
| 2374 | 2233 | |
| 2375 | | −// #[gpui::test] |
| 2376 | | −// async fn test_add_item_with_existing_item(cx: &mut TestAppContext) { |
| 2377 | | −// cx.foreground().forbid_parking(); |
| 2378 | | −// init_test(cx); |
| 2379 | | −// let fs = FakeFs::new(cx.background()); |
| 2380 | | − |
| 2381 | | −// let project = Project::test(fs, None, cx).await; |
| 2382 | | −// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); |
| 2383 | | −// let workspace = window.root(cx); |
| 2384 | | −// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); |
| 2385 | | − |
| 2386 | | −// // 1. Add with a destination index |
| 2387 | | −// // 1a. Add before the active item |
| 2388 | | −// let [_, _, _, d] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx); |
| 2389 | | −// pane.update(cx, |pane, cx| { |
| 2390 | | −// pane.add_item(d, false, false, Some(0), cx); |
| 2391 | | −// }); |
| 2392 | | −// assert_item_labels(&pane, ["D*", "A", "B", "C"], cx); |
| 2393 | | − |
| 2394 | | −// // 1b. Add after the active item |
| 2395 | | −// let [_, _, _, d] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx); |
| 2396 | | −// pane.update(cx, |pane, cx| { |
| 2397 | | −// pane.add_item(d, false, false, Some(2), cx); |
| 2398 | | −// }); |
| 2399 | | −// assert_item_labels(&pane, ["A", "B", "D*", "C"], cx); |
| 2400 | | − |
| 2401 | | −// // 1c. Add at the end of the item list (including off the length) |
| 2402 | | −// let [a, _, _, _] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx); |
| 2403 | | −// pane.update(cx, |pane, cx| { |
| 2404 | | −// pane.add_item(a, false, false, Some(5), cx); |
| 2405 | | −// }); |
| 2406 | | −// assert_item_labels(&pane, ["B", "C", "D", "A*"], cx); |
| 2407 | | − |
| 2408 | | −// // 1d. Add same item to active index |
| 2409 | | −// let [_, b, _] = set_labeled_items(&pane, ["A", "B*", "C"], cx); |
| 2410 | | −// pane.update(cx, |pane, cx| { |
| 2411 | | −// pane.add_item(b, false, false, Some(1), cx); |
| 2412 | | −// }); |
| 2413 | | −// assert_item_labels(&pane, ["A", "B*", "C"], cx); |
| 2414 | | − |
| 2415 | | −// // 1e. Add item to index after same item in last position |
| 2416 | | −// let [_, _, c] = set_labeled_items(&pane, ["A", "B*", "C"], cx); |
| 2417 | | −// pane.update(cx, |pane, cx| { |
| 2418 | | −// pane.add_item(c, false, false, Some(2), cx); |
| 2419 | | −// }); |
| 2420 | | −// assert_item_labels(&pane, ["A", "B", "C*"], cx); |
| 2421 | | − |
| 2422 | | −// // 2. Add without a destination index |
| 2423 | | −// // 2a. Add with active item at the start of the item list |
| 2424 | | −// let [_, _, _, d] = set_labeled_items(&pane, ["A*", "B", "C", "D"], cx); |
| 2425 | | −// pane.update(cx, |pane, cx| { |
| 2426 | | −// pane.add_item(d, false, false, None, cx); |
| 2427 | | −// }); |
| 2428 | | −// assert_item_labels(&pane, ["A", "D*", "B", "C"], cx); |
| 2429 | | − |
| 2430 | | −// // 2b. Add with active item at the end of the item list |
| 2431 | | −// let [a, _, _, _] = set_labeled_items(&pane, ["A", "B", "C", "D*"], cx); |
| 2432 | | −// pane.update(cx, |pane, cx| { |
| 2433 | | −// pane.add_item(a, false, false, None, cx); |
| 2434 | | −// }); |
| 2435 | | −// assert_item_labels(&pane, ["B", "C", "D", "A*"], cx); |
| 2436 | | − |
| 2437 | | −// // 2c. Add active item to active item at end of list |
| 2438 | | −// let [_, _, c] = set_labeled_items(&pane, ["A", "B", "C*"], cx); |
| 2439 | | −// pane.update(cx, |pane, cx| { |
| 2440 | | −// pane.add_item(c, false, false, None, cx); |
| 2441 | | −// }); |
| 2442 | | −// assert_item_labels(&pane, ["A", "B", "C*"], cx); |
| 2443 | | − |
| 2444 | | −// // 2d. Add active item to active item at start of list |
| 2445 | | −// let [a, _, _] = set_labeled_items(&pane, ["A*", "B", "C"], cx); |
| 2446 | | −// pane.update(cx, |pane, cx| { |
| 2447 | | −// pane.add_item(a, false, false, None, cx); |
| 2448 | | −// }); |
| 2449 | | −// assert_item_labels(&pane, ["A*", "B", "C"], cx); |
| 2450 | | −// } |
| 2234 | + #[gpui::test] |
| 2235 | + async fn test_add_item_with_existing_item(cx: &mut TestAppContext) { |
| 2236 | + init_test(cx); |
| 2237 | + let fs = FakeFs::new(cx.executor()); |
| 2451 | 2238 | |
| 2452 | | −// #[gpui::test] |
| 2453 | | −// async fn test_add_item_with_same_project_entries(cx: &mut TestAppContext) { |
| 2454 | | −// cx.foreground().forbid_parking(); |
| 2455 | | −// init_test(cx); |
| 2456 | | −// let fs = FakeFs::new(cx.background()); |
| 2457 | | − |
| 2458 | | −// let project = Project::test(fs, None, cx).await; |
| 2459 | | −// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); |
| 2460 | | −// let workspace = window.root(cx); |
| 2461 | | −// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); |
| 2462 | | − |
| 2463 | | −// // singleton view |
| 2464 | | −// pane.update(cx, |pane, cx| { |
| 2465 | | −// let item = TestItem::new() |
| 2466 | | −// .with_singleton(true) |
| 2467 | | −// .with_label("buffer 1") |
| 2468 | | −// .with_project_items(&[TestProjectItem::new(1, "one.txt", cx)]); |
| 2469 | | − |
| 2470 | | −// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx); |
| 2471 | | −// }); |
| 2472 | | −// assert_item_labels(&pane, ["buffer 1*"], cx); |
| 2473 | | − |
| 2474 | | −// // new singleton view with the same project entry |
| 2475 | | −// pane.update(cx, |pane, cx| { |
| 2476 | | −// let item = TestItem::new() |
| 2477 | | −// .with_singleton(true) |
| 2478 | | −// .with_label("buffer 1") |
| 2479 | | −// .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]); |
| 2480 | | − |
| 2481 | | −// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx); |
| 2482 | | −// }); |
| 2483 | | −// assert_item_labels(&pane, ["buffer 1*"], cx); |
| 2484 | | − |
| 2485 | | −// // new singleton view with different project entry |
| 2486 | | −// pane.update(cx, |pane, cx| { |
| 2487 | | −// let item = TestItem::new() |
| 2488 | | −// .with_singleton(true) |
| 2489 | | −// .with_label("buffer 2") |
| 2490 | | −// .with_project_items(&[TestProjectItem::new(2, "2.txt", cx)]); |
| 2491 | | −// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx); |
| 2492 | | −// }); |
| 2493 | | −// assert_item_labels(&pane, ["buffer 1", "buffer 2*"], cx); |
| 2494 | | − |
| 2495 | | −// // new multibuffer view with the same project entry |
| 2496 | | −// pane.update(cx, |pane, cx| { |
| 2497 | | −// let item = TestItem::new() |
| 2498 | | −// .with_singleton(false) |
| 2499 | | −// .with_label("multibuffer 1") |
| 2500 | | −// .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]); |
| 2501 | | − |
| 2502 | | −// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx); |
| 2503 | | −// }); |
| 2504 | | −// assert_item_labels(&pane, ["buffer 1", "buffer 2", "multibuffer 1*"], cx); |
| 2505 | | − |
| 2506 | | −// // another multibuffer view with the same project entry |
| 2507 | | −// pane.update(cx, |pane, cx| { |
| 2508 | | −// let item = TestItem::new() |
| 2509 | | −// .with_singleton(false) |
| 2510 | | −// .with_label("multibuffer 1b") |
| 2511 | | −// .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]); |
| 2512 | | − |
| 2513 | | −// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx); |
| 2514 | | −// }); |
| 2515 | | −// assert_item_labels( |
| 2516 | | −// &pane, |
| 2517 | | −// ["buffer 1", "buffer 2", "multibuffer 1", "multibuffer 1b*"], |
| 2518 | | −// cx, |
| 2519 | | −// ); |
| 2520 | | −// } |
| 2239 | + let project = Project::test(fs, None, cx).await; |
| 2240 | + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); |
| 2241 | + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); |
| 2521 | 2242 | |
| 2522 | | −// #[gpui::test] |
| 2523 | | −// async fn test_remove_item_ordering(cx: &mut TestAppContext) { |
| 2524 | | −// init_test(cx); |
| 2525 | | −// let fs = FakeFs::new(cx.background()); |
| 2526 | | − |
| 2527 | | −// let project = Project::test(fs, None, cx).await; |
| 2528 | | −// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); |
| 2529 | | −// let workspace = window.root(cx); |
| 2530 | | −// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); |
| 2531 | | − |
| 2532 | | −// add_labeled_item(&pane, "A", false, cx); |
| 2533 | | −// add_labeled_item(&pane, "B", false, cx); |
| 2534 | | −// add_labeled_item(&pane, "C", false, cx); |
| 2535 | | −// add_labeled_item(&pane, "D", false, cx); |
| 2536 | | −// assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); |
| 2537 | | − |
| 2538 | | −// pane.update(cx, |pane, cx| pane.activate_item(1, false, false, cx)); |
| 2539 | | −// add_labeled_item(&pane, "1", false, cx); |
| 2540 | | −// assert_item_labels(&pane, ["A", "B", "1*", "C", "D"], cx); |
| 2541 | | − |
| 2542 | | −// pane.update(cx, |pane, cx| { |
| 2543 | | −// pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) |
| 2544 | | −// }) |
| 2545 | | −// .unwrap() |
| 2546 | | −// .await |
| 2547 | | −// .unwrap(); |
| 2548 | | −// assert_item_labels(&pane, ["A", "B*", "C", "D"], cx); |
| 2549 | | − |
| 2550 | | −// pane.update(cx, |pane, cx| pane.activate_item(3, false, false, cx)); |
| 2551 | | −// assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); |
| 2552 | | − |
| 2553 | | −// pane.update(cx, |pane, cx| { |
| 2554 | | −// pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) |
| 2555 | | −// }) |
| 2556 | | −// .unwrap() |
| 2557 | | −// .await |
| 2558 | | −// .unwrap(); |
| 2559 | | −// assert_item_labels(&pane, ["A", "B*", "C"], cx); |
| 2560 | | − |
| 2561 | | −// pane.update(cx, |pane, cx| { |
| 2562 | | −// pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) |
| 2563 | | −// }) |
| 2564 | | −// .unwrap() |
| 2565 | | −// .await |
| 2566 | | −// .unwrap(); |
| 2567 | | −// assert_item_labels(&pane, ["A", "C*"], cx); |
| 2568 | | − |
| 2569 | | −// pane.update(cx, |pane, cx| { |
| 2570 | | −// pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) |
| 2571 | | −// }) |
| 2572 | | −// .unwrap() |
| 2573 | | −// .await |
| 2574 | | −// .unwrap(); |
| 2575 | | −// assert_item_labels(&pane, ["A*"], cx); |
| 2576 | | −// } |
| 2243 | + // 1. Add with a destination index |
| 2244 | + // 1a. Add before the active item |
| 2245 | + let [_, _, _, d] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx); |
| 2246 | + pane.update(cx, |pane, cx| { |
| 2247 | + pane.add_item(d, false, false, Some(0), cx); |
| 2248 | + }); |
| 2249 | + assert_item_labels(&pane, ["D*", "A", "B", "C"], cx); |
| 2577 | 2250 | |
| 2578 | | −// #[gpui::test] |
| 2579 | | −// async fn test_close_inactive_items(cx: &mut TestAppContext) { |
| 2580 | | −// init_test(cx); |
| 2581 | | −// let fs = FakeFs::new(cx.background()); |
| 2582 | | − |
| 2583 | | −// let project = Project::test(fs, None, cx).await; |
| 2584 | | −// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); |
| 2585 | | −// let workspace = window.root(cx); |
| 2586 | | −// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); |
| 2587 | | − |
| 2588 | | −// set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx); |
| 2589 | | − |
| 2590 | | −// pane.update(cx, |pane, cx| { |
| 2591 | | −// pane.close_inactive_items(&CloseInactiveItems, cx) |
| 2592 | | −// }) |
| 2593 | | −// .unwrap() |
| 2594 | | −// .await |
| 2595 | | −// .unwrap(); |
| 2596 | | −// assert_item_labels(&pane, ["C*"], cx); |
| 2597 | | −// } |
| 2251 | + // 1b. Add after the active item |
| 2252 | + let [_, _, _, d] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx); |
| 2253 | + pane.update(cx, |pane, cx| { |
| 2254 | + pane.add_item(d, false, false, Some(2), cx); |
| 2255 | + }); |
| 2256 | + assert_item_labels(&pane, ["A", "B", "D*", "C"], cx); |
| 2598 | 2257 | |
| 2599 | | −// #[gpui::test] |
| 2600 | | −// async fn test_close_clean_items(cx: &mut TestAppContext) { |
| 2601 | | −// init_test(cx); |
| 2602 | | −// let fs = FakeFs::new(cx.background()); |
| 2603 | | − |
| 2604 | | −// let project = Project::test(fs, None, cx).await; |
| 2605 | | −// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); |
| 2606 | | −// let workspace = window.root(cx); |
| 2607 | | −// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); |
| 2608 | | − |
| 2609 | | −// add_labeled_item(&pane, "A", true, cx); |
| 2610 | | −// add_labeled_item(&pane, "B", false, cx); |
| 2611 | | −// add_labeled_item(&pane, "C", true, cx); |
| 2612 | | −// add_labeled_item(&pane, "D", false, cx); |
| 2613 | | −// add_labeled_item(&pane, "E", false, cx); |
| 2614 | | −// assert_item_labels(&pane, ["A^", "B", "C^", "D", "E*"], cx); |
| 2615 | | − |
| 2616 | | −// pane.update(cx, |pane, cx| pane.close_clean_items(&CloseCleanItems, cx)) |
| 2617 | | −// .unwrap() |
| 2618 | | −// .await |
| 2619 | | −// .unwrap(); |
| 2620 | | −// assert_item_labels(&pane, ["A^", "C*^"], cx); |
| 2621 | | −// } |
| 2258 | + // 1c. Add at the end of the item list (including off the length) |
| 2259 | + let [a, _, _, _] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx); |
| 2260 | + pane.update(cx, |pane, cx| { |
| 2261 | + pane.add_item(a, false, false, Some(5), cx); |
| 2262 | + }); |
| 2263 | + assert_item_labels(&pane, ["B", "C", "D", "A*"], cx); |
| 2622 | 2264 | |
| 2623 | | −// #[gpui::test] |
| 2624 | | −// async fn test_close_items_to_the_left(cx: &mut TestAppContext) { |
| 2625 | | −// init_test(cx); |
| 2626 | | −// let fs = FakeFs::new(cx.background()); |
| 2627 | | − |
| 2628 | | −// let project = Project::test(fs, None, cx).await; |
| 2629 | | −// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); |
| 2630 | | −// let workspace = window.root(cx); |
| 2631 | | −// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); |
| 2632 | | − |
| 2633 | | −// set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx); |
| 2634 | | − |
| 2635 | | −// pane.update(cx, |pane, cx| { |
| 2636 | | −// pane.close_items_to_the_left(&CloseItemsToTheLeft, cx) |
| 2637 | | −// }) |
| 2638 | | −// .unwrap() |
| 2639 | | −// .await |
| 2640 | | −// .unwrap(); |
| 2641 | | −// assert_item_labels(&pane, ["C*", "D", "E"], cx); |
| 2642 | | −// } |
| 2265 | + // 1d. Add same item to active index |
| 2266 | + let [_, b, _] = set_labeled_items(&pane, ["A", "B*", "C"], cx); |
| 2267 | + pane.update(cx, |pane, cx| { |
| 2268 | + pane.add_item(b, false, false, Some(1), cx); |
| 2269 | + }); |
| 2270 | + assert_item_labels(&pane, ["A", "B*", "C"], cx); |
| 2643 | 2271 | |
| 2644 | | −// #[gpui::test] |
| 2645 | | −// async fn test_close_items_to_the_right(cx: &mut TestAppContext) { |
| 2646 | | −// init_test(cx); |
| 2647 | | −// let fs = FakeFs::new(cx.background()); |
| 2648 | | − |
| 2649 | | −// let project = Project::test(fs, None, cx).await; |
| 2650 | | −// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); |
| 2651 | | −// let workspace = window.root(cx); |
| 2652 | | −// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); |
| 2653 | | − |
| 2654 | | −// set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx); |
| 2655 | | − |
| 2656 | | −// pane.update(cx, |pane, cx| { |
| 2657 | | −// pane.close_items_to_the_right(&CloseItemsToTheRight, cx) |
| 2658 | | −// }) |
| 2659 | | −// .unwrap() |
| 2660 | | −// .await |
| 2661 | | −// .unwrap(); |
| 2662 | | −// assert_item_labels(&pane, ["A", "B", "C*"], cx); |
| 2663 | | −// } |
| 2272 | + // 1e. Add item to index after same item in last position |
| 2273 | + let [_, _, c] = set_labeled_items(&pane, ["A", "B*", "C"], cx); |
| 2274 | + pane.update(cx, |pane, cx| { |
| 2275 | + pane.add_item(c, false, false, Some(2), cx); |
| 2276 | + }); |
| 2277 | + assert_item_labels(&pane, ["A", "B", "C*"], cx); |
| 2664 | 2278 | |
| 2665 | | −// #[gpui::test] |
| 2666 | | −// async fn test_close_all_items(cx: &mut TestAppContext) { |
| 2667 | | −// init_test(cx); |
| 2668 | | −// let fs = FakeFs::new(cx.background()); |
| 2669 | | − |
| 2670 | | −// let project = Project::test(fs, None, cx).await; |
| 2671 | | −// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); |
| 2672 | | −// let workspace = window.root(cx); |
| 2673 | | −// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); |
| 2674 | | − |
| 2675 | | −// add_labeled_item(&pane, "A", false, cx); |
| 2676 | | −// add_labeled_item(&pane, "B", false, cx); |
| 2677 | | −// add_labeled_item(&pane, "C", false, cx); |
| 2678 | | −// assert_item_labels(&pane, ["A", "B", "C*"], cx); |
| 2679 | | − |
| 2680 | | −// pane.update(cx, |pane, cx| { |
| 2681 | | −// pane.close_all_items(&CloseAllItems { save_intent: None }, cx) |
| 2682 | | −// }) |
| 2683 | | −// .unwrap() |
| 2684 | | −// .await |
| 2685 | | −// .unwrap(); |
| 2686 | | −// assert_item_labels(&pane, [], cx); |
| 2687 | | − |
| 2688 | | −// add_labeled_item(&pane, "A", true, cx); |
| 2689 | | −// add_labeled_item(&pane, "B", true, cx); |
| 2690 | | −// add_labeled_item(&pane, "C", true, cx); |
| 2691 | | −// assert_item_labels(&pane, ["A^", "B^", "C*^"], cx); |
| 2692 | | − |
| 2693 | | −// let save = pane |
| 2694 | | −// .update(cx, |pane, cx| { |
| 2695 | | −// pane.close_all_items(&CloseAllItems { save_intent: None }, cx) |
| 2696 | | −// }) |
| 2697 | | −// .unwrap(); |
| 2698 | | − |
| 2699 | | −// cx.foreground().run_until_parked(); |
| 2700 | | −// window.simulate_prompt_answer(2, cx); |
| 2701 | | −// save.await.unwrap(); |
| 2702 | | −// assert_item_labels(&pane, [], cx); |
| 2703 | | −// } |
| 2279 | + // 2. Add without a destination index |
| 2280 | + // 2a. Add with active item at the start of the item list |
| 2281 | + let [_, _, _, d] = set_labeled_items(&pane, ["A*", "B", "C", "D"], cx); |
| 2282 | + pane.update(cx, |pane, cx| { |
| 2283 | + pane.add_item(d, false, false, None, cx); |
| 2284 | + }); |
| 2285 | + assert_item_labels(&pane, ["A", "D*", "B", "C"], cx); |
| 2704 | 2286 | |
| 2705 | | −// fn init_test(cx: &mut TestAppContext) { |
| 2706 | | −// cx.update(|cx| { |
| 2707 | | −// cx.set_global(SettingsStore::test(cx)); |
| 2708 | | −// theme::init((), cx); |
| 2709 | | −// crate::init_settings(cx); |
| 2710 | | −// Project::init_settings(cx); |
| 2711 | | −// }); |
| 2712 | | −// } |
| 2287 | + // 2b. Add with active item at the end of the item list |
| 2288 | + let [a, _, _, _] = set_labeled_items(&pane, ["A", "B", "C", "D*"], cx); |
| 2289 | + pane.update(cx, |pane, cx| { |
| 2290 | + pane.add_item(a, false, false, None, cx); |
| 2291 | + }); |
| 2292 | + assert_item_labels(&pane, ["B", "C", "D", "A*"], cx); |
| 2713 | 2293 | |
| 2714 | | −// fn add_labeled_item( |
| 2715 | | −// pane: &ViewHandle<Pane>, |
| 2716 | | −// label: &str, |
| 2717 | | −// is_dirty: bool, |
| 2718 | | −// cx: &mut TestAppContext, |
| 2719 | | −// ) -> Box<ViewHandle<TestItem>> { |
| 2720 | | −// pane.update(cx, |pane, cx| { |
| 2721 | | −// let labeled_item = |
| 2722 | | −// Box::new(cx.add_view(|_| TestItem::new().with_label(label).with_dirty(is_dirty))); |
| 2723 | | −// pane.add_item(labeled_item.clone(), false, false, None, cx); |
| 2724 | | −// labeled_item |
| 2725 | | −// }) |
| 2726 | | −// } |
| 2294 | + // 2c. Add active item to active item at end of list |
| 2295 | + let [_, _, c] = set_labeled_items(&pane, ["A", "B", "C*"], cx); |
| 2296 | + pane.update(cx, |pane, cx| { |
| 2297 | + pane.add_item(c, false, false, None, cx); |
| 2298 | + }); |
| 2299 | + assert_item_labels(&pane, ["A", "B", "C*"], cx); |
| 2727 | 2300 | |
| 2728 | | −// fn set_labeled_items<const COUNT: usize>( |
| 2729 | | −// pane: &ViewHandle<Pane>, |
| 2730 | | −// labels: [&str; COUNT], |
| 2731 | | −// cx: &mut TestAppContext, |
| 2732 | | −// ) -> [Box<ViewHandle<TestItem>>; COUNT] { |
| 2733 | | −// pane.update(cx, |pane, cx| { |
| 2734 | | −// pane.items.clear(); |
| 2735 | | −// let mut active_item_index = 0; |
| 2736 | | − |
| 2737 | | −// let mut index = 0; |
| 2738 | | −// let items = labels.map(|mut label| { |
| 2739 | | −// if label.ends_with("*") { |
| 2740 | | −// label = label.trim_end_matches("*"); |
| 2741 | | −// active_item_index = index; |
| 2742 | | −// } |
| 2743 | | − |
| 2744 | | −// let labeled_item = Box::new(cx.add_view(|_| TestItem::new().with_label(label))); |
| 2745 | | −// pane.add_item(labeled_item.clone(), false, false, None, cx); |
| 2746 | | −// index += 1; |
| 2747 | | −// labeled_item |
| 2748 | | −// }); |
| 2749 | | − |
| 2750 | | −// pane.activate_item(active_item_index, false, false, cx); |
| 2751 | | − |
| 2752 | | −// items |
| 2753 | | −// }) |
| 2754 | | −// } |
| 2301 | + // 2d. Add active item to active item at start of list |
| 2302 | + let [a, _, _] = set_labeled_items(&pane, ["A*", "B", "C"], cx); |
| 2303 | + pane.update(cx, |pane, cx| { |
| 2304 | + pane.add_item(a, false, false, None, cx); |
| 2305 | + }); |
| 2306 | + assert_item_labels(&pane, ["A*", "B", "C"], cx); |
| 2307 | + } |
| 2308 | + |
| 2309 | + #[gpui::test] |
| 2310 | + async fn test_add_item_with_same_project_entries(cx: &mut TestAppContext) { |
| 2311 | + init_test(cx); |
| 2312 | + let fs = FakeFs::new(cx.executor()); |
| 2313 | + |
| 2314 | + let project = Project::test(fs, None, cx).await; |
| 2315 | + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); |
| 2316 | + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); |
| 2317 | + |
| 2318 | + // singleton view |
| 2319 | + pane.update(cx, |pane, cx| { |
| 2320 | + pane.add_item( |
| 2321 | + Box::new(cx.build_view(|cx| { |
| 2322 | + TestItem::new(cx) |
| 2323 | + .with_singleton(true) |
| 2324 | + .with_label("buffer 1") |
| 2325 | + .with_project_items(&[TestProjectItem::new(1, "one.txt", cx)]) |
| 2326 | + })), |
| 2327 | + false, |
| 2328 | + false, |
| 2329 | + None, |
| 2330 | + cx, |
| 2331 | + ); |
| 2332 | + }); |
| 2333 | + assert_item_labels(&pane, ["buffer 1*"], cx); |
| 2334 | + |
| 2335 | + // new singleton view with the same project entry |
| 2336 | + pane.update(cx, |pane, cx| { |
| 2337 | + pane.add_item( |
| 2338 | + Box::new(cx.build_view(|cx| { |
| 2339 | + TestItem::new(cx) |
| 2340 | + .with_singleton(true) |
| 2341 | + .with_label("buffer 1") |
| 2342 | + .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]) |
| 2343 | + })), |
| 2344 | + false, |
| 2345 | + false, |
| 2346 | + None, |
| 2347 | + cx, |
| 2348 | + ); |
| 2349 | + }); |
| 2350 | + assert_item_labels(&pane, ["buffer 1*"], cx); |
| 2351 | + |
| 2352 | + // new singleton view with different project entry |
| 2353 | + pane.update(cx, |pane, cx| { |
| 2354 | + pane.add_item( |
| 2355 | + Box::new(cx.build_view(|cx| { |
| 2356 | + TestItem::new(cx) |
| 2357 | + .with_singleton(true) |
| 2358 | + .with_label("buffer 2") |
| 2359 | + .with_project_items(&[TestProjectItem::new(2, "2.txt", cx)]) |
| 2360 | + })), |
| 2361 | + false, |
| 2362 | + false, |
| 2363 | + None, |
| 2364 | + cx, |
| 2365 | + ); |
| 2366 | + }); |
| 2367 | + assert_item_labels(&pane, ["buffer 1", "buffer 2*"], cx); |
| 2368 | + |
| 2369 | + // new multibuffer view with the same project entry |
| 2370 | + pane.update(cx, |pane, cx| { |
| 2371 | + pane.add_item( |
| 2372 | + Box::new(cx.build_view(|cx| { |
| 2373 | + TestItem::new(cx) |
| 2374 | + .with_singleton(false) |
| 2375 | + .with_label("multibuffer 1") |
| 2376 | + .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]) |
| 2377 | + })), |
| 2378 | + false, |
| 2379 | + false, |
| 2380 | + None, |
| 2381 | + cx, |
| 2382 | + ); |
| 2383 | + }); |
| 2384 | + assert_item_labels(&pane, ["buffer 1", "buffer 2", "multibuffer 1*"], cx); |
| 2385 | + |
| 2386 | + // another multibuffer view with the same project entry |
| 2387 | + pane.update(cx, |pane, cx| { |
| 2388 | + pane.add_item( |
| 2389 | + Box::new(cx.build_view(|cx| { |
| 2390 | + TestItem::new(cx) |
| 2391 | + .with_singleton(false) |
| 2392 | + .with_label("multibuffer 1b") |
| 2393 | + .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]) |
| 2394 | + })), |
| 2395 | + false, |
| 2396 | + false, |
| 2397 | + None, |
| 2398 | + cx, |
| 2399 | + ); |
| 2400 | + }); |
| 2401 | + assert_item_labels( |
| 2402 | + &pane, |
| 2403 | + ["buffer 1", "buffer 2", "multibuffer 1", "multibuffer 1b*"], |
| 2404 | + cx, |
| 2405 | + ); |
| 2406 | + } |
| 2755 | 2407 | |
| 2756 | | −// // Assert the item label, with the active item label suffixed with a '*' |
| 2757 | | −// fn assert_item_labels<const COUNT: usize>( |
| 2758 | | −// pane: &ViewHandle<Pane>, |
| 2759 | | −// expected_states: [&str; COUNT], |
| 2760 | | −// cx: &mut TestAppContext, |
| 2761 | | −// ) { |
| 2762 | | −// pane.read_with(cx, |pane, cx| { |
| 2763 | | −// let actual_states = pane |
| 2764 | | −// .items |
| 2765 | | −// .iter() |
| 2766 | | −// .enumerate() |
| 2767 | | −// .map(|(ix, item)| { |
| 2768 | | −// let mut state = item |
| 2769 | | −// .as_any() |
| 2770 | | −// .downcast_ref::<TestItem>() |
| 2771 | | −// .unwrap() |
| 2772 | | −// .read(cx) |
| 2773 | | −// .label |
| 2774 | | −// .clone(); |
| 2775 | | −// if ix == pane.active_item_index { |
| 2776 | | −// state.push('*'); |
| 2777 | | −// } |
| 2778 | | −// if item.is_dirty(cx) { |
| 2779 | | −// state.push('^'); |
| 2780 | | −// } |
| 2781 | | −// state |
| 2782 | | −// }) |
| 2783 | | −// .collect::<Vec<_>>(); |
| 2784 | | − |
| 2785 | | −// assert_eq!( |
| 2786 | | −// actual_states, expected_states, |
| 2787 | | −// "pane items do not match expectation" |
| 2788 | | −// ); |
| 2789 | | −// }) |
| 2790 | | −// } |
| 2791 | | −// } |
| 2408 | + #[gpui::test] |
| 2409 | + async fn test_remove_item_ordering(cx: &mut TestAppContext) { |
| 2410 | + init_test(cx); |
| 2411 | + let fs = FakeFs::new(cx.executor()); |
| 2412 | + |
| 2413 | + let project = Project::test(fs, None, cx).await; |
| 2414 | + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); |
| 2415 | + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); |
| 2416 | + |
| 2417 | + add_labeled_item(&pane, "A", false, cx); |
| 2418 | + add_labeled_item(&pane, "B", false, cx); |
| 2419 | + add_labeled_item(&pane, "C", false, cx); |
| 2420 | + add_labeled_item(&pane, "D", false, cx); |
| 2421 | + assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); |
| 2422 | + |
| 2423 | + pane.update(cx, |pane, cx| pane.activate_item(1, false, false, cx)); |
| 2424 | + add_labeled_item(&pane, "1", false, cx); |
| 2425 | + assert_item_labels(&pane, ["A", "B", "1*", "C", "D"], cx); |
| 2426 | + |
| 2427 | + pane.update(cx, |pane, cx| { |
| 2428 | + pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) |
| 2429 | + }) |
| 2430 | + .unwrap() |
| 2431 | + .await |
| 2432 | + .unwrap(); |
| 2433 | + assert_item_labels(&pane, ["A", "B*", "C", "D"], cx); |
| 2434 | + |
| 2435 | + pane.update(cx, |pane, cx| pane.activate_item(3, false, false, cx)); |
| 2436 | + assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); |
| 2437 | + |
| 2438 | + pane.update(cx, |pane, cx| { |
| 2439 | + pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) |
| 2440 | + }) |
| 2441 | + .unwrap() |
| 2442 | + .await |
| 2443 | + .unwrap(); |
| 2444 | + assert_item_labels(&pane, ["A", "B*", "C"], cx); |
| 2445 | + |
| 2446 | + pane.update(cx, |pane, cx| { |
| 2447 | + pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) |
| 2448 | + }) |
| 2449 | + .unwrap() |
| 2450 | + .await |
| 2451 | + .unwrap(); |
| 2452 | + assert_item_labels(&pane, ["A", "C*"], cx); |
| 2453 | + |
| 2454 | + pane.update(cx, |pane, cx| { |
| 2455 | + pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) |
| 2456 | + }) |
| 2457 | + .unwrap() |
| 2458 | + .await |
| 2459 | + .unwrap(); |
| 2460 | + assert_item_labels(&pane, ["A*"], cx); |
| 2461 | + } |
| 2462 | + |
| 2463 | + #[gpui::test] |
| 2464 | + async fn test_close_inactive_items(cx: &mut TestAppContext) { |
| 2465 | + init_test(cx); |
| 2466 | + let fs = FakeFs::new(cx.executor()); |
| 2467 | + |
| 2468 | + let project = Project::test(fs, None, cx).await; |
| 2469 | + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); |
| 2470 | + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); |
| 2471 | + |
| 2472 | + set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx); |
| 2473 | + |
| 2474 | + pane.update(cx, |pane, cx| { |
| 2475 | + pane.close_inactive_items(&CloseInactiveItems, cx) |
| 2476 | + }) |
| 2477 | + .unwrap() |
| 2478 | + .await |
| 2479 | + .unwrap(); |
| 2480 | + assert_item_labels(&pane, ["C*"], cx); |
| 2481 | + } |
| 2482 | + |
| 2483 | + #[gpui::test] |
| 2484 | + async fn test_close_clean_items(cx: &mut TestAppContext) { |
| 2485 | + init_test(cx); |
| 2486 | + let fs = FakeFs::new(cx.executor()); |
| 2487 | + |
| 2488 | + let project = Project::test(fs, None, cx).await; |
| 2489 | + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); |
| 2490 | + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); |
| 2491 | + |
| 2492 | + add_labeled_item(&pane, "A", true, cx); |
| 2493 | + add_labeled_item(&pane, "B", false, cx); |
| 2494 | + add_labeled_item(&pane, "C", true, cx); |
| 2495 | + add_labeled_item(&pane, "D", false, cx); |
| 2496 | + add_labeled_item(&pane, "E", false, cx); |
| 2497 | + assert_item_labels(&pane, ["A^", "B", "C^", "D", "E*"], cx); |
| 2498 | + |
| 2499 | + pane.update(cx, |pane, cx| pane.close_clean_items(&CloseCleanItems, cx)) |
| 2500 | + .unwrap() |
| 2501 | + .await |
| 2502 | + .unwrap(); |
| 2503 | + assert_item_labels(&pane, ["A^", "C*^"], cx); |
| 2504 | + } |
| 2505 | + |
| 2506 | + #[gpui::test] |
| 2507 | + async fn test_close_items_to_the_left(cx: &mut TestAppContext) { |
| 2508 | + init_test(cx); |
| 2509 | + let fs = FakeFs::new(cx.executor()); |
| 2510 | + |
| 2511 | + let project = Project::test(fs, None, cx).await; |
| 2512 | + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); |
| 2513 | + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); |
| 2514 | + |
| 2515 | + set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx); |
| 2516 | + |
| 2517 | + pane.update(cx, |pane, cx| { |
| 2518 | + pane.close_items_to_the_left(&CloseItemsToTheLeft, cx) |
| 2519 | + }) |
| 2520 | + .unwrap() |
| 2521 | + .await |
| 2522 | + .unwrap(); |
| 2523 | + assert_item_labels(&pane, ["C*", "D", "E"], cx); |
| 2524 | + } |
| 2525 | + |
| 2526 | + #[gpui::test] |
| 2527 | + async fn test_close_items_to_the_right(cx: &mut TestAppContext) { |
| 2528 | + init_test(cx); |
| 2529 | + let fs = FakeFs::new(cx.executor()); |
| 2530 | + |
| 2531 | + let project = Project::test(fs, None, cx).await; |
| 2532 | + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); |
| 2533 | + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); |
| 2534 | + |
| 2535 | + set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx); |
| 2536 | + |
| 2537 | + pane.update(cx, |pane, cx| { |
| 2538 | + pane.close_items_to_the_right(&CloseItemsToTheRight, cx) |
| 2539 | + }) |
| 2540 | + .unwrap() |
| 2541 | + .await |
| 2542 | + .unwrap(); |
| 2543 | + assert_item_labels(&pane, ["A", "B", "C*"], cx); |
| 2544 | + } |
| 2545 | + |
| 2546 | + #[gpui::test] |
| 2547 | + async fn test_close_all_items(cx: &mut TestAppContext) { |
| 2548 | + init_test(cx); |
| 2549 | + let fs = FakeFs::new(cx.executor()); |
| 2550 | + |
| 2551 | + let project = Project::test(fs, None, cx).await; |
| 2552 | + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); |
| 2553 | + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); |
| 2554 | + |
| 2555 | + add_labeled_item(&pane, "A", false, cx); |
| 2556 | + add_labeled_item(&pane, "B", false, cx); |
| 2557 | + add_labeled_item(&pane, "C", false, cx); |
| 2558 | + assert_item_labels(&pane, ["A", "B", "C*"], cx); |
| 2559 | + |
| 2560 | + pane.update(cx, |pane, cx| { |
| 2561 | + pane.close_all_items(&CloseAllItems { save_intent: None }, cx) |
| 2562 | + }) |
| 2563 | + .unwrap() |
| 2564 | + .await |
| 2565 | + .unwrap(); |
| 2566 | + assert_item_labels(&pane, [], cx); |
| 2567 | + |
| 2568 | + add_labeled_item(&pane, "A", true, cx); |
| 2569 | + add_labeled_item(&pane, "B", true, cx); |
| 2570 | + add_labeled_item(&pane, "C", true, cx); |
| 2571 | + assert_item_labels(&pane, ["A^", "B^", "C*^"], cx); |
| 2572 | + |
| 2573 | + let save = pane |
| 2574 | + .update(cx, |pane, cx| { |
| 2575 | + pane.close_all_items(&CloseAllItems { save_intent: None }, cx) |
| 2576 | + }) |
| 2577 | + .unwrap(); |
| 2578 | + |
| 2579 | + cx.executor().run_until_parked(); |
| 2580 | + cx.simulate_prompt_answer(2); |
| 2581 | + save.await.unwrap(); |
| 2582 | + assert_item_labels(&pane, [], cx); |
| 2583 | + } |
| 2584 | + |
| 2585 | + fn init_test(cx: &mut TestAppContext) { |
| 2586 | + cx.update(|cx| { |
| 2587 | + let settings_store = SettingsStore::test(cx); |
| 2588 | + cx.set_global(settings_store); |
| 2589 | + theme::init(LoadThemes::JustBase, cx); |
| 2590 | + crate::init_settings(cx); |
| 2591 | + Project::init_settings(cx); |
| 2592 | + }); |
| 2593 | + } |
| 2594 | + |
| 2595 | + fn add_labeled_item( |
| 2596 | + pane: &View<Pane>, |
| 2597 | + label: &str, |
| 2598 | + is_dirty: bool, |
| 2599 | + cx: &mut VisualTestContext, |
| 2600 | + ) -> Box<View<TestItem>> { |
| 2601 | + pane.update(cx, |pane, cx| { |
| 2602 | + let labeled_item = Box::new( |
| 2603 | + cx.build_view(|cx| TestItem::new(cx).with_label(label).with_dirty(is_dirty)), |
| 2604 | + ); |
| 2605 | + pane.add_item(labeled_item.clone(), false, false, None, cx); |
| 2606 | + labeled_item |
| 2607 | + }) |
| 2608 | + } |
| 2609 | + |
| 2610 | + fn set_labeled_items<const COUNT: usize>( |
| 2611 | + pane: &View<Pane>, |
| 2612 | + labels: [&str; COUNT], |
| 2613 | + cx: &mut VisualTestContext, |
| 2614 | + ) -> [Box<View<TestItem>>; COUNT] { |
| 2615 | + pane.update(cx, |pane, cx| { |
| 2616 | + pane.items.clear(); |
| 2617 | + let mut active_item_index = 0; |
| 2618 | + |
| 2619 | + let mut index = 0; |
| 2620 | + let items = labels.map(|mut label| { |
| 2621 | + if label.ends_with("*") { |
| 2622 | + label = label.trim_end_matches("*"); |
| 2623 | + active_item_index = index; |
| 2624 | + } |
| 2625 | + |
| 2626 | + let labeled_item = |
| 2627 | + Box::new(cx.build_view(|cx| TestItem::new(cx).with_label(label))); |
| 2628 | + pane.add_item(labeled_item.clone(), false, false, None, cx); |
| 2629 | + index += 1; |
| 2630 | + labeled_item |
| 2631 | + }); |
| 2632 | + |
| 2633 | + pane.activate_item(active_item_index, false, false, cx); |
| 2634 | + |
| 2635 | + items |
| 2636 | + }) |
| 2637 | + } |
| 2638 | + |
| 2639 | + // Assert the item label, with the active item label suffixed with a '*' |
| 2640 | + fn assert_item_labels<const COUNT: usize>( |
| 2641 | + pane: &View<Pane>, |
| 2642 | + expected_states: [&str; COUNT], |
| 2643 | + cx: &mut VisualTestContext, |
| 2644 | + ) { |
| 2645 | + pane.update(cx, |pane, cx| { |
| 2646 | + let actual_states = pane |
| 2647 | + .items |
| 2648 | + .iter() |
| 2649 | + .enumerate() |
| 2650 | + .map(|(ix, item)| { |
| 2651 | + let mut state = item |
| 2652 | + .to_any() |
| 2653 | + .downcast::<TestItem>() |
| 2654 | + .unwrap() |
| 2655 | + .read(cx) |
| 2656 | + .label |
| 2657 | + .clone(); |
| 2658 | + if ix == pane.active_item_index { |
| 2659 | + state.push('*'); |
| 2660 | + } |
| 2661 | + if item.is_dirty(cx) { |
| 2662 | + state.push('^'); |
| 2663 | + } |
| 2664 | + state |
| 2665 | + }) |
| 2666 | + .collect::<Vec<_>>(); |
| 2667 | + |
| 2668 | + assert_eq!( |
| 2669 | + actual_states, expected_states, |
| 2670 | + "pane items do not match expectation" |
| 2671 | + ); |
| 2672 | + }) |
| 2673 | + } |
| 2674 | +} |
| 2792 | 2675 | |
| 2793 | 2676 | impl Render for DraggedTab { |
| 2794 | 2677 | type Element = <Tab as RenderOnce>::Rendered; |