pressable.rs

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