makepad_widget/
desktopbutton.rs

1use makepad_render::*;
2use crate::buttonlogic::*;
3use crate::widgetstyle::*;
4
5#[derive(Clone)]
6pub struct DesktopButton {
7    pub button: ButtonLogic,
8    pub bg: Quad,
9    pub animator: Animator,
10    pub _bg_area: Area,
11}
12
13pub enum DesktopButtonType {
14    WindowsMin,
15    WindowsMax,
16    WindowsMaxToggled,
17    WindowsClose,
18    VRMode,
19}
20
21impl DesktopButtonType {
22    fn shader_float(&self) -> f32 {
23        match self {
24            DesktopButtonType::WindowsMin => 1.,
25            DesktopButtonType::WindowsMax => 2.,
26            DesktopButtonType::WindowsMaxToggled => 3.,
27            DesktopButtonType::WindowsClose => 4.,
28            DesktopButtonType::VRMode => 5.,
29        }
30    }
31}
32
33impl DesktopButton {
34    pub fn proto(cx: &mut Cx) -> Self {
35        Self {
36            button: ButtonLogic::default(),
37            bg: Quad::proto(cx),
38            animator: Animator::default(),
39            _bg_area: Area::Empty,
40        }
41    }
42
43    pub fn instance_hover()->InstanceFloat{uid!()}
44    pub fn instance_down()->InstanceFloat{uid!()}
45    pub fn instance_type()->InstanceFloat{uid!()}
46
47    pub fn anim_default() -> AnimId {uid!()}
48    pub fn anim_over() -> AnimId {uid!()}
49    pub fn anim_down() -> AnimId {uid!()}
50    pub fn shader_bg() -> ShaderId {uid!()}
51    
52    pub fn style(cx: &mut Cx, _opt: &StyleOptions) {
53        
54        Self::anim_default().set(cx,Anim::new(Play::Cut {duration: 0.2}, vec![
55            Track::float(Self::instance_hover(), Ease::Lin, vec![(1.0, 0.)]),
56            Track::float(Self::instance_down(), Ease::Lin, vec![(1.0, 0.)]),
57        ]));
58        
59        Self::anim_over().set(cx, Anim::new(Play::Cut {duration: 0.2}, vec![
60            Track::float(Self::instance_down(), Ease::Lin, vec![(1.0, 0.)]),
61            Track::float(Self::instance_hover(), Ease::Lin, vec![(0.0, 1.0), (1.0, 1.0)]),
62        ]));
63        
64        Self::anim_down().set(cx,Anim::new(Play::Cut {duration: 0.2}, vec![
65            Track::float(Self::instance_down(), Ease::OutExp, vec![(0.0, 0.0), (1.0, 3.1415 * 0.5)]),
66            Track::float(Self::instance_hover(), Ease::Lin, vec![(1.0, 1.0)]),
67        ]));
68        
69        Self::shader_bg().set(cx,Quad::def_quad_shader().compose(shader_ast!({
70            
71            let hover: Self::instance_hover();
72            let down: Self::instance_down();
73            let button_type: Self::instance_type();
74            
75            fn pixel() -> vec4 {
76                df_viewport(pos * vec2(w, h)); // );
77                df_aa *= 3.0;
78                let sz = 4.5;
79                let c = vec2(w, h) * vec2(0.5, 0.5);
80                // WindowsMin
81                if abs(button_type - 1.) < 0.1 {
82                    df_clear(mix(color("#3"), mix(color("#6"), color("#9"), down), hover));
83                    df_move_to(c.x - sz, c.y);
84                    df_line_to(c.x + sz, c.y);
85                    df_stroke(color("white"), 0.5 + 0.5 * dpi_dilate);
86                    return df_result;
87                }
88                // WindowsMax
89                if abs(button_type - 2.) < 0.1 {
90                    df_clear(mix(color("#3"), mix(color("#6"), color("#9"), down), hover));
91                    df_rect(c.x - sz, c.y - sz, 2. * sz, 2. * sz);
92                    df_stroke(color("white"), 0.5 + 0.5 * dpi_dilate);
93                    return df_result;
94                }
95                // WindowsMaxToggled
96                if abs(button_type - 3.) < 0.1 {
97                    let clear = mix(color("#3"), mix(color("#6"), color("#9"), down), hover);
98                    df_clear(clear);
99                    let sz = 3.5;
100                    df_rect(c.x - sz + 1., c.y - sz - 1., 2. * sz, 2. * sz);
101                    df_stroke(color("white"), 0.5 + 0.5 * dpi_dilate);
102                    df_rect(c.x - sz - 1., c.y - sz + 1., 2. * sz, 2. * sz);
103                    df_fill_keep(clear);
104                    df_stroke(color("white"), 0.5 + 0.5 * dpi_dilate);
105                    
106                    return df_result;
107                }
108                // WindowsClose
109                if abs(button_type - 4.) < 0.1 {
110                    df_clear(mix(color("#3"), mix(color("#e00"), color("#c00"), down), hover));
111                    df_move_to(c.x - sz, c.y - sz);
112                    df_line_to(c.x + sz, c.y + sz);
113                    df_move_to(c.x - sz, c.y + sz);
114                    df_line_to(c.x + sz, c.y - sz);
115                    df_stroke(color("white"), 0.5 + 0.5 * dpi_dilate);
116                    return df_result;
117                }
118                // VRMode
119                if abs(button_type - 5.) < 0.1 {
120                    df_clear(mix(color("#3"), mix(color("#0aa"), color("#077"), down), hover));
121                    let w = 12.;
122                    let h = 8.;
123                    df_box(c.x - w, c.y - h, 2. * w, 2. * h, 2.);
124                    // subtract 2 eyes
125                    df_circle(c.x - 5.5,c.y,3.5);
126                    df_subtract();
127                    df_circle(c.x + 5.5,c.y,3.5);
128                    df_subtract();
129                    df_circle(c.x, c.y + h-0.75,2.5);
130                    df_subtract();
131                    df_fill(color("#8"));
132                    
133                    return df_result;
134                }
135                return color("red")/*
136                df_viewport(pos * vec2(w, h));
137                df_box(0., 0., w, h, border_radius);
138                df_shape += 3.;
139                df_fill_keep(color);
140                df_stroke_keep(border_color, border_width);
141                df_blur = 2.;
142                return df_glow(glow_color, glow_size);*/
143            }
144        })));
145    }
146    
147    pub fn handle_button(&mut self, cx: &mut Cx, event: &mut Event) -> ButtonEvent {
148        //let mut ret_event = ButtonEvent::None;
149        let animator = &mut self.animator;
150        self.button.handle_button_logic(cx, event, self._bg_area, | cx, logic_event, area | match logic_event {
151            ButtonLogicEvent::Animate(ae) => animator.calc_area(cx, area, ae.time),
152            ButtonLogicEvent::AnimEnded(_)=> animator.end(),
153            ButtonLogicEvent::Down => animator.play_anim(cx, Self::anim_down().get(cx)),
154            ButtonLogicEvent::Default=> animator.play_anim(cx, Self::anim_default().get(cx)),
155            ButtonLogicEvent::Over=>animator.play_anim(cx, Self::anim_over().get(cx))
156        })
157    }
158
159    pub fn draw_desktop_button(&mut self, cx: &mut Cx, ty: DesktopButtonType) {
160        //self.bg.color = self.animator.last_color(cx, Quad_color::id());
161        self.animator.init(cx, |cx| Self::anim_default().get(cx));
162        let (w,h) = match ty {
163            DesktopButtonType::WindowsMin 
164            | DesktopButtonType::WindowsMax 
165            | DesktopButtonType::WindowsMaxToggled 
166            | DesktopButtonType::WindowsClose => (46.,29.),
167            DesktopButtonType::VRMode => (50.,36.),
168        };
169        self.bg.shader = Self::shader_bg().get(cx);
170        let bg_inst = self.bg.draw_quad(cx, Walk::wh(Width::Fix(w), Height::Fix(h)));
171        bg_inst.push_last_float(cx, &self.animator, Self::instance_down());
172        bg_inst.push_last_float(cx, &self.animator, Self::instance_hover());
173        bg_inst.push_float(cx, ty.shader_float());
174        self._bg_area = bg_inst.into();
175        self.animator.set_area(cx, self._bg_area); // if our area changed, update animation
176    }
177}