Detailed changes
@@ -88,7 +88,7 @@ struct DiagnosticGroupState {
block_count: usize,
}
-impl EventEmitter<ItemEvent> for ProjectDiagnosticsEditor {}
+impl EventEmitter<EditorEvent> for ProjectDiagnosticsEditor {}
impl Render for ProjectDiagnosticsEditor {
type Element = Focusable<Div>;
@@ -158,7 +158,7 @@ impl ProjectDiagnosticsEditor {
});
let editor_event_subscription =
cx.subscribe(&editor, |this, _editor, event: &EditorEvent, cx| {
- Self::emit_item_event_for_editor_event(event, cx);
+ cx.emit(event.clone());
if event == &EditorEvent::Focused && this.path_states.is_empty() {
cx.focus(&this.focus_handle);
}
@@ -183,40 +183,6 @@ impl ProjectDiagnosticsEditor {
this
}
- fn emit_item_event_for_editor_event(event: &EditorEvent, cx: &mut ViewContext<Self>) {
- match event {
- EditorEvent::Closed => cx.emit(ItemEvent::CloseItem),
-
- EditorEvent::Saved | EditorEvent::TitleChanged => {
- cx.emit(ItemEvent::UpdateTab);
- cx.emit(ItemEvent::UpdateBreadcrumbs);
- }
-
- EditorEvent::Reparsed => {
- cx.emit(ItemEvent::UpdateBreadcrumbs);
- }
-
- EditorEvent::SelectionsChanged { local } if *local => {
- cx.emit(ItemEvent::UpdateBreadcrumbs);
- }
-
- EditorEvent::DirtyChanged => {
- cx.emit(ItemEvent::UpdateTab);
- }
-
- EditorEvent::BufferEdited => {
- cx.emit(ItemEvent::Edit);
- cx.emit(ItemEvent::UpdateBreadcrumbs);
- }
-
- EditorEvent::ExcerptsAdded { .. } | EditorEvent::ExcerptsRemoved { .. } => {
- cx.emit(ItemEvent::Edit);
- }
-
- _ => {}
- }
- }
-
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
if let Some(existing) = workspace.item_of_type::<ProjectDiagnosticsEditor>(cx) {
workspace.activate_item(&existing, cx);
@@ -333,8 +299,7 @@ impl ProjectDiagnosticsEditor {
this.update(&mut cx, |this, cx| {
this.summary = this.project.read(cx).diagnostic_summary(false, cx);
- cx.emit(ItemEvent::UpdateTab);
- cx.emit(ItemEvent::UpdateBreadcrumbs);
+ cx.emit(EditorEvent::TitleChanged);
})?;
anyhow::Ok(())
}
@@ -649,6 +614,12 @@ impl FocusableView for ProjectDiagnosticsEditor {
}
impl Item for ProjectDiagnosticsEditor {
+ type Event = EditorEvent;
+
+ fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
+ Editor::to_item_events(event, f)
+ }
+
fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
self.editor.update(cx, |editor, cx| editor.deactivated(cx));
}
@@ -1675,8 +1675,7 @@ impl Editor {
if let Some(project) = project.as_ref() {
if buffer.read(cx).is_singleton() {
project_subscriptions.push(cx.observe(project, |_, _, cx| {
- cx.emit(ItemEvent::UpdateTab);
- cx.emit(ItemEvent::UpdateBreadcrumbs);
+ cx.emit(EditorEvent::TitleChanged);
}));
}
project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
@@ -2141,10 +2140,6 @@ impl Editor {
cx.emit(SearchEvent::ActiveMatchChanged)
}
- if local {
- cx.emit(ItemEvent::UpdateBreadcrumbs);
- }
-
cx.notify();
}
@@ -8573,8 +8568,6 @@ impl Editor {
self.update_visible_copilot_suggestion(cx);
}
cx.emit(EditorEvent::BufferEdited);
- cx.emit(ItemEvent::Edit);
- cx.emit(ItemEvent::UpdateBreadcrumbs);
cx.emit(SearchEvent::MatchesInvalidated);
if *sigleton_buffer_edited {
@@ -8622,20 +8615,14 @@ impl Editor {
self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
}
- multi_buffer::Event::Reparsed => {
- cx.emit(ItemEvent::UpdateBreadcrumbs);
- }
- multi_buffer::Event::DirtyChanged => {
- cx.emit(ItemEvent::UpdateTab);
- }
- multi_buffer::Event::Saved
- | multi_buffer::Event::FileHandleChanged
- | multi_buffer::Event::Reloaded => {
- cx.emit(ItemEvent::UpdateTab);
- cx.emit(ItemEvent::UpdateBreadcrumbs);
+ multi_buffer::Event::Reparsed => cx.emit(EditorEvent::Reparsed),
+ multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
+ multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
+ multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
+ cx.emit(EditorEvent::TitleChanged)
}
multi_buffer::Event::DiffBaseChanged => cx.emit(EditorEvent::DiffBaseChanged),
- multi_buffer::Event::Closed => cx.emit(ItemEvent::CloseItem),
+ multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
multi_buffer::Event::DiagnosticsUpdated => {
self.refresh_active_diagnostics(cx);
}
@@ -32,7 +32,7 @@ use util::{
test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker},
};
use workspace::{
- item::{FollowEvent, FollowableEvents, FollowableItem, Item, ItemHandle},
+ item::{FollowEvent, FollowableItem, Item, ItemHandle},
NavigationEntry, ViewId,
};
@@ -6478,7 +6478,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
cx.subscribe(
&follower.root_view(cx).unwrap(),
move |_, _, event: &EditorEvent, cx| {
- if matches!(event.to_follow_event(), Some(FollowEvent::Unfollow)) {
+ if matches!(Editor::to_follow_event(event), Some(FollowEvent::Unfollow)) {
*is_still_following.borrow_mut() = false;
}
@@ -35,7 +35,7 @@ use theme::{ActiveTheme, Theme};
use ui::{Color, Label};
use util::{paths::PathExt, paths::FILE_ROW_COLUMN_DELIMITER, ResultExt, TryFutureExt};
use workspace::{
- item::{BreadcrumbText, FollowEvent, FollowableEvents, FollowableItemHandle},
+ item::{BreadcrumbText, FollowEvent, FollowableItemHandle},
StatusItemView,
};
use workspace::{
@@ -46,27 +46,7 @@ use workspace::{
pub const MAX_TAB_TITLE_LEN: usize = 24;
-impl FollowableEvents for EditorEvent {
- fn to_follow_event(&self) -> Option<workspace::item::FollowEvent> {
- match self {
- EditorEvent::Edited => Some(FollowEvent::Unfollow),
- EditorEvent::SelectionsChanged { local }
- | EditorEvent::ScrollPositionChanged { local, .. } => {
- if *local {
- Some(FollowEvent::Unfollow)
- } else {
- None
- }
- }
- _ => None,
- }
- }
-}
-
-impl EventEmitter<ItemEvent> for Editor {}
-
impl FollowableItem for Editor {
- type FollowableEvent = EditorEvent;
fn remote_id(&self) -> Option<ViewId> {
self.remote_id
}
@@ -241,9 +221,24 @@ impl FollowableItem for Editor {
}))
}
+ fn to_follow_event(event: &EditorEvent) -> Option<workspace::item::FollowEvent> {
+ match event {
+ EditorEvent::Edited => Some(FollowEvent::Unfollow),
+ EditorEvent::SelectionsChanged { local }
+ | EditorEvent::ScrollPositionChanged { local, .. } => {
+ if *local {
+ Some(FollowEvent::Unfollow)
+ } else {
+ None
+ }
+ }
+ _ => None,
+ }
+ }
+
fn add_event_to_update_proto(
&self,
- event: &Self::FollowableEvent,
+ event: &EditorEvent,
update: &mut Option<proto::update_view::Variant>,
cx: &WindowContext,
) -> bool {
@@ -528,6 +523,8 @@ fn deserialize_anchor(buffer: &MultiBufferSnapshot, anchor: proto::EditorAnchor)
}
impl Item for Editor {
+ type Event = EditorEvent;
+
fn navigate(&mut self, data: Box<dyn std::any::Any>, cx: &mut ViewContext<Self>) -> bool {
if let Ok(data) = data.downcast::<NavigationData>() {
let newest_selection = self.selections.newest::<Point>(cx);
@@ -841,6 +838,40 @@ impl Item for Editor {
Some("Editor")
}
+ fn to_item_events(event: &EditorEvent, mut f: impl FnMut(ItemEvent)) {
+ match event {
+ EditorEvent::Closed => f(ItemEvent::CloseItem),
+
+ EditorEvent::Saved | EditorEvent::TitleChanged => {
+ f(ItemEvent::UpdateTab);
+ f(ItemEvent::UpdateBreadcrumbs);
+ }
+
+ EditorEvent::Reparsed => {
+ f(ItemEvent::UpdateBreadcrumbs);
+ }
+
+ EditorEvent::SelectionsChanged { local } if *local => {
+ f(ItemEvent::UpdateBreadcrumbs);
+ }
+
+ EditorEvent::DirtyChanged => {
+ f(ItemEvent::UpdateTab);
+ }
+
+ EditorEvent::BufferEdited => {
+ f(ItemEvent::Edit);
+ f(ItemEvent::UpdateBreadcrumbs);
+ }
+
+ EditorEvent::ExcerptsAdded { .. } | EditorEvent::ExcerptsRemoved { .. } => {
+ f(ItemEvent::Edit);
+ }
+
+ _ => {}
+ }
+ }
+
fn deserialize(
project: Model<Project>,
_workspace: WeakView<Workspace>,
@@ -736,6 +736,8 @@ impl InputHandler for TerminalView {
}
impl Item for TerminalView {
+ type Event = ItemEvent;
+
fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString> {
Some(self.terminal().read(cx).title().into())
}
@@ -843,6 +845,10 @@ impl Item for TerminalView {
// .detach();
self.workspace_id = workspace.database_id();
}
+
+ fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
+ f(*event)
+ }
}
impl SearchableItem for TerminalView {
@@ -259,6 +259,8 @@ impl FocusableView for WelcomePage {
}
impl Item for WelcomePage {
+ type Event = ItemEvent;
+
fn tab_content(&self, _: Option<usize>, _: &WindowContext) -> AnyElement {
"Welcome to Zed!".into_any()
}
@@ -278,4 +280,8 @@ impl Item for WelcomePage {
_settings_subscription: cx.observe_global::<SettingsStore>(move |_, cx| cx.notify()),
}))
}
+
+ fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
+ f(*event)
+ }
}
@@ -78,7 +78,7 @@ impl Settings for ItemSettings {
}
}
-#[derive(Eq, PartialEq, Hash, Debug)]
+#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum ItemEvent {
CloseItem,
UpdateTab,
@@ -92,7 +92,9 @@ pub struct BreadcrumbText {
pub highlights: Option<Vec<(Range<usize>, HighlightStyle)>>,
}
-pub trait Item: FocusableView + EventEmitter<ItemEvent> {
+pub trait Item: FocusableView + EventEmitter<Self::Event> {
+ type Event;
+
fn deactivated(&mut self, _: &mut ViewContext<Self>) {}
fn workspace_deactivated(&mut self, _: &mut ViewContext<Self>) {}
fn navigate(&mut self, _: Box<dyn Any>, _: &mut ViewContext<Self>) -> bool {
@@ -155,6 +157,8 @@ pub trait Item: FocusableView + EventEmitter<ItemEvent> {
unimplemented!("reload() must be implemented if can_save() returns true")
}
+ fn to_item_events(event: &Self::Event, f: impl FnMut(ItemEvent));
+
fn act_as_type<'a>(
&'a self,
type_id: TypeId,
@@ -206,12 +210,12 @@ pub trait Item: FocusableView + EventEmitter<ItemEvent> {
}
pub trait ItemHandle: 'static + Send {
- fn focus_handle(&self, cx: &WindowContext) -> FocusHandle;
fn subscribe_to_item_events(
&self,
cx: &mut WindowContext,
- handler: Box<dyn Fn(&ItemEvent, &mut WindowContext) + Send>,
+ handler: Box<dyn Fn(ItemEvent, &mut WindowContext)>,
) -> gpui::Subscription;
+ fn focus_handle(&self, cx: &WindowContext) -> FocusHandle;
fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString>;
fn tab_description(&self, detail: usize, cx: &AppContext) -> Option<SharedString>;
fn tab_content(&self, detail: Option<usize>, cx: &WindowContext) -> AnyElement;
@@ -285,20 +289,20 @@ impl dyn ItemHandle {
}
impl<T: Item> ItemHandle for View<T> {
- fn focus_handle(&self, cx: &WindowContext) -> FocusHandle {
- self.focus_handle(cx)
- }
-
fn subscribe_to_item_events(
&self,
cx: &mut WindowContext,
- handler: Box<dyn Fn(&ItemEvent, &mut WindowContext) + Send>,
+ handler: Box<dyn Fn(ItemEvent, &mut WindowContext)>,
) -> gpui::Subscription {
cx.subscribe(self, move |_, event, cx| {
- handler(event, cx);
+ T::to_item_events(event, |item_event| handler(item_event, cx));
})
}
+ fn focus_handle(&self, cx: &WindowContext) -> FocusHandle {
+ self.focus_handle(cx)
+ }
+
fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString> {
self.read(cx).tab_tooltip_text(cx)
}
@@ -461,7 +465,7 @@ impl<T: Item> ItemHandle for View<T> {
}
}
- match event {
+ T::to_item_events(event, |event| match event {
ItemEvent::CloseItem => {
pane.update(cx, |pane, cx| {
pane.close_item_by_id(item.item_id(), crate::SaveIntent::Close, cx)
@@ -489,7 +493,7 @@ impl<T: Item> ItemHandle for View<T> {
}
_ => {}
- }
+ });
}));
cx.on_blur(&self.focus_handle(cx), move |workspace, cx| {
@@ -655,12 +659,7 @@ pub enum FollowEvent {
Unfollow,
}
-pub trait FollowableEvents {
- fn to_follow_event(&self) -> Option<FollowEvent>;
-}
-
pub trait FollowableItem: Item {
- type FollowableEvent: FollowableEvents;
fn remote_id(&self) -> Option<ViewId>;
fn to_state_proto(&self, cx: &WindowContext) -> Option<proto::view::Variant>;
fn from_state_proto(
@@ -670,9 +669,10 @@ pub trait FollowableItem: Item {
state: &mut Option<proto::view::Variant>,
cx: &mut WindowContext,
) -> Option<Task<Result<View<Self>>>>;
+ fn to_follow_event(event: &Self::Event) -> Option<FollowEvent>;
fn add_event_to_update_proto(
&self,
- event: &Self::FollowableEvent,
+ event: &Self::Event,
update: &mut Option<proto::update_view::Variant>,
cx: &WindowContext,
) -> bool;
@@ -683,7 +683,6 @@ pub trait FollowableItem: Item {
cx: &mut ViewContext<Self>,
) -> Task<Result<()>>;
fn is_project_item(&self, cx: &WindowContext) -> bool;
-
fn set_leader_peer_id(&mut self, leader_peer_id: Option<PeerId>, cx: &mut ViewContext<Self>);
}
@@ -739,10 +738,7 @@ impl<T: FollowableItem> FollowableItemHandle for View<T> {
}
fn to_follow_event(&self, event: &dyn Any) -> Option<FollowEvent> {
- event
- .downcast_ref()
- .map(T::FollowableEvent::to_follow_event)
- .flatten()
+ T::to_follow_event(event.downcast_ref()?)
}
fn apply_update_proto(
@@ -929,6 +925,12 @@ pub mod test {
}
impl Item for TestItem {
+ type Event = ItemEvent;
+
+ fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
+ f(*event)
+ }
+
fn tab_description(&self, detail: usize, _: &AppContext) -> Option<SharedString> {
self.tab_descriptions.as_ref().and_then(|descriptions| {
let description = *descriptions.get(detail).or_else(|| descriptions.last())?;
@@ -59,7 +59,6 @@ impl SharedScreen {
}
impl EventEmitter<Event> for SharedScreen {}
-impl EventEmitter<ItemEvent> for SharedScreen {}
impl FocusableView for SharedScreen {
fn focus_handle(&self, _: &AppContext) -> FocusHandle {
@@ -79,9 +78,12 @@ impl Render for SharedScreen {
}
impl Item for SharedScreen {
+ type Event = Event;
+
fn tab_tooltip_text(&self, _: &AppContext) -> Option<SharedString> {
Some(format!("{}'s screen", self.user.github_login).into())
}
+
fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
if let Some(nav_history) = self.nav_history.as_mut() {
nav_history.push::<()>(None, cx);
@@ -111,4 +113,10 @@ impl Item for SharedScreen {
let track = self.track.upgrade()?;
Some(cx.build_view(|cx| Self::new(&track, self.peer_id, self.user.clone(), cx)))
}
+
+ fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
+ match event {
+ Event::Close => f(ItemEvent::CloseItem),
+ }
+ }
}
@@ -2625,8 +2625,6 @@ impl Workspace {
update: proto::UpdateFollowers,
cx: &mut AsyncWindowContext,
) -> Result<()> {
- dbg!("process_leader_update", &update);
-
match update.variant.ok_or_else(|| anyhow!("invalid update"))? {
proto::update_followers::Variant::UpdateActiveView(update_active_view) => {
this.update(cx, |this, _| {
@@ -3880,8 +3878,6 @@ impl WorkspaceStore {
let leader_id = envelope.original_sender_id()?;
let update = envelope.payload;
- dbg!("handle_upate_followers");
-
this.update(&mut cx, |this, cx| {
for workspace in &this.workspaces {
workspace.update(cx, |workspace, cx| {