History

Checkpoint

Antonio Scandurra committed 3 years ago

Commit dd7e1c51 parent 0fbf84e8 files · +207 −191Browse files

Unified · Split

8 files
  1. crates/gpui3/src/element.rs +134 −13
  2. crates/gpui3/src/elements/div.rs +24 −50
  3. crates/gpui3/src/elements/img.rs +11 −8
  4. crates/gpui3/src/elements/svg.rs +11 −8
  5. crates/gpui3/src/interactive.rs +23 −108
  6. crates/ui2/src/components/icon_button.rs +1 −1
  7. crates/ui2/src/elements/button.rs +1 −1
  8. crates/ui2/src/prelude.rs +2 −2
crates/gpui3/src/element.rs+134−13
@@ -1,11 +1,15 @@
11 use crate::{
2− BorrowWindow, Bounds, DispatchPhase, ElementId, FocusHandle, FocusListeners, LayoutId,
3− MouseDownEvent, Pixels, Point, Style, StyleRefinement, ViewContext, WindowContext,
2+ BorrowWindow, Bounds, DispatchPhase, ElementId, FocusHandle, FocusListeners, KeyDownEvent,
3+ KeyListener, KeyMatch, LayoutId, MouseClickEvent, MouseClickListener, MouseDownEvent,
4+ MouseDownListener, MouseMoveEvent, MouseMoveListener, MouseUpEvent, MouseUpListener, Pixels,
5+ Point, ScrollWheelEvent, ScrollWheelListener, Style, StyleRefinement, ViewContext,
6+ WindowContext,
47 };
58 use derive_more::{Deref, DerefMut};
9+use parking_lot::Mutex;
610 use refineable::Refineable;
711 pub(crate) use smallvec::SmallVec;
8−use std::{marker::PhantomData, mem};
12+use std::{any::TypeId, mem, sync::Arc};
913
1014 pub trait Element: 'static + Send + Sync + IntoAnyElement<Self::ViewState> {
1115 type ViewState: 'static + Send + Sync;
@@ -40,19 +44,98 @@ pub trait Element: 'static + Send + Sync + IntoAnyElement<Self::ViewState> { · 28 unmodified lines
4044 pub struct GlobalElementId(SmallVec<[ElementId; 32]>);
4145
4246 pub trait ElementInteractivity<V: 'static + Send + Sync>: 'static + Send + Sync {
47+ fn as_stateless(&self) -> &StatelessInteractivity<V>;
48+ fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V>;
4349 fn as_stateful(&self) -> Option<&StatefulInteractivity<V>>;
50+ fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>>;
51+
52+ fn paint(
53+ &mut self,
54+ bounds: Bounds<Pixels>,
55+ pending_click: Arc<Mutex<Option<MouseDownEvent>>>,
56+ cx: &mut ViewContext<V>,
57+ ) {
58+ let stateless = self.as_stateless();
59+ for listener in stateless.mouse_down_listeners.iter().cloned() {
60+ cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
61+ listener(state, event, &bounds, phase, cx);
62+ })
63+ }
64+
65+ for listener in stateless.mouse_up_listeners.iter().cloned() {
66+ cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
67+ listener(state, event, &bounds, phase, cx);
68+ })
69+ }
70+
71+ for listener in stateless.mouse_move_listeners.iter().cloned() {
72+ cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| {
73+ listener(state, event, &bounds, phase, cx);
74+ })
75+ }
76+
77+ for listener in stateless.scroll_wheel_listeners.iter().cloned() {
78+ cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| {
79+ listener(state, event, &bounds, phase, cx);
80+ })
81+ }
82+
83+ if let Some(stateful) = self.as_stateful() {
84+ let click_listeners = stateful.mouse_click_listeners.clone();
85+
86+ let mouse_down = pending_click.lock().clone();
87+ if let Some(mouse_down) = mouse_down {
88+ cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
89+ if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
90+ let mouse_click = MouseClickEvent {
91+ down: mouse_down.clone(),
92+ up: event.clone(),
93+ };
94+ for listener in &click_listeners {
95+ listener(state, &mouse_click, cx);
96+ }
97+ }
98+
99+ *pending_click.lock() = None;
100+ });
101+ } else {
102+ cx.on_mouse_event(move |_state, event: &MouseDownEvent, phase, _cx| {
103+ if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
104+ *pending_click.lock() = Some(event.clone());
105+ }
106+ });
107+ };
108+ }
109+ }
44110
45111 fn initialize<R>(
46− &self,
112+ &mut self,
47113 cx: &mut ViewContext<V>,
48− f: impl FnOnce(Option<GlobalElementId>, &mut ViewContext<V>) -> R,
114+ f: impl FnOnce(&mut ViewContext<V>) -> R,
49115 ) -> R {
50− if let Some(identified) = self.as_stateful() {
51− cx.with_element_id(identified.id.clone(), |global_id, cx| {
52− f(Some(global_id), cx)
116+ if let Some(stateful) = self.as_stateful_mut() {
117+ cx.with_element_id(stateful.id.clone(), |global_id, cx| {
118+ stateful.key_listeners.push((
119+ TypeId::of::<KeyDownEvent>(),
120+ Arc::new(move |_, key_down, context, phase, cx| {
121+ if phase == DispatchPhase::Bubble {
122+ let key_down = key_down.downcast_ref::<KeyDownEvent>().unwrap();
123+ if let KeyMatch::Some(action) =
124+ cx.match_keystroke(&global_id, &key_down.keystroke, context)
125+ {
126+ return Some(action);
127+ }
128+ }
129+
130+ None
131+ }),
132+ ));
133+ let result = stateful.stateless.initialize(cx, f);
134+ stateful.key_listeners.pop();
135+ result
53136 })
54137 } else {
55− f(None, cx)
138+ cx.with_key_listeners(&self.as_stateless().key_listeners, f)
56139 }
57140 }
58141 }
@@ -62,7 +145,8 @@ pub struct StatefulInteractivity<V: 'static + Send + Sync> { · 3 unmodified lines
62145 pub id: ElementId,
63146 #[deref]
64147 #[deref_mut]
65− common: StatelessInteractivity<V>,
148+ stateless: StatelessInteractivity<V>,
149+ pub mouse_click_listeners: SmallVec<[MouseClickListener<V>; 2]>,
66150 }
67151
68152 impl<V> ElementInteractivity<V> for StatefulInteractivity<V>
@@ -72,6 +156,18 @@ where · 3 unmodified lines
72156 fn as_stateful(&self) -> Option<&StatefulInteractivity<V>> {
73157 Some(self)
74158 }
159+
160+ fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>> {
161+ Some(self)
162+ }
163+
164+ fn as_stateless(&self) -> &StatelessInteractivity<V> {
165+ &self.stateless
166+ }
167+
168+ fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V> {
169+ &mut self.stateless
170+ }
75171 }
76172
77173 impl<V> From<ElementId> for StatefulInteractivity<V>
@@ -81,16 +177,29 @@ where · 3 unmodified lines
81177 fn from(id: ElementId) -> Self {
82178 Self {
83179 id,
84− common: StatelessInteractivity::default(),
180+ stateless: StatelessInteractivity::default(),
181+ mouse_click_listeners: SmallVec::new(),
85182 }
86183 }
87184 }
88185
89−pub struct StatelessInteractivity<V>(PhantomData<V>);
186+pub struct StatelessInteractivity<V> {
187+ pub mouse_down_listeners: SmallVec<[MouseDownListener<V>; 2]>,
188+ pub mouse_up_listeners: SmallVec<[MouseUpListener<V>; 2]>,
189+ pub mouse_move_listeners: SmallVec<[MouseMoveListener<V>; 2]>,
190+ pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener<V>; 2]>,
191+ pub key_listeners: SmallVec<[(TypeId, KeyListener<V>); 32]>,
192+}
90193
91194 impl<V> Default for StatelessInteractivity<V> {
92195 fn default() -> Self {
93− Self(PhantomData)
196+ Self {
197+ mouse_down_listeners: SmallVec::new(),
198+ mouse_up_listeners: SmallVec::new(),
199+ mouse_move_listeners: SmallVec::new(),
200+ scroll_wheel_listeners: SmallVec::new(),
201+ key_listeners: SmallVec::new(),
202+ }
94203 }
95204 }
96205
@@ -101,6 +210,18 @@ where · 4 unmodified lines
101210 fn as_stateful(&self) -> Option<&StatefulInteractivity<V>> {
102211 None
103212 }
213+
214+ fn as_stateful_mut(&mut self) -> Option<&mut StatefulInteractivity<V>> {
215+ None
216+ }
217+
218+ fn as_stateless(&self) -> &StatelessInteractivity<V> {
219+ self
220+ }
221+
222+ fn as_stateless_mut(&mut self) -> &mut StatelessInteractivity<V> {
223+ self
224+ }
104225 }
105226
106227 pub trait ElementFocusability<V: 'static + Send + Sync>: 'static + Send + Sync {
crates/gpui3/src/elements/div.rs+24−50
@@ -1,16 +1,16 @@
11 use crate::{
2− Active, AnyElement, AppContext, BorrowWindow, Bounds, Click, DispatchPhase, Element,
2+ Active, AnyElement, AppContext, BorrowWindow, Bounds, DispatchPhase, Element,
33 ElementFocusability, ElementId, ElementInteractivity, Focus, FocusHandle, FocusListeners,
4− Focusable, GlobalElementId, Hover, Interactive, Interactivity, IntoAnyElement, KeyDownEvent,
5− KeyMatch, LayoutId, MouseDownEvent, MouseMoveEvent, MouseUpEvent, NonFocusable, Overflow,
6− ParentElement, Pixels, Point, SharedString, StatefulInteractivity, StatelessInteractivity,
4+ Focusable, GlobalElementId, Hover, IntoAnyElement, LayoutId, MouseDownEvent, MouseMoveEvent,
5+ MouseUpEvent, NonFocusable, Overflow, ParentElement, Pixels, Point, SharedString,
6+ StatefulInteractivity, StatefullyInteractive, StatelessInteractivity, StatelesslyInteractive,
77 Style, StyleRefinement, Styled, ViewContext,
88 };
99 use collections::HashMap;
1010 use parking_lot::Mutex;
1111 use refineable::Refineable;
1212 use smallvec::SmallVec;
13−use std::{any::TypeId, mem, sync::Arc};
13+use std::sync::Arc;
1414
1515 #[derive(Default)]
1616 pub struct DivState {
@@ -66,9 +66,8 @@ pub struct Div< · 49 unmodified lines
6666 I: ElementInteractivity<V> = StatelessInteractivity<V>,
6767 F: ElementFocusability<V> = NonFocusable,
6868 > {
69− identity: I,
69+ interactivity: I,
7070 focusability: F,
71− interactivity: Interactivity<V>,
7271 children: SmallVec<[AnyElement<V>; 2]>,
7372 group: Option<SharedString>,
7473 base_style: StyleRefinement,
@@ -83,9 +82,8 @@ where · 8 unmodified lines
8382 V: 'static + Send + Sync,
8483 {
8584 Div {
86− identity: StatelessInteractivity::default(),
85+ interactivity: StatelessInteractivity::default(),
8786 focusability: NonFocusable,
88− interactivity: Interactivity::default(),
8987 children: SmallVec::new(),
9088 group: None,
9189 base_style: StyleRefinement::default(),
@@ -108,9 +106,8 @@ where · 16 unmodified lines
108106 {
109107 pub fn id(self, id: impl Into<ElementId>) -> Div<V, StatefulInteractivity<V>, F> {
110108 Div {
111− identity: id.into().into(),
109+ interactivity: id.into().into(),
112110 focusability: self.focusability,
113− interactivity: self.interactivity,
114111 children: self.children,
115112 group: self.group,
116113 base_style: self.base_style,
@@ -277,7 +274,7 @@ where · 160 unmodified lines
277274 {
278275 pub fn focusable(self, handle: &FocusHandle) -> Div<V, I, Focusable<V>> {
279276 Div {
280− identity: self.identity,
277+ interactivity: self.interactivity,
281278 focusability: handle.clone().into(),
282279 children: self.children,
283280 group: self.group,
@@ -286,7 +283,6 @@ where · 2 unmodified lines
286283 group_hover: self.group_hover,
287284 active_style: self.active_style,
288285 group_active: self.group_active,
289− interactivity: self.interactivity,
290286 }
291287 }
292288 }
@@ -327,7 +323,7 @@ where · 34 unmodified lines
327323 type ElementState = DivState;
328324
329325 fn id(&self) -> Option<ElementId> {
330− self.identity
326+ self.interactivity
331327 .as_stateful()
332328 .map(|identified| identified.id.clone())
333329 }
@@ -338,39 +334,14 @@ where · 4 unmodified lines
338334 element_state: Option<Self::ElementState>,
339335 cx: &mut ViewContext<Self::ViewState>,
340336 ) -> Self::ElementState {
341− self.with_element_id(cx, |this, global_id, cx| {
342− let element_state = element_state.unwrap_or_default();
343−
344− let mut key_listeners = mem::take(&mut this.interactivity.key);
345− if let Some(global_id) = global_id {
346− key_listeners.push((
347− TypeId::of::<KeyDownEvent>(),
348− Arc::new(move |_, key_down, context, phase, cx| {
349− if phase == DispatchPhase::Bubble {
350− let key_down = key_down.downcast_ref::<KeyDownEvent>().unwrap();
351− if let KeyMatch::Some(action) =
352− cx.match_keystroke(&global_id, &key_down.keystroke, context)
353− {
354− return Some(action);
355− }
356− }
357−
358− None
359− }),
360− ));
361− }
362−
363− cx.with_key_listeners(&key_listeners, |cx| {
364− this.focusability.initialize(cx, |cx| {
365− for child in &mut this.children {
366− child.initialize(view_state, cx);
367− }
368− });
337+ self.interactivity.initialize(cx, |cx| {
338+ self.focusability.initialize(cx, |cx| {
339+ for child in &mut self.children {
340+ child.initialize(view_state, cx);
341+ }
369342 });
370− this.interactivity.key = key_listeners;
371−
372− element_state
373− })
343+ });
344+ element_state.unwrap_or_default()
374345 }
375346
376347 fn layout(
@@ -490,14 +461,14 @@ where · 113 unmodified lines
490461 }
491462 }
492463
493−impl<V, I, F> Interactive for Div<V, I, F>
464+impl<V, I, F> StatelesslyInteractive for Div<V, I, F>
494465 where
495466 I: ElementInteractivity<V>,
496467 F: ElementFocusability<V>,
497468 V: 'static + Send + Sync,
498469 {
499− fn interactivity(&mut self) -> &mut Interactivity<V> {
500− &mut self.interactivity
470+ fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity<V> {
471+ self.interactivity.as_stateless_mut()
501472 }
502473 }
503474
@@ -516,11 +487,14 @@ where · 12 unmodified lines
516487 }
517488 }
518489
519−impl<V, F> Click for Div<V, StatefulInteractivity<V>, F>
490+impl<V, F> StatefullyInteractive for Div<V, StatefulInteractivity<V>, F>
520491 where
521492 F: ElementFocusability<V>,
522493 V: 'static + Send + Sync,
523494 {
495+ fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity<Self::ViewState> {
496+ &mut self.interactivity
497+ }
524498 }
525499
526500 impl<V, F> Active for Div<V, StatefulInteractivity<V>, F>
crates/gpui3/src/elements/img.rs+11−8
@@ -1,8 +1,8 @@
11 use crate::{
2− div, Active, AnyElement, BorrowWindow, Bounds, Click, Div, DivState, Element,
3− ElementFocusability, ElementId, ElementInteractivity, Focus, FocusListeners, Focusable, Hover,
4− Interactive, Interactivity, IntoAnyElement, LayoutId, NonFocusable, Pixels, SharedString,
5− StatefulInteractivity, StatelessInteractivity, StyleRefinement, Styled, ViewContext,
2+ div, Active, AnyElement, BorrowWindow, Bounds, Div, DivState, Element, ElementFocusability,
3+ ElementId, ElementInteractivity, Focus, FocusListeners, Focusable, Hover, IntoAnyElement,
4+ LayoutId, NonFocusable, Pixels, SharedString, StatefulInteractivity, StatefullyInteractive,
5+ StatelessInteractivity, StatelesslyInteractive, StyleRefinement, Styled, ViewContext,
66 };
77 use futures::FutureExt;
88 use util::ResultExt;
@@ -150,14 +150,14 @@ where · 141 unmodified lines
150150 }
151151 }
152152
153−impl<V, I, F> Interactive for Img<V, I, F>
153+impl<V, I, F> StatelesslyInteractive for Img<V, I, F>
154154 where
155155 V: 'static + Send + Sync,
156156 I: ElementInteractivity<V>,
157157 F: ElementFocusability<V>,
158158 {
159− fn interactivity(&mut self) -> &mut Interactivity<V> {
160− self.base.interactivity()
159+ fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity<V> {
160+ self.base.stateless_interactivity()
161161 }
162162 }
163163
@@ -172,11 +172,14 @@ where · 8 unmodified lines
172172 }
173173 }
174174
175−impl<V, F> Click for Img<V, StatefulInteractivity<V>, F>
175+impl<V, F> StatefullyInteractive for Img<V, StatefulInteractivity<V>, F>
176176 where
177177 V: 'static + Send + Sync,
178178 F: ElementFocusability<V>,
179179 {
180+ fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity<Self::ViewState> {
181+ self.base.stateful_interactivity()
182+ }
180183 }
181184
182185 impl<V, F> Active for Img<V, StatefulInteractivity<V>, F>
crates/gpui3/src/elements/svg.rs+11−8
@@ -1,8 +1,8 @@
11 use crate::{
2− div, Active, AnyElement, Bounds, Click, Div, DivState, Element, ElementFocusability, ElementId,
3− ElementInteractivity, Focus, FocusListeners, Focusable, Hover, Interactive, Interactivity,
4− IntoAnyElement, LayoutId, NonFocusable, Pixels, SharedString, StatefulInteractivity,
5− StatelessInteractivity, StyleRefinement, Styled, ViewContext,
2+ div, Active, AnyElement, Bounds, Div, DivState, Element, ElementFocusability, ElementId,
3+ ElementInteractivity, Focus, FocusListeners, Focusable, Hover, IntoAnyElement, LayoutId,
4+ NonFocusable, Pixels, SharedString, StatefulInteractivity, StatefullyInteractive,
5+ StatelessInteractivity, StatelesslyInteractive, StyleRefinement, Styled, ViewContext,
66 };
77 use util::ResultExt;
88
@@ -124,14 +124,14 @@ where · 115 unmodified lines
124124 }
125125 }
126126
127−impl<V, I, F> Interactive for Svg<V, I, F>
127+impl<V, I, F> StatelesslyInteractive for Svg<V, I, F>
128128 where
129129 V: 'static + Send + Sync,
130130 I: ElementInteractivity<V>,
131131 F: ElementFocusability<V>,
132132 {
133− fn interactivity(&mut self) -> &mut Interactivity<V> {
134− self.base.interactivity()
133+ fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity<V> {
134+ self.base.stateless_interactivity()
135135 }
136136 }
137137
@@ -146,11 +146,14 @@ where · 8 unmodified lines
146146 }
147147 }
148148
149−impl<V, F> Click for Svg<V, StatefulInteractivity<V>, F>
149+impl<V, F> StatefullyInteractive for Svg<V, StatefulInteractivity<V>, F>
150150 where
151151 V: 'static + Send + Sync,
152152 F: ElementFocusability<V>,
153153 {
154+ fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity<Self::ViewState> {
155+ self.base.stateful_interactivity()
156+ }
154157 }
155158
156159 impl<V, F> Active for Svg<V, StatefulInteractivity<V>, F>
crates/gpui3/src/interactive.rs+23−108
@@ -1,19 +1,15 @@
1−use parking_lot::Mutex;
2−use smallvec::SmallVec;
3−
41 use crate::{
52 point, Action, Bounds, DispatchContext, DispatchPhase, Element, FocusHandle, Keystroke,
6− Modifiers, Pixels, Point, ViewContext,
3+ Modifiers, Pixels, Point, StatefulInteractivity, StatelessInteractivity, ViewContext,
74 };
85 use std::{
96 any::{Any, TypeId},
10− mem,
117 ops::Deref,
128 sync::Arc,
139 };
1410
15−pub trait Interactive: Element {
16− fn interactivity(&mut self) -> &mut Interactivity<Self::ViewState>;
11+pub trait StatelesslyInteractive: Element {
12+ fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity<Self::ViewState>;
1713
1814 fn on_mouse_down(
1915 mut self,
@@ -26,8 +22,8 @@ pub trait Interactive: Element { · 6 unmodified lines
2622 where
2723 Self: Sized,
2824 {
29− self.interactivity()
30− .mouse_down
25+ self.stateless_interactivity()
26+ .mouse_down_listeners
3127 .push(Arc::new(move |view, event, bounds, phase, cx| {
3228 if phase == DispatchPhase::Bubble
3329 && event.button == button
@@ -50,8 +46,8 @@ pub trait Interactive: Element { · 16 unmodified lines
5046 where
5147 Self: Sized,
5248 {
53− self.interactivity()
54− .mouse_up
49+ self.stateless_interactivity()
50+ .mouse_up_listeners
5551 .push(Arc::new(move |view, event, bounds, phase, cx| {
5652 if phase == DispatchPhase::Bubble
5753 && event.button == button
@@ -74,8 +70,8 @@ pub trait Interactive: Element { · 16 unmodified lines
7470 where
7571 Self: Sized,
7672 {
77− self.interactivity()
78− .mouse_down
73+ self.stateless_interactivity()
74+ .mouse_down_listeners
7975 .push(Arc::new(move |view, event, bounds, phase, cx| {
8076 if phase == DispatchPhase::Capture
8177 && event.button == button
@@ -98,8 +94,8 @@ pub trait Interactive: Element { · 16 unmodified lines
9894 where
9995 Self: Sized,
10096 {
101− self.interactivity()
102− .mouse_up
97+ self.stateless_interactivity()
98+ .mouse_up_listeners
10399 .push(Arc::new(move |view, event, bounds, phase, cx| {
104100 if phase == DispatchPhase::Capture
105101 && event.button == button
@@ -121,8 +117,8 @@ pub trait Interactive: Element { · 15 unmodified lines
121117 where
122118 Self: Sized,
123119 {
124− self.interactivity()
125− .mouse_move
120+ self.stateless_interactivity()
121+ .mouse_move_listeners
126122 .push(Arc::new(move |view, event, bounds, phase, cx| {
127123 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
128124 handler(view, event, cx);
@@ -141,8 +137,8 @@ pub trait Interactive: Element { · 12 unmodified lines
141137 where
142138 Self: Sized,
143139 {
144− self.interactivity()
145− .scroll_wheel
140+ self.stateless_interactivity()
141+ .scroll_wheel_listeners
146142 .push(Arc::new(move |view, event, bounds, phase, cx| {
147143 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
148144 handler(view, event, cx);
@@ -165,7 +161,7 @@ pub trait Interactive: Element { · 16 unmodified lines
165161 where
166162 Self: Sized,
167163 {
168− self.interactivity().key.push((
164+ self.stateless_interactivity().key_listeners.push((
169165 TypeId::of::<KeyDownEvent>(),
170166 Arc::new(move |view, event, _, phase, cx| {
171167 let event = event.downcast_ref().unwrap();
@@ -186,7 +182,7 @@ pub trait Interactive: Element { · 14 unmodified lines
186182 where
187183 Self: Sized,
188184 {
189− self.interactivity().key.push((
185+ self.stateless_interactivity().key_listeners.push((
190186 TypeId::of::<KeyUpEvent>(),
191187 Arc::new(move |view, event, _, phase, cx| {
192188 let event = event.downcast_ref().unwrap();
@@ -207,7 +203,7 @@ pub trait Interactive: Element { · 14 unmodified lines
207203 where
208204 Self: Sized,
209205 {
210− self.interactivity().key.push((
206+ self.stateless_interactivity().key_listeners.push((
211207 TypeId::of::<A>(),
212208 Arc::new(move |view, event, _, phase, cx| {
213209 let event = event.downcast_ref().unwrap();
@@ -219,7 +215,9 @@ pub trait Interactive: Element { · 5 unmodified lines
219215 }
220216 }
221217
222−pub trait Click: Interactive {
218+pub trait StatefullyInteractive: StatelesslyInteractive {
219+ fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity<Self::ViewState>;
220+
223221 fn on_click(
224222 mut self,
225223 handler: impl Fn(&mut Self::ViewState, &MouseClickEvent, &mut ViewContext<Self::ViewState>)
@@ -230,8 +228,8 @@ pub trait Click: Interactive { · 4 unmodified lines
230228 where
231229 Self: Sized,
232230 {
233− self.interactivity()
234− .mouse_click
231+ self.stateful_interactivity()
232+ .mouse_click_listeners
235233 .push(Arc::new(move |view, event, cx| handler(view, event, cx)));
236234 self
237235 }
@@ -495,86 +493,3 @@ pub type KeyListener<V> = Arc< · 257 unmodified lines
495493 + Sync
496494 + 'static,
497495 >;
498−
499−pub struct Interactivity<V> {
500− pub mouse_down: SmallVec<[MouseDownListener<V>; 2]>,
501− pub mouse_up: SmallVec<[MouseUpListener<V>; 2]>,
502− pub mouse_click: SmallVec<[MouseClickListener<V>; 2]>,
503− pub mouse_move: SmallVec<[MouseMoveListener<V>; 2]>,
504− pub scroll_wheel: SmallVec<[ScrollWheelListener<V>; 2]>,
505− pub key: SmallVec<[(TypeId, KeyListener<V>); 32]>,
506−}
507−
508−impl<V> Default for Interactivity<V> {
509− fn default() -> Self {
510− Self {
511− mouse_down: SmallVec::new(),
512− mouse_up: SmallVec::new(),
513− mouse_click: SmallVec::new(),
514− mouse_move: SmallVec::new(),
515− scroll_wheel: SmallVec::new(),
516− key: SmallVec::new(),
517− }
518− }
519−}
520−
521−impl<V> Interactivity<V>
522−where
523− V: 'static + Send + Sync,
524−{
525− pub fn paint(
526− &mut self,
527− bounds: Bounds<Pixels>,
528− pending_click: Arc<Mutex<Option<MouseDownEvent>>>,
529− cx: &mut ViewContext<V>,
530− ) {
531− let click_listeners = mem::take(&mut self.mouse_click);
532−
533− let mouse_down = pending_click.lock().clone();
534− if let Some(mouse_down) = mouse_down {
535− cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
536− if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
537− let mouse_click = MouseClickEvent {
538− down: mouse_down.clone(),
539− up: event.clone(),
540− };
541− for listener in &click_listeners {
542− listener(state, &mouse_click, cx);
543− }
544− }
545−
546− *pending_click.lock() = None;
547− });
548− } else {
549− cx.on_mouse_event(move |_state, event: &MouseDownEvent, phase, _cx| {
550− if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
551− *pending_click.lock() = Some(event.clone());
552− }
553− });
554− }
555−
556− for listener in mem::take(&mut self.mouse_down) {
557− cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
558− listener(state, event, &bounds, phase, cx);
559− })
560− }
561−
562− for listener in mem::take(&mut self.mouse_up) {
563− cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
564− listener(state, event, &bounds, phase, cx);
565− })
566− }
567−
568− for listener in mem::take(&mut self.mouse_move) {
569− cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| {
570− listener(state, event, &bounds, phase, cx);
571− })
572− }
573−
574− for listener in mem::take(&mut self.scroll_wheel) {
575− cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| {
576− listener(state, event, &bounds, phase, cx);
577− })
578− }
579− }
580−}
crates/ui2/src/components/icon_button.rs+1−1
@@ -1,7 +1,7 @@
11 use std::marker::PhantomData;
22 use std::sync::Arc;
33
4−use gpui3::{Interactive, MouseButton};
4+use gpui3::{MouseButton, StatelesslyInteractive};
55
66 use crate::{h_stack, prelude::*};
77 use crate::{theme, ClickHandler, Icon, IconColor, IconElement};
crates/ui2/src/elements/button.rs+1−1
@@ -1,7 +1,7 @@
11 use std::marker::PhantomData;
22 use std::sync::Arc;
33
4−use gpui3::{DefiniteLength, Hsla, Interactive, MouseButton, WindowContext};
4+use gpui3::{DefiniteLength, Hsla, MouseButton, StatelesslyInteractive, WindowContext};
55
66 use crate::settings::user_settings;
77 use crate::{h_stack, Icon, IconColor, IconElement, Label, LabelColor};
crates/ui2/src/prelude.rs+2−2
@@ -1,6 +1,6 @@
11 pub use gpui3::{
2− div, Active, Click, Element, Hover, IntoAnyElement, ParentElement, ScrollState, SharedString,
3− Styled, ViewContext, WindowContext,
2+ div, Click, Element, Hover, IntoAnyElement, ParentElement, ScrollState, SharedString,
3+ StatefullyInteractivee, Styled, ViewContext, WindowContext,
44 };
55
66 use crate::settings::user_settings;

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