Switch from associated type to generic on EventEmitter trait (#3281)
This removes a lot of ad-hoc event translation code in the workspace and replaces it with a GPUI feature and trait bounds. TODO: - [x] Proof out idea - [x] Convert the workspace - [x] Convert the rest of the app Release Notes: - N/A
This commit is contained in:
Generated
-1
@@ -6109,7 +6109,6 @@ dependencies = [
|
||||
"settings2",
|
||||
"theme2",
|
||||
"util",
|
||||
"workspace2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -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<client::Subscription>,
|
||||
}
|
||||
|
||||
impl EventEmitter for ActiveCall {
|
||||
type Event = room::Event;
|
||||
}
|
||||
impl EventEmitter<Event> for ActiveCall {}
|
||||
|
||||
impl ActiveCall {
|
||||
fn new(client: Arc<Client>, user_store: Model<UserStore>, cx: &mut ModelContext<Self>) -> Self {
|
||||
|
||||
@@ -79,9 +79,7 @@ pub struct Room {
|
||||
maintain_connection: Option<Task<Option<()>>>,
|
||||
}
|
||||
|
||||
impl EventEmitter for Room {
|
||||
type Event = Event;
|
||||
}
|
||||
impl EventEmitter<Event> for Room {}
|
||||
|
||||
impl Room {
|
||||
pub fn channel_id(&self) -> Option<u64> {
|
||||
|
||||
@@ -38,9 +38,7 @@ pub enum ChannelBufferEvent {
|
||||
ChannelChanged,
|
||||
}
|
||||
|
||||
impl EventEmitter for ChannelBuffer {
|
||||
type Event = ChannelBufferEvent;
|
||||
}
|
||||
impl EventEmitter<ChannelBufferEvent> for ChannelBuffer {}
|
||||
|
||||
impl ChannelBuffer {
|
||||
pub(crate) async fn new(
|
||||
|
||||
@@ -76,9 +76,7 @@ pub enum ChannelChatEvent {
|
||||
},
|
||||
}
|
||||
|
||||
impl EventEmitter for ChannelChat {
|
||||
type Event = ChannelChatEvent;
|
||||
}
|
||||
impl EventEmitter<ChannelChatEvent> for ChannelChat {}
|
||||
pub fn init(client: &Arc<Client>) {
|
||||
client.add_model_message_handler(ChannelChat::handle_message_sent);
|
||||
client.add_model_message_handler(ChannelChat::handle_message_removed);
|
||||
|
||||
@@ -114,9 +114,7 @@ pub enum ChannelEvent {
|
||||
ChannelRenamed(ChannelId),
|
||||
}
|
||||
|
||||
impl EventEmitter for ChannelStore {
|
||||
type Event = ChannelEvent;
|
||||
}
|
||||
impl EventEmitter<ChannelEvent> for ChannelStore {}
|
||||
|
||||
enum OpenedModelHandle<E> {
|
||||
Open(WeakModel<E>),
|
||||
|
||||
@@ -103,9 +103,7 @@ pub enum ContactEventKind {
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
impl EventEmitter for UserStore {
|
||||
type Event = Event;
|
||||
}
|
||||
impl EventEmitter<Event> for UserStore {}
|
||||
|
||||
enum UpdateContacts {
|
||||
Update(proto::UpdateContacts),
|
||||
|
||||
@@ -284,9 +284,7 @@ pub enum Event {
|
||||
CopilotLanguageServerStarted,
|
||||
}
|
||||
|
||||
impl EventEmitter for Copilot {
|
||||
type Event = Event;
|
||||
}
|
||||
impl EventEmitter<Event> for Copilot {}
|
||||
|
||||
impl Copilot {
|
||||
pub fn global(cx: &AppContext) -> Option<Model<Self>> {
|
||||
|
||||
@@ -96,7 +96,9 @@ use theme::{
|
||||
ActiveTheme, DiagnosticStyle, PlayerColor, SyntaxTheme, Theme, ThemeColors, ThemeSettings,
|
||||
};
|
||||
use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
|
||||
use workspace::{ItemNavHistory, SplitDirection, ViewId, Workspace};
|
||||
use workspace::{
|
||||
item::ItemEvent, searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace,
|
||||
};
|
||||
|
||||
const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
|
||||
const MAX_LINE_LEN: usize = 1024;
|
||||
@@ -1904,7 +1906,8 @@ impl Editor {
|
||||
if let Some(project) = project.as_ref() {
|
||||
if buffer.read(cx).is_singleton() {
|
||||
project_subscriptions.push(cx.observe(project, |_, _, cx| {
|
||||
cx.emit(Event::TitleChanged);
|
||||
cx.emit(ItemEvent::UpdateTab);
|
||||
cx.emit(ItemEvent::UpdateBreadcrumbs);
|
||||
}));
|
||||
}
|
||||
project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
|
||||
@@ -2363,6 +2366,15 @@ impl Editor {
|
||||
|
||||
self.blink_manager.update(cx, BlinkManager::pause_blinking);
|
||||
cx.emit(Event::SelectionsChanged { local });
|
||||
|
||||
if self.selections.disjoint_anchors().len() == 1 {
|
||||
cx.emit(SearchEvent::ActiveMatchChanged)
|
||||
}
|
||||
|
||||
if local {
|
||||
cx.emit(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
@@ -8762,6 +8774,9 @@ impl Editor {
|
||||
self.update_visible_copilot_suggestion(cx);
|
||||
}
|
||||
cx.emit(Event::BufferEdited);
|
||||
cx.emit(ItemEvent::Edit);
|
||||
cx.emit(ItemEvent::UpdateBreadcrumbs);
|
||||
cx.emit(SearchEvent::MatchesInvalidated);
|
||||
|
||||
if *sigleton_buffer_edited {
|
||||
if let Some(project) = &self.project {
|
||||
@@ -8808,13 +8823,20 @@ impl Editor {
|
||||
self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
|
||||
cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
|
||||
}
|
||||
multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
|
||||
multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
|
||||
multi_buffer::Event::Saved => cx.emit(Event::Saved),
|
||||
multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
|
||||
multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
|
||||
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::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
|
||||
multi_buffer::Event::Closed => cx.emit(Event::Closed),
|
||||
multi_buffer::Event::Closed => cx.emit(ItemEvent::CloseItem),
|
||||
multi_buffer::Event::DiagnosticsUpdated => {
|
||||
self.refresh_active_diagnostics(cx);
|
||||
}
|
||||
@@ -9380,12 +9402,8 @@ pub enum Event {
|
||||
},
|
||||
BufferEdited,
|
||||
Edited,
|
||||
Reparsed,
|
||||
Focused,
|
||||
Blurred,
|
||||
DirtyChanged,
|
||||
Saved,
|
||||
TitleChanged,
|
||||
DiffBaseChanged,
|
||||
SelectionsChanged {
|
||||
local: bool,
|
||||
@@ -9394,7 +9412,6 @@ pub enum Event {
|
||||
local: bool,
|
||||
autoscroll: bool,
|
||||
},
|
||||
Closed,
|
||||
}
|
||||
|
||||
pub struct EditorFocused(pub View<Editor>);
|
||||
@@ -9409,9 +9426,7 @@ pub struct EditorReleased(pub WeakView<Editor>);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
impl EventEmitter for Editor {
|
||||
type Event = Event;
|
||||
}
|
||||
impl EventEmitter<Event> for Editor {}
|
||||
|
||||
impl Render for Editor {
|
||||
type Element = EditorElement;
|
||||
|
||||
+26
-58
@@ -7,9 +7,9 @@ use anyhow::{anyhow, Context, Result};
|
||||
use collections::HashSet;
|
||||
use futures::future::try_join_all;
|
||||
use gpui::{
|
||||
div, point, AnyElement, AppContext, AsyncAppContext, Entity, EntityId, FocusHandle, Model,
|
||||
ParentElement, Pixels, SharedString, Styled, Subscription, Task, View, ViewContext,
|
||||
VisualContext, WeakView,
|
||||
div, point, AnyElement, AppContext, AsyncAppContext, Entity, EntityId, EventEmitter,
|
||||
FocusHandle, Model, ParentElement, Pixels, SharedString, Styled, Subscription, Task, View,
|
||||
ViewContext, VisualContext, WeakView,
|
||||
};
|
||||
use language::{
|
||||
proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, OffsetRangeExt, Point,
|
||||
@@ -29,7 +29,7 @@ use std::{
|
||||
use text::Selection;
|
||||
use theme::{ActiveTheme, Theme};
|
||||
use util::{paths::PathExt, ResultExt, TryFutureExt};
|
||||
use workspace::item::{BreadcrumbText, FollowableItemHandle};
|
||||
use workspace::item::{BreadcrumbText, FollowEvent, FollowableEvents, FollowableItemHandle};
|
||||
use workspace::{
|
||||
item::{FollowableItem, Item, ItemEvent, ItemHandle, ProjectItem},
|
||||
searchable::{Direction, SearchEvent, SearchableItem, SearchableItemHandle},
|
||||
@@ -38,7 +38,26 @@ use workspace::{
|
||||
|
||||
pub const MAX_TAB_TITLE_LEN: usize = 24;
|
||||
|
||||
impl FollowableEvents for Event {
|
||||
fn to_follow_event(&self) -> Option<workspace::item::FollowEvent> {
|
||||
match self {
|
||||
Event::Edited => Some(FollowEvent::Unfollow),
|
||||
Event::SelectionsChanged { local } | Event::ScrollPositionChanged { local, .. } => {
|
||||
if *local {
|
||||
Some(FollowEvent::Unfollow)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<ItemEvent> for Editor {}
|
||||
|
||||
impl FollowableItem for Editor {
|
||||
type FollowableEvent = Event;
|
||||
fn remote_id(&self) -> Option<ViewId> {
|
||||
self.remote_id
|
||||
}
|
||||
@@ -217,7 +236,7 @@ impl FollowableItem for Editor {
|
||||
|
||||
fn add_event_to_update_proto(
|
||||
&self,
|
||||
event: &Self::Event,
|
||||
event: &Self::FollowableEvent,
|
||||
update: &mut Option<proto::update_view::Variant>,
|
||||
cx: &AppContext,
|
||||
) -> bool {
|
||||
@@ -292,15 +311,6 @@ impl FollowableItem for Editor {
|
||||
})
|
||||
}
|
||||
|
||||
fn should_unfollow_on_event(event: &Self::Event, _: &AppContext) -> bool {
|
||||
match event {
|
||||
Event::Edited => true,
|
||||
Event::SelectionsChanged { local } => *local,
|
||||
Event::ScrollPositionChanged { local, .. } => *local,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_project_item(&self, _cx: &AppContext) -> bool {
|
||||
true
|
||||
}
|
||||
@@ -739,32 +749,6 @@ impl Item for Editor {
|
||||
})
|
||||
}
|
||||
|
||||
fn to_item_events(event: &Self::Event) -> SmallVec<[ItemEvent; 2]> {
|
||||
let mut result = SmallVec::new();
|
||||
match event {
|
||||
Event::Closed => result.push(ItemEvent::CloseItem),
|
||||
Event::Saved | Event::TitleChanged => {
|
||||
result.push(ItemEvent::UpdateTab);
|
||||
result.push(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
Event::Reparsed => {
|
||||
result.push(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
Event::SelectionsChanged { local } if *local => {
|
||||
result.push(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
Event::DirtyChanged => {
|
||||
result.push(ItemEvent::UpdateTab);
|
||||
}
|
||||
Event::BufferEdited => {
|
||||
result.push(ItemEvent::Edit);
|
||||
result.push(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn as_searchable(&self, handle: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
|
||||
Some(Box::new(handle.clone()))
|
||||
}
|
||||
@@ -913,28 +897,12 @@ impl ProjectItem for Editor {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<SearchEvent> for Editor {}
|
||||
|
||||
pub(crate) enum BufferSearchHighlights {}
|
||||
impl SearchableItem for Editor {
|
||||
type Match = Range<Anchor>;
|
||||
|
||||
fn to_search_event(
|
||||
&mut self,
|
||||
event: &Self::Event,
|
||||
_: &mut ViewContext<Self>,
|
||||
) -> Option<SearchEvent> {
|
||||
match event {
|
||||
Event::BufferEdited => Some(SearchEvent::MatchesInvalidated),
|
||||
Event::SelectionsChanged { .. } => {
|
||||
if self.selections.disjoint_anchors().len() == 1 {
|
||||
Some(SearchEvent::ActiveMatchChanged)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn clear_matches(&mut self, cx: &mut ViewContext<Self>) {
|
||||
todo!()
|
||||
// self.clear_background_highlights::<BufferSearchHighlights>(cx);
|
||||
|
||||
@@ -8,7 +8,7 @@ use text::{Bias, Point};
|
||||
use theme::ActiveTheme;
|
||||
use ui::{h_stack, modal, v_stack, Label, LabelColor};
|
||||
use util::paths::FILE_ROW_COLUMN_DELIMITER;
|
||||
use workspace::{Modal, ModalEvent, Workspace};
|
||||
use workspace::{ModalEvent, Workspace};
|
||||
|
||||
actions!(Toggle);
|
||||
|
||||
@@ -41,9 +41,9 @@ pub enum Event {
|
||||
Dismissed,
|
||||
}
|
||||
|
||||
impl EventEmitter for GoToLine {
|
||||
type Event = Event;
|
||||
}
|
||||
impl EventEmitter<Event> for GoToLine {}
|
||||
|
||||
impl EventEmitter<ModalEvent> for GoToLine {}
|
||||
|
||||
impl GoToLine {
|
||||
pub fn new(active_editor: View<Editor>, cx: &mut ViewContext<Self>) -> Self {
|
||||
@@ -149,14 +149,6 @@ impl GoToLine {
|
||||
}
|
||||
}
|
||||
|
||||
impl Modal for GoToLine {
|
||||
fn to_modal_event(&self, e: &Self::Event) -> Option<ModalEvent> {
|
||||
match e {
|
||||
Event::Dismissed => Some(ModalEvent::Dismissed),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for GoToLine {
|
||||
type Element = Div<Self, StatefulInteractivity<Self>>;
|
||||
|
||||
|
||||
+36
-18
@@ -203,7 +203,8 @@ pub struct AppContext {
|
||||
pub(crate) pending_notifications: HashSet<EntityId>,
|
||||
pub(crate) pending_global_notifications: HashSet<TypeId>,
|
||||
pub(crate) observers: SubscriberSet<EntityId, Handler>,
|
||||
pub(crate) event_listeners: SubscriberSet<EntityId, Listener>,
|
||||
// TypeId is the type of the event that the listener callback expects
|
||||
pub(crate) event_listeners: SubscriberSet<EntityId, (TypeId, Listener)>,
|
||||
pub(crate) release_listeners: SubscriberSet<EntityId, ReleaseListener>,
|
||||
pub(crate) global_observers: SubscriberSet<TypeId, Handler>,
|
||||
pub(crate) quit_observers: SubscriberSet<(), QuitHandler>,
|
||||
@@ -354,14 +355,15 @@ impl AppContext {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn subscribe<T, E>(
|
||||
pub fn subscribe<T, E, Evt>(
|
||||
&mut self,
|
||||
entity: &E,
|
||||
mut on_event: impl FnMut(E, &T::Event, &mut AppContext) + 'static,
|
||||
mut on_event: impl FnMut(E, &Evt, &mut AppContext) + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
T: 'static + EventEmitter,
|
||||
T: 'static + EventEmitter<Evt>,
|
||||
E: Entity<T>,
|
||||
Evt: 'static,
|
||||
{
|
||||
self.subscribe_internal(entity, move |entity, event, cx| {
|
||||
on_event(entity, event, cx);
|
||||
@@ -369,27 +371,32 @@ impl AppContext {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn subscribe_internal<T, E>(
|
||||
pub(crate) fn subscribe_internal<T, E, Evt>(
|
||||
&mut self,
|
||||
entity: &E,
|
||||
mut on_event: impl FnMut(E, &T::Event, &mut AppContext) -> bool + 'static,
|
||||
mut on_event: impl FnMut(E, &Evt, &mut AppContext) -> bool + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
T: 'static + EventEmitter,
|
||||
T: 'static + EventEmitter<Evt>,
|
||||
E: Entity<T>,
|
||||
Evt: 'static,
|
||||
{
|
||||
let entity_id = entity.entity_id();
|
||||
let entity = entity.downgrade();
|
||||
|
||||
self.event_listeners.insert(
|
||||
entity_id,
|
||||
Box::new(move |event, cx| {
|
||||
let event: &T::Event = event.downcast_ref().expect("invalid event type");
|
||||
if let Some(handle) = E::upgrade_from(&entity) {
|
||||
on_event(handle, event, cx)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}),
|
||||
(
|
||||
TypeId::of::<Evt>(),
|
||||
Box::new(move |event, cx| {
|
||||
let event: &Evt = event.downcast_ref().expect("invalid event type");
|
||||
if let Some(handle) = E::upgrade_from(&entity) {
|
||||
on_event(handle, event, cx)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -512,7 +519,11 @@ impl AppContext {
|
||||
Effect::Notify { emitter } => {
|
||||
self.apply_notify_effect(emitter);
|
||||
}
|
||||
Effect::Emit { emitter, event } => self.apply_emit_effect(emitter, event),
|
||||
Effect::Emit {
|
||||
emitter,
|
||||
event_type,
|
||||
event,
|
||||
} => self.apply_emit_effect(emitter, event_type, event),
|
||||
Effect::FocusChanged {
|
||||
window_handle,
|
||||
focused,
|
||||
@@ -608,10 +619,16 @@ impl AppContext {
|
||||
.retain(&emitter, |handler| handler(self));
|
||||
}
|
||||
|
||||
fn apply_emit_effect(&mut self, emitter: EntityId, event: Box<dyn Any>) {
|
||||
fn apply_emit_effect(&mut self, emitter: EntityId, event_type: TypeId, event: Box<dyn Any>) {
|
||||
self.event_listeners
|
||||
.clone()
|
||||
.retain(&emitter, |handler| handler(event.as_ref(), self));
|
||||
.retain(&emitter, |(stored_type, handler)| {
|
||||
if *stored_type == event_type {
|
||||
handler(event.as_ref(), self)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn apply_focus_changed_effect(
|
||||
@@ -999,6 +1016,7 @@ pub(crate) enum Effect {
|
||||
},
|
||||
Emit {
|
||||
emitter: EntityId,
|
||||
event_type: TypeId,
|
||||
event: Box<dyn Any>,
|
||||
},
|
||||
FocusChanged {
|
||||
|
||||
@@ -59,15 +59,16 @@ impl<'a, T: 'static> ModelContext<'a, T> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn subscribe<T2, E>(
|
||||
pub fn subscribe<T2, E, Evt>(
|
||||
&mut self,
|
||||
entity: &E,
|
||||
mut on_event: impl FnMut(&mut T, E, &T2::Event, &mut ModelContext<'_, T>) + 'static,
|
||||
mut on_event: impl FnMut(&mut T, E, &Evt, &mut ModelContext<'_, T>) + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
T: 'static,
|
||||
T2: 'static + EventEmitter,
|
||||
T2: 'static + EventEmitter<Evt>,
|
||||
E: Entity<T2>,
|
||||
Evt: 'static,
|
||||
{
|
||||
let this = self.weak_model();
|
||||
self.app.subscribe_internal(entity, move |e, event, cx| {
|
||||
@@ -189,13 +190,15 @@ impl<'a, T: 'static> ModelContext<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> ModelContext<'a, T>
|
||||
where
|
||||
T: EventEmitter,
|
||||
{
|
||||
pub fn emit(&mut self, event: T::Event) {
|
||||
impl<'a, T> ModelContext<'a, T> {
|
||||
pub fn emit<Evt>(&mut self, event: Evt)
|
||||
where
|
||||
T: EventEmitter<Evt>,
|
||||
Evt: 'static,
|
||||
{
|
||||
self.app.pending_effects.push_back(Effect::Emit {
|
||||
emitter: self.model_state.entity_id,
|
||||
event_type: TypeId::of::<Evt>(),
|
||||
event: Box::new(event),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -197,12 +197,12 @@ impl TestAppContext {
|
||||
rx
|
||||
}
|
||||
|
||||
pub fn events<T: 'static + EventEmitter>(
|
||||
pub fn events<Evt, T: 'static + EventEmitter<Evt>>(
|
||||
&mut self,
|
||||
entity: &Model<T>,
|
||||
) -> futures::channel::mpsc::UnboundedReceiver<T::Event>
|
||||
) -> futures::channel::mpsc::UnboundedReceiver<Evt>
|
||||
where
|
||||
T::Event: 'static + Clone,
|
||||
Evt: 'static + Clone,
|
||||
{
|
||||
let (tx, rx) = futures::channel::mpsc::unbounded();
|
||||
entity
|
||||
@@ -240,10 +240,11 @@ impl TestAppContext {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + EventEmitter> Model<T> {
|
||||
pub fn next_event(&self, cx: &mut TestAppContext) -> T::Event
|
||||
impl<T: Send> Model<T> {
|
||||
pub fn next_event<Evt>(&self, cx: &mut TestAppContext) -> Evt
|
||||
where
|
||||
T::Event: Send + Clone,
|
||||
Evt: Send + Clone + 'static,
|
||||
T: EventEmitter<Evt>,
|
||||
{
|
||||
let (tx, mut rx) = futures::channel::mpsc::unbounded();
|
||||
let _subscription = self.update(cx, |_, cx| {
|
||||
|
||||
@@ -138,6 +138,8 @@ pub trait Entity<T>: Sealed {
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
pub trait EventEmitter<E: Any>: 'static {}
|
||||
|
||||
pub enum GlobalKey {
|
||||
Numeric(usize),
|
||||
View(EntityId),
|
||||
@@ -171,10 +173,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub trait EventEmitter: 'static {
|
||||
type Event: Any;
|
||||
}
|
||||
|
||||
pub trait Flatten<T> {
|
||||
fn flatten(self) -> Result<T>;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,8 @@ where
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// Call the given callback for each subscriber to the given emitter.
|
||||
/// If the callback returns false, the subscriber is removed.
|
||||
pub fn retain<F>(&self, emitter: &EmitterKey, mut f: F)
|
||||
where
|
||||
F: FnMut(&mut Callback) -> bool,
|
||||
|
||||
+47
-38
@@ -438,33 +438,37 @@ impl<'a> WindowContext<'a> {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn subscribe<Emitter, E>(
|
||||
pub fn subscribe<Emitter, E, Evt>(
|
||||
&mut self,
|
||||
entity: &E,
|
||||
mut on_event: impl FnMut(E, &Emitter::Event, &mut WindowContext<'_>) + 'static,
|
||||
mut on_event: impl FnMut(E, &Evt, &mut WindowContext<'_>) + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
Emitter: EventEmitter,
|
||||
Emitter: EventEmitter<Evt>,
|
||||
E: Entity<Emitter>,
|
||||
Evt: 'static,
|
||||
{
|
||||
let entity_id = entity.entity_id();
|
||||
let entity = entity.downgrade();
|
||||
let window_handle = self.window.handle;
|
||||
self.app.event_listeners.insert(
|
||||
entity_id,
|
||||
Box::new(move |event, cx| {
|
||||
window_handle
|
||||
.update(cx, |_, cx| {
|
||||
if let Some(handle) = E::upgrade_from(&entity) {
|
||||
let event = event.downcast_ref().expect("invalid event type");
|
||||
on_event(handle, event, cx);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}),
|
||||
(
|
||||
TypeId::of::<Evt>(),
|
||||
Box::new(move |event, cx| {
|
||||
window_handle
|
||||
.update(cx, |_, cx| {
|
||||
if let Some(handle) = E::upgrade_from(&entity) {
|
||||
let event = event.downcast_ref().expect("invalid event type");
|
||||
on_event(handle, event, cx);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1817,14 +1821,15 @@ impl<'a, V: 'static> ViewContext<'a, V> {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn subscribe<V2, E>(
|
||||
pub fn subscribe<V2, E, Evt>(
|
||||
&mut self,
|
||||
entity: &E,
|
||||
mut on_event: impl FnMut(&mut V, E, &V2::Event, &mut ViewContext<'_, V>) + 'static,
|
||||
mut on_event: impl FnMut(&mut V, E, &Evt, &mut ViewContext<'_, V>) + 'static,
|
||||
) -> Subscription
|
||||
where
|
||||
V2: EventEmitter,
|
||||
V2: EventEmitter<Evt>,
|
||||
E: Entity<V2>,
|
||||
Evt: 'static,
|
||||
{
|
||||
let view = self.view().downgrade();
|
||||
let entity_id = entity.entity_id();
|
||||
@@ -1832,19 +1837,22 @@ impl<'a, V: 'static> ViewContext<'a, V> {
|
||||
let window_handle = self.window.handle;
|
||||
self.app.event_listeners.insert(
|
||||
entity_id,
|
||||
Box::new(move |event, cx| {
|
||||
window_handle
|
||||
.update(cx, |_, cx| {
|
||||
if let Some(handle) = E::upgrade_from(&handle) {
|
||||
let event = event.downcast_ref().expect("invalid event type");
|
||||
view.update(cx, |this, cx| on_event(this, handle, event, cx))
|
||||
.is_ok()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}),
|
||||
(
|
||||
TypeId::of::<Evt>(),
|
||||
Box::new(move |event, cx| {
|
||||
window_handle
|
||||
.update(cx, |_, cx| {
|
||||
if let Some(handle) = E::upgrade_from(&handle) {
|
||||
let event = event.downcast_ref().expect("invalid event type");
|
||||
view.update(cx, |this, cx| on_event(this, handle, event, cx))
|
||||
.is_ok()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2176,15 +2184,16 @@ impl<'a, V: 'static> ViewContext<'a, V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> ViewContext<'_, V>
|
||||
where
|
||||
V: EventEmitter,
|
||||
V::Event: 'static,
|
||||
{
|
||||
pub fn emit(&mut self, event: V::Event) {
|
||||
impl<V> ViewContext<'_, V> {
|
||||
pub fn emit<Evt>(&mut self, event: Evt)
|
||||
where
|
||||
Evt: 'static,
|
||||
V: EventEmitter<Evt>,
|
||||
{
|
||||
let emitter = self.view.model.entity_id;
|
||||
self.app.push_effect(Effect::Emit {
|
||||
emitter,
|
||||
event_type: TypeId::of::<Evt>(),
|
||||
event: Box::new(event),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1815,9 +1815,7 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter for Buffer {
|
||||
type Event = Event;
|
||||
}
|
||||
impl EventEmitter<Event> for Buffer {}
|
||||
|
||||
impl Deref for Buffer {
|
||||
type Target = TextBuffer;
|
||||
|
||||
@@ -1872,9 +1872,7 @@ impl MultiBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter for MultiBuffer {
|
||||
type Event = Event;
|
||||
}
|
||||
impl EventEmitter<Event> for MultiBuffer {}
|
||||
|
||||
impl MultiBufferSnapshot {
|
||||
pub fn text(&self) -> String {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -9062,9 +9062,7 @@ impl<'a> Iterator for PathMatchCandidateSetIter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter for Project {
|
||||
type Event = Event;
|
||||
}
|
||||
impl EventEmitter<Event> for Project {}
|
||||
|
||||
impl<P: AsRef<Path>> From<(WorktreeId, P)> for ProjectPath {
|
||||
fn from((worktree_id, path): (WorktreeId, P)) -> Self {
|
||||
|
||||
@@ -281,9 +281,7 @@ pub enum Event {
|
||||
UpdatedGitRepositories(UpdatedGitRepositoriesSet),
|
||||
}
|
||||
|
||||
impl EventEmitter for Worktree {
|
||||
type Event = Event;
|
||||
}
|
||||
impl EventEmitter<Event> for Worktree {}
|
||||
|
||||
impl Worktree {
|
||||
pub async fn local(
|
||||
|
||||
@@ -1351,9 +1351,7 @@ impl Drop for Terminal {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter for Terminal {
|
||||
type Event = Event;
|
||||
}
|
||||
impl EventEmitter<Event> 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.
|
||||
|
||||
@@ -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<PanelEvent> {
|
||||
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<String> {
|
||||
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<Self>) {}
|
||||
fn set_active(&mut self, _active: bool, _cx: &mut ViewContext<Self>) {}
|
||||
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!(),
|
||||
}
|
||||
}),
|
||||
];
|
||||
@@ -460,10 +471,6 @@ impl PanelButtons {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter for PanelButtons {
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
// impl Render for PanelButtons {
|
||||
// type Element = ();
|
||||
|
||||
@@ -633,7 +640,7 @@ impl StatusItemView for PanelButtons {
|
||||
_active_pane_item: Option<&dyn crate::ItemHandle>,
|
||||
_cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
// todo!(This is empty in the old `workspace::dock`)
|
||||
// Nothing to do, panel buttons don't depend on the active center item
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,16 +649,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,
|
||||
@@ -660,9 +657,7 @@ pub mod test {
|
||||
pub size: f32,
|
||||
}
|
||||
|
||||
impl EventEmitter for TestPanel {
|
||||
type Event = TestPanelEvent;
|
||||
}
|
||||
impl EventEmitter<PanelEvent> for TestPanel {}
|
||||
|
||||
impl TestPanel {
|
||||
pub fn new(position: DockPosition) -> Self {
|
||||
@@ -699,7 +694,7 @@ pub mod test {
|
||||
|
||||
fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext<Self>) {
|
||||
self.position = position;
|
||||
cx.emit(TestPanelEvent::PositionChanged);
|
||||
cx.emit(PanelEvent::ChangePosition);
|
||||
}
|
||||
|
||||
fn size(&self, _: &WindowContext) -> f32 {
|
||||
@@ -718,18 +713,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
|
||||
}
|
||||
@@ -742,20 +725,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ pub struct BreadcrumbText {
|
||||
pub highlights: Option<Vec<(Range<usize>, HighlightStyle)>>,
|
||||
}
|
||||
|
||||
pub trait Item: Render + EventEmitter {
|
||||
pub trait Item: Render + EventEmitter<ItemEvent> {
|
||||
fn focus_handle(&self) -> FocusHandle;
|
||||
fn deactivated(&mut self, _: &mut ViewContext<Self>) {}
|
||||
fn workspace_deactivated(&mut self, _: &mut ViewContext<Self>) {}
|
||||
@@ -106,12 +106,13 @@ pub trait Item: Render + EventEmitter {
|
||||
}
|
||||
fn tab_content<V: 'static>(&self, detail: Option<usize>, cx: &AppContext) -> AnyElement<V>;
|
||||
|
||||
/// (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<Result<()>> {
|
||||
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<dyn Fn(ItemEvent, &mut WindowContext) + Send>,
|
||||
handler: Box<dyn Fn(&ItemEvent, &mut WindowContext) + Send>,
|
||||
) -> gpui::Subscription;
|
||||
fn tab_tooltip_text(&self, cx: &AppContext) -> Option<SharedString>;
|
||||
fn tab_description(&self, detail: usize, cx: &AppContext) -> Option<SharedString>;
|
||||
@@ -300,12 +292,10 @@ impl<T: Item> ItemHandle for View<T> {
|
||||
fn subscribe_to_item_events(
|
||||
&self,
|
||||
cx: &mut WindowContext,
|
||||
handler: Box<dyn Fn(ItemEvent, &mut WindowContext) + Send>,
|
||||
handler: Box<dyn Fn(&ItemEvent, &mut WindowContext) + Send>,
|
||||
) -> 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<T: Item> ItemHandle for View<T> {
|
||||
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<T: Item> ItemHandle for View<T> {
|
||||
}
|
||||
}
|
||||
|
||||
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<FollowEvent>;
|
||||
}
|
||||
|
||||
pub trait FollowableItem: Item {
|
||||
type FollowableEvent: FollowableEvents;
|
||||
fn remote_id(&self) -> Option<ViewId>;
|
||||
fn to_state_proto(&self, cx: &AppContext) -> Option<proto::view::Variant>;
|
||||
fn from_state_proto(
|
||||
@@ -672,7 +672,7 @@ pub trait FollowableItem: Item {
|
||||
) -> Option<Task<Result<View<Self>>>>;
|
||||
fn add_event_to_update_proto(
|
||||
&self,
|
||||
event: &Self::Event,
|
||||
event: &Self::FollowableEvent,
|
||||
update: &mut Option<proto::update_view::Variant>,
|
||||
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<PeerId>, cx: &mut ViewContext<Self>);
|
||||
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<proto::update_view::Variant>,
|
||||
cx: &AppContext,
|
||||
) -> bool;
|
||||
fn to_follow_event(&self, event: &dyn Any) -> Option<FollowEvent>;
|
||||
fn apply_update_proto(
|
||||
&self,
|
||||
project: &Model<Project>,
|
||||
message: proto::update_view::Variant,
|
||||
cx: &mut WindowContext,
|
||||
) -> Task<Result<()>>;
|
||||
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<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()
|
||||
}
|
||||
|
||||
fn apply_update_proto(
|
||||
&self,
|
||||
project: &Model<Project>,
|
||||
@@ -748,14 +754,6 @@ impl<T: FollowableItem> FollowableItemHandle for View<T> {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,6 @@ pub enum ModalEvent {
|
||||
Dismissed,
|
||||
}
|
||||
|
||||
pub trait Modal: EventEmitter + Render {
|
||||
fn to_modal_event(&self, _: &Self::Event) -> Option<ModalEvent>;
|
||||
}
|
||||
|
||||
impl ModalLayer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
@@ -31,7 +27,7 @@ impl ModalLayer {
|
||||
|
||||
pub fn register_modal<A: 'static, V, B>(&mut self, action: A, build_view: B)
|
||||
where
|
||||
V: Modal,
|
||||
V: EventEmitter<ModalEvent> + Render,
|
||||
B: Fn(&mut Workspace, &mut ViewContext<Workspace>) -> Option<View<V>> + 'static,
|
||||
{
|
||||
let build_view = Arc::new(build_view);
|
||||
@@ -51,12 +47,12 @@ impl ModalLayer {
|
||||
));
|
||||
}
|
||||
|
||||
pub fn show_modal<V: Modal>(&mut self, new_modal: View<V>, cx: &mut ViewContext<Workspace>) {
|
||||
self.subscription = Some(cx.subscribe(&new_modal, |this, modal, e, cx| {
|
||||
match modal.read(cx).to_modal_event(e) {
|
||||
Some(ModalEvent::Dismissed) => this.modal_layer().hide_modal(cx),
|
||||
None => {}
|
||||
}
|
||||
pub fn show_modal<V>(&mut self, new_modal: View<V>, cx: &mut ViewContext<Workspace>)
|
||||
where
|
||||
V: EventEmitter<ModalEvent> + Render,
|
||||
{
|
||||
self.subscription = Some(cx.subscribe(&new_modal, |this, modal, e, cx| match e {
|
||||
ModalEvent::Dismissed => this.modal_layer().hide_modal(cx),
|
||||
}));
|
||||
self.open_modal = Some(new_modal.into());
|
||||
cx.notify();
|
||||
|
||||
@@ -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<NotificationEvent> + 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<Cow<'static, str>>,
|
||||
}
|
||||
|
||||
pub enum MessageNotificationEvent {
|
||||
Dismiss,
|
||||
}
|
||||
|
||||
impl EventEmitter for MessageNotification {
|
||||
type Event = MessageNotificationEvent;
|
||||
}
|
||||
impl EventEmitter<NotificationMessage> for MessageNotification {}
|
||||
|
||||
impl MessageNotification {
|
||||
pub fn new<S>(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<NotificationEvent> for MessageNotification {}
|
||||
impl Notification for MessageNotification {}
|
||||
}
|
||||
|
||||
pub trait NotifyResultExt {
|
||||
|
||||
@@ -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<Pane>,
|
||||
// }
|
||||
|
||||
// #[derive(Clone, PartialEq, Debug, Deserialize, Default)]
|
||||
// #[serde(rename_all = "camelCase")]
|
||||
// pub struct CloseActiveItem {
|
||||
// pub save_intent: Option<SaveIntent>,
|
||||
// }
|
||||
#[register_action]
|
||||
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CloseActiveItem {
|
||||
pub save_intent: Option<SaveIntent>,
|
||||
}
|
||||
|
||||
// #[derive(Clone, PartialEq, Debug, Deserialize)]
|
||||
// #[serde(rename_all = "camelCase")]
|
||||
// pub struct CloseAllItems {
|
||||
// pub save_intent: Option<SaveIntent>,
|
||||
// }
|
||||
#[register_action]
|
||||
#[derive(Clone, PartialEq, Debug, Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CloseAllItems {
|
||||
pub save_intent: Option<SaveIntent>,
|
||||
}
|
||||
|
||||
// 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<Event> for Pane {}
|
||||
|
||||
impl Pane {
|
||||
pub fn new(
|
||||
|
||||
@@ -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<SearchEvent> {
|
||||
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<Self>,
|
||||
) -> Option<SearchEvent>;
|
||||
|
||||
fn clear_matches(&mut self, cx: &mut ViewContext<Self>);
|
||||
fn update_matches(&mut self, matches: Vec<Self::Match>, cx: &mut ViewContext<Self>);
|
||||
fn query_suggestion(&mut self, cx: &mut ViewContext<Self>) -> String;
|
||||
@@ -95,7 +93,7 @@ pub trait SearchableItemHandle: ItemHandle {
|
||||
fn subscribe_to_search_events(
|
||||
&self,
|
||||
cx: &mut WindowContext,
|
||||
handler: Box<dyn Fn(SearchEvent, &mut WindowContext) + Send>,
|
||||
handler: Box<dyn Fn(&SearchEvent, &mut WindowContext) + Send>,
|
||||
) -> Subscription;
|
||||
fn clear_matches(&self, cx: &mut WindowContext);
|
||||
fn update_matches(&self, matches: &Vec<Box<dyn Any + Send>>, cx: &mut WindowContext);
|
||||
@@ -146,14 +144,9 @@ impl<T: SearchableItem> SearchableItemHandle for View<T> {
|
||||
fn subscribe_to_search_events(
|
||||
&self,
|
||||
cx: &mut WindowContext,
|
||||
handler: Box<dyn Fn(SearchEvent, &mut WindowContext) + Send>,
|
||||
handler: Box<dyn Fn(&SearchEvent, &mut WindowContext) + Send>,
|
||||
) -> 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) {
|
||||
|
||||
@@ -1,25 +1,19 @@
|
||||
use crate::ItemHandle;
|
||||
use gpui::{
|
||||
AnyView, AppContext, Div, Entity, EntityId, EventEmitter, Render, View, ViewContext,
|
||||
WindowContext,
|
||||
AnyView, Div, Entity, EntityId, EventEmitter, Render, View, ViewContext, WindowContext,
|
||||
};
|
||||
|
||||
pub trait ToolbarItemView: Render + EventEmitter {
|
||||
pub enum ToolbarItemEvent {
|
||||
ChangeLocation(ToolbarItemLocation),
|
||||
}
|
||||
|
||||
pub trait ToolbarItemView: Render + EventEmitter<ToolbarItemEvent> {
|
||||
fn set_active_pane_item(
|
||||
&mut self,
|
||||
active_pane_item: Option<&dyn crate::ItemHandle>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> 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<Self>) {}
|
||||
|
||||
/// Number of times toolbar's height will be repeated to get the effective height.
|
||||
@@ -141,61 +135,6 @@ impl Render for Toolbar {
|
||||
// }
|
||||
// }
|
||||
|
||||
// <<<<<<< HEAD
|
||||
// =======
|
||||
// #[allow(clippy::too_many_arguments)]
|
||||
// fn nav_button<A: Action, F: 'static + Fn(&mut Toolbar, &mut ViewContext<Toolbar>)>(
|
||||
// svg_path: &'static str,
|
||||
// style: theme::Interactive<theme::IconButton>,
|
||||
// nav_button_height: f32,
|
||||
// tooltip_style: TooltipStyle,
|
||||
// enabled: bool,
|
||||
// spacing: f32,
|
||||
// on_click: F,
|
||||
// tooltip_action: A,
|
||||
// action_name: &'static str,
|
||||
// cx: &mut ViewContext<Toolbar>,
|
||||
// ) -> AnyElement<Toolbar> {
|
||||
// MouseEventHandler::new::<A, _>(0, cx, |state, _| {
|
||||
// let style = if enabled {
|
||||
// style.style_for(state)
|
||||
// } else {
|
||||
// style.disabled_style()
|
||||
// };
|
||||
// Svg::new(svg_path)
|
||||
// .with_color(style.color)
|
||||
// .constrained()
|
||||
// .with_width(style.icon_width)
|
||||
// .aligned()
|
||||
// .contained()
|
||||
// .with_style(style.container)
|
||||
// .constrained()
|
||||
// .with_width(style.button_width)
|
||||
// .with_height(nav_button_height)
|
||||
// .aligned()
|
||||
// .top()
|
||||
// })
|
||||
// .with_cursor_style(if enabled {
|
||||
// CursorStyle::PointingHand
|
||||
// } else {
|
||||
// CursorStyle::default()
|
||||
// })
|
||||
// .on_click(MouseButton::Left, move |_, toolbar, cx| {
|
||||
// on_click(toolbar, cx)
|
||||
// })
|
||||
// .with_tooltip::<A>(
|
||||
// 0,
|
||||
// action_name,
|
||||
// Some(Box::new(tooltip_action)),
|
||||
// tooltip_style,
|
||||
// cx,
|
||||
// )
|
||||
// .contained()
|
||||
// .with_margin_right(spacing)
|
||||
// .into_any_named("nav button")
|
||||
// }
|
||||
|
||||
// >>>>>>> 139cbbfd3aebd0863a7d51b0c12d748764cf0b2e
|
||||
impl Toolbar {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
@@ -220,12 +159,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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,
|
||||
@@ -87,35 +87,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 {
|
||||
@@ -967,6 +964,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| {
|
||||
@@ -997,6 +997,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);
|
||||
@@ -1004,6 +1007,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;
|
||||
@@ -1011,6 +1017,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) {
|
||||
@@ -3694,9 +3703,7 @@ fn notify_if_database_failed(workspace: WindowHandle<Workspace>, cx: &mut AsyncA
|
||||
.log_err();
|
||||
}
|
||||
|
||||
impl EventEmitter for Workspace {
|
||||
type Event = Event;
|
||||
}
|
||||
impl EventEmitter<Event> for Workspace {}
|
||||
|
||||
impl Render for Workspace {
|
||||
type Element = Div<Self>;
|
||||
@@ -4138,10 +4145,6 @@ impl WorkspaceStore {
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter for WorkspaceStore {
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
impl ViewId {
|
||||
pub(crate) fn from_proto(message: proto::ViewId) -> Result<Self> {
|
||||
Ok(Self {
|
||||
|
||||
Reference in New Issue
Block a user