From d4b1d1b52881f387afc00a18742d999b36372604 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Thu, 9 Nov 2023 21:51:48 -0700 Subject: [PATCH] Move from register_modals to register_workspace_action --- .../command_palette2/src/command_palette.rs | 23 +++--- crates/go_to_line2/src/go_to_line.rs | 30 ++++---- crates/workspace2/src/modal_layer.rs | 70 ++++--------------- crates/workspace2/src/workspace2.rs | 58 +++++++++++---- 4 files changed, 84 insertions(+), 97 deletions(-) diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 77d64d63da..3b3a6684d5 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -21,19 +21,7 @@ actions!(Toggle); pub fn init(cx: &mut AppContext) { cx.set_global(HitCounts::default()); - - cx.observe_new_views( - |workspace: &mut Workspace, _: &mut ViewContext| { - workspace.modal_layer().register_modal(Toggle, |cx| { - let Some(previous_focus_handle) = cx.focused() else { - return None; - }; - - Some(cx.build_view(|cx| CommandPalette::new(previous_focus_handle, cx))) - }); - }, - ) - .detach(); + cx.observe_new_views(CommandPalette::register).detach(); } pub struct CommandPalette { @@ -41,6 +29,15 @@ pub struct CommandPalette { } impl CommandPalette { + fn register(workspace: &mut Workspace, _: &mut ViewContext) { + workspace.register_action(|workspace, _: &Toggle, cx| { + let Some(previous_focus_handle) = cx.focused() else { + return; + }; + workspace.toggle_modal(cx, move |cx| CommandPalette::new(previous_focus_handle, cx)); + }); + } + fn new(previous_focus_handle: FocusHandle, cx: &mut ViewContext) -> Self { let filter = cx.try_global::(); diff --git a/crates/go_to_line2/src/go_to_line.rs b/crates/go_to_line2/src/go_to_line.rs index 38b46df4e2..9ec770e05c 100644 --- a/crates/go_to_line2/src/go_to_line.rs +++ b/crates/go_to_line2/src/go_to_line.rs @@ -13,22 +13,7 @@ use workspace::{Modal, ModalEvent, Workspace}; actions!(Toggle); pub fn init(cx: &mut AppContext) { - cx.observe_new_views( - |workspace: &mut Workspace, cx: &mut ViewContext| { - let handle = cx.view().downgrade(); - - workspace.modal_layer().register_modal(Toggle, move |cx| { - let workspace = handle.upgrade()?; - let editor = workspace - .read(cx) - .active_item(cx) - .and_then(|active_item| active_item.downcast::())?; - - Some(cx.build_view(|cx| GoToLine::new(editor, cx))) - }); - }, - ) - .detach(); + cx.observe_new_views(GoToLine::register).detach(); } pub struct GoToLine { @@ -47,6 +32,19 @@ impl Modal 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 { + return; + }; + + workspace.toggle_modal(cx, move |cx| GoToLine::new(editor, cx)); + }); + } + pub fn new(active_editor: View, cx: &mut ViewContext) -> Self { let line_editor = cx.build_view(|cx| Editor::single_line(cx)); let line_editor_change = cx.subscribe(&line_editor, Self::on_line_editor_event); diff --git a/crates/workspace2/src/modal_layer.rs b/crates/workspace2/src/modal_layer.rs index aa5b2e7848..22fc2cd6b9 100644 --- a/crates/workspace2/src/modal_layer.rs +++ b/crates/workspace2/src/modal_layer.rs @@ -2,7 +2,7 @@ use crate::Workspace; use gpui::{ div, px, AnyView, Component, Div, EventEmitter, FocusHandle, ParentElement, Render, StatefulInteractivity, StatelessInteractive, Styled, Subscription, View, ViewContext, - WindowContext, + VisualContext, WindowContext, }; use std::{any::TypeId, sync::Arc}; use ui::v_stack; @@ -16,14 +16,6 @@ pub struct ActiveModal { pub struct ModalLayer { active_modal: Option, - registered_modals: Vec<( - TypeId, - Box< - dyn Fn( - Div>, - ) -> Div>, - >, - )>, } pub trait Modal: Render + EventEmitter { @@ -36,35 +28,13 @@ pub enum ModalEvent { impl ModalLayer { pub fn new() -> Self { - Self { - active_modal: None, - registered_modals: Vec::new(), - } + Self { active_modal: None } } - pub fn register_modal(&mut self, action: A, build_view: B) + pub fn toggle_modal(&mut self, cx: &mut ViewContext, build_view: B) where V: Modal, - B: Fn(&mut WindowContext) -> Option> + 'static, - { - let build_view = Arc::new(build_view); - - self.registered_modals.push(( - TypeId::of::(), - Box::new(move |mut div| { - let build_view = build_view.clone(); - - div.on_action(move |workspace, event: &A, cx| { - workspace.modal_layer().toggle_modal(build_view.clone(), cx) - }) - }), - )); - } - - pub fn toggle_modal(&mut self, build_view: Arc, cx: &mut ViewContext) - where - V: Modal, - B: Fn(&mut WindowContext) -> Option> + 'static, + B: FnOnce(&mut ViewContext) -> V, { let previous_focus = cx.focused(); @@ -74,28 +44,23 @@ impl ModalLayer { return; } } - let Some(new_modal) = (build_view)(cx) else { - return; - }; - self.show_modal(previous_focus, new_modal, cx); + let new_modal = cx.build_view(build_view); + self.show_modal(new_modal, cx); } - pub fn show_modal( - &mut self, - previous_focus: Option, - new_modal: View, - cx: &mut ViewContext, - ) where + pub fn show_modal(&mut self, new_modal: View, cx: &mut ViewContext) + where V: Modal, { self.active_modal = Some(ActiveModal { modal: new_modal.clone().into(), - subscription: cx.subscribe(&new_modal, |this, modal, e, cx| match e { - ModalEvent::Dismissed => this.modal_layer().hide_modal(cx), + subscription: cx.subscribe(&new_modal, |workspace, modal, e, cx| match e { + ModalEvent::Dismissed => workspace.modal_layer.hide_modal(cx), }), - previous_focus_handle: previous_focus, + previous_focus_handle: cx.focused(), focus_handle: cx.focus_handle(), }); + new_modal.update(cx, |modal, cx| modal.focus(cx)); cx.notify(); } @@ -115,12 +80,7 @@ impl ModalLayer { &self, cx: &ViewContext, ) -> Div> { - let mut parent = div().id("modal layer").relative().size_full(); - - for (_, action) in self.registered_modals.iter() { - parent = (action)(parent); - } - + let parent = div().id("boop"); parent.when_some(self.active_modal.as_ref(), |parent, open_modal| { let container1 = div() .absolute() @@ -137,8 +97,8 @@ impl ModalLayer { .relative() .top_20() .track_focus(&open_modal.focus_handle) - .on_mouse_down_out(|workspace: &mut Workspace, _, cx| { - workspace.modal_layer().hide_modal(cx); + .on_mouse_down_out(|workspace: &mut Workspace, event, cx| { + workspace.modal_layer.hide_modal(cx); }); parent.child(container1.child(container2.child(open_modal.modal.clone()))) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 54c8709d7e..7e43941af8 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -36,11 +36,12 @@ use futures::{ Future, FutureExt, StreamExt, }; use gpui::{ - actions, div, point, rems, size, AnyModel, AnyView, AnyWeakView, AppContext, AsyncAppContext, - AsyncWindowContext, Bounds, Component, DispatchContext, Div, Entity, EntityId, EventEmitter, - FocusHandle, GlobalPixels, Model, ModelContext, ParentElement, Point, Render, Size, - StatefulInteractive, StatefulInteractivity, Styled, Subscription, Task, View, ViewContext, - VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions, + actions, div, point, rems, size, Action, AnyModel, AnyView, AnyWeakView, AppContext, + AsyncAppContext, AsyncWindowContext, Bounds, Component, DispatchContext, Div, Entity, EntityId, + EventEmitter, FocusHandle, GlobalPixels, Model, ModelContext, ParentElement, Point, Render, + Size, StatefulInteractive, StatefulInteractivity, StatelessInteractive, Styled, Subscription, + Task, View, ViewContext, VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle, + WindowOptions, }; use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem}; use itertools::Itertools; @@ -530,6 +531,13 @@ pub enum Event { pub struct Workspace { weak_self: WeakView, focus_handle: FocusHandle, + workspace_actions: Vec< + Box< + dyn Fn( + Div>, + ) -> Div>, + >, + >, zoomed: Option, zoomed_position: Option, center: PaneGroup, @@ -775,13 +783,10 @@ impl Workspace { leader_updates_tx, subscriptions, pane_history_timestamp, + workspace_actions: Default::default(), } } - pub fn modal_layer(&mut self) -> &mut ModalLayer { - &mut self.modal_layer - } - fn new_local( abs_paths: Vec, app_state: Arc, @@ -3495,6 +3500,34 @@ impl Workspace { // ) // } // } + pub fn register_action( + &mut self, + callback: impl Fn(&mut Self, &A, &mut ViewContext) + 'static, + ) { + let callback = Arc::new(callback); + + self.workspace_actions.push(Box::new(move |div| { + let callback = callback.clone(); + div.on_action(move |workspace, event, cx| (callback.clone())(workspace, event, cx)) + })); + } + + fn add_workspace_actions_listeners( + &self, + mut div: Div>, + ) -> Div> { + for action in self.workspace_actions.iter() { + div = (action)(div) + } + div + } + + pub fn toggle_modal(&mut self, cx: &mut ViewContext, build: B) + where + B: FnOnce(&mut ViewContext) -> V, + { + self.modal_layer.toggle_modal(cx, build) + } } fn window_bounds_env_override(cx: &AsyncAppContext) -> Option { @@ -3706,14 +3739,13 @@ fn notify_if_database_failed(workspace: WindowHandle, cx: &mut AsyncA impl EventEmitter for Workspace {} impl Render for Workspace { - type Element = Div>; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let mut context = DispatchContext::default(); context.insert("Workspace"); cx.with_key_dispatch_context(context, |cx| { div() - .id("workspace") .relative() .size_full() .flex() @@ -3727,8 +3759,7 @@ impl Render for Workspace { .child(self.render_titlebar(cx)) .child( // todo! should this be a component a view? - self.modal_layer - .wrapper_element(cx) + self.add_workspace_actions_listeners(div().id("workspace")) .relative() .flex_1() .w_full() @@ -3737,6 +3768,7 @@ impl Render for Workspace { .border_t() .border_b() .border_color(cx.theme().colors().border) + .child(self.modal_layer.wrapper_element(cx)) // .children( // Some( // Panel::new("project-panel-outer", cx)