makepad_widgets/
fold_button.rs

1use crate::{
2    makepad_derive_widget::*,
3    makepad_draw::*,
4    widget::*,
5};
6
7live_design!{
8    FoldButtonBase = {{FoldButton}} {}
9}
10
11#[derive(Live)]
12pub struct FoldButton {
13    #[animator] animator: Animator,
14    
15    #[live] draw_bg: DrawQuad,
16    #[live] abs_size: DVec2,
17    #[live] abs_offset: DVec2,
18    #[walk] walk: Walk,
19}
20
21impl LiveHook for FoldButton{
22    fn before_live_design(cx:&mut Cx){
23        register_widget!(cx,FoldButton)
24    }
25}
26
27#[derive(Clone, WidgetAction)]
28pub enum FoldButtonAction {
29    None,
30    Opening,
31    Closing,
32    Animating(f64)
33}
34
35impl FoldButton {
36    
37    pub fn handle_event_with(
38        &mut self,
39        cx: &mut Cx,
40        event: &Event,
41        dispatch_action: &mut dyn FnMut(&mut Cx, FoldButtonAction),
42    ) {
43        if self.animator_handle_event(cx, event).is_animating() {
44            if self.animator.is_track_animating(cx, id!(open)) {
45                let mut value = [0.0];
46                self.draw_bg.get_instance(cx, id!(open),&mut value);
47                dispatch_action(cx, FoldButtonAction::Animating(value[0] as f64))
48            }
49        };
50        
51        match event.hits(cx, self.draw_bg.area()) {
52            Hit::FingerDown(_fe) => {
53                if self.animator_in_state(cx, id!(open.yes)) {
54                    self.animator_play(cx, id!(open.no));
55                    dispatch_action(cx, FoldButtonAction::Closing)
56                }
57                else {
58                    self.animator_play(cx, id!(open.yes));
59                    dispatch_action(cx, FoldButtonAction::Opening)
60                }
61                self.animator_play(cx, id!(hover.on));
62            },
63            Hit::FingerHoverIn(_) => {
64                cx.set_cursor(MouseCursor::Hand);
65                 self.animator_play(cx, id!(hover.on));
66            }
67            Hit::FingerHoverOut(_) => {
68                self.animator_play(cx, id!(hover.off));
69            }
70            Hit::FingerUp(fe) => if fe.is_over {
71                if fe.device.has_hovers() {
72                    self.animator_play(cx, id!(hover.on));
73                }
74                else{
75                    self.animator_play(cx, id!(hover.off));
76                }
77            }
78            else {
79                self.animator_play(cx, id!(hover.off));
80            }
81            _ => ()
82        };
83    }
84    
85    pub fn set_is_open(&mut self, cx: &mut Cx, is_open: bool, animate: Animate) {
86        self.animator_toggle(cx, is_open, animate, id!(open.yes), id!(open.no))
87    }
88    
89    pub fn draw_walk(&mut self, cx: &mut Cx2d, walk: Walk) {
90        self.draw_bg.draw_walk(cx, walk);
91    }
92    
93    pub fn area(&mut self)->Area{
94        self.draw_bg.area()
95    }
96    
97    pub fn draw_abs(&mut self, cx: &mut Cx2d, pos: DVec2, fade: f64) {
98        self.draw_bg.apply_over(cx, live!{fade: (fade)});
99        self.draw_bg.draw_abs(cx, Rect {
100            pos: pos + self.abs_offset,
101            size: self.abs_size
102        });
103    }
104}
105
106impl Widget for FoldButton {
107    fn redraw(&mut self, cx: &mut Cx) {
108        self.draw_bg.redraw(cx);
109    }
110    
111    fn handle_widget_event_with(&mut self, cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, WidgetActionItem)) {
112        let uid = self.widget_uid();
113        self.handle_event_with(cx, event, &mut | cx, action | {
114            dispatch_action(cx, WidgetActionItem::new(action.into(), uid))
115        });
116    }
117    
118    fn walk(&mut self, _cx:&mut Cx) -> Walk {self.walk}
119    
120    fn draw_walk_widget(&mut self, cx: &mut Cx2d, walk: Walk) -> WidgetDraw {
121        self.draw_walk(cx, walk);
122        WidgetDraw::done()
123    }
124}
125
126
127#[derive(Clone, Debug, PartialEq, WidgetRef)]
128pub struct FoldButtonRef(WidgetRef); 
129
130impl FoldButtonRef {
131    
132    pub fn opening(&self, actions:&WidgetActions) -> bool {
133        if let Some(item) = actions.find_single_action(self.widget_uid()) {
134            if let FoldButtonAction::Opening = item.action() {
135                return true
136            }
137        }
138        false
139    }
140
141    pub fn closing(&self, actions:&WidgetActions) -> bool {
142        if let Some(item) = actions.find_single_action(self.widget_uid()) {
143            if let FoldButtonAction::Closing = item.action() {
144                return true
145            }
146        }
147        false
148    }
149    
150    pub fn animating(&self, actions:&WidgetActions) -> Option<f64> {
151        if let Some(item) = actions.find_single_action(self.widget_uid()) {
152            if let FoldButtonAction::Animating(v) = item.action() {
153                return Some(v)
154            }
155        }
156        None
157    }
158}
159