use crate::{ pane::{self, Pane}, persistence::model::ItemId, searchable::SearchableItemHandle, workspace_settings::{AutosaveSetting, WorkspaceSettings}, DelayedDebouncedEditAction, FollowableViewRegistry, ItemNavHistory, SerializableItemRegistry, ToolbarItemLocation, ViewId, Workspace, WorkspaceId,};use anyhow::Result;use client::{ proto::{self, PeerId}, Client,};use futures::{channel::mpsc, StreamExt};use gpui::{ AnyElement, AnyView, AppContext, Entity, EntityId, EventEmitter, FocusHandle, FocusableView, Font, HighlightStyle, Model, Pixels, Point, SharedString, Task, View, ViewContext, WeakView, WindowContext,};use project::{Project, ProjectEntryId, ProjectPath};use schemars::JsonSchema;use serde::{Deserialize, Serialize};use settings::{Settings, SettingsLocation, SettingsSources};use smallvec::SmallVec;use std::{ any::{Any, TypeId}, cell::RefCell, ops::Range, rc::Rc, sync::Arc, time::Duration,};use theme::Theme;use ui::{Color, Element as _, Icon, IntoElement, Label, LabelCommon};use util::ResultExt; pub const LEADER_UPDATE_THROTTLE: Duration = Duration::from_millis(200); #[derive(Deserialize)]pub struct ItemSettings { pub git_status: bool, pub close_position: ClosePosition, pub activate_on_close: ActivateOnClose, pub file_icons: bool, pub show_diagnostics: ShowDiagnostics, pub always_show_close_button: bool,} #[derive(Deserialize)]pub struct PreviewTabsSettings { pub enabled: bool, pub enable_preview_from_file_finder: bool, pub enable_preview_from_code_navigation: bool,} #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]#[serde(rename_all = "lowercase")]pub enum ClosePosition { Left, #[default] Right,} #[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]#[serde(rename_all = "snake_case")]pub enum ShowDiagnostics { #[default] Off, Errors, All,} #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]#[serde(rename_all = "snake_case")]pub enum ActivateOnClose { #[default] History, Neighbour, LeftNeighbour,} #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]pub struct ItemSettingsContent { /// Whether to show the Git file status on a tab item. /// /// Default: false git_status: Option<bool>, /// Position of the close button in a tab. /// /// Default: right close_position: Option<ClosePosition>, /// Whether to show the file icon for a tab. /// /// Default: false file_icons: Option<bool>, /// What to do after closing the current tab. /// /// Default: history pub activate_on_close: Option<ActivateOnClose>, /// Which files containing diagnostic errors/warnings to mark in the tabs. /// This setting can take the following three values: /// /// Default: off show_diagnostics: Option<ShowDiagnostics>, /// Whether to always show the close button on tabs. /// /// Default: false always_show_close_button: Option<bool>,} #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]pub struct PreviewTabsSettingsContent { /// Whether to show opened editors as preview tabs. /// Preview tabs do not stay open, are reused until explicitly set to be kept open opened (via double-click or editing) and show file names in italic. /// /// Default: true enabled: Option<bool>, /// Whether to open tabs in preview mode when selected from the file finder. /// /// Default: false enable_preview_from_file_finder: Option<bool>, /// Whether a preview tab gets replaced when code navigation is used to navigate away from the tab. /// /// Default: false enable_preview_from_code_navigation: Option<bool>,} impl Settings for ItemSettings { const KEY: Option<&'static str> = Some("tabs"); type FileContent = ItemSettingsContent; fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> { sources.json_merge() }} impl Settings for PreviewTabsSettings { const KEY: Option<&'static str> = Some("preview_tabs"); type FileContent = PreviewTabsSettingsContent; fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> { sources.json_merge() }} #[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]pub enum ItemEvent { CloseItem, UpdateTab, UpdateBreadcrumbs, Edit,} // TODO: Combine this with existing HighlightedText struct?pub struct BreadcrumbText { pub text: String, pub highlights: Option<Vec<(Range<usize>, HighlightStyle)>>, pub font: Option<Font>,} #[derive(Debug, Clone, Copy)]pub struct TabContentParams { pub detail: Option<usize>, pub selected: bool, pub preview: bool,} impl TabContentParams { /// Returns the text color to be used for the tab content. pub fn text_color(&self) -> Color { if self.selected { Color::Default } else { Color::Muted } }} pub enum TabTooltipContent { Text(SharedString), Custom(Box<dyn Fn(&mut WindowContext) -> AnyView>),} pub trait Item: FocusableView + EventEmitter<Self::Event> { type Event; /// Returns the tab contents. /// /// By default this returns a [`Label`] that displays that text from /// `tab_content_text`. fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement { let Some(text) = self.tab_content_text(cx) else { return gpui::Empty.into_any(); }; Label::new(text) .color(params.text_color()) .into_any_element() } /// Returns the textual contents of the tab. /// /// Use this if you don't need to customize the tab contents. fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> { None } fn tab_icon(&self, _cx: &WindowContext) -> Option<Icon> { None } /// Returns the tab tooltip text. /// /// Use this if you don't need to customize the tab tooltip content. fn tab_tooltip_text(&self, _: &AppContext) -> Option<SharedString> { None } /// Returns the tab tooltip content. /// /// By default this returns a Tooltip text from /// `tab_tooltip_text`. fn tab_tooltip_content(&self, cx: &AppContext) -> Option<TabTooltipContent> { self.tab_tooltip_text(cx).map(TabTooltipContent::Text) } fn tab_description(&self, _: usize, _: &AppContext) -> Option<SharedString> { None } fn to_item_events(_event: &Self::Event, _f: impl FnMut(ItemEvent)) {} fn deactivated(&mut self, _: &mut ViewContext<Self>) {} fn discarded(&self, _project: Model<Project>, _cx: &mut ViewContext<Self>) {} fn workspace_deactivated(&mut self, _: &mut ViewContext<Self>) {} fn navigate(&mut self, _: Box<dyn Any>, _: &mut ViewContext<Self>) -> bool { false } fn telemetry_event_text(&self) -> Option<&'static str> { None } /// (model id, Item) fn for_each_project_item( &self, _: &AppContext, _: &mut dyn FnMut(EntityId, &dyn project::ProjectItem), ) { } fn is_singleton(&self, _cx: &AppContext) -> bool { false } fn set_nav_history(&mut self, _: ItemNavHistory, _: &mut ViewContext<Self>) {} fn clone_on_split( &self, _workspace_id: Option<WorkspaceId>, _: &mut ViewContext<Self>, ) -> Option<View<Self>> where Self: Sized, { None } fn is_dirty(&self, _: &AppContext) -> bool { false } fn has_deleted_file(&self, _: &AppContext) -> bool { false } fn has_conflict(&self, _: &AppContext) -> bool { false } fn can_save(&self, _cx: &AppContext) -> bool { false } fn save( &mut self, _format: bool, _project: Model<Project>, _cx: &mut ViewContext<Self>, ) -> Task<Result<()>> { unimplemented!("save() must be implemented if can_save() returns true") } fn save_as( &mut self, _project: Model<Project>, _path: ProjectPath, _cx: &mut ViewContext<Self>, ) -> Task<Result<()>> { unimplemented!("save_as() must be implemented if can_save() returns true") } fn reload( &mut self, _project: Model<Project>, _cx: &mut ViewContext<Self>, ) -> Task<Result<()>> { unimplemented!("reload() must be implemented if can_save() returns true") } fn act_as_type<'a>( &'a self, type_id: TypeId, self_handle: &'a View<Self>, _: &'a AppContext, ) -> Option<AnyView> { if TypeId::of::<Self>() == type_id { Some(self_handle.clone().into()) } else { None } } fn as_searchable(&self, _: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> { None } fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation { ToolbarItemLocation::Hidden } fn breadcrumbs(&self, _theme: &Theme, _cx: &AppContext) -> Option<Vec<BreadcrumbText>> { None } fn added_to_workspace(&mut self, _workspace: &mut Workspace, _cx: &mut ViewContext<Self>) {} fn show_toolbar(&self) -> bool { true } fn pixel_position_of_cursor(&self, _: &AppContext) -> Option<Point<Pixels>> { None } fn preserve_preview(&self, _cx: &AppContext) -> bool { false } fn include_in_nav_history() -> bool { true }} pub trait SerializableItem: Item { fn serialized_item_kind() -> &'static str; fn cleanup( workspace_id: WorkspaceId, alive_items: Vec<ItemId>, cx: &mut WindowContext, ) -> Task<Result<()>>; fn deserialize( _project: Model<Project>, _workspace: WeakView<Workspace>, _workspace_id: WorkspaceId, _item_id: ItemId, _cx: &mut WindowContext, ) -> Task<Result<View<Self>>>; fn serialize( &mut self, workspace: &mut Workspace, item_id: ItemId, closing: bool, cx: &mut ViewContext<Self>, ) -> Option<Task<Result<()>>>; fn should_serialize(&self, event: &Self::Event) -> bool;} pub trait SerializableItemHandle: ItemHandle { fn serialized_item_kind(&self) -> &'static str; fn serialize( &self, workspace: &mut Workspace, closing: bool, cx: &mut WindowContext, ) -> Option<Task<Result<()>>>; fn should_serialize(&self, event: &dyn Any, cx: &AppContext) -> bool;} impl<T> SerializableItemHandle for View<T>where T: SerializableItem,{ fn serialized_item_kind(&self) -> &'static str { T::serialized_item_kind() } fn serialize( &self, workspace: &mut Workspace, closing: bool, cx: &mut WindowContext, ) -> Option<Task<Result<()>>> { self.update(cx, |this, cx| { this.serialize(workspace, cx.entity_id().as_u64(), closing, cx) }) } fn should_serialize(&self, event: &dyn Any, cx: &AppContext) -> bool { event .downcast_ref::<T::Event>() .map_or(false, |event| self.read(cx).should_serialize(event)) }} pub trait ItemHandle: 'static + Send { fn subscribe_to_item_events( &self, cx: &mut WindowContext, handler: Box<dyn Fn(ItemEvent, &mut WindowContext)>, ) -> gpui::Subscription; fn focus_handle(&self, cx: &WindowContext) -> FocusHandle; fn tab_description(&self, detail: usize, cx: &AppContext) -> Option<SharedString>; fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement; fn tab_icon(&self, cx: &WindowContext) -> Option<Icon>; fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString>; fn tab_tooltip_content(&self, cx: &AppContext) -> Option<TabTooltipContent>; fn telemetry_event_text(&self, cx: &WindowContext) -> Option<&'static str>; fn dragged_tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement; fn project_path(&self, cx: &AppContext) -> Option<ProjectPath>; fn project_entry_ids(&self, cx: &AppContext) -> SmallVec<[ProjectEntryId; 3]>; fn project_paths(&self, cx: &AppContext) -> SmallVec<[ProjectPath; 3]>; fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[EntityId; 3]>; fn for_each_project_item( &self, _: &AppContext, _: &mut dyn FnMut(EntityId, &dyn project::ProjectItem), ); fn is_singleton(&self, cx: &AppContext) -> bool; fn boxed_clone(&self) -> Box<dyn ItemHandle>; fn clone_on_split( &self, workspace_id: Option<WorkspaceId>, cx: &mut WindowContext, ) -> Option<Box<dyn ItemHandle>>; fn added_to_pane( &self, workspace: &mut Workspace, pane: View<Pane>, cx: &mut ViewContext<Workspace>, ); fn deactivated(&self, cx: &mut WindowContext); fn discarded(&self, project: Model<Project>, cx: &mut WindowContext); fn workspace_deactivated(&self, cx: &mut WindowContext); fn navigate(&self, data: Box<dyn Any>, cx: &mut WindowContext) -> bool; fn item_id(&self) -> EntityId; fn to_any(&self) -> AnyView; fn is_dirty(&self, cx: &AppContext) -> bool; fn has_deleted_file(&self, cx: &AppContext) -> bool; fn has_conflict(&self, cx: &AppContext) -> bool; fn can_save(&self, cx: &AppContext) -> bool; fn save( &self, format: bool, project: Model<Project>, cx: &mut WindowContext, ) -> Task<Result<()>>; fn save_as( &self, project: Model<Project>, path: ProjectPath, cx: &mut WindowContext, ) -> Task<Result<()>>; fn reload(&self, project: Model<Project>, cx: &mut WindowContext) -> Task<Result<()>>; fn act_as_type(&self, type_id: TypeId, cx: &AppContext) -> Option<AnyView>; fn to_followable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn FollowableItemHandle>>; fn to_serializable_item_handle( &self, cx: &AppContext, ) -> Option<Box<dyn SerializableItemHandle>>; fn on_release( &self, cx: &mut AppContext, callback: Box<dyn FnOnce(&mut AppContext) + Send>, ) -> gpui::Subscription; fn to_searchable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>; fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation; fn breadcrumbs(&self, theme: &Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>>; fn show_toolbar(&self, cx: &AppContext) -> bool; fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Point<Pixels>>; fn downgrade_item(&self) -> Box<dyn WeakItemHandle>; fn workspace_settings<'a>(&self, cx: &'a AppContext) -> &'a WorkspaceSettings; fn preserve_preview(&self, cx: &AppContext) -> bool; fn include_in_nav_history(&self) -> bool;} pub trait WeakItemHandle: Send + Sync { fn id(&self) -> EntityId; fn boxed_clone(&self) -> Box<dyn WeakItemHandle>; fn upgrade(&self) -> Option<Box<dyn ItemHandle>>;} impl dyn ItemHandle { pub fn downcast<V: 'static>(&self) -> Option<View<V>> {Lines 1–500 of 1431. Load more
use crate::{ pane::{self, Pane}, persistence::model::ItemId, searchable::SearchableItemHandle, workspace_settings::{AutosaveSetting, WorkspaceSettings}, DelayedDebouncedEditAction, FollowableViewRegistry, ItemNavHistory, SerializableItemRegistry, ToolbarItemLocation, ViewId, Workspace, WorkspaceId, }; use anyhow::Result; use client::{ proto::{self, PeerId}, Client, }; use futures::{channel::mpsc, StreamExt}; use gpui::{ AnyElement, AnyView, AppContext, Entity, EntityId, EventEmitter, FocusHandle, FocusableView, Font, HighlightStyle, Model, Pixels, Point, SharedString, Task, View, ViewContext, WeakView, WindowContext, }; use project::{Project, ProjectEntryId, ProjectPath}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings::{Settings, SettingsLocation, SettingsSources}; use smallvec::SmallVec; use std::{ any::{Any, TypeId}, cell::RefCell, ops::Range, rc::Rc, sync::Arc, time::Duration, }; use theme::Theme; use ui::{Color, Element as _, Icon, IntoElement, Label, LabelCommon}; use util::ResultExt; pub const LEADER_UPDATE_THROTTLE: Duration = Duration::from_millis(200); #[derive(Deserialize)] pub struct ItemSettings { pub git_status: bool, pub close_position: ClosePosition, pub activate_on_close: ActivateOnClose, pub file_icons: bool, pub show_diagnostics: ShowDiagnostics, pub always_show_close_button: bool, } #[derive(Deserialize)] pub struct PreviewTabsSettings { pub enabled: bool, pub enable_preview_from_file_finder: bool, pub enable_preview_from_code_navigation: bool, } #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "lowercase")] pub enum ClosePosition { Left, #[default] Right, } #[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum ShowDiagnostics { #[default] Off, Errors, All, } #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum ActivateOnClose { #[default] History, Neighbour, LeftNeighbour, } #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] pub struct ItemSettingsContent { /// Whether to show the Git file status on a tab item. /// /// Default: false git_status: Option<bool>, /// Position of the close button in a tab. /// /// Default: right close_position: Option<ClosePosition>, /// Whether to show the file icon for a tab. /// /// Default: false file_icons: Option<bool>, /// What to do after closing the current tab. /// /// Default: history pub activate_on_close: Option<ActivateOnClose>, /// Which files containing diagnostic errors/warnings to mark in the tabs. /// This setting can take the following three values: /// /// Default: off show_diagnostics: Option<ShowDiagnostics>, /// Whether to always show the close button on tabs. /// /// Default: false always_show_close_button: Option<bool>, } #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] pub struct PreviewTabsSettingsContent { /// Whether to show opened editors as preview tabs. /// Preview tabs do not stay open, are reused until explicitly set to be kept open opened (via double-click or editing) and show file names in italic. /// /// Default: true enabled: Option<bool>, /// Whether to open tabs in preview mode when selected from the file finder. /// /// Default: false enable_preview_from_file_finder: Option<bool>, /// Whether a preview tab gets replaced when code navigation is used to navigate away from the tab. /// /// Default: false enable_preview_from_code_navigation: Option<bool>, } impl Settings for ItemSettings { const KEY: Option<&'static str> = Some("tabs"); type FileContent = ItemSettingsContent; fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> { sources.json_merge() } } impl Settings for PreviewTabsSettings { const KEY: Option<&'static str> = Some("preview_tabs"); type FileContent = PreviewTabsSettingsContent; fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> { sources.json_merge() } } #[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] pub enum ItemEvent { CloseItem, UpdateTab, UpdateBreadcrumbs, Edit, } // TODO: Combine this with existing HighlightedText struct? pub struct BreadcrumbText { pub text: String, pub highlights: Option<Vec<(Range<usize>, HighlightStyle)>>, pub font: Option<Font>, } #[derive(Debug, Clone, Copy)] pub struct TabContentParams { pub detail: Option<usize>, pub selected: bool, pub preview: bool, } impl TabContentParams { /// Returns the text color to be used for the tab content. pub fn text_color(&self) -> Color { if self.selected { Color::Default } else { Color::Muted } } } pub enum TabTooltipContent { Text(SharedString), Custom(Box<dyn Fn(&mut WindowContext) -> AnyView>), } pub trait Item: FocusableView + EventEmitter<Self::Event> { type Event; /// Returns the tab contents. /// /// By default this returns a [`Label`] that displays that text from /// `tab_content_text`. fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement { let Some(text) = self.tab_content_text(cx) else { return gpui::Empty.into_any(); }; Label::new(text) .color(params.text_color()) .into_any_element() } /// Returns the textual contents of the tab. /// /// Use this if you don't need to customize the tab contents. fn tab_content_text(&self, _cx: &WindowContext) -> Option<SharedString> { None } fn tab_icon(&self, _cx: &WindowContext) -> Option<Icon> { None } /// Returns the tab tooltip text. /// /// Use this if you don't need to customize the tab tooltip content. fn tab_tooltip_text(&self, _: &AppContext) -> Option<SharedString> { None } /// Returns the tab tooltip content. /// /// By default this returns a Tooltip text from /// `tab_tooltip_text`. fn tab_tooltip_content(&self, cx: &AppContext) -> Option<TabTooltipContent> { self.tab_tooltip_text(cx).map(TabTooltipContent::Text) } fn tab_description(&self, _: usize, _: &AppContext) -> Option<SharedString> { None } fn to_item_events(_event: &Self::Event, _f: impl FnMut(ItemEvent)) {} fn deactivated(&mut self, _: &mut ViewContext<Self>) {} fn discarded(&self, _project: Model<Project>, _cx: &mut ViewContext<Self>) {} fn workspace_deactivated(&mut self, _: &mut ViewContext<Self>) {} fn navigate(&mut self, _: Box<dyn Any>, _: &mut ViewContext<Self>) -> bool { false } fn telemetry_event_text(&self) -> Option<&'static str> { None } /// (model id, Item) fn for_each_project_item( &self, _: &AppContext, _: &mut dyn FnMut(EntityId, &dyn project::ProjectItem), ) { } fn is_singleton(&self, _cx: &AppContext) -> bool { false } fn set_nav_history(&mut self, _: ItemNavHistory, _: &mut ViewContext<Self>) {} fn clone_on_split( &self, _workspace_id: Option<WorkspaceId>, _: &mut ViewContext<Self>, ) -> Option<View<Self>> where Self: Sized, { None } fn is_dirty(&self, _: &AppContext) -> bool { false } fn has_deleted_file(&self, _: &AppContext) -> bool { false } fn has_conflict(&self, _: &AppContext) -> bool { false } fn can_save(&self, _cx: &AppContext) -> bool { false } fn save( &mut self, _format: bool, _project: Model<Project>, _cx: &mut ViewContext<Self>, ) -> Task<Result<()>> { unimplemented!("save() must be implemented if can_save() returns true") } fn save_as( &mut self, _project: Model<Project>, _path: ProjectPath, _cx: &mut ViewContext<Self>, ) -> Task<Result<()>> { unimplemented!("save_as() must be implemented if can_save() returns true") } fn reload( &mut self, _project: Model<Project>, _cx: &mut ViewContext<Self>, ) -> Task<Result<()>> { unimplemented!("reload() must be implemented if can_save() returns true") } fn act_as_type<'a>( &'a self, type_id: TypeId, self_handle: &'a View<Self>, _: &'a AppContext, ) -> Option<AnyView> { if TypeId::of::<Self>() == type_id { Some(self_handle.clone().into()) } else { None } } fn as_searchable(&self, _: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> { None } fn breadcrumb_location(&self, _: &AppContext) -> ToolbarItemLocation { ToolbarItemLocation::Hidden } fn breadcrumbs(&self, _theme: &Theme, _cx: &AppContext) -> Option<Vec<BreadcrumbText>> { None } fn added_to_workspace(&mut self, _workspace: &mut Workspace, _cx: &mut ViewContext<Self>) {} fn show_toolbar(&self) -> bool { true } fn pixel_position_of_cursor(&self, _: &AppContext) -> Option<Point<Pixels>> { None } fn preserve_preview(&self, _cx: &AppContext) -> bool { false } fn include_in_nav_history() -> bool { true } } pub trait SerializableItem: Item { fn serialized_item_kind() -> &'static str; fn cleanup( workspace_id: WorkspaceId, alive_items: Vec<ItemId>, cx: &mut WindowContext, ) -> Task<Result<()>>; fn deserialize( _project: Model<Project>, _workspace: WeakView<Workspace>, _workspace_id: WorkspaceId, _item_id: ItemId, _cx: &mut WindowContext, ) -> Task<Result<View<Self>>>; fn serialize( &mut self, workspace: &mut Workspace, item_id: ItemId, closing: bool, cx: &mut ViewContext<Self>, ) -> Option<Task<Result<()>>>; fn should_serialize(&self, event: &Self::Event) -> bool; } pub trait SerializableItemHandle: ItemHandle { fn serialized_item_kind(&self) -> &'static str; fn serialize( &self, workspace: &mut Workspace, closing: bool, cx: &mut WindowContext, ) -> Option<Task<Result<()>>>; fn should_serialize(&self, event: &dyn Any, cx: &AppContext) -> bool; } impl<T> SerializableItemHandle for View<T> where T: SerializableItem, { fn serialized_item_kind(&self) -> &'static str { T::serialized_item_kind() } fn serialize( &self, workspace: &mut Workspace, closing: bool, cx: &mut WindowContext, ) -> Option<Task<Result<()>>> { self.update(cx, |this, cx| { this.serialize(workspace, cx.entity_id().as_u64(), closing, cx) }) } fn should_serialize(&self, event: &dyn Any, cx: &AppContext) -> bool { event .downcast_ref::<T::Event>() .map_or(false, |event| self.read(cx).should_serialize(event)) } } pub trait ItemHandle: 'static + Send { fn subscribe_to_item_events( &self, cx: &mut WindowContext, handler: Box<dyn Fn(ItemEvent, &mut WindowContext)>, ) -> gpui::Subscription; fn focus_handle(&self, cx: &WindowContext) -> FocusHandle; fn tab_description(&self, detail: usize, cx: &AppContext) -> Option<SharedString>; fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement; fn tab_icon(&self, cx: &WindowContext) -> Option<Icon>; fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString>; fn tab_tooltip_content(&self, cx: &AppContext) -> Option<TabTooltipContent>; fn telemetry_event_text(&self, cx: &WindowContext) -> Option<&'static str>; fn dragged_tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement; fn project_path(&self, cx: &AppContext) -> Option<ProjectPath>; fn project_entry_ids(&self, cx: &AppContext) -> SmallVec<[ProjectEntryId; 3]>; fn project_paths(&self, cx: &AppContext) -> SmallVec<[ProjectPath; 3]>; fn project_item_model_ids(&self, cx: &AppContext) -> SmallVec<[EntityId; 3]>; fn for_each_project_item( &self, _: &AppContext, _: &mut dyn FnMut(EntityId, &dyn project::ProjectItem), ); fn is_singleton(&self, cx: &AppContext) -> bool; fn boxed_clone(&self) -> Box<dyn ItemHandle>; fn clone_on_split( &self, workspace_id: Option<WorkspaceId>, cx: &mut WindowContext, ) -> Option<Box<dyn ItemHandle>>; fn added_to_pane( &self, workspace: &mut Workspace, pane: View<Pane>, cx: &mut ViewContext<Workspace>, ); fn deactivated(&self, cx: &mut WindowContext); fn discarded(&self, project: Model<Project>, cx: &mut WindowContext); fn workspace_deactivated(&self, cx: &mut WindowContext); fn navigate(&self, data: Box<dyn Any>, cx: &mut WindowContext) -> bool; fn item_id(&self) -> EntityId; fn to_any(&self) -> AnyView; fn is_dirty(&self, cx: &AppContext) -> bool; fn has_deleted_file(&self, cx: &AppContext) -> bool; fn has_conflict(&self, cx: &AppContext) -> bool; fn can_save(&self, cx: &AppContext) -> bool; fn save( &self, format: bool, project: Model<Project>, cx: &mut WindowContext, ) -> Task<Result<()>>; fn save_as( &self, project: Model<Project>, path: ProjectPath, cx: &mut WindowContext, ) -> Task<Result<()>>; fn reload(&self, project: Model<Project>, cx: &mut WindowContext) -> Task<Result<()>>; fn act_as_type(&self, type_id: TypeId, cx: &AppContext) -> Option<AnyView>; fn to_followable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn FollowableItemHandle>>; fn to_serializable_item_handle( &self, cx: &AppContext, ) -> Option<Box<dyn SerializableItemHandle>>; fn on_release( &self, cx: &mut AppContext, callback: Box<dyn FnOnce(&mut AppContext) + Send>, ) -> gpui::Subscription; fn to_searchable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>; fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation; fn breadcrumbs(&self, theme: &Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>>; fn show_toolbar(&self, cx: &AppContext) -> bool; fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Point<Pixels>>; fn downgrade_item(&self) -> Box<dyn WeakItemHandle>; fn workspace_settings<'a>(&self, cx: &'a AppContext) -> &'a WorkspaceSettings; fn preserve_preview(&self, cx: &AppContext) -> bool; fn include_in_nav_history(&self) -> bool; } pub trait WeakItemHandle: Send + Sync { fn id(&self) -> EntityId; fn boxed_clone(&self) -> Box<dyn WeakItemHandle>; fn upgrade(&self) -> Option<Box<dyn ItemHandle>>; } impl dyn ItemHandle { pub fn downcast<V: 'static>(&self) -> Option<View<V>> {