History

Refactor GoToLine to use cx.observe_new_views()

Conrad Irwin committed 3 years ago

Commit 1b9f76c1 parent cbdd4ac11 files · +137 −66Browse files

Unified · Split

11 files
  1. crates/editor2/src/editor.rs +2 −1
  2. crates/go_to_line2/src/go_to_line.rs +43 −12
  3. crates/gpui2/src/app.rs +23 −2
  4. crates/gpui2/src/app/async_context.rs +1 −1
  5. crates/gpui2/src/gpui2.rs +1 −1
  6. crates/gpui2/src/interactive.rs +4 −0
  7. crates/gpui2/src/window.rs +12 −3
  8. crates/workspace2/src/dock.rs +8 −0
  9. crates/workspace2/src/modal_layer.rs +21 −36
  10. crates/workspace2/src/toolbar.rs +10 −1
  11. crates/workspace2/src/workspace2.rs +12 −9
crates/editor2/src/editor.rs+2−1
@@ -57,6 +57,7 @@ use language::{ · 56 unmodified lines
5757 Diagnostic, IndentKind, IndentSize, Language, LanguageRegistry, LanguageServerName,
5858 OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
5959 };
60+use lazy_static::lazy_static;
6061 use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState};
6162 use lsp::{DiagnosticSeverity, Documentation, LanguageServerId};
6263 use movement::TextLayoutDetails;
@@ -66,7 +67,7 @@ pub use multi_buffer::{ · 3 unmodified lines
6667 ToPoint,
6768 };
6869 use ordered_float::OrderedFloat;
69−use parking_lot::RwLock;
70+use parking_lot::{Mutex, RwLock};
7071 use project::{FormatTrigger, Location, Project};
7172 use rand::prelude::*;
7273 use rpc::proto::*;
crates/go_to_line2/src/go_to_line.rs+43−12
@@ -1,25 +1,55 @@
11 use editor::Editor;
22 use gpui::{
33 actions, div, AppContext, Div, EventEmitter, ParentElement, Render, SharedString,
4− StatelessInteractive, Styled, View, ViewContext, VisualContext,
4+ StatefulInteractivity, StatelessInteractive, Styled, View, ViewContext, VisualContext,
55 };
66 use text::Point;
77 use theme::ActiveTheme;
88 use ui::{h_stack, modal, v_stack, Label, LabelColor};
99 use util::paths::FILE_ROW_COLUMN_DELIMITER;
10−use workspace::{ModalRegistry, Modal, ModalEvent};
10+use workspace::{Modal, ModalEvent, Workspace};
1111
1212 actions!(Toggle);
1313
1414 pub fn init(cx: &mut AppContext) {
15− cx.global_mut::<ModalRegistry>()
16− .register_modal(Toggle, |workspace, cx| {
17− let editor = workspace
18− .active_item(cx)
19− .and_then(|active_item| active_item.downcast::<Editor>())?;
20−
21− Some(cx.build_view(|cx| GoToLine::new(editor, cx)))
22− });
15+ cx.observe_new_views(
16+ |workspace: &mut Workspace, _: &mut ViewContext<Workspace>| {
17+ workspace
18+ .modal_layer()
19+ .register_modal(Toggle, |workspace, cx| {
20+ let editor = workspace
21+ .active_item(cx)
22+ .and_then(|active_item| active_item.downcast::<Editor>())?;
23+
24+ Some(cx.build_view(|cx| GoToLine::new(editor, cx)))
25+ });
26+ dbg!("hey!");
27+ },
28+ )
29+ .detach();
30+
31+ // // cx.window_global()
32+ // // cx.window_global::<Workspace>
33+ // // cx.window_global::<ActiveEditor>()
34+ // Workspace::on_init(|workspace, cx| {
35+ // workspace.on_open_item()
36+ // });
37+
38+ // Editor::on_init(|editor, cx|{
39+
40+ // })
41+
42+ // Editor::register_action(|_editor, _: &Toggle, cx| {
43+ // dbg!("HEY!");
44+ // // let editor = cx.view();
45+ // // cx.update_window(cx.window().handle(), |cx, view| {
46+ // // let workspace = view.downcast::<Workspace>();
47+ // // })
48+ // // workspace.show_modal(cx.build_view(|cx| GoToLine::new(editor, cx)))
49+ // })
50+ // cx.global_mut::<ModalRegistry>()
51+ // .register_modal(Toggle, |workspace, cx| {
52+ // });
2353 }
2454
2555 pub struct GoToLine {
@@ -128,13 +158,14 @@ impl Modal for GoToLine { · 102 unmodified lines
128158 }
129159
130160 impl Render for GoToLine {
131− type Element = Div<Self>;
161+ type Element = Div<Self, StatefulInteractivity<Self>>;
132162
133163 fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
134164 modal(cx)
135− .w_96()
165+ .id("go to line")
136166 .on_action(Self::cancel)
137167 .on_action(Self::confirm)
168+ .w_96()
138169 .child(
139170 v_stack()
140171 .px_1()
crates/gpui2/src/app.rs+23−2
@@ -18,8 +18,8 @@ use crate::{ · 17 unmodified lines
1818 AppMetadata, AssetSource, BackgroundExecutor, ClipboardItem, Context, DispatchPhase, DisplayId,
1919 Entity, EventEmitter, FocusEvent, FocusHandle, FocusId, ForegroundExecutor, KeyBinding, Keymap,
2020 LayoutId, PathPromptOptions, Pixels, Platform, PlatformDisplay, Point, Render, SubscriberSet,
21− Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem, View, Window,
22− WindowContext, WindowHandle, WindowId,
21+ Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem, View, ViewContext,
22+ Window, WindowContext, WindowHandle, WindowId,
2323 };
2424 use anyhow::{anyhow, Result};
2525 use collections::{HashMap, HashSet, VecDeque};
@@ -167,6 +167,7 @@ type Handler = Box<dyn FnMut(&mut AppContext) -> bool + 'static>; · 141 unmodified lines
167167 type Listener = Box<dyn FnMut(&dyn Any, &mut AppContext) -> bool + 'static>;
168168 type QuitHandler = Box<dyn FnOnce(&mut AppContext) -> LocalBoxFuture<'static, ()> + 'static>;
169169 type ReleaseListener = Box<dyn FnOnce(&mut dyn Any, &mut AppContext) + 'static>;
170+type NewViewListener = Box<dyn FnMut(AnyView, &mut WindowContext) + 'static>;
170171
171172 // struct FrameConsumer {
172173 // next_frame_callbacks: Vec<FrameCallback>,
@@ -193,6 +194,7 @@ pub struct AppContext { · 20 unmodified lines
193194 pub(crate) text_style_stack: Vec<TextStyleRefinement>,
194195 pub(crate) globals_by_type: HashMap<TypeId, AnyBox>,
195196 pub(crate) entities: EntityMap,
197+ pub(crate) new_view_observers: SubscriberSet<TypeId, NewViewListener>,
196198 pub(crate) windows: SlotMap<WindowId, Option<Window>>,
197199 pub(crate) keymap: Arc<Mutex<Keymap>>,
198200 pub(crate) global_action_listeners:
@@ -251,6 +253,7 @@ impl AppContext { · 52 unmodified lines
251253 text_style_stack: Vec::new(),
252254 globals_by_type: HashMap::default(),
253255 entities,
256+ new_view_observers: SubscriberSet::new(),
254257 windows: SlotMap::with_key(),
255258 keymap: Arc::new(Mutex::new(Keymap::default())),
256259 global_action_listeners: HashMap::default(),
@@ -599,6 +602,7 @@ impl AppContext { · 342 unmodified lines
599602
600603 fn apply_notify_effect(&mut self, emitter: EntityId) {
601604 self.pending_notifications.remove(&emitter);
605+
602606 self.observers
603607 .clone()
604608 .retain(&emitter, |handler| handler(self));
@@ -828,6 +832,23 @@ impl AppContext { · 223 unmodified lines
828832 self.globals_by_type.insert(global_type, lease.global);
829833 }
830834
835+ pub fn observe_new_views<V: 'static>(
836+ &mut self,
837+ on_new: impl 'static + Fn(&mut V, &mut ViewContext<V>),
838+ ) -> Subscription {
839+ self.new_view_observers.insert(
840+ TypeId::of::<V>(),
841+ Box::new(move |any_view: AnyView, cx: &mut WindowContext| {
842+ any_view
843+ .downcast::<V>()
844+ .unwrap()
845+ .update(cx, |view_state, cx| {
846+ on_new(view_state, cx);
847+ })
848+ }),
849+ )
850+ }
851+
831852 pub fn observe_release<E, T>(
832853 &mut self,
833854 handle: &E,
crates/gpui2/src/app/async_context.rs+1−1
@@ -258,7 +258,7 @@ impl VisualContext for AsyncWindowContext { · 257 unmodified lines
258258 build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
259259 ) -> Self::Result<View<V>>
260260 where
261− V: 'static,
261+ V: 'static + Render,
262262 {
263263 self.window
264264 .update(self, |_, cx| cx.build_view(build_view_state))
crates/gpui2/src/gpui2.rs+1−1
@@ -112,7 +112,7 @@ pub trait VisualContext: Context { · 111 unmodified lines
112112 build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
113113 ) -> Self::Result<View<V>>
114114 where
115− V: 'static;
115+ V: 'static + Render;
116116
117117 fn update_view<V: 'static, R>(
118118 &mut self,
crates/gpui2/src/interactive.rs+4−0
@@ -414,10 +414,14 @@ pub trait ElementInteractivity<V: 'static>: 'static { · 413 unmodified lines
414414 Box::new(move |_, key_down, context, phase, cx| {
415415 if phase == DispatchPhase::Bubble {
416416 let key_down = key_down.downcast_ref::<KeyDownEvent>().unwrap();
417+ dbg!(key_down);
417418 if let KeyMatch::Some(action) =
418419 cx.match_keystroke(&global_id, &key_down.keystroke, context)
419420 {
421+ dbg!(&action);
420422 return Some(action);
423+ } else {
424+ dbg!("none");
421425 }
422426 }
423427
crates/gpui2/src/window.rs+12−3
@@ -1411,7 +1411,7 @@ impl VisualContext for WindowContext<'_> { · 1410 unmodified lines
14111411 build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
14121412 ) -> Self::Result<View<V>>
14131413 where
1414− V: 'static,
1414+ V: 'static + Render,
14151415 {
14161416 let slot = self.app.entities.reserve();
14171417 let view = View {
@@ -1419,7 +1419,16 @@ impl VisualContext for WindowContext<'_> { · 1 unmodified line
14191419 };
14201420 let mut cx = ViewContext::new(&mut *self.app, &mut *self.window, &view);
14211421 let entity = build_view_state(&mut cx);
1422− self.entities.insert(slot, entity);
1422+ cx.entities.insert(slot, entity);
1423+
1424+ cx.new_view_observers
1425+ .clone()
1426+ .retain(&TypeId::of::<V>(), |observer| {
1427+ let any_view = AnyView::from(view.clone());
1428+ (observer)(any_view, self);
1429+ true
1430+ });
1431+
14231432 view
14241433 }
14251434
@@ -2102,7 +2111,7 @@ impl<V> Context for ViewContext<'_, V> { · 676 unmodified lines
21022111 }
21032112
21042113 impl<V: 'static> VisualContext for ViewContext<'_, V> {
2105− fn build_view<W: 'static>(
2114+ fn build_view<W: Render + 'static>(
21062115 &mut self,
21072116 build_view_state: impl FnOnce(&mut ViewContext<'_, W>) -> W,
21082117 ) -> Self::Result<View<W>> {
crates/workspace2/src/dock.rs+8−0
@@ -407,6 +407,14 @@ impl Dock { · 406 unmodified lines
407407 // }
408408 }
409409
410+impl Render for Dock {
411+ type Element = Div<Self>;
412+
413+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
414+ todo!()
415+ }
416+}
417+
410418 // todo!()
411419 // impl View for Dock {
412420 // fn ui_name() -> &'static str {
crates/workspace2/src/modal_layer.rs+21−36
@@ -1,25 +1,15 @@
11 use crate::Workspace;
22 use gpui::{
3− div, px, AnyView, AppContext, Component, Div, EventEmitter, ParentElement, Render,
4− StatelessInteractive, Styled, Subscription, View, ViewContext, WeakView,
3+ div, px, AnyView, Component, Div, EventEmitter, ParentElement, Render, StatelessInteractive,
4+ Styled, Subscription, View, ViewContext,
55 };
66 use std::{any::TypeId, sync::Arc};
77 use ui::v_stack;
88
9−pub struct ModalRegistry {
10− registered_modals: Vec<(TypeId, Box<dyn Fn(Div<Workspace>) -> Div<Workspace>>)>,
11−}
12−
139 pub struct ModalLayer {
14− workspace: WeakView<Workspace>,
1510 open_modal: Option<AnyView>,
1611 subscription: Option<Subscription>,
17−}
18−
19−pub fn init_modal_registry(cx: &mut AppContext) {
20− cx.set_global(ModalRegistry {
21− registered_modals: Vec::new(),
22− });
12+ registered_modals: Vec<(TypeId, Box<dyn Fn(Div<Workspace>) -> Div<Workspace>>)>,
2313 }
2414
2515 pub enum ModalEvent {
@@ -30,7 +20,15 @@ pub trait Modal: EventEmitter + Render { · 4 unmodified lines
3020 fn to_modal_event(&self, _: &Self::Event) -> Option<ModalEvent>;
3121 }
3222
33−impl ModalRegistry {
23+impl ModalLayer {
24+ pub fn new() -> Self {
25+ Self {
26+ open_modal: None,
27+ subscription: None,
28+ registered_modals: Vec::new(),
29+ }
30+ }
31+
3432 pub fn register_modal<A: 'static, V, B>(&mut self, action: A, build_view: B)
3533 where
3634 V: Modal,
@@ -44,32 +42,19 @@ impl ModalRegistry { · 7 unmodified lines
4442 let build_view = build_view.clone();
4543
4644 div.on_action(move |workspace, event: &A, cx| {
47− let Some(new_modal) =
48− (build_view)(workspace, cx) else {
49− return
50− };
51− workspace.modal_layer.update(cx, |modal_layer, cx| {
52− modal_layer.show_modal(new_modal, cx);
53− })
45+ let Some(new_modal) = (build_view)(workspace, cx) else {
46+ return;
47+ };
48+ workspace.modal_layer().show_modal(new_modal, cx);
5449 })
5550 }),
5651 ));
5752 }
58−}
59−
60−impl ModalLayer {
61− pub fn new(workspace: WeakView<Workspace>) -> Self {
62− Self {
63− workspace,
64− open_modal: None,
65− subscription: None,
66− }
67− }
6853
69− pub fn show_modal<V: Modal>(&mut self, new_modal: View<V>, cx: &mut ViewContext<Self>) {
54+ pub fn show_modal<V: Modal>(&mut self, new_modal: View<V>, cx: &mut ViewContext<Workspace>) {
7055 self.subscription = Some(cx.subscribe(&new_modal, |this, modal, e, cx| {
7156 match modal.read(cx).to_modal_event(e) {
72− Some(ModalEvent::Dismissed) => this.hide_modal(cx),
57+ Some(ModalEvent::Dismissed) => this.modal_layer().hide_modal(cx),
7358 None => {}
7459 }
7560 }));
@@ -77,16 +62,16 @@ impl ModalLayer { · 1 unmodified line
7762 cx.notify();
7863 }
7964
80− pub fn hide_modal(&mut self, cx: &mut ViewContext<Self>) {
65+ pub fn hide_modal(&mut self, cx: &mut ViewContext<Workspace>) {
8166 self.open_modal.take();
8267 self.subscription.take();
8368 cx.notify();
8469 }
8570
86− pub fn render(&self, cx: &ViewContext<Workspace>) -> Div<Workspace> {
71+ pub fn wrapper_element(&self, cx: &ViewContext<Workspace>) -> Div<Workspace> {
8772 let mut parent = div().relative().size_full();
8873
89− for (_, action) in cx.global::<ModalRegistry>().registered_modals.iter() {
74+ for (_, action) in self.registered_modals.iter() {
9075 parent = (action)(parent);
9176 }
9277
crates/workspace2/src/toolbar.rs+10−1
@@ -1,6 +1,7 @@
11 use crate::ItemHandle;
22 use gpui::{
3− AnyView, AppContext, Entity, EntityId, EventEmitter, Render, View, ViewContext, WindowContext,
3+ AnyView, AppContext, Div, Entity, EntityId, EventEmitter, Render, View, ViewContext,
4+ WindowContext,
45 };
56
67 pub trait ToolbarItemView: Render + EventEmitter {
@@ -56,6 +57,14 @@ pub struct Toolbar { · 49 unmodified lines
5657 items: Vec<(Box<dyn ToolbarItemViewHandle>, ToolbarItemLocation)>,
5758 }
5859
60+impl Render for Toolbar {
61+ type Element = Div<Self>;
62+
63+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
64+ todo!()
65+ }
66+}
67+
5968 // todo!()
6069 // impl View for Toolbar {
6170 // fn ui_name() -> &'static str {
crates/workspace2/src/workspace2.rs+12−9
@@ -37,10 +37,10 @@ use futures::{ · 36 unmodified lines
3737 };
3838 use gpui::{
3939 div, point, size, AnyModel, AnyView, AnyWeakView, AppContext, AsyncAppContext,
40− AsyncWindowContext, Bounds, Component, Div, Entity, EntityId, EventEmitter, FocusHandle,
41− GlobalPixels, Model, ModelContext, ParentElement, Point, Render, Size, StatefulInteractive,
42− Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowBounds,
43− WindowContext, WindowHandle, WindowOptions,
40+ AsyncWindowContext, Bounds, Component, Context, Div, Entity, EntityId, EventEmitter,
41+ FocusHandle, GlobalPixels, Model, ModelContext, ParentElement, Point, Render, Size,
42+ StatefulInteractive, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView,
43+ WindowBounds, WindowContext, WindowHandle, WindowOptions,
4444 };
4545 use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
4646 use itertools::Itertools;
@@ -225,7 +225,6 @@ pub fn init_settings(cx: &mut AppContext) { · 178 unmodified lines
225225
226226 pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
227227 init_settings(cx);
228− init_modal_registry(cx);
229228 pane::init(cx);
230229 notifications::init(cx);
231230
@@ -545,7 +544,7 @@ pub struct Workspace { · 313 unmodified lines
545544 last_active_center_pane: Option<WeakView<Pane>>,
546545 last_active_view_id: Option<proto::ViewId>,
547546 status_bar: View<StatusBar>,
548− modal_layer: View<ModalLayer>,
547+ modal_layer: ModalLayer,
549548 // titlebar_item: Option<AnyViewHandle>,
550549 notifications: Vec<(TypeId, usize, Box<dyn NotificationHandle>)>,
551550 project: Model<Project>,
@@ -697,7 +696,7 @@ impl Workspace { · 145 unmodified lines
697696 });
698697
699698 let workspace_handle = cx.view().downgrade();
700− let modal_layer = cx.build_view(|cx| ModalLayer::new(workspace_handle));
699+ let modal_layer = ModalLayer::new();
701700
702701 // todo!()
703702 // cx.update_default_global::<DragAndDrop<Workspace>, _, _>(|drag_and_drop, _| {
@@ -781,6 +780,10 @@ impl Workspace { · 77 unmodified lines
781780 }
782781 }
783782
783+ pub fn modal_layer(&mut self) -> &mut ModalLayer {
784+ &mut self.modal_layer
785+ }
786+
784787 fn new_local(
785788 abs_paths: Vec<PathBuf>,
786789 app_state: Arc<AppState>,
@@ -3707,9 +3710,9 @@ impl Render for Workspace { · 2920 unmodified lines
37073710 .bg(cx.theme().colors().background)
37083711 .child(self.render_titlebar(cx))
37093712 .child(
3713+ // todo! should this be a component a view?
37103714 self.modal_layer
3711− .read(cx)
3712− .render(cx)
3715+ .wrapper_element(cx)
37133716 .relative()
37143717 .flex_1()
37153718 .w_full()

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t