makepad_widgets/
expandable_panel.rs

1use {
2    crate::{
3        touch_gesture::*,
4        makepad_derive_widget::*,
5        makepad_draw::*,
6        widget::*,
7        view::*,
8    }
9};
10
11live_design! {
12    ExpandablePanelBase = {{ExpandablePanel}} {}
13}
14
15#[derive(Clone, DefaultNone, Debug)]
16pub enum ExpandablePanelAction {
17    ScrolledAt(f64),
18    None,
19}
20
21#[derive(Live, Widget)]
22pub struct ExpandablePanel {
23    #[deref] view: View,
24    #[rust] touch_gesture: Option<TouchGesture>,
25    #[live] initial_offset: f64,
26}
27
28impl LiveHook for ExpandablePanel {
29    fn after_apply_from(&mut self, cx: &mut Cx, apply: &mut Apply) {
30        if apply.from.is_from_doc() {
31            self.apply_over(cx, live! {
32                panel = { margin: { top: (self.initial_offset) }}
33            });
34        }
35    }
36}
37
38impl Widget for ExpandablePanel {
39    fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
40        self.view.handle_event(cx, event, scope);
41
42        if let Some(touch_gesture) = self.touch_gesture.as_mut() {
43            if touch_gesture.handle_event(cx, event, self.view.area()).has_changed() {
44                let scrolled_at = touch_gesture.scrolled_at;
45                let panel_margin = self.initial_offset - scrolled_at;
46                self.apply_over(cx, live! {
47                    panel = { margin: { top: (panel_margin) }}
48                });
49                self.redraw(cx);
50
51                cx.widget_action(
52                    self.widget_uid(),
53                    &scope.path,
54                    ExpandablePanelAction::ScrolledAt(scrolled_at),
55                );
56            }
57        }
58    }
59
60    fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
61        let result = self.view.draw_walk(cx, scope, walk);
62
63        if self.touch_gesture.is_none() {
64            let mut touch_gesture = TouchGesture::new();
65            touch_gesture.set_mode(ScrollMode::Swipe);
66
67            // Limit the amount of dragging allowed for the panel
68            let panel_height = self.view(id!(panel)).area().rect(cx).size.y;
69            touch_gesture.set_range(0.0, panel_height - self.initial_offset);
70
71            touch_gesture.reset_scrolled_at();
72            self.touch_gesture = Some(touch_gesture);
73        }
74
75        result
76    }
77}