diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 3320359440..39d7d9ed09 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -40,11 +40,12 @@ use fuzzy::{StringMatch, StringMatchCandidate}; use git::diff_hunk_to_display; use gpui::{ actions, div, point, prelude::*, px, relative, rems, size, uniform_list, Action, AnyElement, - AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Context, ElementId, - EventEmitter, FocusHandle, FocusableView, FontFeatures, FontStyle, FontWeight, HighlightStyle, - Hsla, InputHandler, InteractiveText, KeyContext, Model, MouseButton, ParentElement, Pixels, - Render, RenderOnce, SharedString, Styled, StyledText, Subscription, Task, TextRun, TextStyle, - UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WhiteSpace, WindowContext, + AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Context, + DispatchPhase, Div, ElementId, EventEmitter, FocusHandle, FocusableView, FontFeatures, + FontStyle, FontWeight, HighlightStyle, Hsla, InputHandler, InteractiveText, KeyContext, Model, + MouseButton, ParentElement, Pixels, Render, RenderOnce, SharedString, Styled, StyledText, + Subscription, Task, TextRun, TextStyle, UniformListScrollHandle, View, ViewContext, + VisualContext, WeakView, WhiteSpace, WindowContext, }; use highlight_matching_bracket::refresh_matching_bracket_highlights; use hover_popover::{hide_hover, HoverState}; @@ -103,7 +104,7 @@ use util::{post_inc, RangeExt, ResultExt, TryFutureExt}; use workspace::{ item::{ItemEvent, ItemHandle}, searchable::SearchEvent, - ItemNavHistory, SplitDirection, ViewId, Workspace, + ItemNavHistory, Pane, SplitDirection, ViewId, Workspace, }; const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500); @@ -662,6 +663,7 @@ pub struct Editor { pixel_position_of_newest_cursor: Option>, gutter_width: Pixels, style: Option, + editor_actions: Vec)>>, } pub struct EditorSnapshot { @@ -1890,6 +1892,7 @@ impl Editor { pixel_position_of_newest_cursor: None, gutter_width: Default::default(), style: None, + editor_actions: Default::default(), _subscriptions: vec![ cx.observe(&buffer, Self::on_buffer_changed), cx.subscribe(&buffer, Self::on_buffer_event), @@ -2021,10 +2024,14 @@ impl Editor { &self.buffer } - fn workspace(&self) -> Option> { + pub fn workspace(&self) -> Option> { self.workspace.as_ref()?.0.upgrade() } + pub fn pane(&self, cx: &AppContext) -> Option> { + self.workspace()?.read(cx).pane_for(&self.handle.upgrade()?) + } + pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> { self.buffer().read(cx).title(cx) } @@ -9181,6 +9188,26 @@ impl Editor { cx.emit(EditorEvent::Blurred); cx.notify(); } + + pub fn register_action( + &mut self, + listener: impl Fn(&A, &mut WindowContext) + 'static, + ) -> &mut Self { + let listener = Arc::new(listener); + + self.editor_actions.push(Box::new(move |cx| { + let view = cx.view().clone(); + let cx = cx.window_context(); + let listener = listener.clone(); + cx.on_action(TypeId::of::(), move |action, phase, cx| { + let action = action.downcast_ref().unwrap(); + if phase == DispatchPhase::Bubble { + listener(action, cx) + } + }) + })); + self + } } pub trait CollaborationHub { diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 5b510095ff..6a6afd5461 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -128,6 +128,11 @@ impl EditorElement { fn register_actions(&self, cx: &mut WindowContext) { let view = &self.editor; + self.editor.update(cx, |editor, cx| { + for action in editor.editor_actions.iter() { + (action)(cx) + } + }); register_action(view, cx, Editor::move_left); register_action(view, cx, Editor::move_right); register_action(view, cx, Editor::move_down); @@ -4068,7 +4073,7 @@ fn scale_horizontal_mouse_autoscroll_delta(delta: Pixels) -> f32 { // } // } -fn register_action( +pub fn register_action( view: &View, cx: &mut WindowContext, listener: impl Fn(&mut Editor, &T, &mut ViewContext) + 'static, diff --git a/crates/go_to_line2/src/go_to_line.rs b/crates/go_to_line2/src/go_to_line.rs index d1119de9b4..c734281d22 100644 --- a/crates/go_to_line2/src/go_to_line.rs +++ b/crates/go_to_line2/src/go_to_line.rs @@ -8,7 +8,6 @@ use text::{Bias, Point}; use theme::ActiveTheme; use ui::{h_stack, v_stack, Color, Label, StyledExt}; use util::paths::FILE_ROW_COLUMN_DELIMITER; -use workspace::Workspace; actions!(Toggle); @@ -26,22 +25,24 @@ pub struct GoToLine { impl FocusableView for GoToLine { fn focus_handle(&self, cx: &AppContext) -> FocusHandle { - self.active_editor.focus_handle(cx) + self.line_editor.focus_handle(cx) } } impl EventEmitter for GoToLine {} impl GoToLine { - fn register(workspace: &mut Workspace, _: &mut ViewContext) { - workspace.register_action(|workspace, _: &Toggle, cx| { - let Some(editor) = workspace - .active_item(cx) - .and_then(|active_item| active_item.downcast::()) - else { + fn register(editor: &mut Editor, cx: &mut ViewContext) { + let handle = cx.view().downgrade(); + editor.register_action(move |_: &Toggle, cx| { + let Some(editor) = handle.upgrade() else { return; }; - - workspace.toggle_modal(cx, move |cx| GoToLine::new(editor, cx)); + let Some(workspace) = editor.read(cx).workspace() else { + return; + }; + workspace.update(cx, |workspace, cx| { + workspace.toggle_modal(cx, move |cx| GoToLine::new(editor, cx)); + }) }); } diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index 70a8df21e1..dc6b77c7c7 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -114,6 +114,7 @@ impl Picker { } fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext) { + dbg!("canceling!"); self.delegate.dismissed(cx); } diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index d2d30556eb..b027209870 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -644,6 +644,7 @@ impl ProjectPanel { } fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext) { + dbg!("odd"); self.edit_state = None; self.update_visible_entries(None, cx); cx.focus(&self.focus_handle); diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index ad549256f9..d80d9f5d50 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -7,12 +7,12 @@ use crate::{ ToggleCaseSensitive, ToggleReplace, ToggleWholeWord, }; use collections::HashMap; -use editor::Editor; +use editor::{Editor, EditorMode}; use futures::channel::oneshot; use gpui::{ actions, div, red, Action, AppContext, Div, EventEmitter, InteractiveElement as _, IntoElement, ParentElement as _, Render, Styled, Subscription, Task, View, ViewContext, VisualContext as _, - WindowContext, + WeakView, WindowContext, }; use project::search::SearchQuery; use serde::Deserialize; @@ -23,7 +23,7 @@ use util::ResultExt; use workspace::{ item::ItemHandle, searchable::{Direction, SearchEvent, SearchableItemHandle, WeakSearchableItemHandle}, - ToolbarItemLocation, ToolbarItemView, Workspace, + ToolbarItemLocation, ToolbarItemView, }; #[derive(PartialEq, Clone, Deserialize, Default, Action)] @@ -38,7 +38,7 @@ pub enum Event { } pub fn init(cx: &mut AppContext) { - cx.observe_new_views(|workspace: &mut Workspace, _| BufferSearchBar::register(workspace)) + cx.observe_new_views(|editor: &mut Editor, cx| BufferSearchBar::register(editor, cx)) .detach(); } @@ -187,6 +187,7 @@ impl Render for BufferSearchBar { }) .on_action(cx.listener(Self::previous_history_query)) .on_action(cx.listener(Self::next_history_query)) + .on_action(cx.listener(Self::dismiss)) .w_full() .p_1() .child( @@ -294,9 +295,19 @@ impl ToolbarItemView for BufferSearchBar { } impl BufferSearchBar { - pub fn register(workspace: &mut Workspace) { - workspace.register_action(|workspace, a: &Deploy, cx| { - workspace.active_pane().update(cx, |this, cx| { + pub fn register(editor: &mut Editor, cx: &mut ViewContext) { + if editor.mode() != EditorMode::Full { + return; + }; + + let handle = cx.view().downgrade(); + + editor.register_action(move |a: &Deploy, cx| { + let Some(pane) = handle.upgrade().and_then(|editor| editor.read(cx).pane(cx)) else { + return; + }; + + pane.update(cx, |this, cx| { this.toolbar().update(cx, |this, cx| { if let Some(search_bar) = this.item_of_type::() { search_bar.update(cx, |this, cx| { @@ -316,11 +327,16 @@ impl BufferSearchBar { }); }); fn register_action( - workspace: &mut Workspace, + editor: &mut Editor, + handle: WeakView, update: fn(&mut BufferSearchBar, &A, &mut ViewContext), ) { - workspace.register_action(move |workspace, action: &A, cx| { - workspace.active_pane().update(cx, move |this, cx| { + editor.register_action(move |action: &A, cx| { + let Some(pane) = handle.upgrade().and_then(|editor| editor.read(cx).pane(cx)) + else { + return; + }; + pane.update(cx, move |this, cx| { this.toolbar().update(cx, move |this, cx| { if let Some(search_bar) = this.item_of_type::() { search_bar.update(cx, move |this, cx| update(this, action, cx)); @@ -331,49 +347,76 @@ impl BufferSearchBar { }); } - register_action(workspace, |this, action: &ToggleCaseSensitive, cx| { - if this.supported_options().case { - this.toggle_case_sensitive(action, cx); - } - }); - register_action(workspace, |this, action: &ToggleWholeWord, cx| { - if this.supported_options().word { - this.toggle_whole_word(action, cx); - } - }); - register_action(workspace, |this, action: &ToggleReplace, cx| { - if this.supported_options().replacement { - this.toggle_replace(action, cx); - } - }); - register_action(workspace, |this, _: &ActivateRegexMode, cx| { + let handle = cx.view().downgrade(); + register_action( + editor, + handle.clone(), + |this, action: &ToggleCaseSensitive, cx| { + if this.supported_options().case { + this.toggle_case_sensitive(action, cx); + } + }, + ); + register_action( + editor, + handle.clone(), + |this, action: &ToggleWholeWord, cx| { + if this.supported_options().word { + this.toggle_whole_word(action, cx); + } + }, + ); + register_action( + editor, + handle.clone(), + |this, action: &ToggleReplace, cx| { + if this.supported_options().replacement { + this.toggle_replace(action, cx); + } + }, + ); + register_action(editor, handle.clone(), |this, _: &ActivateRegexMode, cx| { if this.supported_options().regex { this.activate_search_mode(SearchMode::Regex, cx); } }); - register_action(workspace, |this, _: &ActivateTextMode, cx| { + register_action(editor, handle.clone(), |this, _: &ActivateTextMode, cx| { this.activate_search_mode(SearchMode::Text, cx); }); - register_action(workspace, |this, action: &CycleMode, cx| { + register_action(editor, handle.clone(), |this, action: &CycleMode, cx| { if this.supported_options().regex { // If regex is not supported then search has just one mode (text) - in that case there's no point in supporting // cycling. this.cycle_mode(action, cx) } }); - register_action(workspace, |this, action: &SelectNextMatch, cx| { - this.select_next_match(action, cx); - }); - register_action(workspace, |this, action: &SelectPrevMatch, cx| { - this.select_prev_match(action, cx); - }); - register_action(workspace, |this, action: &SelectAllMatches, cx| { - this.select_all_matches(action, cx); - }); - register_action(workspace, |this, _: &editor::Cancel, cx| { + register_action( + editor, + handle.clone(), + |this, action: &SelectNextMatch, cx| { + this.select_next_match(action, cx); + }, + ); + register_action( + editor, + handle.clone(), + |this, action: &SelectPrevMatch, cx| { + this.select_prev_match(action, cx); + }, + ); + register_action( + editor, + handle.clone(), + |this, action: &SelectAllMatches, cx| { + this.select_all_matches(action, cx); + }, + ); + register_action(editor, handle.clone(), |this, _: &editor::Cancel, cx| { if !this.dismissed { this.dismiss(&Dismiss, cx); + return; } + cx.propagate(); }); } pub fn new(cx: &mut ViewContext) -> Self { diff --git a/crates/workspace2/src/modal_layer.rs b/crates/workspace2/src/modal_layer.rs index 6b14151e09..6d28a6299b 100644 --- a/crates/workspace2/src/modal_layer.rs +++ b/crates/workspace2/src/modal_layer.rs @@ -46,6 +46,7 @@ impl ModalLayer { previous_focus_handle: cx.focused(), focus_handle: cx.focus_handle(), }); + dbg!("focusing"); cx.focus_view(&new_modal); cx.notify(); } diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index fbc706c560..50f8611c4c 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -2342,6 +2342,11 @@ impl Workspace { &self.active_pane } + pub fn pane_for(&self, handle: &dyn ItemHandle) -> Option> { + let weak_pane = self.panes_by_item.get(&handle.item_id())?; + weak_pane.upgrade() + } + fn collaborator_left(&mut self, peer_id: PeerId, cx: &mut ViewContext) { self.follower_states.retain(|_, state| { if state.leader_id == peer_id {