pressable.rs

  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// }