1use {
2 crate::{
3 makepad_derive_widget::*,
4 button::ButtonAction,
5 makepad_draw::*,
6 widget::*
7 }
8};
9
10live_design!{
11 link widgets;
12 use link::theme::*;
13 use makepad_draw::shader::std::*;
14
15 pub DrawDesktopButton = {{DrawDesktopButton}} {}
16 pub DesktopButtonBase = {{DesktopButton}} {}
17
18 pub DesktopButton = <DesktopButtonBase> {
19 draw_bg: {
20 uniform color: (THEME_COLOR_LABEL_INNER)
21 uniform color_hover: (THEME_COLOR_LABEL_INNER_HOVER)
22 uniform color_down: (THEME_COLOR_LABEL_INNER_DOWN)
23
24 fn pixel(self) -> vec4 {
25 let sdf = Sdf2d::viewport(self.pos * self.rect_size);
26 sdf.aa *= 3.0;
27 let sz = 4.5;
28 let c = self.rect_size * vec2(0.5, 0.5);
29
30 match self.button_type {
32 DesktopButtonType::WindowsMin => {
33 sdf.move_to(c.x - sz, c.y);
34 sdf.line_to(c.x + sz, c.y);
35 sdf.stroke(
36 mix(
37 self.color,
38 mix(
39 self.color_hover,
40 self.color_down,
41 self.down
42 ),
43 self.hover
44 ),
45 0.5 + 0.5 * self.dpi_dilate
46 );
47 return sdf.result;
48 }
49 DesktopButtonType::WindowsMax => {
50 sdf.rect(c.x - sz, c.y - sz, 2. * sz, 2. * sz);
51 sdf.stroke(
52 mix(
53 self.color,
54 mix(
55 self.color_hover,
56 self.color_down,
57 self.down
58 ),
59 self.hover
60 ),
61 0.5 + 0.5 * self.dpi_dilate
62 );
63 return sdf.result;
64 }
65 DesktopButtonType::WindowsMaxToggled => {
66 let sz = 5.;
67 sdf.rect(c.x - sz + 1., c.y - sz - 1., 2. * sz, 2. * sz);
68 sdf.stroke(#f, 0.5 + 0.5 * self.dpi_dilate);
69 sdf.rect(c.x - sz - 1., c.y - sz + 1., 2. * sz, 2. * sz);
70 sdf.stroke(
71 mix(
72 self.color,
73 mix(
74 self.color_hover,
75 self.color_down,
76 self.down
77 ),
78 self.hover
79 ),
80 0.5 + 0.5 * self.dpi_dilate
81 );
82 return sdf.result;
83 }
84 DesktopButtonType::WindowsClose => {
85 sdf.move_to(c.x - sz, c.y - sz);
86 sdf.line_to(c.x + sz, c.y + sz);
87 sdf.move_to(c.x - sz, c.y + sz);
88 sdf.line_to(c.x + sz, c.y - sz);
89 sdf.stroke(
90 mix(
91 self.color,
92 mix(
93 self.color_hover,
94 self.color_down,
95 self.down
96 ),
97 self.hover
98 ),
99 0.5 + 0.5 * self.dpi_dilate
100 );
101 return sdf.result;
102 }
103 DesktopButtonType::XRMode => {
104 let w = 12.;
105 let h = 8.;
106 sdf.box(c.x - w, c.y - h, 2. * w, 2. * h, 2.);
107 sdf.circle(c.x - 5.5, c.y, 3.5);
109 sdf.subtract();
110 sdf.circle(c.x + 5.5, c.y, 3.5);
111 sdf.subtract();
112 sdf.circle(c.x, c.y + h - 0.75, 2.5);
113 sdf.subtract();
114 sdf.fill(
115 mix(
116 self.color,
117 mix(
118 self.color_hover,
119 self.color_down,
120 self.down
121 ),
122 self.hover
123 )
124
125 ); return sdf.result;
128 }
129 DesktopButtonType::Fullscreen => {
130 sz = 8.;
131 sdf.rect(c.x - sz, c.y - sz, 2. * sz, 2. * sz);
132 sdf.rect(c.x - sz + 1.5, c.y - sz + 1.5, 2. * (sz - 1.5), 2. * (sz - 1.5));
133 sdf.subtract();
134 sdf.rect(c.x - sz + 4., c.y - sz - 2., 2. * (sz - 4.), 2. * (sz + 2.));
135 sdf.subtract();
136 sdf.rect(c.x - sz - 2., c.y - sz + 4., 2. * (sz + 2.), 2. * (sz - 4.));
137 sdf.subtract();
138 sdf.fill(
139 mix(
140 self.color,
141 mix(
142 self.color_hover,
143 self.color_down,
144 self.down
145 ),
146 self.hover
147 )
148
149 ); return sdf.result;
152 }
153 }
154 return #f00;
155 }
156 }
157 animator: {
158 hover = {
159 default: off,
160 off = {
161 from: {all: Forward {duration: 0.1}}
162 apply: {
163 draw_bg: {down: 0.0, hover: 0.0}
164 }
165 }
166
167 on = {
168 from: {
169 all: Forward {duration: 0.1}
170 state_down: Snap
171 }
172 apply: {
173 draw_bg: {
174 down: 0.0,
175 hover: 1.0,
176 }
177 }
178 }
179
180 down = {
181 from: {all: Snap}
182 apply: {
183 draw_bg: {
184 down: 1.0,
185 hover: 1.0,
186 }
187 }
188 }
189 }
190 }
191 }
192
193}
194
195#[derive(Live, Widget)]
196pub struct DesktopButton {
197 #[animator] animator: Animator,
198 #[walk] walk: Walk,
199 #[redraw] #[live] draw_bg: DrawDesktopButton,
200
201}
202
203impl Widget for DesktopButton{
204 fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
205 let uid = self.widget_uid();
206 self.animator_handle_event(cx, event);
207
208 match event.hits(cx, self.draw_bg.area()) {
209 Hit::FingerDown(fe) => {
210 cx.widget_action(uid, &scope.path, ButtonAction::Pressed(fe.modifiers));
211 self.animator_play(cx, id!(hover.down));
212 },
213 Hit::FingerHoverIn(_) => {
214 cx.set_cursor(MouseCursor::Hand);
215 self.animator_play(cx, id!(hover.on));
216 }
217 Hit::FingerHoverOut(_) => {
218 self.animator_play(cx, id!(hover.off));
219 }
220 Hit::FingerLongPress(_) => {
221 cx.widget_action(uid, &scope.path, ButtonAction::LongPressed);
222 }
223 Hit::FingerUp(fe) => if fe.is_over {
224 cx.widget_action(uid, &scope.path, ButtonAction::Clicked(fe.modifiers));
225 if fe.device.has_hovers() {
226 self.animator_play(cx, id!(hover.on));
227 }
228 else{
229 self.animator_play(cx, id!(hover.off));
230 }
231 }
232 else {
233 cx.widget_action(uid, &scope.path, ButtonAction::Released(fe.modifiers));
234 self.animator_play(cx, id!(hover.off));
235 }
236 _ => ()
237 };
238 }
239
240 fn draw_walk(&mut self, cx: &mut Cx2d, _scope:&mut Scope, walk: Walk) -> DrawStep {
241 let _ = self.draw_bg.draw_walk(cx, walk);
242 DrawStep::done()
243 }
244}
245
246#[derive(Live, LiveHook)]
247#[live_ignore]
248#[repr(u32)]
249pub enum DesktopButtonType {
250 WindowsMin = shader_enum(1),
251 WindowsMax = shader_enum(2),
252 WindowsMaxToggled = shader_enum(3),
253 WindowsClose = shader_enum(4),
254 XRMode = shader_enum(5),
255 #[pick] Fullscreen = shader_enum(6),
256}
257
258#[derive(Live, LiveHook, LiveRegister)]
259#[repr(C)]
260pub struct DrawDesktopButton {
261 #[deref] draw_super: DrawQuad,
262 #[live] hover: f32,
263 #[live] down: f32,
264 #[live] button_type: DesktopButtonType
265}
266
267impl LiveHook for DesktopButton {
268 fn after_apply_from_doc(&mut self, _cx: &mut Cx) {
269 let (w, h) = match self.draw_bg.button_type {
270 DesktopButtonType::WindowsMin
271 | DesktopButtonType::WindowsMax
272 | DesktopButtonType::WindowsMaxToggled
273 | DesktopButtonType::WindowsClose => (46., 29.),
274 DesktopButtonType::XRMode => (50., 36.),
275 DesktopButtonType::Fullscreen => (50., 36.),
276 };
277 self.walk = Walk::fixed_size(dvec2(w, h))
278 }
279}
280
281impl DesktopButtonRef{
282 pub fn clicked(&self, actions: &Actions) -> bool {
283 if let ButtonAction::Clicked(_) = actions.find_widget_action(self.widget_uid()).cast() {
284 true
285 } else {
286 false
287 }
288 }
289}