From 4c31a0c9891a17f225b4578fd3ad705f123cea71 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 8 Nov 2023 10:45:10 -0800 Subject: [PATCH] Preserve stateless interactivity when assigning elements an id Co-authored-by: Nathan Co-authored-by: Piotr --- crates/go_to_line2/src/go_to_line.rs | 1 - crates/gpui2/src/elements/div.rs | 2 +- crates/gpui2/src/elements/uniform_list.rs | 2 +- crates/gpui2/src/interactive.rs | 54 +++++++++++------------ crates/gpui2/src/window.rs | 6 +-- 5 files changed, 28 insertions(+), 37 deletions(-) diff --git a/crates/go_to_line2/src/go_to_line.rs b/crates/go_to_line2/src/go_to_line.rs index b8b91b1646..3c9cd5e31e 100644 --- a/crates/go_to_line2/src/go_to_line.rs +++ b/crates/go_to_line2/src/go_to_line.rs @@ -27,7 +27,6 @@ impl Render for GoToLine { type Element = Div; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { - dbg!("rendering GoToLine"); div().bg(red()).w(px(100.0)).h(px(100.0)) } } diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 9b8c9dbf85..d88a4119b7 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -37,7 +37,7 @@ where { pub fn id(self, id: impl Into) -> Div, F> { Div { - interactivity: id.into().into(), + interactivity: StatefulInteractivity::new(id.into(), self.interactivity), focus: self.focus, children: self.children, group: self.group, diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index d43c6b5992..e116022763 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -30,7 +30,7 @@ where .map(|component| component.render()) .collect() }), - interactivity: id.into(), + interactivity: StatefulInteractivity::new(id, StatelessInteractivity::default()), scroll_handle: None, } } diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index 308c39fe7f..a546c1b40b 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -189,10 +189,10 @@ pub trait StatelessInteractive: Element { { self.stateless_interactivity().key_listeners.push(( TypeId::of::(), - Box::new(move |view, event, _, phase, cx| { - let event = event.downcast_ref().unwrap(); + Box::new(move |view, action, _dipatch_context, phase, cx| { + let action = action.downcast_ref().unwrap(); if phase == DispatchPhase::Capture { - listener(view, event, cx) + listener(view, action, cx) } None }), @@ -210,10 +210,10 @@ pub trait StatelessInteractive: Element { { self.stateless_interactivity().key_listeners.push(( TypeId::of::(), - Box::new(move |view, event, _, phase, cx| { - let event = event.downcast_ref().unwrap(); + Box::new(move |view, action, _dispatch_context, phase, cx| { + let action = action.downcast_ref().unwrap(); if phase == DispatchPhase::Bubble { - listener(view, event, cx) + listener(view, action, cx) } None @@ -407,6 +407,8 @@ pub trait ElementInteractivity: 'static { ) -> R { if let Some(stateful) = self.as_stateful_mut() { cx.with_element_id(stateful.id.clone(), |global_id, cx| { + // In addition to any key down/up listeners registered directly on the element, + // we also add a key listener to match actions from the keymap. stateful.key_listeners.push(( TypeId::of::(), Box::new(move |_, key_down, context, phase, cx| { @@ -774,6 +776,21 @@ pub struct StatefulInteractivity { tooltip_builder: Option>, } +impl StatefulInteractivity { + pub fn new(id: ElementId, stateless: StatelessInteractivity) -> Self { + Self { + id, + stateless, + click_listeners: SmallVec::new(), + active_style: StyleRefinement::default(), + group_active_style: None, + drag_listener: None, + hover_listener: None, + tooltip_builder: None, + } + } +} + impl ElementInteractivity for StatefulInteractivity { fn as_stateful(&self) -> Option<&StatefulInteractivity> { Some(self) @@ -792,21 +809,6 @@ impl ElementInteractivity for StatefulInteractivity { } } -impl From for StatefulInteractivity { - fn from(id: ElementId) -> Self { - Self { - id, - stateless: StatelessInteractivity::default(), - click_listeners: SmallVec::new(), - drag_listener: None, - hover_listener: None, - tooltip_builder: None, - active_style: StyleRefinement::default(), - group_active_style: None, - } - } -} - type DropListener = dyn Fn(&mut V, AnyView, &mut ViewContext) + 'static; pub struct StatelessInteractivity { @@ -1284,14 +1286,8 @@ mod test { fn render(&mut self, _: &mut gpui::ViewContext) -> Self::Element { div().id("testview").child( div() - .on_key_down(|this: &mut TestView, _, _, _| { - dbg!("ola!"); - this.saw_key_down = true - }) - .on_action(|this: &mut TestView, _: &TestAction, _| { - dbg!("ola!"); - this.saw_action = true - }) + .on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true) + .on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true) .track_focus(&self.focus_handle), ) } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index e55f0152d8..1e88d08538 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1170,7 +1170,6 @@ impl<'a> WindowContext<'a> { .insert(any_mouse_event.type_id(), handlers); } } else if let Some(any_key_event) = event.keyboard_event() { - let mut did_handle_action = false; let key_dispatch_stack = mem::take(&mut self.window.key_dispatch_stack); let key_event_type = any_key_event.type_id(); let mut context_stack = SmallVec::<[&DispatchContext; 16]>::new(); @@ -1191,7 +1190,6 @@ impl<'a> WindowContext<'a> { self.dispatch_action(action, &key_dispatch_stack[..ix]); } if !self.app.propagate_event { - did_handle_action = true; break; } } @@ -1220,7 +1218,6 @@ impl<'a> WindowContext<'a> { } if !self.app.propagate_event { - did_handle_action = true; break; } } @@ -1234,10 +1231,9 @@ impl<'a> WindowContext<'a> { drop(context_stack); self.window.key_dispatch_stack = key_dispatch_stack; - return did_handle_action; } - true + !self.app.propagate_event } /// Attempt to map a keystroke to an action based on the keymap.