diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index de10c7f33877e85bc14d8f036b158849b2410c6f..8bef25b92d796c7113ac3f165d8f85cbf7127985 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -305,42 +305,6 @@ impl Component for AnyView { } } -impl Element<()> for AnyView { - type ElementState = AnyBox; - - fn id(&self) -> Option { - Some(ElementId::View(self.0.entity_id())) - } - - fn initialize( - &mut self, - _: &mut (), - _: Option, - cx: &mut ViewContext<()>, - ) -> Self::ElementState { - self.0.initialize(cx) - } - - fn layout( - &mut self, - _: &mut (), - element: &mut Self::ElementState, - cx: &mut ViewContext<()>, - ) -> LayoutId { - self.0.layout(element, cx) - } - - fn paint( - &mut self, - bounds: Bounds, - _: &mut (), - element: &mut AnyBox, - cx: &mut ViewContext<()>, - ) { - self.0.paint(bounds, element, cx) - } -} - impl std::fmt::Debug for AnyView { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.0.debug(f) @@ -376,7 +340,7 @@ impl Element for EraseAnyViewState { type ElementState = AnyBox; fn id(&self) -> Option { - Element::id(&self.view) + Some(self.view.0.entity_id().into()) } fn initialize( diff --git a/crates/workspace2/src/item.rs b/crates/workspace2/src/item.rs index eddc9200f9b48fcd2e7b1c35f34a1f16537d5c04..5995487f075ce28e65791041026eb4d0487039b8 100644 --- a/crates/workspace2/src/item.rs +++ b/crates/workspace2/src/item.rs @@ -5,7 +5,7 @@ // use crate::{AutosaveSetting, DelayedDebouncedEditAction, WorkspaceSettings}; use anyhow::Result; use client2::{ - proto::{self, PeerId, ViewId}, + proto::{self, PeerId}, Client, }; use settings2::Settings; @@ -98,12 +98,12 @@ pub struct BreadcrumbText { pub highlights: Option, HighlightStyle)>>, } -pub trait Item: EventEmitter + Sized { - // fn deactivated(&mut self, _: &mut ViewContext) {} - // fn workspace_deactivated(&mut self, _: &mut ViewContext) {} - // fn navigate(&mut self, _: Box, _: &mut ViewContext) -> bool { - // false - // } +pub trait Item: Render + EventEmitter + Send { + fn deactivated(&mut self, _: &mut ViewContext) {} + fn workspace_deactivated(&mut self, _: &mut ViewContext) {} + fn navigate(&mut self, _: Box, _: &mut ViewContext) -> bool { + false + } fn tab_tooltip_text(&self, _: &AppContext) -> Option { None } @@ -117,53 +117,53 @@ pub trait Item: EventEmitter + Sized { fn is_singleton(&self, _cx: &AppContext) -> bool { false } - // fn set_nav_history(&mut self, _: ItemNavHistory, _: &mut ViewContext) {} - fn clone_on_split(&self, _workspace_id: WorkspaceId, _: &mut ViewContext) -> Option + fn set_nav_history(&mut self, _: ItemNavHistory, _: &mut ViewContext) {} + fn clone_on_split( + &self, + _workspace_id: WorkspaceId, + _: &mut ViewContext, + ) -> Option> where Self: Sized, { None } - // fn is_dirty(&self, _: &AppContext) -> bool { - // false - // } - // fn has_conflict(&self, _: &AppContext) -> bool { - // false - // } - // fn can_save(&self, _cx: &AppContext) -> bool { - // false - // } - // fn save( - // &mut self, - // _project: Model, - // _cx: &mut ViewContext, - // ) -> Task> { - // unimplemented!("save() must be implemented if can_save() returns true") - // } - // fn save_as( - // &mut self, - // _project: Model, - // _abs_path: PathBuf, - // _cx: &mut ViewContext, - // ) -> Task> { - // unimplemented!("save_as() must be implemented if can_save() returns true") - // } - // fn reload( - // &mut self, - // _project: Model, - // _cx: &mut ViewContext, - // ) -> Task> { - // unimplemented!("reload() must be implemented if can_save() returns true") - // } + fn is_dirty(&self, _: &AppContext) -> bool { + false + } + fn has_conflict(&self, _: &AppContext) -> bool { + false + } + fn can_save(&self, _cx: &AppContext) -> bool { + false + } + fn save(&mut self, _project: Model, _cx: &mut ViewContext) -> Task> { + unimplemented!("save() must be implemented if can_save() returns true") + } + fn save_as( + &mut self, + _project: Model, + _abs_path: PathBuf, + _cx: &mut ViewContext, + ) -> Task> { + unimplemented!("save_as() must be implemented if can_save() returns true") + } + fn reload( + &mut self, + _project: Model, + _cx: &mut ViewContext, + ) -> Task> { + unimplemented!("reload() must be implemented if can_save() returns true") + } fn to_item_events(_event: &Self::Event) -> SmallVec<[ItemEvent; 2]> { SmallVec::new() } - // fn should_close_item_on_event(_: &Self::Event) -> bool { - // false - // } - // fn should_update_tab_on_event(_: &Self::Event) -> bool { - // false - // } + fn should_close_item_on_event(_: &Self::Event) -> bool { + false + } + fn should_update_tab_on_event(_: &Self::Event) -> bool { + false + } // fn act_as_type<'a>( // &'a self, @@ -178,41 +178,41 @@ pub trait Item: EventEmitter + Sized { // } // } - // fn as_searchable(&self, _: &View) -> Option> { - // None - // } + fn as_searchable(&self, _: &View) -> Option> { + None + } - // fn breadcrumb_location(&self) -> ToolbarItemLocation { - // ToolbarItemLocation::Hidden - // } + fn breadcrumb_location(&self) -> ToolbarItemLocation { + ToolbarItemLocation::Hidden + } - // fn breadcrumbs(&self, _theme: &Theme, _cx: &AppContext) -> Option> { - // None - // } + fn breadcrumbs(&self, _theme: &Theme, _cx: &AppContext) -> Option> { + None + } - // fn added_to_workspace(&mut self, _workspace: &mut Workspace, _cx: &mut ViewContext) {} + fn added_to_workspace(&mut self, _workspace: &mut Workspace, _cx: &mut ViewContext) {} - // fn serialized_item_kind() -> Option<&'static str> { - // None - // } + fn serialized_item_kind() -> Option<&'static str> { + None + } - // fn deserialize( - // _project: Model, - // _workspace: WeakViewHandle, - // _workspace_id: WorkspaceId, - // _item_id: ItemId, - // _cx: &mut ViewContext, - // ) -> Task>> { - // unimplemented!( - // "deserialize() must be implemented if serialized_item_kind() returns Some(_)" - // ) - // } - // fn show_toolbar(&self) -> bool { - // true - // } - // fn pixel_position_of_cursor(&self, _: &AppContext) -> Option { - // None - // } + fn deserialize( + _project: Model, + _workspace: WeakView, + _workspace_id: WorkspaceId, + _item_id: ItemId, + _cx: &mut ViewContext, + ) -> Task>> { + unimplemented!( + "deserialize() must be implemented if serialized_item_kind() returns Some(_)" + ) + } + fn show_toolbar(&self) -> bool { + true + } + fn pixel_position_of_cursor(&self, _: &AppContext) -> Option> { + None + } } use std::{ @@ -229,18 +229,19 @@ use std::{ }; use gpui2::{ - AnyElement, AnyWindowHandle, AppContext, EventEmitter, HighlightStyle, Model, Pixels, Point, - SharedString, Task, View, ViewContext, WindowContext, + AnyElement, AnyView, AnyWindowHandle, AppContext, EventEmitter, HighlightStyle, Model, Pixels, + Point, Render, SharedString, Task, View, ViewContext, WeakView, WindowContext, }; use project2::{Project, ProjectEntryId, ProjectPath}; use smallvec::SmallVec; use crate::{ pane::{self, Pane}, + persistence::model::ItemId, searchable::SearchableItemHandle, workspace_settings::{AutosaveSetting, WorkspaceSettings}, - DelayedDebouncedEditAction, FollowableItemBuilders, ToolbarItemLocation, Workspace, - WorkspaceId, + DelayedDebouncedEditAction, FollowableItemBuilders, ItemNavHistory, ToolbarItemLocation, + ViewId, Workspace, WorkspaceId, }; pub trait ItemHandle: 'static + Send { @@ -275,7 +276,7 @@ pub trait ItemHandle: 'static + Send { fn navigate(&self, data: Box, cx: &mut WindowContext) -> bool; fn id(&self) -> usize; fn window(&self) -> AnyWindowHandle; - // fn as_any(&self) -> &AnyView; todo!() + fn to_any(&self) -> AnyView; fn is_dirty(&self, cx: &AppContext) -> bool; fn has_conflict(&self, cx: &AppContext) -> bool; fn can_save(&self, cx: &AppContext) -> bool; @@ -302,10 +303,10 @@ pub trait ItemHandle: 'static + Send { fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option>; } -pub trait WeakItemHandle { +pub trait WeakItemHandle: Send { fn id(&self) -> usize; fn window(&self) -> AnyWindowHandle; - fn upgrade(&self, cx: &AppContext) -> Option>; + fn upgrade(&self) -> Option>; } // todo!() @@ -399,10 +400,8 @@ impl ItemHandle for View { workspace_id: WorkspaceId, cx: &mut WindowContext, ) -> Option> { - self.update(cx, |item, cx| { - cx.add_option_view(|cx| item.clone_on_split(workspace_id, cx)) - }) - .map(|handle| Box::new(handle) as Box) + self.update(cx, |item, cx| item.clone_on_split(workspace_id, cx)) + .map(|handle| Box::new(handle) as Box) } fn added_to_pane( @@ -447,7 +446,7 @@ impl ItemHandle for View { let pane = if let Some(pane) = workspace .panes_by_item .get(&item.id()) - .and_then(|pane| pane.upgrade(cx)) + .and_then(|pane| pane.upgrade()) { pane } else { @@ -570,10 +569,9 @@ impl ItemHandle for View { // AnyViewHandle::window(self) } - // todo!() - // fn as_any(&self) -> &AnyViewHandle { - // self - // } + fn to_any(&self) -> AnyView { + self.clone().into_any() + } fn is_dirty(&self, cx: &AppContext) -> bool { self.read(cx).is_dirty(cx) @@ -652,17 +650,17 @@ impl ItemHandle for View { } } -// impl From> for AnyViewHandle { -// fn from(val: Box) -> Self { -// val.as_any().clone() -// } -// } +impl From> for AnyView { + fn from(val: Box) -> Self { + val.to_any() + } +} -// impl From<&Box> for AnyViewHandle { -// fn from(val: &Box) -> Self { -// val.as_any().clone() -// } -// } +impl From<&Box> for AnyView { + fn from(val: &Box) -> Self { + val.to_any() + } +} impl Clone for Box { fn clone(&self) -> Box { @@ -670,19 +668,19 @@ impl Clone for Box { } } -// impl WeakItemHandle for WeakViewHandle { -// fn id(&self) -> usize { -// self.id() -// } +impl WeakItemHandle for WeakView { + fn id(&self) -> usize { + self.id() + } -// fn window(&self) -> AnyWindowHandle { -// self.window() -// } + fn window(&self) -> AnyWindowHandle { + self.window() + } -// fn upgrade(&self, cx: &AppContext) -> Option> { -// self.upgrade(cx).map(|v| Box::new(v) as Box) -// } -// } + fn upgrade(&self) -> Option> { + self.upgrade().map(|v| Box::new(v) as Box) + } +} pub trait ProjectItem: Item { type Item: project2::Item; diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index e0eb1b7ec248a25dd0129a9c52b82bac1ad40366..ca42b0ef2e6c88145b2f16ad76a0cee1ce4e52c6 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1,48 +1,20 @@ // mod dragged_item_receiver; -// use super::{ItemHandle, SplitDirection}; -// pub use crate::toolbar::Toolbar; -// use crate::{ -// item::{ItemSettings, WeakItemHandle}, -// notify_of_new_dock, AutosaveSetting, Item, NewCenterTerminal, NewFile, NewSearch, ToggleZoom, -// Workspace, WorkspaceSettings, -// }; -// use anyhow::Result; -// use collections::{HashMap, HashSet, VecDeque}; -// // use context_menu::{ContextMenu, ContextMenuItem}; - -// use dragged_item_receiver::dragged_item_receiver; -// use fs2::repository::GitFileStatus; -// use futures::StreamExt; -// use gpui2::{ -// actions, -// elements::*, -// geometry::{ -// rect::RectF, -// vector::{vec2f, Vector2F}, -// }, -// impl_actions, -// keymap_matcher::KeymapContext, -// platform::{CursorStyle, MouseButton, NavigationDirection, PromptLevel}, -// Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext, -// ModelHandle, MouseRegion, Quad, Task, View, ViewContext, ViewHandle, WeakViewHandle, -// WindowContext, -// }; -// use project2::{Project, ProjectEntryId, ProjectPath}; +use crate::{ + item::{Item, ItemHandle, WeakItemHandle}, + SplitDirection, Workspace, +}; +use collections::{HashMap, VecDeque}; +use gpui2::{EventEmitter, Model, View, ViewContext, WeakView}; +use parking_lot::Mutex; +use project2::{Project, ProjectEntryId, ProjectPath}; use serde::Deserialize; -// use std::{ -// any::Any, -// cell::RefCell, -// cmp, mem, -// path::{Path, PathBuf}, -// rc::Rc, -// sync::{ -// atomic::{AtomicUsize, Ordering}, -// Arc, -// }, -// }; -// use theme2::{Theme, ThemeSettings}; -// use util::truncate_and_remove_front; +use std::{ + any::Any, + cmp, fmt, mem, + path::PathBuf, + sync::{atomic::AtomicUsize, Arc}, +}; #[derive(PartialEq, Clone, Copy, Deserialize, Debug)] #[serde(rename_all = "camelCase")] @@ -69,19 +41,19 @@ pub enum SaveIntent { // #[derive(Clone, PartialEq)] // pub struct CloseItemById { // pub item_id: usize, -// pub pane: WeakViewHandle, +// pub pane: WeakView, // } // #[derive(Clone, PartialEq)] // pub struct CloseItemsToTheLeftById { // pub item_id: usize, -// pub pane: WeakViewHandle, +// pub pane: WeakView, // } // #[derive(Clone, PartialEq)] // pub struct CloseItemsToTheRightById { // pub item_id: usize, -// pub pane: WeakViewHandle, +// pub pane: WeakView, // } // #[derive(Clone, PartialEq, Debug, Deserialize, Default)] @@ -146,7 +118,6 @@ pub enum SaveIntent { // cx.add_action(|pane: &mut Pane, _: &SplitDown, cx| pane.split(SplitDirection::Down, cx)); // } -#[derive(Debug)] pub enum Event { AddItem { item: Box }, ActivateItem { local: bool }, @@ -159,35 +130,44 @@ pub enum Event { ZoomOut, } -use crate::{ - item::{ItemHandle, WeakItemHandle}, - SplitDirection, -}; -use collections::{HashMap, VecDeque}; -use gpui2::{Handle, ViewContext, WeakView}; -use project2::{Project, ProjectEntryId, ProjectPath}; -use std::{ - any::Any, - cell::RefCell, - cmp, mem, - path::PathBuf, - rc::Rc, - sync::{atomic::AtomicUsize, Arc}, -}; +impl fmt::Debug for Event { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Event::AddItem { item } => f.debug_struct("AddItem").field("item", &item.id()).finish(), + Event::ActivateItem { local } => f + .debug_struct("ActivateItem") + .field("local", local) + .finish(), + Event::Remove => f.write_str("Remove"), + Event::RemoveItem { item_id } => f + .debug_struct("RemoveItem") + .field("item_id", item_id) + .finish(), + Event::Split(direction) => f + .debug_struct("Split") + .field("direction", direction) + .finish(), + Event::ChangeItemTitle => f.write_str("ChangeItemTitle"), + Event::Focus => f.write_str("Focus"), + Event::ZoomIn => f.write_str("ZoomIn"), + Event::ZoomOut => f.write_str("ZoomOut"), + } + } +} pub struct Pane { items: Vec>, - // activation_history: Vec, + activation_history: Vec, // zoomed: bool, - // active_item_index: usize, + active_item_index: usize, // last_focused_view_by_item: HashMap, // autoscroll: bool, nav_history: NavHistory, - // toolbar: ViewHandle, + toolbar: View, // tab_bar_context_menu: TabBarContextMenu, // tab_context_menu: ViewHandle, - // workspace: WeakViewHandle, - project: Handle, + // workspace: WeakView, + project: Model, // has_focus: bool, // can_drop: Rc, &WindowContext) -> bool>, // can_split: bool, @@ -196,11 +176,11 @@ pub struct Pane { pub struct ItemNavHistory { history: NavHistory, - item: Rc, + item: Arc, } #[derive(Clone)] -pub struct NavHistory(Rc>); +pub struct NavHistory(Arc>); struct NavHistoryState { mode: NavigationMode, @@ -229,14 +209,14 @@ impl Default for NavigationMode { } pub struct NavigationEntry { - pub item: Rc, + pub item: Arc, pub data: Option>, pub timestamp: usize, } // pub struct DraggedItem { // pub handle: Box, -// pub pane: WeakViewHandle, +// pub pane: WeakView, // } // pub enum ReorderBehavior { @@ -315,108 +295,113 @@ pub struct NavigationEntry { // .into_any_named("nav button") // } -impl Pane { - // pub fn new( - // workspace: WeakViewHandle, - // project: ModelHandle, - // next_timestamp: Arc, - // cx: &mut ViewContext, - // ) -> Self { - // let pane_view_id = cx.view_id(); - // let handle = cx.weak_handle(); - // let context_menu = cx.add_view(|cx| ContextMenu::new(pane_view_id, cx)); - // context_menu.update(cx, |menu, _| { - // menu.set_position_mode(OverlayPositionMode::Local) - // }); - - // Self { - // items: Vec::new(), - // activation_history: Vec::new(), - // zoomed: false, - // active_item_index: 0, - // last_focused_view_by_item: Default::default(), - // autoscroll: false, - // nav_history: NavHistory(Rc::new(RefCell::new(NavHistoryState { - // mode: NavigationMode::Normal, - // backward_stack: Default::default(), - // forward_stack: Default::default(), - // closed_stack: Default::default(), - // paths_by_item: Default::default(), - // pane: handle.clone(), - // next_timestamp, - // }))), - // toolbar: cx.add_view(|_| Toolbar::new()), - // tab_bar_context_menu: TabBarContextMenu { - // kind: TabBarContextMenuKind::New, - // handle: context_menu, - // }, - // tab_context_menu: cx.add_view(|cx| ContextMenu::new(pane_view_id, cx)), - // workspace, - // project, - // has_focus: false, - // can_drop: Rc::new(|_, _| true), - // can_split: true, - // render_tab_bar_buttons: Rc::new(move |pane, cx| { - // Flex::row() - // // New menu - // .with_child(Self::render_tab_bar_button( - // 0, - // "icons/plus.svg", - // false, - // Some(("New...".into(), None)), - // cx, - // |pane, cx| pane.deploy_new_menu(cx), - // |pane, cx| { - // pane.tab_bar_context_menu - // .handle - // .update(cx, |menu, _| menu.delay_cancel()) - // }, - // pane.tab_bar_context_menu - // .handle_if_kind(TabBarContextMenuKind::New), - // )) - // .with_child(Self::render_tab_bar_button( - // 1, - // "icons/split.svg", - // false, - // Some(("Split Pane".into(), None)), - // cx, - // |pane, cx| pane.deploy_split_menu(cx), - // |pane, cx| { - // pane.tab_bar_context_menu - // .handle - // .update(cx, |menu, _| menu.delay_cancel()) - // }, - // pane.tab_bar_context_menu - // .handle_if_kind(TabBarContextMenuKind::Split), - // )) - // .with_child({ - // let icon_path; - // let tooltip_label; - // if pane.is_zoomed() { - // icon_path = "icons/minimize.svg"; - // tooltip_label = "Zoom In"; - // } else { - // icon_path = "icons/maximize.svg"; - // tooltip_label = "Zoom In"; - // } +impl EventEmitter for Pane { + type Event = Event; +} - // Pane::render_tab_bar_button( - // 2, - // icon_path, - // pane.is_zoomed(), - // Some((tooltip_label, Some(Box::new(ToggleZoom)))), - // cx, - // move |pane, cx| pane.toggle_zoom(&Default::default(), cx), - // move |_, _| {}, - // None, - // ) - // }) - // .into_any() - // }), - // } - // } +impl Pane { + pub fn new( + workspace: WeakView, + project: Model, + next_timestamp: Arc, + cx: &mut ViewContext, + ) -> Self { + // todo!("context menu") + // let pane_view_id = cx.view_id(); + // let context_menu = cx.add_view(|cx| ContextMenu::new(pane_view_id, cx)); + // context_menu.update(cx, |menu, _| { + // menu.set_position_mode(OverlayPositionMode::Local) + // }); + + let handle = cx.view(); + Self { + items: Vec::new(), + activation_history: Vec::new(), + // zoomed: false, + active_item_index: 0, + // last_focused_view_by_item: Default::default(), + // autoscroll: false, + nav_history: NavHistory(Arc::new(Mutex::new(NavHistoryState { + mode: NavigationMode::Normal, + backward_stack: Default::default(), + forward_stack: Default::default(), + closed_stack: Default::default(), + paths_by_item: Default::default(), + pane: handle.clone(), + next_timestamp, + }))), + // toolbar: cx.add_view(|_| Toolbar::new()), + // tab_bar_context_menu: TabBarContextMenu { + // kind: TabBarContextMenuKind::New, + // handle: context_menu, + // }, + // tab_context_menu: cx.add_view(|cx| ContextMenu::new(pane_view_id, cx)), + // workspace, + project, + // has_focus: false, + // can_drop: Rc::new(|_, _| true), + // can_split: true, + // render_tab_bar_buttons: Rc::new(move |pane, cx| { + // Flex::row() + // // New menu + // .with_child(Self::render_tab_bar_button( + // 0, + // "icons/plus.svg", + // false, + // Some(("New...".into(), None)), + // cx, + // |pane, cx| pane.deploy_new_menu(cx), + // |pane, cx| { + // pane.tab_bar_context_menu + // .handle + // .update(cx, |menu, _| menu.delay_cancel()) + // }, + // pane.tab_bar_context_menu + // .handle_if_kind(TabBarContextMenuKind::New), + // )) + // .with_child(Self::render_tab_bar_button( + // 1, + // "icons/split.svg", + // false, + // Some(("Split Pane".into(), None)), + // cx, + // |pane, cx| pane.deploy_split_menu(cx), + // |pane, cx| { + // pane.tab_bar_context_menu + // .handle + // .update(cx, |menu, _| menu.delay_cancel()) + // }, + // pane.tab_bar_context_menu + // .handle_if_kind(TabBarContextMenuKind::Split), + // )) + // .with_child({ + // let icon_path; + // let tooltip_label; + // if pane.is_zoomed() { + // icon_path = "icons/minimize.svg"; + // tooltip_label = "Zoom In"; + // } else { + // icon_path = "icons/maximize.svg"; + // tooltip_label = "Zoom In"; + // } + + // Pane::render_tab_bar_button( + // 2, + // icon_path, + // pane.is_zoomed(), + // Some((tooltip_label, Some(Box::new(ToggleZoom)))), + // cx, + // move |pane, cx| pane.toggle_zoom(&Default::default(), cx), + // move |_, _| {}, + // None, + // ) + // }) + // .into_any() + // }), + } + } - // pub(crate) fn workspace(&self) -> &WeakViewHandle { + // pub(crate) fn workspace(&self) -> &WeakView { // &self.workspace // } @@ -455,12 +440,12 @@ impl Pane { // cx.notify(); // } - // pub fn nav_history_for_item(&self, item: &ViewHandle) -> ItemNavHistory { - // ItemNavHistory { - // history: self.nav_history.clone(), - // item: Rc::new(item.downgrade()), - // } - // } + pub fn nav_history_for_item(&self, item: &View) -> ItemNavHistory { + ItemNavHistory { + history: self.nav_history.clone(), + item: Arc::new(item.downgrade()), + } + } // pub fn nav_history(&self) -> &NavHistory { // &self.nav_history @@ -532,7 +517,7 @@ impl Pane { let abs_path = project.absolute_path(&project_path, cx); self.nav_history .0 - .borrow_mut() + .lock() .paths_by_item .insert(item.id(), (project_path, abs_path)); } @@ -1071,8 +1056,8 @@ impl Pane { // } // pub async fn save_item( - // project: ModelHandle, - // pane: &WeakViewHandle, + // project: Model, + // pane: &WeakView, // item_ix: usize, // item: &dyn ItemHandle, // save_intent: SaveIntent, @@ -1178,7 +1163,7 @@ impl Pane { // pub fn autosave_item( // item: &dyn ItemHandle, - // project: ModelHandle, + // project: Model, // cx: &mut WindowContext, // ) -> Task> { // if Self::can_autosave_item(item, cx) { @@ -1340,15 +1325,15 @@ impl Pane { // Some(()) // } - // fn update_toolbar(&mut self, cx: &mut ViewContext) { - // let active_item = self - // .items - // .get(self.active_item_index) - // .map(|item| item.as_ref()); - // self.toolbar.update(cx, |toolbar, cx| { - // toolbar.set_active_item(active_item, cx); - // }); - // } + fn update_toolbar(&mut self, cx: &mut ViewContext) { + let active_item = self + .items + .get(self.active_item_index) + .map(|item| item.as_ref()); + self.toolbar.update(cx, |toolbar, cx| { + toolbar.set_active_item(active_item, cx); + }); + } // fn render_tabs(&mut self, cx: &mut ViewContext) -> impl Element { // let theme = theme::current(cx).clone(); @@ -1544,7 +1529,7 @@ impl Pane { // fn render_tab( // item: &Box, - // pane: WeakViewHandle, + // pane: WeakView, // first: bool, // detail: Option, // hovered: bool, @@ -1557,7 +1542,7 @@ impl Pane { // fn render_dragged_tab( // item: &Box, - // pane: WeakViewHandle, + // pane: WeakView, // first: bool, // detail: Option, // hovered: bool, @@ -1571,7 +1556,7 @@ impl Pane { // fn render_tab_with_title( // title: AnyElement, // item: &Box, - // pane: WeakViewHandle, + // pane: WeakView, // first: bool, // hovered: bool, // tab_style: &theme::Tab, @@ -1736,387 +1721,387 @@ impl Pane { // pub fn is_zoomed(&self) -> bool { // self.zoomed // } - // } - - // impl Entity for Pane { - // type Event = Event; - // } - - // impl View for Pane { - // fn ui_name() -> &'static str { - // "Pane" - // } - - // fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - // enum MouseNavigationHandler {} - - // MouseEventHandler::new::(0, cx, |_, cx| { - // let active_item_index = self.active_item_index; - - // if let Some(active_item) = self.active_item() { - // Flex::column() - // .with_child({ - // let theme = theme::current(cx).clone(); - - // let mut stack = Stack::new(); - - // enum TabBarEventHandler {} - // stack.add_child( - // MouseEventHandler::new::(0, cx, |_, _| { - // Empty::new() - // .contained() - // .with_style(theme.workspace.tab_bar.container) - // }) - // .on_down( - // MouseButton::Left, - // move |_, this, cx| { - // this.activate_item(active_item_index, true, true, cx); - // }, - // ), - // ); - // let tooltip_style = theme.tooltip.clone(); - // let tab_bar_theme = theme.workspace.tab_bar.clone(); - - // let nav_button_height = tab_bar_theme.height; - // let button_style = tab_bar_theme.nav_button; - // let border_for_nav_buttons = tab_bar_theme - // .tab_style(false, false) - // .container - // .border - // .clone(); +} - // let mut tab_row = Flex::row() - // .with_child(nav_button( - // "icons/arrow_left.svg", - // button_style.clone(), - // nav_button_height, - // tooltip_style.clone(), - // self.can_navigate_backward(), - // { - // move |pane, cx| { - // if let Some(workspace) = pane.workspace.upgrade(cx) { - // let pane = cx.weak_handle(); - // cx.window_context().defer(move |cx| { - // workspace.update(cx, |workspace, cx| { - // workspace - // .go_back(pane, cx) - // .detach_and_log_err(cx) - // }) - // }) - // } - // } - // }, - // super::GoBack, - // "Go Back", - // cx, - // )) - // .with_child( - // nav_button( - // "icons/arrow_right.svg", - // button_style.clone(), - // nav_button_height, - // tooltip_style, - // self.can_navigate_forward(), - // { - // move |pane, cx| { - // if let Some(workspace) = pane.workspace.upgrade(cx) { - // let pane = cx.weak_handle(); - // cx.window_context().defer(move |cx| { - // workspace.update(cx, |workspace, cx| { - // workspace - // .go_forward(pane, cx) - // .detach_and_log_err(cx) - // }) - // }) - // } - // } - // }, - // super::GoForward, - // "Go Forward", - // cx, - // ) - // .contained() - // .with_border(border_for_nav_buttons), - // ) - // .with_child(self.render_tabs(cx).flex(1., true).into_any_named("tabs")); - - // if self.has_focus { - // let render_tab_bar_buttons = self.render_tab_bar_buttons.clone(); - // tab_row.add_child( - // (render_tab_bar_buttons)(self, cx) - // .contained() - // .with_style(theme.workspace.tab_bar.pane_button_container) - // .flex(1., false) - // .into_any(), - // ) - // } +// impl Entity for Pane { +// type Event = Event; +// } - // stack.add_child(tab_row); - // stack - // .constrained() - // .with_height(theme.workspace.tab_bar.height) - // .flex(1., false) - // .into_any_named("tab bar") - // }) - // .with_child({ - // enum PaneContentTabDropTarget {} - // dragged_item_receiver::( - // self, - // 0, - // self.active_item_index + 1, - // !self.can_split, - // if self.can_split { Some(100.) } else { None }, - // cx, - // { - // let toolbar = self.toolbar.clone(); - // let toolbar_hidden = toolbar.read(cx).hidden(); - // move |_, cx| { - // Flex::column() - // .with_children( - // (!toolbar_hidden) - // .then(|| ChildView::new(&toolbar, cx).expanded()), - // ) - // .with_child( - // ChildView::new(active_item.as_any(), cx).flex(1., true), - // ) - // } - // }, - // ) - // .flex(1., true) - // }) - // .with_child(ChildView::new(&self.tab_context_menu, cx)) - // .into_any() - // } else { - // enum EmptyPane {} - // let theme = theme::current(cx).clone(); +// impl View for Pane { +// fn ui_name() -> &'static str { +// "Pane" +// } - // dragged_item_receiver::(self, 0, 0, false, None, cx, |_, cx| { - // self.render_blank_pane(&theme, cx) - // }) - // .on_down(MouseButton::Left, |_, _, cx| { - // cx.focus_parent(); - // }) - // .into_any() - // } - // }) - // .on_down( - // MouseButton::Navigate(NavigationDirection::Back), - // move |_, pane, cx| { - // if let Some(workspace) = pane.workspace.upgrade(cx) { - // let pane = cx.weak_handle(); - // cx.window_context().defer(move |cx| { - // workspace.update(cx, |workspace, cx| { - // workspace.go_back(pane, cx).detach_and_log_err(cx) - // }) - // }) - // } - // }, - // ) - // .on_down(MouseButton::Navigate(NavigationDirection::Forward), { - // move |_, pane, cx| { - // if let Some(workspace) = pane.workspace.upgrade(cx) { - // let pane = cx.weak_handle(); - // cx.window_context().defer(move |cx| { - // workspace.update(cx, |workspace, cx| { - // workspace.go_forward(pane, cx).detach_and_log_err(cx) - // }) - // }) - // } - // } - // }) - // .into_any_named("pane") - // } +// fn render(&mut self, cx: &mut ViewContext) -> AnyElement { +// enum MouseNavigationHandler {} + +// MouseEventHandler::new::(0, cx, |_, cx| { +// let active_item_index = self.active_item_index; + +// if let Some(active_item) = self.active_item() { +// Flex::column() +// .with_child({ +// let theme = theme::current(cx).clone(); + +// let mut stack = Stack::new(); + +// enum TabBarEventHandler {} +// stack.add_child( +// MouseEventHandler::new::(0, cx, |_, _| { +// Empty::new() +// .contained() +// .with_style(theme.workspace.tab_bar.container) +// }) +// .on_down( +// MouseButton::Left, +// move |_, this, cx| { +// this.activate_item(active_item_index, true, true, cx); +// }, +// ), +// ); +// let tooltip_style = theme.tooltip.clone(); +// let tab_bar_theme = theme.workspace.tab_bar.clone(); + +// let nav_button_height = tab_bar_theme.height; +// let button_style = tab_bar_theme.nav_button; +// let border_for_nav_buttons = tab_bar_theme +// .tab_style(false, false) +// .container +// .border +// .clone(); + +// let mut tab_row = Flex::row() +// .with_child(nav_button( +// "icons/arrow_left.svg", +// button_style.clone(), +// nav_button_height, +// tooltip_style.clone(), +// self.can_navigate_backward(), +// { +// move |pane, cx| { +// if let Some(workspace) = pane.workspace.upgrade(cx) { +// let pane = cx.weak_handle(); +// cx.window_context().defer(move |cx| { +// workspace.update(cx, |workspace, cx| { +// workspace +// .go_back(pane, cx) +// .detach_and_log_err(cx) +// }) +// }) +// } +// } +// }, +// super::GoBack, +// "Go Back", +// cx, +// )) +// .with_child( +// nav_button( +// "icons/arrow_right.svg", +// button_style.clone(), +// nav_button_height, +// tooltip_style, +// self.can_navigate_forward(), +// { +// move |pane, cx| { +// if let Some(workspace) = pane.workspace.upgrade(cx) { +// let pane = cx.weak_handle(); +// cx.window_context().defer(move |cx| { +// workspace.update(cx, |workspace, cx| { +// workspace +// .go_forward(pane, cx) +// .detach_and_log_err(cx) +// }) +// }) +// } +// } +// }, +// super::GoForward, +// "Go Forward", +// cx, +// ) +// .contained() +// .with_border(border_for_nav_buttons), +// ) +// .with_child(self.render_tabs(cx).flex(1., true).into_any_named("tabs")); + +// if self.has_focus { +// let render_tab_bar_buttons = self.render_tab_bar_buttons.clone(); +// tab_row.add_child( +// (render_tab_bar_buttons)(self, cx) +// .contained() +// .with_style(theme.workspace.tab_bar.pane_button_container) +// .flex(1., false) +// .into_any(), +// ) +// } + +// stack.add_child(tab_row); +// stack +// .constrained() +// .with_height(theme.workspace.tab_bar.height) +// .flex(1., false) +// .into_any_named("tab bar") +// }) +// .with_child({ +// enum PaneContentTabDropTarget {} +// dragged_item_receiver::( +// self, +// 0, +// self.active_item_index + 1, +// !self.can_split, +// if self.can_split { Some(100.) } else { None }, +// cx, +// { +// let toolbar = self.toolbar.clone(); +// let toolbar_hidden = toolbar.read(cx).hidden(); +// move |_, cx| { +// Flex::column() +// .with_children( +// (!toolbar_hidden) +// .then(|| ChildView::new(&toolbar, cx).expanded()), +// ) +// .with_child( +// ChildView::new(active_item.as_any(), cx).flex(1., true), +// ) +// } +// }, +// ) +// .flex(1., true) +// }) +// .with_child(ChildView::new(&self.tab_context_menu, cx)) +// .into_any() +// } else { +// enum EmptyPane {} +// let theme = theme::current(cx).clone(); + +// dragged_item_receiver::(self, 0, 0, false, None, cx, |_, cx| { +// self.render_blank_pane(&theme, cx) +// }) +// .on_down(MouseButton::Left, |_, _, cx| { +// cx.focus_parent(); +// }) +// .into_any() +// } +// }) +// .on_down( +// MouseButton::Navigate(NavigationDirection::Back), +// move |_, pane, cx| { +// if let Some(workspace) = pane.workspace.upgrade(cx) { +// let pane = cx.weak_handle(); +// cx.window_context().defer(move |cx| { +// workspace.update(cx, |workspace, cx| { +// workspace.go_back(pane, cx).detach_and_log_err(cx) +// }) +// }) +// } +// }, +// ) +// .on_down(MouseButton::Navigate(NavigationDirection::Forward), { +// move |_, pane, cx| { +// if let Some(workspace) = pane.workspace.upgrade(cx) { +// let pane = cx.weak_handle(); +// cx.window_context().defer(move |cx| { +// workspace.update(cx, |workspace, cx| { +// workspace.go_forward(pane, cx).detach_and_log_err(cx) +// }) +// }) +// } +// } +// }) +// .into_any_named("pane") +// } - // fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext) { - // if !self.has_focus { - // self.has_focus = true; - // cx.emit(Event::Focus); - // cx.notify(); - // } +// fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext) { +// 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); - // }); +// 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()); - // } - // } +// 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()); - // } - // } - // } +// 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.has_focus = false; - // self.toolbar.update(cx, |toolbar, cx| { - // toolbar.focus_changed(false, cx); - // }); - // cx.notify(); - // } +// fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { +// 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); - // } - // } +// fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) { +// Self::reset_to_default_keymap_context(keymap); +// } +// } - // impl ItemNavHistory { - // pub fn push(&mut self, data: Option, cx: &mut WindowContext) { - // self.history.push(data, self.item.clone(), cx); - // } +impl ItemNavHistory { + pub fn push(&mut self, data: Option, cx: &mut WindowContext) { + self.history.push(data, self.item.clone(), cx); + } - // pub fn pop_backward(&mut self, cx: &mut WindowContext) -> Option { - // self.history.pop(NavigationMode::GoingBack, cx) - // } + pub fn pop_backward(&mut self, cx: &mut WindowContext) -> Option { + self.history.pop(NavigationMode::GoingBack, cx) + } - // pub fn pop_forward(&mut self, cx: &mut WindowContext) -> Option { - // self.history.pop(NavigationMode::GoingForward, cx) - // } - // } + pub fn pop_forward(&mut self, cx: &mut WindowContext) -> Option { + self.history.pop(NavigationMode::GoingForward, cx) + } +} - // impl NavHistory { - // pub fn for_each_entry( - // &self, - // cx: &AppContext, - // mut f: impl FnMut(&NavigationEntry, (ProjectPath, Option)), - // ) { - // let borrowed_history = self.0.borrow(); - // borrowed_history - // .forward_stack - // .iter() - // .chain(borrowed_history.backward_stack.iter()) - // .chain(borrowed_history.closed_stack.iter()) - // .for_each(|entry| { - // if let Some(project_and_abs_path) = - // borrowed_history.paths_by_item.get(&entry.item.id()) - // { - // f(entry, project_and_abs_path.clone()); - // } else if let Some(item) = entry.item.upgrade(cx) { - // if let Some(path) = item.project_path(cx) { - // f(entry, (path, None)); - // } - // } - // }) - // } +impl NavHistory { + pub fn for_each_entry( + &self, + cx: &AppContext, + mut f: impl FnMut(&NavigationEntry, (ProjectPath, Option)), + ) { + let borrowed_history = self.0.borrow(); + borrowed_history + .forward_stack + .iter() + .chain(borrowed_history.backward_stack.iter()) + .chain(borrowed_history.closed_stack.iter()) + .for_each(|entry| { + if let Some(project_and_abs_path) = + borrowed_history.paths_by_item.get(&entry.item.id()) + { + f(entry, project_and_abs_path.clone()); + } else if let Some(item) = entry.item.upgrade(cx) { + if let Some(path) = item.project_path(cx) { + f(entry, (path, None)); + } + } + }) + } - // pub fn set_mode(&mut self, mode: NavigationMode) { - // self.0.borrow_mut().mode = mode; - // } + pub fn set_mode(&mut self, mode: NavigationMode) { + self.0.borrow_mut().mode = mode; + } pub fn mode(&self) -> NavigationMode { self.0.borrow().mode } - // pub fn disable(&mut self) { - // self.0.borrow_mut().mode = NavigationMode::Disabled; - // } + pub fn disable(&mut self) { + self.0.borrow_mut().mode = NavigationMode::Disabled; + } - // pub fn enable(&mut self) { - // self.0.borrow_mut().mode = NavigationMode::Normal; - // } + pub fn enable(&mut self) { + self.0.borrow_mut().mode = NavigationMode::Normal; + } - // pub fn pop(&mut self, mode: NavigationMode, cx: &mut WindowContext) -> Option { - // let mut state = self.0.borrow_mut(); - // let entry = match mode { - // NavigationMode::Normal | NavigationMode::Disabled | NavigationMode::ClosingItem => { - // return None - // } - // NavigationMode::GoingBack => &mut state.backward_stack, - // NavigationMode::GoingForward => &mut state.forward_stack, - // NavigationMode::ReopeningClosedItem => &mut state.closed_stack, - // } - // .pop_back(); - // if entry.is_some() { - // state.did_update(cx); - // } - // entry - // } + pub fn pop(&mut self, mode: NavigationMode, cx: &mut WindowContext) -> Option { + let mut state = self.0.borrow_mut(); + let entry = match mode { + NavigationMode::Normal | NavigationMode::Disabled | NavigationMode::ClosingItem => { + return None + } + NavigationMode::GoingBack => &mut state.backward_stack, + NavigationMode::GoingForward => &mut state.forward_stack, + NavigationMode::ReopeningClosedItem => &mut state.closed_stack, + } + .pop_back(); + if entry.is_some() { + state.did_update(cx); + } + entry + } - // pub fn push( - // &mut self, - // data: Option, - // item: Rc, - // cx: &mut WindowContext, - // ) { - // let state = &mut *self.0.borrow_mut(); - // match state.mode { - // NavigationMode::Disabled => {} - // NavigationMode::Normal | NavigationMode::ReopeningClosedItem => { - // if state.backward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN { - // state.backward_stack.pop_front(); - // } - // state.backward_stack.push_back(NavigationEntry { - // item, - // data: data.map(|data| Box::new(data) as Box), - // timestamp: state.next_timestamp.fetch_add(1, Ordering::SeqCst), - // }); - // state.forward_stack.clear(); - // } - // NavigationMode::GoingBack => { - // if state.forward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN { - // state.forward_stack.pop_front(); - // } - // state.forward_stack.push_back(NavigationEntry { - // item, - // data: data.map(|data| Box::new(data) as Box), - // timestamp: state.next_timestamp.fetch_add(1, Ordering::SeqCst), - // }); - // } - // NavigationMode::GoingForward => { - // if state.backward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN { - // state.backward_stack.pop_front(); - // } - // state.backward_stack.push_back(NavigationEntry { - // item, - // data: data.map(|data| Box::new(data) as Box), - // timestamp: state.next_timestamp.fetch_add(1, Ordering::SeqCst), - // }); - // } - // NavigationMode::ClosingItem => { - // if state.closed_stack.len() >= MAX_NAVIGATION_HISTORY_LEN { - // state.closed_stack.pop_front(); - // } - // state.closed_stack.push_back(NavigationEntry { - // item, - // data: data.map(|data| Box::new(data) as Box), - // timestamp: state.next_timestamp.fetch_add(1, Ordering::SeqCst), - // }); - // } - // } - // state.did_update(cx); - // } + pub fn push( + &mut self, + data: Option, + item: Rc, + cx: &mut WindowContext, + ) { + let state = &mut *self.0.borrow_mut(); + match state.mode { + NavigationMode::Disabled => {} + NavigationMode::Normal | NavigationMode::ReopeningClosedItem => { + if state.backward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN { + state.backward_stack.pop_front(); + } + state.backward_stack.push_back(NavigationEntry { + item, + data: data.map(|data| Box::new(data) as Box), + timestamp: state.next_timestamp.fetch_add(1, Ordering::SeqCst), + }); + state.forward_stack.clear(); + } + NavigationMode::GoingBack => { + if state.forward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN { + state.forward_stack.pop_front(); + } + state.forward_stack.push_back(NavigationEntry { + item, + data: data.map(|data| Box::new(data) as Box), + timestamp: state.next_timestamp.fetch_add(1, Ordering::SeqCst), + }); + } + NavigationMode::GoingForward => { + if state.backward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN { + state.backward_stack.pop_front(); + } + state.backward_stack.push_back(NavigationEntry { + item, + data: data.map(|data| Box::new(data) as Box), + timestamp: state.next_timestamp.fetch_add(1, Ordering::SeqCst), + }); + } + NavigationMode::ClosingItem => { + if state.closed_stack.len() >= MAX_NAVIGATION_HISTORY_LEN { + state.closed_stack.pop_front(); + } + state.closed_stack.push_back(NavigationEntry { + item, + data: data.map(|data| Box::new(data) as Box), + timestamp: state.next_timestamp.fetch_add(1, Ordering::SeqCst), + }); + } + } + state.did_update(cx); + } - // pub fn remove_item(&mut self, item_id: usize) { - // let mut state = self.0.borrow_mut(); - // state.paths_by_item.remove(&item_id); - // state - // .backward_stack - // .retain(|entry| entry.item.id() != item_id); - // state - // .forward_stack - // .retain(|entry| entry.item.id() != item_id); - // state - // .closed_stack - // .retain(|entry| entry.item.id() != item_id); - // } + pub fn remove_item(&mut self, item_id: usize) { + let mut state = self.0.borrow_mut(); + state.paths_by_item.remove(&item_id); + state + .backward_stack + .retain(|entry| entry.item.id() != item_id); + state + .forward_stack + .retain(|entry| entry.item.id() != item_id); + state + .closed_stack + .retain(|entry| entry.item.id() != item_id); + } - // pub fn path_for_item(&self, item_id: usize) -> Option<(ProjectPath, Option)> { - // self.0.borrow().paths_by_item.get(&item_id).cloned() - // } + pub fn path_for_item(&self, item_id: usize) -> Option<(ProjectPath, Option)> { + self.0.borrow().paths_by_item.get(&item_id).cloned() + } } // impl NavHistoryState { diff --git a/crates/workspace2/src/persistence/model.rs b/crates/workspace2/src/persistence/model.rs index 2e28dabffb596b2a4cf20aee8ff882467cd6ec00..8265848497aceedebd5d15769335345c1389807b 100644 --- a/crates/workspace2/src/persistence/model.rs +++ b/crates/workspace2/src/persistence/model.rs @@ -7,7 +7,7 @@ use db2::sqlez::{ bindable::{Bind, Column, StaticColumnCount}, statement::Statement, }; -use gpui2::{AsyncAppContext, Handle, Task, View, WeakView, WindowBounds}; +use gpui2::{AsyncAppContext, AsyncWindowContext, Handle, Task, View, WeakView, WindowBounds}; use project2::Project; use std::{ path::{Path, PathBuf}, @@ -154,7 +154,7 @@ impl SerializedPaneGroup { project: &Handle, workspace_id: WorkspaceId, workspace: &WeakView, - cx: &mut AsyncAppContext, + cx: &mut AsyncWindowContext, ) -> Option<(Member, Option>, Vec>>)> { match self { SerializedPaneGroup::Group { diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 3731094b26fb3b83fd0c7eaa9d1d51ea3be658f5..d00ef2c26a74afa29449736952ddf205f30bd828 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -11,65 +11,30 @@ mod toolbar; mod workspace_settings; use anyhow::{anyhow, Result}; -// use call2::ActiveCall; -// use client2::{ -// proto::{self, PeerId}, -// Client, Status, TypedEnvelope, UserStore, -// }; -// use collections::{hash_map, HashMap, HashSet}; -// use futures::{ -// channel::{mpsc, oneshot}, -// future::try_join_all, -// FutureExt, StreamExt, -// }; -// use gpui2::{ -// actions, -// elements::*, -// geometry::{ -// rect::RectF, -// vector::{vec2f, Vector2F}, -// }, -// impl_actions, -// platform::{ -// CursorStyle, ModifiersChangedEvent, MouseButton, PathPromptOptions, Platform, PromptLevel, -// WindowBounds, WindowOptions, -// }, -// AnyModelHandle, AnyViewHandle, AnyWeakViewHandle, AnyWindowHandle, AppContext, AsyncAppContext, -// Entity, ModelContext, ModelHandle, SizeConstraint, Subscription, Task, View, ViewContext, -// View, WeakViewHandle, WindowContext, WindowHandle, -// }; -// use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem}; -// use itertools::Itertools; -// use language2::{LanguageRegistry, Rope}; -// use node_runtime::NodeRuntime;// // - -use futures::channel::oneshot; -// use crate::{ -// notifications::{simple_message_notification::MessageNotification, NotificationTracker}, -// persistence::model::{ -// DockData, DockStructure, SerializedPane, SerializedPaneGroup, SerializedWorkspace, -// }, -// }; -// use dock::{Dock, DockPosition, Panel, PanelButtons, PanelHandle}; -// use lazy_static::lazy_static; -// use notifications::{NotificationHandle, NotifyResultExt}; +use client2::{ + proto::{self, PeerId}, + Client, UserStore, +}; +use collections::{HashMap, HashSet}; +use futures::{channel::oneshot, FutureExt}; +use gpui2::{ + AnyModel, AnyView, AppContext, AsyncAppContext, DisplayId, MainThread, Model, Task, View, + ViewContext, VisualContext, WeakModel, WeakView, WindowBounds, WindowHandle, WindowOptions, +}; +use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem}; +use language2::LanguageRegistry; +use node_runtime::NodeRuntime; pub use pane::*; pub use pane_group::*; -// use persistence::{model::SerializedItem, DB}; -// pub use persistence::{ -// model::{ItemId, WorkspaceLocation}, -// WorkspaceDb, DB as WORKSPACE_DB, -// }; -// use postage::prelude::Stream; -// use project::{Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId}; -// use serde::Deserialize; -// use shared_screen::SharedScreen; -// use status_bar::StatusBar; -// pub use status_bar::StatusItemView; -// use theme::{Theme, ThemeSettings}; +use project2::{Project, ProjectEntryId, ProjectPath, Worktree}; +use std::{ + any::TypeId, + path::{Path, PathBuf}, + sync::{atomic::AtomicUsize, Arc}, + time::Duration, +}; pub use toolbar::{ToolbarItemLocation, ToolbarItemView}; -// use util::ResultExt; -// pub use workspace_settings::{AutosaveSetting, GitGutterSetting, WorkspaceSettings}; +use util::ResultExt; // lazy_static! { // static ref ZED_WINDOW_SIZE: Option = env::var("ZED_WINDOW_SIZE") @@ -367,13 +332,12 @@ pub type WorkspaceId = i64; // } type ProjectItemBuilders = - HashMap, AnyHandle, &mut ViewContext) -> Box>; + HashMap, AnyModel, &mut ViewContext) -> Box>; pub fn register_project_item(cx: &mut AppContext) { - cx.update_default_global(|builders: &mut ProjectItemBuilders, _| { - builders.insert(TypeId::of::(), |project, model, cx| { - let item = model.downcast::().unwrap(); - Box::new(cx.add_view(|cx| I::for_project_item(project, item, cx))) - }); + let builders = cx.default_global::(); + builders.insert(TypeId::of::(), |project, model, cx| { + let item = model.downcast::().unwrap(); + Box::new(cx.build_view(|cx| I::for_project_item(project, item, cx))) }); } @@ -392,26 +356,25 @@ type FollowableItemBuilders = HashMap< ), >; pub fn register_followable_item(cx: &mut AppContext) { - cx.update_default_global(|builders: &mut FollowableItemBuilders, _| { - builders.insert( - TypeId::of::(), - ( - |pane, workspace, id, state, cx| { - I::from_state_proto(pane, workspace, id, state, cx).map(|task| { - cx.foreground() - .spawn(async move { Ok(Box::new(task.await?) as Box<_>) }) - }) - }, - |this| Box::new(this.clone().downcast::().unwrap()), - ), - ); - }); + let builders = cx.default_global::(); + builders.insert( + TypeId::of::(), + ( + |pane, workspace, id, state, cx| { + I::from_state_proto(pane, workspace, id, state, cx).map(|task| { + cx.executor() + .spawn(async move { Ok(Box::new(task.await?) as Box<_>) }) + }) + }, + |this| Box::new(this.clone().downcast::().unwrap()), + ), + ); } type ItemDeserializers = HashMap< Arc, fn( - Handle, + Model, WeakView, WorkspaceId, ItemId, @@ -436,18 +399,18 @@ pub fn register_deserializable_item(cx: &mut AppContext) { pub struct AppState { pub languages: Arc, pub client: Arc, - pub user_store: Handle, - pub workspace_store: Handle, + pub user_store: Model, + pub workspace_store: Model, pub fs: Arc, pub build_window_options: fn(Option, Option, &MainThread) -> WindowOptions, pub initialize_workspace: - fn(WeakHandle, bool, Arc, AsyncAppContext) -> Task>, + fn(WeakModel, bool, Arc, AsyncAppContext) -> Task>, pub node_runtime: Arc, } pub struct WorkspaceStore { - workspaces: HashSet>, + workspaces: HashSet>, followers: Vec, client: Arc, _subscriptions: Vec, @@ -520,7 +483,7 @@ impl DelayedDebouncedEditAction { let previous_task = self.task.take(); self.task = Some(cx.spawn(|workspace, mut cx| async move { - let mut timer = cx.background().timer(delay).fuse(); + let mut timer = cx.executor().timer(delay).fuse(); if let Some(previous_task) = previous_task { previous_task.await; } @@ -540,13 +503,13 @@ impl DelayedDebouncedEditAction { } } -// pub enum Event { -// PaneAdded(View), -// ContactRequestedJoin(u64), -// } +pub enum Event { + PaneAdded(View), + ContactRequestedJoin(u64), +} pub struct Workspace { - weak_self: WeakHandle, + weak_self: WeakView, // modal: Option, // zoomed: Option, // zoomed_position: Option, @@ -555,16 +518,16 @@ pub struct Workspace { // bottom_dock: View, // right_dock: View, panes: Vec>, - // panes_by_item: HashMap>, + panes_by_item: HashMap>, // active_pane: View, last_active_center_pane: Option>, // last_active_view_id: Option, // status_bar: View, // titlebar_item: Option, // notifications: Vec<(TypeId, usize, Box)>, - project: Handle, + project: Model, // follower_states: HashMap, FollowerState>, - // last_leaders_by_pane: HashMap, PeerId>, + // last_leaders_by_pane: HashMap, PeerId>, // window_edited: bool, // active_call: Option<(ModelHandle, Vec)>, // leader_updates_tx: mpsc::UnboundedSender<(PeerId, proto::UpdateFollowers)>, @@ -574,7 +537,7 @@ pub struct Workspace { // _apply_leader_updates: Task>, // _observe_current_user: Task>, // _schedule_serialize: Option>, - // pane_history_timestamp: Arc, + pane_history_timestamp: Arc, } // struct ActiveModal { @@ -582,11 +545,11 @@ pub struct Workspace { // previously_focused_view_id: Option, // } -// #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -// pub struct ViewId { -// pub creator: PeerId, -// pub id: u64, -// } +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct ViewId { + pub creator: PeerId, + pub id: u64, +} #[derive(Default)] struct FollowerState { @@ -595,7 +558,7 @@ struct FollowerState { items_by_leader_view_id: HashMap>, } -// enum WorkspaceBounds {} +enum WorkspaceBounds {} impl Workspace { // pub fn new( @@ -799,7 +762,7 @@ impl Workspace { // requesting_window: Option>, // cx: &mut AppContext, // ) -> Task<( - // WeakViewHandle, + // WeakView, // Vec, anyhow::Error>>>, // )> { // let project_handle = Project::local( @@ -927,21 +890,21 @@ impl Workspace { // }) // } - // pub fn weak_handle(&self) -> WeakViewHandle { - // self.weak_self.clone() - // } + pub fn weak_handle(&self) -> WeakView { + self.weak_self.clone() + } - // pub fn left_dock(&self) -> &View { - // &self.left_dock - // } + // pub fn left_dock(&self) -> &View { + // &self.left_dock + // } - // pub fn bottom_dock(&self) -> &View { - // &self.bottom_dock - // } + // pub fn bottom_dock(&self) -> &View { + // &self.bottom_dock + // } - // pub fn right_dock(&self) -> &View { - // &self.right_dock - // } + // pub fn right_dock(&self) -> &View { + // &self.right_dock + // } // pub fn add_panel(&mut self, panel: View, cx: &mut ViewContext) // where @@ -1038,15 +1001,15 @@ impl Workspace { // &self.status_bar // } - // pub fn app_state(&self) -> &Arc { - // &self.app_state - // } + pub fn app_state(&self) -> &Arc { + &self.app_state + } - // pub fn user_store(&self) -> &ModelHandle { - // &self.app_state.user_store - // } + pub fn user_store(&self) -> &Model { + &self.app_state.user_store + } - pub fn project(&self) -> &Handle { + pub fn project(&self) -> &Model { &self.project } @@ -1108,7 +1071,7 @@ impl Workspace { // fn navigate_history( // &mut self, - // pane: WeakViewHandle, + // pane: WeakView, // mode: NavigationMode, // cx: &mut ViewContext, // ) -> Task> { @@ -1193,7 +1156,7 @@ impl Workspace { // pub fn go_back( // &mut self, - // pane: WeakViewHandle, + // pane: WeakView, // cx: &mut ViewContext, // ) -> Task> { // self.navigate_history(pane, NavigationMode::GoingBack, cx) @@ -1201,7 +1164,7 @@ impl Workspace { // pub fn go_forward( // &mut self, - // pane: WeakViewHandle, + // pane: WeakView, // cx: &mut ViewContext, // ) -> Task> { // self.navigate_history(pane, NavigationMode::GoingForward, cx) @@ -1592,11 +1555,11 @@ impl Workspace { // } fn project_path_for_path( - project: Handle, + project: Model, abs_path: &Path, visible: bool, cx: &mut AppContext, - ) -> Task, ProjectPath)>> { + ) -> Task, ProjectPath)>> { let entry = project.update(cx, |project, cx| { project.find_or_create_local_worktree(abs_path, visible, cx) }); @@ -1957,21 +1920,21 @@ impl Workspace { // cx.notify(); // } - // fn add_pane(&mut self, cx: &mut ViewContext) -> View { - // let pane = cx.add_view(|cx| { - // Pane::new( - // self.weak_handle(), - // self.project.clone(), - // self.pane_history_timestamp.clone(), - // cx, - // ) - // }); - // cx.subscribe(&pane, Self::handle_pane_event).detach(); - // self.panes.push(pane.clone()); - // cx.focus(&pane); - // cx.emit(Event::PaneAdded(pane.clone())); - // pane - // } + fn add_pane(&mut self, cx: &mut ViewContext) -> View { + let pane = cx.build_view(|cx| { + Pane::new( + self.weak_handle(), + self.project.clone(), + self.pane_history_timestamp.clone(), + cx, + ) + }); + cx.subscribe(&pane, Self::handle_pane_event).detach(); + self.panes.push(pane.clone()); + cx.focus(&pane); + cx.emit(Event::PaneAdded(pane.clone())); + pane + } // pub fn add_item_to_center( // &mut self, @@ -2397,9 +2360,9 @@ impl Workspace { // pub fn split_pane_with_item( // &mut self, - // pane_to_split: WeakViewHandle, + // pane_to_split: WeakView, // split_direction: SplitDirection, - // from: WeakViewHandle, + // from: WeakView, // item_id_to_move: usize, // cx: &mut ViewContext, // ) { @@ -2420,7 +2383,7 @@ impl Workspace { // pub fn split_pane_with_project_entry( // &mut self, - // pane_to_split: WeakViewHandle, + // pane_to_split: WeakView, // split_direction: SplitDirection, // project_entry: ProjectEntryId, // cx: &mut ViewContext, @@ -2899,7 +2862,7 @@ impl Workspace { // } // async fn process_leader_update( - // this: &WeakViewHandle, + // this: &WeakView, // leader_id: PeerId, // update: proto::UpdateFollowers, // cx: &mut AsyncAppContext, @@ -2958,7 +2921,7 @@ impl Workspace { // } // async fn add_views_from_leader( - // this: WeakViewHandle, + // this: WeakView, // leader_id: PeerId, // panes: Vec>, // views: Vec, @@ -3045,25 +3008,25 @@ impl Workspace { // } // } - // fn update_followers( - // &self, - // project_only: bool, - // update: proto::update_followers::Variant, - // cx: &AppContext, - // ) -> Option<()> { - // let project_id = if project_only { - // self.project.read(cx).remote_id() - // } else { - // None - // }; - // self.app_state().workspace_store.read_with(cx, |store, cx| { - // store.update_followers(project_id, update, cx) - // }) - // } + fn update_followers( + &self, + project_only: bool, + update: proto::update_followers::Variant, + cx: &AppContext, + ) -> Option<()> { + let project_id = if project_only { + self.project.read(cx).remote_id() + } else { + None + }; + self.app_state().workspace_store.read_with(cx, |store, cx| { + store.update_followers(project_id, update, cx) + }) + } - // pub fn leader_for_pane(&self, pane: &View) -> Option { - // self.follower_states.get(pane).map(|state| state.leader_id) - // } + pub fn leader_for_pane(&self, pane: &View) -> Option { + self.follower_states.get(pane).map(|state| state.leader_id) + } // fn leader_updated(&mut self, leader_id: PeerId, cx: &mut ViewContext) -> Option<()> { // cx.notify(); @@ -3380,7 +3343,7 @@ impl Workspace { // } // pub(crate) fn load_workspace( - // workspace: WeakViewHandle, + // workspace: WeakView, // serialized_workspace: SerializedWorkspace, // paths_to_open: Vec>, // cx: &mut AppContext, @@ -3570,7 +3533,7 @@ impl Workspace { // async fn open_items( // serialized_workspace: Option, - // workspace: &WeakViewHandle, + // workspace: &WeakView, // mut project_paths_to_open: Vec<(PathBuf, Option)>, // app_state: Arc, // mut cx: AsyncAppContext, @@ -3660,7 +3623,7 @@ impl Workspace { // Ok(opened_items) // } - // fn notify_of_new_dock(workspace: &WeakViewHandle, cx: &mut AsyncAppContext) { + // fn notify_of_new_dock(workspace: &WeakView, cx: &mut AsyncAppContext) { // const NEW_PANEL_BLOG_POST: &str = "https://zed.dev/blog/new-panel-system"; // const NEW_DOCK_HINT_KEY: &str = "show_new_dock_key"; // const MESSAGE_ID: usize = 2; @@ -3741,7 +3704,7 @@ impl Workspace { // .ok(); } -// fn notify_if_database_failed(workspace: &WeakViewHandle, cx: &mut AsyncAppContext) { +// fn notify_if_database_failed(workspace: &WeakView, cx: &mut AsyncAppContext) { // const REPORT_ISSUE_URL: &str ="https://github.com/zed-industries/community/issues/new?assignees=&labels=defect%2Ctriage&template=2_bug_report.yml"; // workspace @@ -4054,23 +4017,23 @@ impl Workspace { // type Event = (); // } -// impl ViewId { -// pub(crate) fn from_proto(message: proto::ViewId) -> Result { -// Ok(Self { -// creator: message -// .creator -// .ok_or_else(|| anyhow!("creator is missing"))?, -// id: message.id, -// }) -// } +impl ViewId { + pub(crate) fn from_proto(message: proto::ViewId) -> Result { + Ok(Self { + creator: message + .creator + .ok_or_else(|| anyhow!("creator is missing"))?, + id: message.id, + }) + } -// pub(crate) fn to_proto(&self) -> proto::ViewId { -// proto::ViewId { -// creator: Some(self.creator), -// id: self.id, -// } -// } -// } + pub(crate) fn to_proto(&self) -> proto::ViewId { + proto::ViewId { + creator: Some(self.creator), + id: self.id, + } + } +} // pub trait WorkspaceHandle { // fn file_project_paths(&self, cx: &AppContext) -> Vec; @@ -4099,7 +4062,7 @@ impl Workspace { // } // } -// pub struct WorkspaceCreated(pub WeakViewHandle); +// pub struct WorkspaceCreated(pub WeakView); pub async fn activate_workspace_for_project( cx: &mut AsyncAppContext, @@ -4321,27 +4284,6 @@ pub async fn activate_workspace_for_project( // None // } -use client2::{ - proto::{self, PeerId, ViewId}, - Client, UserStore, -}; -use collections::{HashMap, HashSet}; -use gpui2::{ - AnyHandle, AnyView, AppContext, AsyncAppContext, DisplayId, Handle, MainThread, Task, View, - ViewContext, WeakHandle, WeakView, WindowBounds, WindowHandle, WindowOptions, -}; -use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem}; -use language2::LanguageRegistry; -use node_runtime::NodeRuntime; -use project2::{Project, ProjectEntryId, ProjectPath, Worktree}; -use std::{ - any::TypeId, - path::{Path, PathBuf}, - sync::Arc, - time::Duration, -}; -use util::ResultExt; - #[allow(clippy::type_complexity)] pub fn open_paths( abs_paths: &[PathBuf],