1use crate::{
2 AnyElement, Bounds, DispatchPhase, Element, Identified, Interactive, MouseDownEvent,
3 MouseEventListeners, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Styled, ViewContext,
4};
5use anyhow::Result;
6use refineable::{CascadeSlot, Refineable, RefinementCascade};
7use smallvec::SmallVec;
8use std::sync::{
9 atomic::{AtomicBool, Ordering::SeqCst},
10 Arc,
11};
12
13pub struct Pressable<E: Styled> {
14 pressed: Arc<AtomicBool>,
15 cascade_slot: CascadeSlot,
16 pressed_style: <E::Style as Refineable>::Refinement,
17 child: E,
18}
19
20impl<E: Identified + Styled> Pressable<E> {
21 pub fn new(mut child: E) -> Self {
22 Self {
23 pressed: Arc::new(AtomicBool::new(false)),
24 cascade_slot: child.style_cascade().reserve(),
25 pressed_style: Default::default(),
26 child,
27 }
28 }
29}
30
31impl<E> Styled for Pressable<E>
32where
33 E: Styled,
34{
35 type Style = E::Style;
36
37 fn style_cascade(&mut self) -> &mut RefinementCascade<E::Style> {
38 self.child.style_cascade()
39 }
40
41 fn declared_style(&mut self) -> &mut <Self::Style as refineable::Refineable>::Refinement {
42 &mut self.pressed_style
43 }
44}
45
46impl<S: 'static + Send + Sync, E: Interactive<S> + Styled> Interactive<S> for Pressable<E> {
47 fn listeners(&mut self) -> &mut MouseEventListeners<S> {
48 self.child.listeners()
49 }
50}
51
52impl<E: Element + Identified + Styled> Element for Pressable<E> {
53 type State = E::State;
54 type FrameState = E::FrameState;
55
56 fn layout(
57 &mut self,
58 state: &mut Self::State,
59 cx: &mut ViewContext<Self::State>,
60 ) -> Result<(crate::LayoutId, Self::FrameState)> {
61 Ok(self.child.layout(state, cx)?)
62 }
63
64 fn paint(
65 &mut self,
66 bounds: Bounds<Pixels>,
67 state: &mut Self::State,
68 frame_state: &mut Self::FrameState,
69 cx: &mut ViewContext<Self::State>,
70 ) -> Result<()> {
71 let pressed = bounds.contains_point(cx.mouse_position());
72 let slot = self.cascade_slot;
73 let style = pressed.then_some(self.pressed_style.clone());
74 self.style_cascade().set(slot, style);
75 self.pressed.store(pressed, SeqCst);
76
77 let hovered = self.pressed.clone();
78 cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
79 if phase == DispatchPhase::Capture {
80 if bounds.contains_point(event.position) != hovered.load(SeqCst) {
81 cx.notify();
82 }
83 }
84 });
85 cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| {
86 if phase == DispatchPhase::Capture {
87 if bounds.contains_point(event.position) != hovered.load(SeqCst) {
88 cx.notify();
89 }
90 }
91 });
92
93 cx.frame_state::<Self>(self.id().to_global(cx))
94 // cx.frame_state
95
96 self.child.paint(bounds, state, frame_state, cx)?;
97 Ok(())
98 }
99}
100
101impl<E: ParentElement + Styled> ParentElement for Pressable<E> {
102 type State = E::State;
103
104 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::State>; 2]> {
105 self.child.children_mut()
106 }
107}
108
109// use crate::{
110// element::{AnyElement, Element, IntoElement, Layout, ParentElement},
111// interactive::{InteractionHandlers, Interactive},
112// style::{Style, StyleHelpers, Styleable},
113// ViewContext,
114// };
115// use anyhow::Result;
116// use gpui::{geometry::vector::Vector2F, platform::MouseButtonEvent, LayoutId};
117// use refineable::{CascadeSlot, Refineable, RefinementCascade};
118// use smallvec::SmallVec;
119// use std::{cell::Cell, rc::Rc};
120
121// pub struct Pressable<E: Styleable> {
122// pressed: Rc<Cell<bool>>,
123// pressed_style: <E::Style as Refineable>::Refinement,
124// cascade_slot: CascadeSlot,
125// child: E,
126// }
127
128// pub fn pressable<E: Styleable>(mut child: E) -> Pressable<E> {
129// Pressable {
130// pressed: Rc::new(Cell::new(false)),
131// pressed_style: Default::default(),
132// cascade_slot: child.style_cascade().reserve(),
133// child,
134// }
135// }
136
137// impl<E: Styleable> Styleable for Pressable<E> {
138// type Style = E::Style;
139
140// fn declared_style(&mut self) -> &mut <Self::Style as Refineable>::Refinement {
141// &mut self.pressed_style
142// }
143
144// fn style_cascade(&mut self) -> &mut RefinementCascade<E::Style> {
145// self.child.style_cascade()
146// }
147// }
148
149// impl<V: 'static, E: Element<V> + Styleable> Element<V> for Pressable<E> {
150// type PaintState = E::PaintState;
151
152// fn layout(
153// &mut self,
154// view: &mut V,
155// cx: &mut ViewContext<V>,
156// ) -> Result<(LayoutId, Self::PaintState)>
157// where
158// Self: Sized,
159// {
160// self.child.layout(view, cx)
161// }
162
163// fn paint(
164// &mut self,
165// view: &mut V,
166// parent_origin: Vector2F,
167// layout: &Layout,
168// paint_state: &mut Self::PaintState,
169// cx: &mut ViewContext<V>,
170// ) where
171// Self: Sized,
172// {
173// let slot = self.cascade_slot;
174// let style = self.pressed.get().then_some(self.pressed_style.clone());
175// self.style_cascade().set(slot, style);
176
177// let pressed = self.pressed.clone();
178// let bounds = layout.bounds + parent_origin;
179// cx.on_event(layout.order, move |_view, event: &MouseButtonEvent, cx| {
180// if event.is_down {
181// if bounds.contains_point(event.position) {
182// pressed.set(true);
183// cx.repaint();
184// }
185// } else if pressed.get() {
186// pressed.set(false);
187// cx.repaint();
188// }
189// });
190
191// self.child
192// .paint(view, parent_origin, layout, paint_state, cx);
193// }
194// }
195
196// impl<V: 'static, E: Interactive<V> + Styleable> Interactive<V> for Pressable<E> {
197// fn interaction_handlers(&mut self) -> &mut InteractionHandlers<V> {
198// self.child.interaction_handlers()
199// }
200// }
201
202// impl<V: 'static, E: ParentElement<V> + Styleable> ParentElement<V> for Pressable<E> {
203// fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
204// self.child.children_mut()
205// }
206// }
207
208// impl<V: 'static, E: Element<V> + Styleable> IntoElement<V> for Pressable<E> {
209// type Element = Self;
210
211// fn into_element(self) -> Self::Element {
212// self
213// }
214// }