From a97c8bf58f7d650b4f846681fb36313bab7c0a09 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Wed, 8 Nov 2023 19:29:00 -0800 Subject: [PATCH] Get workspace compiling with new event emitters --- Cargo.lock | 1 - crates/call2/src/call2.rs | 5 +- crates/call2/src/room.rs | 4 +- crates/channel2/src/channel_buffer.rs | 4 +- crates/channel2/src/channel_chat.rs | 4 +- crates/channel2/src/channel_store.rs | 4 +- crates/client2/src/user.rs | 4 +- crates/copilot2/src/copilot2.rs | 4 +- crates/editor2/src/editor.rs | 4 +- crates/gpui2/src/app.rs | 2 +- crates/gpui2/src/window.rs | 18 ---- crates/language2/src/buffer.rs | 4 +- crates/multi_buffer2/src/multi_buffer2.rs | 4 +- crates/picker2/Cargo.toml | 2 - crates/project2/src/project2.rs | 4 +- crates/project2/src/worktree.rs | 4 +- crates/terminal2/src/terminal2.rs | 4 +- crates/workspace2/src/dock.rs | 115 ++++++++-------------- crates/workspace2/src/item.rs | 106 ++++++++++---------- crates/workspace2/src/notifications.rs | 38 +++---- crates/workspace2/src/pane.rs | 76 +++++++------- crates/workspace2/src/searchable.rs | 23 ++--- crates/workspace2/src/toolbar.rs | 32 +++--- crates/workspace2/src/workspace2.rs | 77 ++++++++------- 24 files changed, 224 insertions(+), 319 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2787475e83..6058497013 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6109,7 +6109,6 @@ dependencies = [ "settings2", "theme2", "util", - "workspace2", ] [[package]] diff --git a/crates/call2/src/call2.rs b/crates/call2/src/call2.rs index b19720bcdc..2fab3d40ce 100644 --- a/crates/call2/src/call2.rs +++ b/crates/call2/src/call2.rs @@ -17,6 +17,7 @@ use gpui::{ }; use postage::watch; use project::Project; +use room::Event; use settings::Settings; use std::sync::Arc; @@ -85,9 +86,7 @@ pub struct ActiveCall { _subscriptions: Vec, } -impl EventEmitter for ActiveCall { - type Event = room::Event; -} +impl EventEmitter for ActiveCall {} impl ActiveCall { fn new(client: Arc, user_store: Model, cx: &mut ModelContext) -> Self { diff --git a/crates/call2/src/room.rs b/crates/call2/src/room.rs index 27bc51a277..87118764fd 100644 --- a/crates/call2/src/room.rs +++ b/crates/call2/src/room.rs @@ -79,9 +79,7 @@ pub struct Room { maintain_connection: Option>>, } -impl EventEmitter for Room { - type Event = Event; -} +impl EventEmitter for Room {} impl Room { pub fn channel_id(&self) -> Option { diff --git a/crates/channel2/src/channel_buffer.rs b/crates/channel2/src/channel_buffer.rs index 4c321a8fbc..764f5f7661 100644 --- a/crates/channel2/src/channel_buffer.rs +++ b/crates/channel2/src/channel_buffer.rs @@ -38,9 +38,7 @@ pub enum ChannelBufferEvent { ChannelChanged, } -impl EventEmitter for ChannelBuffer { - type Event = ChannelBufferEvent; -} +impl EventEmitter for ChannelBuffer {} impl ChannelBuffer { pub(crate) async fn new( diff --git a/crates/channel2/src/channel_chat.rs b/crates/channel2/src/channel_chat.rs index a5b5249853..eb92eb18e4 100644 --- a/crates/channel2/src/channel_chat.rs +++ b/crates/channel2/src/channel_chat.rs @@ -76,9 +76,7 @@ pub enum ChannelChatEvent { }, } -impl EventEmitter for ChannelChat { - type Event = ChannelChatEvent; -} +impl EventEmitter for ChannelChat {} pub fn init(client: &Arc) { client.add_model_message_handler(ChannelChat::handle_message_sent); client.add_model_message_handler(ChannelChat::handle_message_removed); diff --git a/crates/channel2/src/channel_store.rs b/crates/channel2/src/channel_store.rs index 3c9abd59e2..5fcc2b9566 100644 --- a/crates/channel2/src/channel_store.rs +++ b/crates/channel2/src/channel_store.rs @@ -114,9 +114,7 @@ pub enum ChannelEvent { ChannelRenamed(ChannelId), } -impl EventEmitter for ChannelStore { - type Event = ChannelEvent; -} +impl EventEmitter for ChannelStore {} enum OpenedModelHandle { Open(WeakModel), diff --git a/crates/client2/src/user.rs b/crates/client2/src/user.rs index 8ff134e6b7..a5dba03d2d 100644 --- a/crates/client2/src/user.rs +++ b/crates/client2/src/user.rs @@ -103,9 +103,7 @@ pub enum ContactEventKind { Cancelled, } -impl EventEmitter for UserStore { - type Event = Event; -} +impl EventEmitter for UserStore {} enum UpdateContacts { Update(proto::UpdateContacts), diff --git a/crates/copilot2/src/copilot2.rs b/crates/copilot2/src/copilot2.rs index 9e82823b9b..2daf2fec12 100644 --- a/crates/copilot2/src/copilot2.rs +++ b/crates/copilot2/src/copilot2.rs @@ -284,9 +284,7 @@ pub enum Event { CopilotLanguageServerStarted, } -impl EventEmitter for Copilot { - type Event = Event; -} +impl EventEmitter for Copilot {} impl Copilot { pub fn global(cx: &AppContext) -> Option> { diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 049d304750..5bb765e1e0 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -9407,9 +9407,7 @@ pub struct EditorReleased(pub WeakView); // } // } // -impl EventEmitter for Editor { - type Event = Event; -} +impl EventEmitter for Editor {} impl Render for Editor { type Element = EditorElement; diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 9673f946a8..c36fe02f30 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -201,7 +201,7 @@ pub struct AppContext { pub(crate) pending_notifications: HashSet, pub(crate) pending_global_notifications: HashSet, pub(crate) observers: SubscriberSet, - // (Entity, Event Type) + // TypeId is the type of the event that the listener callback expects pub(crate) event_listeners: SubscriberSet, pub(crate) release_listeners: SubscriberSet, pub(crate) global_observers: SubscriberSet, diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 0392c0e83c..405d7c5bd1 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1813,24 +1813,6 @@ impl<'a, V: 'static> ViewContext<'a, V> { ) } - // Options for simplifying this new event API: - // - // - Make a new stlye of API which does partial application of the arguments to capture - // the types involved e.g. - // `cx.for_entity(handle).subscribe::(..)` - // - // - Make it so there are less types: - // - Bail on this idea all together, go back to associated types. - // causes our event enums to be a blob of anything that could happen ever, and - // makes applications have some translation boilerplate - // - // - Move some of the types into the method names, - // `cx.subscribe_model::<_, ItemEvents>(handle)` - // - // - Do something drastic like removing views and models, or removing the multiple - // kind of contexts. (Not going to happen, we already tried this before.) - // - // - Accept it, and use `cx.subscribe::<_, _, ItemEvents>(handle, ...)` pub fn subscribe( &mut self, entity: &E, diff --git a/crates/language2/src/buffer.rs b/crates/language2/src/buffer.rs index b19cf97354..2c8c55d577 100644 --- a/crates/language2/src/buffer.rs +++ b/crates/language2/src/buffer.rs @@ -1815,9 +1815,7 @@ impl Buffer { } } -impl EventEmitter for Buffer { - type Event = Event; -} +impl EventEmitter for Buffer {} impl Deref for Buffer { type Target = TextBuffer; diff --git a/crates/multi_buffer2/src/multi_buffer2.rs b/crates/multi_buffer2/src/multi_buffer2.rs index df33f98b4b..a38d36f02f 100644 --- a/crates/multi_buffer2/src/multi_buffer2.rs +++ b/crates/multi_buffer2/src/multi_buffer2.rs @@ -1872,9 +1872,7 @@ impl MultiBuffer { } } -impl EventEmitter for MultiBuffer { - type Event = Event; -} +impl EventEmitter for MultiBuffer {} impl MultiBufferSnapshot { pub fn text(&self) -> String { diff --git a/crates/picker2/Cargo.toml b/crates/picker2/Cargo.toml index 8d88c25366..90e1ae931c 100644 --- a/crates/picker2/Cargo.toml +++ b/crates/picker2/Cargo.toml @@ -15,7 +15,6 @@ menu = { package = "menu2", path = "../menu2" } settings = { package = "settings2", path = "../settings2" } util = { path = "../util" } theme = { package = "theme2", path = "../theme2" } -workspace = { package = "workspace2", path = "../workspace2" } parking_lot.workspace = true @@ -23,6 +22,5 @@ parking_lot.workspace = true editor = { package = "editor2", path = "../editor2", features = ["test-support"] } gpui = { package = "gpui2", path = "../gpui2", features = ["test-support"] } serde_json.workspace = true -workspace = { package = "workspace2", path = "../workspace2", features = ["test-support"] } ctor.workspace = true env_logger.workspace = true diff --git a/crates/project2/src/project2.rs b/crates/project2/src/project2.rs index 5d7c976e77..95f04dfc82 100644 --- a/crates/project2/src/project2.rs +++ b/crates/project2/src/project2.rs @@ -9062,9 +9062,7 @@ impl<'a> Iterator for PathMatchCandidateSetIter<'a> { } } -impl EventEmitter for Project { - type Event = Event; -} +impl EventEmitter for Project {} impl> From<(WorktreeId, P)> for ProjectPath { fn from((worktree_id, path): (WorktreeId, P)) -> Self { diff --git a/crates/project2/src/worktree.rs b/crates/project2/src/worktree.rs index 937a549a31..65959d3f31 100644 --- a/crates/project2/src/worktree.rs +++ b/crates/project2/src/worktree.rs @@ -281,9 +281,7 @@ pub enum Event { UpdatedGitRepositories(UpdatedGitRepositoriesSet), } -impl EventEmitter for Worktree { - type Event = Event; -} +impl EventEmitter for Worktree {} impl Worktree { pub async fn local( diff --git a/crates/terminal2/src/terminal2.rs b/crates/terminal2/src/terminal2.rs index 3d06b48812..9f94339504 100644 --- a/crates/terminal2/src/terminal2.rs +++ b/crates/terminal2/src/terminal2.rs @@ -1351,9 +1351,7 @@ impl Drop for Terminal { } } -impl EventEmitter for Terminal { - type Event = Event; -} +impl EventEmitter for Terminal {} /// Based on alacritty/src/display/hint.rs > regex_match_at /// Retrieve the match, if the specified point is inside the content matching the regex. diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index e6b6c7561d..14646b55ac 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -7,7 +7,16 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::sync::Arc; -pub trait Panel: Render + EventEmitter { +pub enum PanelEvent { + ChangePosition, + ZoomIn, + ZoomOut, + Activate, + Close, + Focus, +} + +pub trait Panel: Render + EventEmitter { fn persistent_name(&self) -> &'static str; fn position(&self, cx: &WindowContext) -> DockPosition; fn position_is_valid(&self, position: DockPosition) -> bool; @@ -19,26 +28,12 @@ pub trait Panel: Render + EventEmitter { fn icon_label(&self, _: &WindowContext) -> Option { None } - fn should_change_position_on_event(_: &Self::Event) -> bool; - fn should_zoom_in_on_event(_: &Self::Event) -> bool { - false - } - fn should_zoom_out_on_event(_: &Self::Event) -> bool { - false - } fn is_zoomed(&self, _cx: &WindowContext) -> bool { false } fn set_zoomed(&mut self, _zoomed: bool, _cx: &mut ViewContext) {} fn set_active(&mut self, _active: bool, _cx: &mut ViewContext) {} - fn should_activate_on_event(_: &Self::Event) -> bool { - false - } - fn should_close_on_event(_: &Self::Event) -> bool { - false - } fn has_focus(&self, cx: &WindowContext) -> bool; - fn is_focus_event(_: &Self::Event) -> bool; } pub trait PanelHandle: Send + Sync { @@ -268,21 +263,37 @@ impl Dock { let subscriptions = [ cx.observe(&panel, |_, _, cx| cx.notify()), cx.subscribe(&panel, |this, panel, event, cx| { - if T::should_activate_on_event(event) { - if let Some(ix) = this - .panel_entries - .iter() - .position(|entry| entry.panel.id() == panel.id()) - { - this.set_open(true, cx); - this.activate_panel(ix, cx); - // todo!() - // cx.focus(&panel); + match event { + PanelEvent::ChangePosition => { + //todo!() + // see: Workspace::add_panel_with_extra_event_handler } - } else if T::should_close_on_event(event) - && this.visible_panel().map_or(false, |p| p.id() == panel.id()) - { - this.set_open(false, cx); + PanelEvent::ZoomIn => { + //todo!() + // see: Workspace::add_panel_with_extra_event_handler + } + PanelEvent::ZoomOut => { + // todo!() + // // see: Workspace::add_panel_with_extra_event_handler + } + PanelEvent::Activate => { + if let Some(ix) = this + .panel_entries + .iter() + .position(|entry| entry.panel.id() == panel.id()) + { + this.set_open(true, cx); + this.activate_panel(ix, cx); + //` todo!() + // cx.focus(&panel); + } + } + PanelEvent::Close => { + if this.visible_panel().map_or(false, |p| p.id() == panel.id()) { + this.set_open(false, cx); + } + } + PanelEvent::Focus => todo!(), } }), ]; @@ -452,10 +463,6 @@ impl PanelButtons { } } -impl EventEmitter for PanelButtons { - type Event = (); -} - // impl Render for PanelButtons { // type Element = (); @@ -625,7 +632,7 @@ impl StatusItemView for PanelButtons { _active_pane_item: Option<&dyn crate::ItemHandle>, _cx: &mut ViewContext, ) { - // todo!(This is empty in the old `workspace::dock`) + // Nothing to do, panel buttons don't depend on the active center item } } @@ -634,16 +641,6 @@ pub mod test { use super::*; use gpui::{div, Div, ViewContext, WindowContext}; - #[derive(Debug)] - pub enum TestPanelEvent { - PositionChanged, - Activated, - Closed, - ZoomIn, - ZoomOut, - Focus, - } - pub struct TestPanel { pub position: DockPosition, pub zoomed: bool, @@ -652,9 +649,7 @@ pub mod test { pub size: f32, } - impl EventEmitter for TestPanel { - type Event = TestPanelEvent; - } + impl EventEmitter for TestPanel {} impl TestPanel { pub fn new(position: DockPosition) -> Self { @@ -691,7 +686,7 @@ pub mod test { fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext) { self.position = position; - cx.emit(TestPanelEvent::PositionChanged); + cx.emit(PanelEvent::ChangePosition); } fn size(&self, _: &WindowContext) -> f32 { @@ -710,18 +705,6 @@ pub mod test { ("Test Panel".into(), None) } - fn should_change_position_on_event(event: &Self::Event) -> bool { - matches!(event, TestPanelEvent::PositionChanged) - } - - fn should_zoom_in_on_event(event: &Self::Event) -> bool { - matches!(event, TestPanelEvent::ZoomIn) - } - - fn should_zoom_out_on_event(event: &Self::Event) -> bool { - matches!(event, TestPanelEvent::ZoomOut) - } - fn is_zoomed(&self, _: &WindowContext) -> bool { self.zoomed } @@ -734,20 +717,8 @@ pub mod test { self.active = active; } - fn should_activate_on_event(event: &Self::Event) -> bool { - matches!(event, TestPanelEvent::Activated) - } - - fn should_close_on_event(event: &Self::Event) -> bool { - matches!(event, TestPanelEvent::Closed) - } - fn has_focus(&self, _cx: &WindowContext) -> bool { self.has_focus } - - fn is_focus_event(event: &Self::Event) -> bool { - matches!(event, TestPanelEvent::Focus) - } } } diff --git a/crates/workspace2/src/item.rs b/crates/workspace2/src/item.rs index 1a7f30646d..2b750a9861 100644 --- a/crates/workspace2/src/item.rs +++ b/crates/workspace2/src/item.rs @@ -91,7 +91,7 @@ pub struct BreadcrumbText { pub highlights: Option, HighlightStyle)>>, } -pub trait Item: Render + EventEmitter { +pub trait Item: Render + EventEmitter { fn focus_handle(&self) -> FocusHandle; fn deactivated(&mut self, _: &mut ViewContext) {} fn workspace_deactivated(&mut self, _: &mut ViewContext) {} @@ -106,12 +106,13 @@ pub trait Item: Render + EventEmitter { } fn tab_content(&self, detail: Option, cx: &AppContext) -> AnyElement; + /// (model id, Item) fn for_each_project_item( &self, _: &AppContext, _: &mut dyn FnMut(EntityId, &dyn project2::Item), ) { - } // (model id, Item) + } fn is_singleton(&self, _cx: &AppContext) -> bool { false } @@ -153,15 +154,6 @@ pub trait Item: Render + EventEmitter { ) -> 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 act_as_type<'a>( &'a self, @@ -218,7 +210,7 @@ pub trait ItemHandle: 'static + Send { fn subscribe_to_item_events( &self, cx: &mut WindowContext, - handler: Box, + handler: Box, ) -> gpui::Subscription; fn tab_tooltip_text(&self, cx: &AppContext) -> Option; fn tab_description(&self, detail: usize, cx: &AppContext) -> Option; @@ -300,12 +292,10 @@ impl ItemHandle for View { fn subscribe_to_item_events( &self, cx: &mut WindowContext, - handler: Box, + handler: Box, ) -> gpui::Subscription { cx.subscribe(self, move |_, event, cx| { - for item_event in T::to_item_events(event) { - handler(item_event, cx) - } + handler(event, cx); }) } @@ -433,7 +423,10 @@ impl ItemHandle for View { let is_project_item = item.is_project_item(cx); let leader_id = workspace.leader_for_pane(&pane); - if leader_id.is_some() && item.should_unfollow_on_event(event, cx) { + let follow_event = item.to_follow_event(event); + if leader_id.is_some() + && matches!(follow_event, Some(FollowEvent::Unfollow)) + { workspace.unfollow(&pane, cx); } @@ -467,36 +460,34 @@ impl ItemHandle for View { } } - for item_event in T::to_item_events(event).into_iter() { - match item_event { - ItemEvent::CloseItem => { - pane.update(cx, |pane, cx| { - pane.close_item_by_id(item.id(), crate::SaveIntent::Close, cx) - }) - .detach_and_log_err(cx); - return; - } + match event { + ItemEvent::CloseItem => { + pane.update(cx, |pane, cx| { + pane.close_item_by_id(item.id(), crate::SaveIntent::Close, cx) + }) + .detach_and_log_err(cx); + return; + } - ItemEvent::UpdateTab => { - pane.update(cx, |_, cx| { - cx.emit(pane::Event::ChangeItemTitle); - cx.notify(); + ItemEvent::UpdateTab => { + pane.update(cx, |_, cx| { + cx.emit(pane::Event::ChangeItemTitle); + cx.notify(); + }); + } + + ItemEvent::Edit => { + let autosave = WorkspaceSettings::get_global(cx).autosave; + if let AutosaveSetting::AfterDelay { milliseconds } = autosave { + let delay = Duration::from_millis(milliseconds); + let item = item.clone(); + pending_autosave.fire_new(delay, cx, move |workspace, cx| { + Pane::autosave_item(&item, workspace.project().clone(), cx) }); } - - ItemEvent::Edit => { - let autosave = WorkspaceSettings::get_global(cx).autosave; - if let AutosaveSetting::AfterDelay { milliseconds } = autosave { - let delay = Duration::from_millis(milliseconds); - let item = item.clone(); - pending_autosave.fire_new(delay, cx, move |workspace, cx| { - Pane::autosave_item(&item, workspace.project().clone(), cx) - }); - } - } - - _ => {} } + + _ => {} } })); @@ -660,7 +651,16 @@ pub trait ProjectItem: Item { Self: Sized; } +pub enum FollowEvent { + Unfollow, +} + +pub trait FollowableEvents { + fn to_follow_event(&self) -> Option; +} + pub trait FollowableItem: Item { + type FollowableEvent: FollowableEvents; fn remote_id(&self) -> Option; fn to_state_proto(&self, cx: &AppContext) -> Option; fn from_state_proto( @@ -672,7 +672,7 @@ pub trait FollowableItem: Item { ) -> Option>>>; fn add_event_to_update_proto( &self, - event: &Self::Event, + event: &Self::FollowableEvent, update: &mut Option, cx: &AppContext, ) -> bool; @@ -685,7 +685,6 @@ pub trait FollowableItem: Item { fn is_project_item(&self, cx: &AppContext) -> bool; fn set_leader_peer_id(&mut self, leader_peer_id: Option, cx: &mut ViewContext); - fn should_unfollow_on_event(event: &Self::Event, cx: &AppContext) -> bool; } pub trait FollowableItemHandle: ItemHandle { @@ -698,13 +697,13 @@ pub trait FollowableItemHandle: ItemHandle { update: &mut Option, cx: &AppContext, ) -> bool; + fn to_follow_event(&self, event: &dyn Any) -> Option; fn apply_update_proto( &self, project: &Model, message: proto::update_view::Variant, cx: &mut WindowContext, ) -> Task>; - fn should_unfollow_on_event(&self, event: &dyn Any, cx: &AppContext) -> bool; fn is_project_item(&self, cx: &AppContext) -> bool; } @@ -739,6 +738,13 @@ impl FollowableItemHandle for View { } } + fn to_follow_event(&self, event: &dyn Any) -> Option { + event + .downcast_ref() + .map(T::FollowableEvent::to_follow_event) + .flatten() + } + fn apply_update_proto( &self, project: &Model, @@ -748,14 +754,6 @@ impl FollowableItemHandle for View { self.update(cx, |this, cx| this.apply_update_proto(project, message, cx)) } - fn should_unfollow_on_event(&self, event: &dyn Any, cx: &AppContext) -> bool { - if let Some(event) = event.downcast_ref() { - T::should_unfollow_on_event(event, cx) - } else { - false - } - } - fn is_project_item(&self, cx: &AppContext) -> bool { self.read(cx).is_project_item(cx) } diff --git a/crates/workspace2/src/notifications.rs b/crates/workspace2/src/notifications.rs index 5dd5b2c7ae..7277cc6fc4 100644 --- a/crates/workspace2/src/notifications.rs +++ b/crates/workspace2/src/notifications.rs @@ -9,10 +9,12 @@ pub fn init(cx: &mut AppContext) { // simple_message_notification::init(cx); } -pub trait Notification: EventEmitter + Render { - fn should_dismiss_notification_on_event(&self, event: &Self::Event) -> bool; +pub enum NotificationEvent { + Dismiss, } +pub trait Notification: EventEmitter + Render {} + pub trait NotificationHandle: Send { fn id(&self) -> EntityId; fn to_any(&self) -> AnyView; @@ -101,11 +103,14 @@ impl Workspace { }) { let notification = build_notification(cx); - cx.subscribe(¬ification, move |this, handle, event, cx| { - if handle.read(cx).should_dismiss_notification_on_event(event) { - this.dismiss_notification_internal(type_id, id, cx); - } - }) + cx.subscribe( + ¬ification, + move |this, handle, event: &NotificationEvent, cx| match event { + NotificationEvent::Dismiss => { + this.dismiss_notification_internal(type_id, id, cx); + } + }, + ) .detach(); self.notifications .push((type_id, id, Box::new(notification))); @@ -159,7 +164,7 @@ impl Workspace { } pub mod simple_message_notification { - use super::Notification; + use super::{Notification, NotificationEvent}; use gpui::{AnyElement, AppContext, Div, EventEmitter, Render, TextStyle, ViewContext}; use serde::Deserialize; use std::{borrow::Cow, sync::Arc}; @@ -200,13 +205,7 @@ pub mod simple_message_notification { click_message: Option>, } - pub enum MessageNotificationEvent { - Dismiss, - } - - impl EventEmitter for MessageNotification { - type Event = MessageNotificationEvent; - } + impl EventEmitter for MessageNotification {} impl MessageNotification { pub fn new(message: S) -> MessageNotification @@ -359,13 +358,8 @@ pub mod simple_message_notification { // } // } - impl Notification for MessageNotification { - fn should_dismiss_notification_on_event(&self, event: &Self::Event) -> bool { - match event { - MessageNotificationEvent::Dismiss => true, - } - } - } + impl EventEmitter for MessageNotification {} + impl Notification for MessageNotification {} } pub trait NotifyResultExt { diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 5af5514da4..2bba684d12 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -9,8 +9,9 @@ use crate::{ use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; use gpui::{ - AppContext, AsyncWindowContext, Component, Div, EntityId, EventEmitter, FocusHandle, Model, - PromptLevel, Render, Task, View, ViewContext, VisualContext, WeakView, WindowContext, + actions, register_action, AppContext, AsyncWindowContext, Component, Div, EntityId, + EventEmitter, FocusHandle, Model, PromptLevel, Render, Task, View, ViewContext, VisualContext, + WeakView, WindowContext, }; use parking_lot::Mutex; use project2::{Project, ProjectEntryId, ProjectPath}; @@ -48,8 +49,10 @@ pub enum SaveIntent { Skip, } -// #[derive(Clone, Deserialize, PartialEq)] -// pub struct ActivateItem(pub usize); +//todo!("Do we need the default bound on actions? Decide soon") +// #[register_action] +#[derive(Clone, Deserialize, PartialEq, Debug)] +pub struct ActivateItem(pub usize); // #[derive(Clone, PartialEq)] // pub struct CloseItemById { @@ -69,40 +72,37 @@ pub enum SaveIntent { // pub pane: WeakView, // } -// #[derive(Clone, PartialEq, Debug, Deserialize, Default)] -// #[serde(rename_all = "camelCase")] -// pub struct CloseActiveItem { -// pub save_intent: Option, -// } +#[register_action] +#[derive(Clone, PartialEq, Debug, Deserialize, Default)] +#[serde(rename_all = "camelCase")] +pub struct CloseActiveItem { + pub save_intent: Option, +} -// #[derive(Clone, PartialEq, Debug, Deserialize)] -// #[serde(rename_all = "camelCase")] -// pub struct CloseAllItems { -// pub save_intent: Option, -// } +#[register_action] +#[derive(Clone, PartialEq, Debug, Deserialize, Default)] +#[serde(rename_all = "camelCase")] +pub struct CloseAllItems { + pub save_intent: Option, +} -// todo!() -// actions!( -// pane, -// [ -// ActivatePrevItem, -// ActivateNextItem, -// ActivateLastItem, -// CloseInactiveItems, -// CloseCleanItems, -// CloseItemsToTheLeft, -// CloseItemsToTheRight, -// GoBack, -// GoForward, -// ReopenClosedItem, -// SplitLeft, -// SplitUp, -// SplitRight, -// SplitDown, -// ] -// ); - -// impl_actions!(pane, [ActivateItem, CloseActiveItem, CloseAllItems]); +// todo!(These used to be under pane::{Action}. Are they now workspace::pane::{Action}?) +actions!( + ActivatePrevItem, + ActivateNextItem, + ActivateLastItem, + CloseInactiveItems, + CloseCleanItems, + CloseItemsToTheLeft, + CloseItemsToTheRight, + GoBack, + GoForward, + ReopenClosedItem, + SplitLeft, + SplitUp, + SplitRight, + SplitDown, +); const MAX_NAVIGATION_HISTORY_LEN: usize = 1024; @@ -310,9 +310,7 @@ pub struct NavigationEntry { // .into_any_named("nav button") // } -impl EventEmitter for Pane { - type Event = Event; -} +impl EventEmitter for Pane {} impl Pane { pub fn new( diff --git a/crates/workspace2/src/searchable.rs b/crates/workspace2/src/searchable.rs index 2b870c2944..2a393a9f6d 100644 --- a/crates/workspace2/src/searchable.rs +++ b/crates/workspace2/src/searchable.rs @@ -1,6 +1,8 @@ use std::{any::Any, sync::Arc}; -use gpui::{AnyView, AppContext, Subscription, Task, View, ViewContext, WindowContext}; +use gpui::{ + AnyView, AppContext, EventEmitter, Subscription, Task, View, ViewContext, WindowContext, +}; use project2::search::SearchQuery; use crate::{ @@ -29,7 +31,7 @@ pub struct SearchOptions { pub replacement: bool, } -pub trait SearchableItem: Item { +pub trait SearchableItem: Item + EventEmitter { type Match: Any + Sync + Send + Clone; fn supported_options() -> SearchOptions { @@ -40,11 +42,7 @@ pub trait SearchableItem: Item { replacement: true, } } - fn to_search_event( - &mut self, - event: &Self::Event, - cx: &mut ViewContext, - ) -> Option; + fn clear_matches(&mut self, cx: &mut ViewContext); fn update_matches(&mut self, matches: Vec, cx: &mut ViewContext); fn query_suggestion(&mut self, cx: &mut ViewContext) -> String; @@ -95,7 +93,7 @@ pub trait SearchableItemHandle: ItemHandle { fn subscribe_to_search_events( &self, cx: &mut WindowContext, - handler: Box, + handler: Box, ) -> Subscription; fn clear_matches(&self, cx: &mut WindowContext); fn update_matches(&self, matches: &Vec>, cx: &mut WindowContext); @@ -146,14 +144,9 @@ impl SearchableItemHandle for View { fn subscribe_to_search_events( &self, cx: &mut WindowContext, - handler: Box, + handler: Box, ) -> Subscription { - cx.subscribe(self, move |handle, event, cx| { - let search_event = handle.update(cx, |handle, cx| handle.to_search_event(event, cx)); - if let Some(search_event) = search_event { - handler(search_event, cx) - } - }) + cx.subscribe(self, move |_, event: &SearchEvent, cx| handler(event, cx)) } fn clear_matches(&self, cx: &mut WindowContext) { diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index 80503ad7bb..1e45a17897 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -1,24 +1,17 @@ use crate::ItemHandle; -use gpui::{ - AnyView, AppContext, Entity, EntityId, EventEmitter, Render, View, ViewContext, WindowContext, -}; +use gpui::{AnyView, Entity, EntityId, EventEmitter, Render, View, ViewContext, WindowContext}; -pub trait ToolbarItemView: Render + EventEmitter { +pub enum ToolbarItemEvent { + ChangeLocation(ToolbarItemLocation), +} + +pub trait ToolbarItemView: Render + EventEmitter { fn set_active_pane_item( &mut self, active_pane_item: Option<&dyn crate::ItemHandle>, cx: &mut ViewContext, ) -> ToolbarItemLocation; - fn location_for_event( - &self, - _event: &Self::Event, - current_location: ToolbarItemLocation, - _cx: &AppContext, - ) -> ToolbarItemLocation { - current_location - } - fn pane_focus_update(&mut self, _pane_focused: bool, _cx: &mut ViewContext) {} /// Number of times toolbar's height will be repeated to get the effective height. @@ -211,12 +204,13 @@ impl Toolbar { if let Some((_, current_location)) = this.items.iter_mut().find(|(i, _)| i.id() == item.id()) { - let new_location = item - .read(cx) - .location_for_event(event, *current_location, cx); - if new_location != *current_location { - *current_location = new_location; - cx.notify(); + match event { + ToolbarItemEvent::ChangeLocation(new_location) => { + if new_location != current_location { + *current_location = *new_location; + cx.notify(); + } + } } } }) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index bc2c649637..cc40659354 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -36,7 +36,7 @@ use futures::{ Future, FutureExt, StreamExt, }; use gpui::{ - div, point, rems, size, AnyModel, AnyView, AnyWeakView, AppContext, AsyncAppContext, + actions, div, point, rems, size, AnyModel, AnyView, AnyWeakView, AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Component, Div, Entity, EntityId, EventEmitter, FocusHandle, GlobalPixels, Model, ModelContext, ParentElement, Point, Render, Size, StatefulInteractive, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowBounds, @@ -88,35 +88,32 @@ lazy_static! { // #[derive(Clone, PartialEq)] // pub struct RemoveWorktreeFromProject(pub WorktreeId); -// actions!( -// workspace, -// [ -// Open, -// NewFile, -// NewWindow, -// CloseWindow, -// CloseInactiveTabsAndPanes, -// AddFolderToProject, -// Unfollow, -// SaveAs, -// ReloadActiveItem, -// ActivatePreviousPane, -// ActivateNextPane, -// FollowNextCollaborator, -// NewTerminal, -// NewCenterTerminal, -// ToggleTerminalFocus, -// NewSearch, -// Feedback, -// Restart, -// Welcome, -// ToggleZoom, -// ToggleLeftDock, -// ToggleRightDock, -// ToggleBottomDock, -// CloseAllDocks, -// ] -// ); +actions!( + Open, + NewFile, + NewWindow, + CloseWindow, + CloseInactiveTabsAndPanes, + AddFolderToProject, + Unfollow, + SaveAs, + ReloadActiveItem, + ActivatePreviousPane, + ActivateNextPane, + FollowNextCollaborator, + NewTerminal, + NewCenterTerminal, + ToggleTerminalFocus, + NewSearch, + Feedback, + Restart, + Welcome, + ToggleZoom, + ToggleLeftDock, + ToggleRightDock, + ToggleBottomDock, + CloseAllDocks, +); // #[derive(Clone, PartialEq)] // pub struct OpenPaths { @@ -964,6 +961,9 @@ impl Workspace { // let mut prev_position = panel.position(cx); // move |this, panel, event, cx| { // if T::should_change_position_on_event(event) { + // THIS HAS BEEN MOVED TO NORMAL EVENT EMISSION + // See: Dock::add_panel + // // let new_position = panel.read(cx).position(cx); // let mut was_visible = false; // dock.update(cx, |dock, cx| { @@ -994,6 +994,9 @@ impl Workspace { // } // }); // } else if T::should_zoom_in_on_event(event) { + // THIS HAS BEEN MOVED TO NORMAL EVENT EMISSION + // See: Dock::add_panel + // // dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, true, cx)); // if !panel.has_focus(cx) { // cx.focus(&panel); @@ -1001,6 +1004,9 @@ impl Workspace { // this.zoomed = Some(panel.downgrade().into_any()); // this.zoomed_position = Some(panel.read(cx).position(cx)); // } else if T::should_zoom_out_on_event(event) { + // THIS HAS BEEN MOVED TO NORMAL EVENT EMISSION + // See: Dock::add_panel + // // dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, false, cx)); // if this.zoomed_position == Some(prev_position) { // this.zoomed = None; @@ -1008,6 +1014,9 @@ impl Workspace { // } // cx.notify(); // } else if T::is_focus_event(event) { + // THIS HAS BEEN MOVED TO NORMAL EVENT EMISSION + // See: Dock::add_panel + // // let position = panel.read(cx).position(cx); // this.dismiss_zoomed_items_to_reveal(Some(position), cx); // if panel.is_zoomed(cx) { @@ -3691,9 +3700,7 @@ fn notify_if_database_failed(workspace: WindowHandle, cx: &mut AsyncA .log_err(); } -impl EventEmitter for Workspace { - type Event = Event; -} +impl EventEmitter for Workspace {} impl Render for Workspace { type Element = Div; @@ -4135,10 +4142,6 @@ impl WorkspaceStore { } } -impl EventEmitter for WorkspaceStore { - type Event = (); -} - impl ViewId { pub(crate) fn from_proto(message: proto::ViewId) -> Result { Ok(Self {