1use {
2 crate::{
3 makepad_derive_widget::*,
4 makepad_draw::*,
5 widget::*,
6 }
7};
8
9live_design!{
10 link widgets;
11 use link::theme::*;
12 use makepad_draw::shader::std::*;
13
14 pub DrawCheckBox = {{DrawCheckBox}} {}
15 pub CheckBoxBase = {{CheckBox}} {}
16
17 pub CheckBox = <CheckBoxBase> {
18 width: Fit, height: Fit,
19 padding: <THEME_MSPACE_2> {}
20 align: { x: 0., y: 0. }
21
22 label_walk: {
23 width: Fit, height: Fit,
24 margin: <THEME_MSPACE_H_1> { left: 13. }
25 }
26
27 draw_bg: {
28 instance disabled: 0.0,
29 instance down: 0.0,
30
31 uniform size: 14.0;
32
33 uniform border_size: (THEME_BEVELING)
34 uniform border_radius: (THEME_CORNER_RADIUS)
35
36 uniform color_dither: 1.0
37
38 uniform color: (THEME_COLOR_INSET)
39 uniform color_hover: (THEME_COLOR_INSET_HOVER)
40 uniform color_down: (THEME_COLOR_INSET_DOWN)
41 uniform color_active: (THEME_COLOR_INSET_ACTIVE)
42 uniform color_focus: (THEME_COLOR_INSET_FOCUS)
43 uniform color_disabled: (THEME_COLOR_INSET_DISABLED)
44
45 uniform border_color_1: (THEME_COLOR_BEVEL_INSET_2)
46 uniform border_color_1_hover: (THEME_COLOR_BEVEL_INSET_2_HOVER)
47 uniform border_color_1_down: (THEME_COLOR_BEVEL_INSET_2_DOWN)
48 uniform border_color_1_active: (THEME_COLOR_BEVEL_INSET_2_ACTIVE)
49 uniform border_color_1_focus: (THEME_COLOR_BEVEL_INSET_2_FOCUS)
50 uniform border_color_1_disabled: (THEME_COLOR_BEVEL_INSET_2_DISABLED)
51
52 uniform border_color_2: (THEME_COLOR_BEVEL_INSET_1)
53 uniform border_color_2_hover: (THEME_COLOR_BEVEL_INSET_1_HOVER)
54 uniform border_color_2_down: (THEME_COLOR_BEVEL_INSET_1_DOWN)
55 uniform border_color_2_active: (THEME_COLOR_BEVEL_INSET_1_ACTIVE)
56 uniform border_color_2_focus: (THEME_COLOR_BEVEL_INSET_1_FOCUS)
57 uniform border_color_2_disabled: (THEME_COLOR_BEVEL_INSET_1_DISABLED)
58
59 uniform mark_size: 0.65
60 uniform mark_color: (THEME_COLOR_U_HIDDEN)
61 uniform mark_color_hover: (THEME_COLOR_U_HIDDEN)
62 uniform mark_color_down: (THEME_COLOR_U_HIDDEN)
63 uniform mark_color_active: (THEME_COLOR_MARK_ACTIVE)
64 uniform mark_color_active_hover: (THEME_COLOR_MARK_ACTIVE_HOVER)
65 uniform mark_color_focus: (THEME_COLOR_MARK_FOCUS)
66 uniform mark_color_disabled: (THEME_COLOR_MARK_DISABLED)
67
68 fn pixel(self) -> vec4 {
69 let sdf = Sdf2d::viewport(self.pos * self.rect_size);
70 let dither = Math::random_2d(self.pos.xy) * 0.04 * self.color_dither;
71
72 let sz_px = self.size;
73 let sz_inner_px = sz_px - self.border_size * 2.;
74 let shift_px = vec2(0, 0)
75 let center_px = vec2(
76 sz_px * 0.5,
77 self.rect_size.y * 0.5
78 )
79
80 let offset_px = vec2(
81 shift_px.x,
82 shift_px.y + center_px.y - sz_px * 0.5
83 )
84
85 let offset_uv = vec2(
86 offset_px.x / self.rect_size.x,
87 offset_px.y / self.rect_size.y
88 )
89
90 let border_sz_uv = vec2(
91 self.border_size / self.rect_size.x,
92 self.border_size / self.rect_size.y
93 )
94
95 let scale_factor_border = vec2(
96 self.rect_size.x / sz_px,
97 self.rect_size.y / sz_px
98 );
99
100 let gradient_border = vec2(
101 (self.pos.x - offset_uv.x) * scale_factor_border.x + dither,
102 (self.pos.y - offset_uv.y) * scale_factor_border.y + dither
103 )
104
105 let scale_factor_fill = vec2(
106 self.rect_size.x / sz_inner_px,
107 self.rect_size.y / sz_inner_px
108 );
109
110 let gradient_fill = vec2(
111 (self.pos.x - offset_uv.x) * scale_factor_fill.x - border_sz_uv.x * 2. + dither,
112 (self.pos.y - offset_uv.y) * scale_factor_fill.y - border_sz_uv.y * 2. + dither
113 )
114
115 match self.check_type {
116 CheckType::Check => {
117
118 sdf.box(
120 offset_px.x + self.border_size,
121 offset_px.y + self.border_size,
122 sz_px - self.border_size * 2.,
123 sz_px - self.border_size * 2.,
124 self.border_radius * 0.5
125 );
126
127 sdf.stroke_keep(
128 mix(
129 mix(
130 mix(
131 mix(
132 mix(self.border_color_1, self.border_color_2, gradient_border.y),
133 mix(self.border_color_1_focus, self.border_color_2_focus, gradient_border.y),
134 self.focus
135 ),
136 mix(
137 mix(self.border_color_1_active, self.border_color_2_active, gradient_border.y),
138 mix(self.border_color_1_focus, self.border_color_2_focus, gradient_border.y),
139 self.focus
140 ),
141 self.active
142 ),
143 mix(
144 mix(self.border_color_1_down, self.border_color_2_down, gradient_border.y),
145 mix(self.border_color_1_hover, self.border_color_2_hover, gradient_border.y),
146 self.down
147 ),
148 self.hover
149 ),
150 mix(self.border_color_1_disabled, self.border_color_2_disabled, gradient_border.y),
151 self.disabled
152 ), self.border_size
153 )
154
155 sdf.fill(
156 mix(
157 mix(
158 mix(
159 mix(
160 self.color,
161 self.color_focus,
162 self.focus
163 ),
164 mix(
165 self.color_active,
166 self.color_focus,
167 self.focus
168 ),
169 self.active
170 ),
171 mix(
172 self.color_hover,
173 self.color_down,
174 self.down
175 ),
176 self.hover
177 ),
178 self.color_disabled,
179 self.disabled
180 )
181 )
182
183 let mark_padding = 0.275 * self.size
185 sdf.move_to(mark_padding, center_px.y);
186 sdf.line_to(center_px.x, center_px.y + sz_px * 0.5 - mark_padding);
187 sdf.line_to(sz_px - mark_padding, offset_px.y + mark_padding);
188
189 sdf.stroke(
190 mix(
191 mix(
192 mix(self.mark_color, self.mark_color_hover, self.hover),
193 mix(self.mark_color_active, self.mark_color_active_hover, self.hover),
194 self.active
195 ),
196 self.mark_color_disabled,
197 self.disabled
198 ), self.size * 0.09
199 );
200
201 }
202
203 CheckType::None => {
206 sdf.fill(THEME_COLOR_D_HIDDEN);
207 }
208 }
209 return sdf.result
210 }
211 }
212
213 draw_text: {
214 instance focus: 0.0
215 instance hover: 0.0
216 instance down: 0.0
217 instance active: 0.0
218 instance disabled: 0.0
219
220 uniform color: (THEME_COLOR_LABEL_OUTER)
221 uniform color_hover: (THEME_COLOR_LABEL_OUTER_HOVER)
222 uniform color_down: (THEME_COLOR_LABEL_OUTER_DOWN)
223 uniform color_focus: (THEME_COLOR_LABEL_OUTER_FOCUS)
224 uniform color_active: (THEME_COLOR_LABEL_OUTER_ACTIVE)
225 uniform color_disabled: (THEME_COLOR_LABEL_OUTER_DISABLED)
226
227 fn get_color(self) -> vec4 {
228 return
229 mix(
230 mix(
231 mix(
232 mix(self.color, self.color_active, self.active),
233 self.color_focus,
234 self.focus
235 ),
236 mix(
237 self.color_hover,
238 self.color_down,
239 self.down
240 ),
241 self.hover
242 ),
243 self.color_disabled,
244 self.disabled
245 )
246 }
247 text_style: <THEME_FONT_REGULAR> {
248 font_size: (THEME_FONT_SIZE_P)
249 }
250 }
251
252 draw_icon: {
253 instance active: 0.0
254 instance disabled: 0.0
255
256 uniform color: (THEME_COLOR_ICON)
257 uniform color_active: (THEME_COLOR_ICON_ACTIVE)
258 uniform color_disabled: (THEME_COLOR_ICON_DISABLED)
259
260 fn get_color(self) -> vec4 {
261 return
262 mix(
263 mix(
264 self.color,
265 self.color_active,
266 self.active
267 ),
268 self.color_disabled,
269 self.disabled
270 )
271
272 }
273 }
274
275 icon_walk: {
276 width: 14.0, height: Fit
277 }
278
279 animator: {
280 disabled = {
281 default: off,
282 off = {
283 from: {all: Forward {duration: 0.}}
284 apply: {
285 draw_bg: {disabled: 0.0}
286 draw_text: {disabled: 0.0}
287 draw_icon: {disabled: 0.0}
288 }
289 }
290 on = {
291 from: {all: Forward {duration: 0.2}}
292 apply: {
293 draw_bg: {disabled: 1.0}
294 draw_text: {disabled: 1.0}
295 draw_icon: {disabled: 1.0}
296 }
297 }
298 }
299 hover = {
300 default: off
301 off = {
302 from: {all: Forward {duration: 0.15}}
303 apply: {
304 draw_bg: {down: [{time: 0.0, value: 0.0}], hover: 0.0}
305 draw_text: {down: [{time: 0.0, value: 0.0}], hover: 0.0}
306 }
307 }
308 on = {
309 from: {all: Snap}
310 apply: {
311 draw_bg: {down: [{time: 0.0, value: 0.0}], hover: 1.0}
312 draw_text: {down: [{time: 0.0, value: 0.0}], hover: 1.0}
313 }
314 }
315 down = {
316 from: {all: Forward {duration: 0.2}}
317 apply: {
318 draw_bg: {down: [{time: 0.0, value: 1.0}], hover: 1.0,}
319 draw_text: {down: [{time: 0.0, value: 1.0}], hover: 1.0,}
320 }
321 }
322 }
323 focus = {
324 default: off
325 off = {
326 from: {all: Snap}
327 apply: {
328 draw_bg: {focus: 0.0}
329 draw_text: {focus: 0.0}
330 }
331 }
332 on = {
333 from: {all: Snap}
334 apply: {
335 draw_bg: {focus: 1.0}
336 draw_text: {focus: 1.0}
337 }
338 }
339 }
340 active = {
341 default: off
342 off = {
343 from: {all: Forward {duration: 0.1}}
344 apply: {
345 draw_bg: {active: 0.0},
346 draw_text: {active: 0.0},
347 draw_icon: {active: 0.0},
348 }
349 }
350 on = {
351 from: {all: Forward {duration: 0.0}}
352 apply: {
353 draw_bg: {active: 1.0}
354 draw_text: {active: 1.0}
355 draw_icon: {active: 1.0},
356 }
357 }
358 }
359 }
360 }
361
362 pub CheckBoxFlat = <CheckBox> {
363 draw_bg: {
364 color: (THEME_COLOR_INSET)
365 color_hover: (THEME_COLOR_INSET_HOVER)
366 color_down: (THEME_COLOR_INSET_DOWN)
367 color_active: (THEME_COLOR_INSET_ACTIVE)
368 color_focus: (THEME_COLOR_INSET_FOCUS)
369 color_disabled: (THEME_COLOR_INSET_DISABLED)
370
371 border_color_1: (THEME_COLOR_BEVEL)
372 border_color_1_hover: (THEME_COLOR_BEVEL_HOVER)
373 border_color_1_down: (THEME_COLOR_BEVEL_DOWN)
374 border_color_1_active: (THEME_COLOR_BEVEL_ACTIVE)
375 border_color_1_focus: (THEME_COLOR_BEVEL_FOCUS)
376 border_color_1_down: (THEME_COLOR_BEVEL_DISABLED)
377
378 border_color_2: (THEME_COLOR_BEVEL)
379 border_color_2_hover: (THEME_COLOR_BEVEL_HOVER)
380 border_color_2_down: (THEME_COLOR_BEVEL_DOWN)
381 border_color_2_active: (THEME_COLOR_BEVEL_ACTIVE)
382 border_color_2_focus: (THEME_COLOR_BEVEL_FOCUS)
383 border_color_2_down: (THEME_COLOR_BEVEL_DISABLED)
384 }
385
386 }
387
388 pub CheckBoxFlatter = <CheckBoxFlat> {
389 draw_bg: {
390 border_color_1: (THEME_COLOR_U_HIDDEN)
391 border_color_1_hover: (THEME_COLOR_U_HIDDEN)
392 border_color_1_down: (THEME_COLOR_U_HIDDEN)
393 border_color_1_active: (THEME_COLOR_U_HIDDEN)
394 border_color_1_focus: (THEME_COLOR_U_HIDDEN)
395 border_color_1_disabled: (THEME_COLOR_U_HIDDEN)
396
397 border_color_2: (THEME_COLOR_U_HIDDEN)
398 border_color_2_hover: (THEME_COLOR_U_HIDDEN)
399 border_color_2_down: (THEME_COLOR_U_HIDDEN)
400 border_color_2_active: (THEME_COLOR_U_HIDDEN)
401 border_color_2_focus: (THEME_COLOR_U_HIDDEN)
402 border_color_2_disabled: (THEME_COLOR_U_HIDDEN)
403 }
404
405 }
406
407 pub CheckBoxGradientY = <CheckBox> {
408 width: Fit, height: Fit,
409 padding: <THEME_MSPACE_2> {}
410 align: { x: 0., y: 0. }
411
412 label_walk: {
413 width: Fit, height: Fit,
414 margin: <THEME_MSPACE_H_1> { left: 13. }
415 }
416
417 draw_bg: {
418 instance disabled: 0.0,
419 instance down: 0.0,
420
421 uniform size: 15.0;
422
423 uniform border_size: (THEME_BEVELING)
424 uniform border_radius: (THEME_CORNER_RADIUS)
425
426 uniform color_dither: 1.0
427
428 uniform color_1: (THEME_COLOR_INSET_1)
429 uniform color_1_hover: (THEME_COLOR_INSET_1_HOVER)
430 uniform color_1_down: (THEME_COLOR_INSET_1_DOWN)
431 uniform color_1_active: (THEME_COLOR_INSET_1_ACTIVE)
432 uniform color_1_focus: (THEME_COLOR_INSET_1_FOCUS)
433 uniform color_1_disabled: (THEME_COLOR_INSET_1_DISABLED)
434
435 uniform color_2: (THEME_COLOR_INSET_2)
436 uniform color_2_hover: (THEME_COLOR_INSET_2_HOVER)
437 uniform color_2_down: (THEME_COLOR_INSET_2_DOWN)
438 uniform color_2_active: (THEME_COLOR_INSET_2_ACTIVE)
439 uniform color_2_focus: (THEME_COLOR_INSET_2_FOCUS)
440 uniform color_2_disabled: (THEME_COLOR_INSET_2_DISABLED)
441
442 uniform border_color_1: (THEME_COLOR_BEVEL_INSET_2)
443 uniform border_color_1_hover: (THEME_COLOR_BEVEL_INSET_2_HOVER)
444 uniform border_color_1_down: (THEME_COLOR_BEVEL_INSET_2_DOWN)
445 uniform border_color_1_active: (THEME_COLOR_BEVEL_INSET_2_ACTIVE)
446 uniform border_color_1_focus: (THEME_COLOR_BEVEL_INSET_2_FOCUS)
447 uniform border_color_1_disabled: (THEME_COLOR_BEVEL_INSET_2_DISABLED)
448
449 uniform border_color_2: (THEME_COLOR_BEVEL_INSET_1)
450 uniform border_color_2_hover: (THEME_COLOR_BEVEL_INSET_1_HOVER)
451 uniform border_color_2_down: (THEME_COLOR_BEVEL_INSET_1_DOWN)
452 uniform border_color_2_active: (THEME_COLOR_BEVEL_INSET_1_ACTIVE)
453 uniform border_color_2_focus: (THEME_COLOR_BEVEL_INSET_1_FOCUS)
454 uniform border_color_2_disabled: (THEME_COLOR_BEVEL_INSET_1_DISABLED)
455
456 uniform mark_size: 0.65
457 uniform mark_color: (THEME_COLOR_U_HIDDEN)
458 uniform mark_color_hover: (THEME_COLOR_U_HIDDEN)
459 uniform mark_color_down: (THEME_COLOR_U_HIDDEN)
460 uniform mark_color_active: (THEME_COLOR_MARK_ACTIVE)
461 uniform mark_color_active_hover: (THEME_COLOR_MARK_ACTIVE_HOVER)
462 uniform mark_color_focus: (THEME_COLOR_MARK_FOCUS)
463 uniform mark_color_disabled: (THEME_COLOR_MARK_DISABLED)
464
465 fn pixel(self) -> vec4 {
466 let sdf = Sdf2d::viewport(self.pos * self.rect_size);
467 let dither = Math::random_2d(self.pos.xy) * 0.04 * self.color_dither;
468
469 let sz_px = self.size;
470 let sz_inner_px = sz_px - self.border_size * 2.;
471 let shift_px = vec2(0, 0)
472 let center_px = vec2(
473 sz_px * 0.5,
474 self.rect_size.y * 0.5
475 )
476
477 let offset_px = vec2(
478 shift_px.x,
479 shift_px.y + center_px.y - sz_px * 0.5
480 )
481
482 let offset_uv = vec2(
483 offset_px.x / self.rect_size.x,
484 offset_px.y / self.rect_size.y
485 )
486
487 let border_sz_uv = vec2(
488 self.border_size / self.rect_size.x,
489 self.border_size / self.rect_size.y
490 )
491
492 let scale_factor_border = vec2(
493 self.rect_size.x / sz_px,
494 self.rect_size.y / sz_px
495 );
496
497 let gradient_border = vec2(
498 (self.pos.x - offset_uv.x) * scale_factor_border.x + dither,
499 (self.pos.y - offset_uv.y) * scale_factor_border.y + dither
500 )
501
502 let scale_factor_fill = vec2(
503 self.rect_size.x / sz_inner_px,
504 self.rect_size.y / sz_inner_px
505 );
506
507 let gradient_fill = vec2(
508 (self.pos.x - offset_uv.x) * scale_factor_fill.x - border_sz_uv.x * 2. + dither,
509 (self.pos.y - offset_uv.y) * scale_factor_fill.y - border_sz_uv.y * 2. + dither
510 )
511
512 match self.check_type {
513 CheckType::Check => {
514
515 sdf.box(
517 offset_px.x + self.border_size,
518 offset_px.y + self.border_size,
519 sz_px - self.border_size * 2.,
520 sz_px - self.border_size * 2.,
521 self.border_radius * 0.5
522 );
523
524 sdf.stroke_keep(
525 mix(
526 mix(
527 mix(
528 mix(
529 mix(self.border_color_1, self.border_color_2, gradient_border.y),
530 mix(self.border_color_1_focus, self.border_color_2_focus, gradient_border.y),
531 self.focus
532 ),
533 mix(
534 mix(self.border_color_1_active, self.border_color_2_active, gradient_border.y),
535 mix(self.border_color_1_focus, self.border_color_2_focus, gradient_border.y),
536 self.focus
537 ),
538 self.active
539 ),
540 mix(
541 mix(self.border_color_1_down, self.border_color_2_down, gradient_border.y),
542 mix(self.border_color_1_hover, self.border_color_2_hover, gradient_border.y),
543 self.down
544 ),
545 self.hover
546 ),
547 mix(self.border_color_1_disabled, self.border_color_2_disabled, gradient_border.y),
548 self.disabled
549 ), self.border_size
550 )
551
552 sdf.fill(
553 mix(
554 mix(
555 mix(
556 mix(
557 mix(self.color_1, self.color_2, gradient_fill.y),
558 mix(self.color_1_focus, self.color_2_focus, gradient_fill.y),
559 self.focus
560 ),
561 mix(
562 mix(self.color_1_active, self.color_2_active, gradient_fill.y),
563 mix(self.color_1_focus, self.color_2_focus, gradient_fill.y),
564 self.focus
565 ),
566 self.active
567 ),
568 mix(
569 mix(self.color_1_hover, self.color_2_hover, gradient_fill.y),
570 mix(self.color_1_down, self.color_2_down, gradient_fill.y),
571 self.down
572 ),
573 self.hover
574 ),
575 mix(self.color_1_disabled, self.color_2_disabled, gradient_fill.y),
576 self.disabled
577 )
578 )
579
580 let mark_padding = 0.275 * self.size
582 sdf.move_to(mark_padding, center_px.y);
583 sdf.line_to(center_px.x, center_px.y + sz_px * 0.5 - mark_padding);
584 sdf.line_to(sz_px - mark_padding, offset_px.y + mark_padding);
585
586 sdf.stroke(
587 mix(
588 mix(
589 mix(self.mark_color, self.mark_color_hover, self.hover),
590 mix(self.mark_color_active, self.mark_color_active_hover, self.hover),
591 self.active
592 ),
593 self.mark_color_disabled,
594 self.disabled
595 ), self.size * 0.09
596 );
597
598 }
599
600 CheckType::None => {
603 sdf.fill(THEME_COLOR_D_HIDDEN);
604 }
605 }
606 return sdf.result
607 }
608 }
609 }
610
611 pub CheckBoxGradientX = <CheckBoxGradientY> {
612 draw_bg: {
613 fn pixel(self) -> vec4 {
614 let sdf = Sdf2d::viewport(self.pos * self.rect_size);
615 let dither = Math::random_2d(self.pos.xy) * 0.04 * self.color_dither;
616
617 let sz_px = self.size;
618 let sz_inner_px = sz_px - self.border_size * 2.;
619 let shift_px = vec2(0, 0)
620 let center_px = vec2(
621 sz_px * 0.5,
622 self.rect_size.y * 0.5
623 )
624
625 let offset_px = vec2(
626 shift_px.x,
627 shift_px.y + center_px.y - sz_px * 0.5
628 )
629
630 let offset_uv = vec2(
631 offset_px.x / self.rect_size.x,
632 offset_px.y / self.rect_size.y
633 )
634
635 let border_sz_uv = vec2(
636 self.border_size / self.rect_size.x,
637 self.border_size / self.rect_size.y
638 )
639
640 let scale_factor_border = vec2(
641 self.rect_size.x / sz_px,
642 self.rect_size.y / sz_px
643 );
644
645 let gradient_border = vec2(
646 (self.pos.x - offset_uv.x) * scale_factor_border.x + dither,
647 (self.pos.y - offset_uv.y) * scale_factor_border.y + dither
648 )
649
650 let scale_factor_fill = vec2(
651 self.rect_size.x / sz_inner_px,
652 self.rect_size.y / sz_inner_px
653 );
654
655 let gradient_fill = vec2(
656 (self.pos.x - offset_uv.x) * scale_factor_fill.x - border_sz_uv.x * 2. + dither,
657 (self.pos.y - offset_uv.y) * scale_factor_fill.y - border_sz_uv.y * 2. + dither
658 )
659
660 sdf.box(
662 offset_px.x + self.border_size,
663 offset_px.y + self.border_size,
664 sz_px - self.border_size * 2.,
665 sz_px - self.border_size * 2.,
666 self.border_radius * 0.5
667 );
668
669 sdf.stroke_keep(
670 mix(
671 mix(
672 mix(
673 mix(
674 mix(self.border_color_1, self.border_color_2, gradient_border.y),
675 mix(self.border_color_1_focus, self.border_color_2_focus, gradient_border.y),
676 self.focus
677 ),
678 mix(
679 mix(self.border_color_1_active, self.border_color_2_active, gradient_border.y),
680 mix(self.border_color_1_focus, self.border_color_2_focus, gradient_border.y),
681 self.focus
682 ),
683 self.active
684 ),
685 mix(
686 mix(self.border_color_1_hover, self.border_color_2_hover, gradient_border.y),
687 mix(self.border_color_1_down, self.border_color_2_down, gradient_border.y),
688 self.down
689 ),
690 self.hover
691 ),
692 mix(self.border_color_1_disabled, self.border_color_2_disabled, gradient_border.y),
693 self.disabled
694 ), self.border_size
695 )
696
697 sdf.fill(
698 mix(
699 mix(
700 mix(
701 mix(
702 mix(self.color_1, self.color_2, gradient_fill.x),
703 mix(self.color_1_focus, self.color_2_focus, gradient_fill.x),
704 self.focus
705 ),
706 mix(
707 mix(self.color_1_active, self.color_2_active, gradient_fill.x),
708 mix(self.color_1_focus, self.color_2_focus, gradient_fill.x),
709 self.focus
710 ),
711 self.active
712 ),
713 mix(
714 mix(self.color_1_hover, self.color_2_hover, gradient_fill.x),
715 mix(self.color_1_down, self.color_2_down, gradient_fill.x),
716 self.down
717 ),
718 self.hover
719 ),
720 mix(self.color_1_disabled, self.color_2_disabled, gradient_fill.x),
721 self.disabled
722 )
723 )
724
725 let mark_padding = 0.275 * self.size
727 sdf.move_to(mark_padding, center_px.y);
728 sdf.line_to(center_px.x, center_px.y + sz_px * 0.5 - mark_padding);
729 sdf.line_to(sz_px - mark_padding, offset_px.y + mark_padding);
730
731 sdf.stroke(
732 mix(
733 mix(
734 mix(self.mark_color, self.mark_color_hover, self.hover),
735 mix(self.mark_color_active, self.mark_color_active_hover, self.hover),
736 self.active
737 ),
738 self.mark_color_disabled,
739 self.disabled
740 ), self.size * 0.09
741 );
742
743 return sdf.result
744 }
745 }
746 }
747
748 pub Toggle = <CheckBox> {
749 label_walk: {
750 margin: <THEME_MSPACE_H_1> { left: (15.0 + THEME_SPACE_2) }
751 }
752
753 draw_bg: {
754 uniform size: 15.;
755
756 mark_color: (THEME_COLOR_LABEL_OUTER)
757 mark_color_hover: (THEME_COLOR_LABEL_OUTER_ACTIVE)
758 mark_color_down: (THEME_COLOR_LABEL_OUTER_DOWN)
759
760 fn pixel(self) -> vec4 {
761 let sdf = Sdf2d::viewport(self.pos * self.rect_size);
762 let dither = Math::random_2d(self.pos.xy) * 0.04 * self.color_dither;
763
764 let sz_px = vec2(
765 self.size * 1.6,
766 self.size
767 );
768 let sz_inner_px = vec2(
769 sz_px.x - self.border_size * 2.,
770 sz_px.y - self.border_size * 2.
771 );
772 let shift_px = vec2(0., 0.);
773 let center_px = vec2(
774 sz_px.x * 0.5,
775 self.rect_size.y * 0.5
776 )
777
778 let offset_px = vec2(
779 shift_px.x,
780 shift_px.y + center_px.y - sz_px.y * 0.5
781 )
782
783 let offset_uv = vec2(
784 offset_px.x / self.rect_size.x,
785 offset_px.y / self.rect_size.y
786 )
787
788 let border_sz_uv = vec2(
789 self.border_size / self.rect_size.x,
790 self.border_size / self.rect_size.y
791 )
792
793 let scale_factor_border = vec2(
794 self.rect_size.x / sz_px.x,
795 self.rect_size.y / sz_px.y
796 );
797
798 let gradient_border = vec2(
799 (self.pos.x - offset_uv.x) * scale_factor_border.x + dither,
800 (self.pos.y - offset_uv.y) * scale_factor_border.y + dither
801 )
802
803 let scale_factor_fill = vec2(
804 self.rect_size.x / sz_inner_px.x,
805 self.rect_size.y / sz_inner_px.y
806 );
807
808 let gradient_fill = vec2(
809 (self.pos.x - offset_uv.x) * scale_factor_fill.x - border_sz_uv.x * 2. + dither,
810 (self.pos.y - offset_uv.y) * scale_factor_fill.y - border_sz_uv.y * 2. + dither
811 )
812
813 sdf.box(
815 offset_px.x + self.border_size,
816 offset_px.y + self.border_size,
817 sz_px.x - self.border_size * 2.,
818 sz_px.y - self.border_size * 2.,
819 self.border_radius * self.size * 0.1
820 );
821
822 sdf.stroke_keep(
823 mix(
824 mix(
825 mix(
826 mix(
827 mix(self.border_color_1, self.border_color_2, gradient_border.y),
828 mix(self.border_color_1_focus, self.border_color_2_focus, gradient_border.y),
829 self.focus
830 ),
831 mix(
832 mix(self.border_color_1_active, self.border_color_2_active, gradient_border.y),
833 mix(self.border_color_1_focus, self.border_color_2_focus, gradient_border.y),
834 self.focus
835 ),
836 self.active
837 ),
838 mix(
839 mix(self.border_color_1_hover, self.border_color_2_hover, gradient_border.y),
840 mix(self.border_color_1_down, self.border_color_2_down, gradient_border.y),
841 self.down
842 ),
843 self.hover
844 ),
845 mix(self.border_color_1_disabled, self.border_color_2_disabled, gradient_border.y),
846 self.disabled
847 ), self.border_size
848 )
849
850 sdf.fill(
851 mix(
852 mix(
853 mix(
854 mix(
855 self.color,
856 self.color_active,
857 self.active
858 ),
859 self.color_focus,
860 self.focus
861 ),
862 mix(
863 self.color_hover,
864 self.color_down,
865 self.down
866 ),
867 self.hover
868 ),
869 self.color_disabled,
870 self.disabled
871 )
872 )
873
874 let mark_padding = 1.5;
904 let mark_size = sz_px.y * 0.5 - self.border_size - mark_padding;
905 let mark_target_y = sz_px.y - sz_px.x + self.border_size + mark_padding;
906 let mark_pos_y = sz_px.y * 0.5 + self.border_size - mark_target_y * self.active;
907
908 sdf.circle(
909 mark_pos_y,
910 center_px.y,
911 mark_size
912 );
913 sdf.circle(
914 mark_pos_y,
915 center_px.y,
916 mark_size * 0.45
917 );
918 sdf.subtract();
919
920 sdf.circle(
921 mark_pos_y,
922 center_px.y,
923 mark_size
924 );
925
926 sdf.blend(self.active)
927
928 sdf.fill(
929 mix(
930 mix(
931 mix(self.mark_color, self.mark_color_hover, self.hover),
932 mix(self.mark_color_active, self.mark_color_active_hover, self.hover),
933 self.active
934 ),
935 self.mark_color_disabled,
936 self.disabled
937 )
938 )
939 return sdf.result
940 }
941 }
942
943 animator: {
944 disabled = {
945 default: off,
946 off = {
947 from: {all: Forward {duration: 0.}}
948 apply: {
949 draw_bg: {disabled: 0.0}
950 draw_text: {disabled: 0.0}
951 draw_icon: {disabled: 0.0}
952 }
953 }
954 on = {
955 from: {all: Forward {duration: 0.2}}
956 apply: {
957 draw_bg: {disabled: 1.0}
958 draw_text: {disabled: 1.0}
959 draw_icon: {disabled: 1.0}
960 }
961 }
962 }
963
964 hover = {
965 default: off
966 off = {
967 from: {all: Forward {duration: 0.15}}
968 apply: {
969 draw_bg: {down: [{time: 0.0, value: 0.0}], hover: 0.0}
970 draw_text: {down: [{time: 0.0, value: 0.0}], hover: 0.0}
971 }
972 }
973 on = {
974 from: {all: Snap}
975 apply: {
976 draw_bg: {down: [{time: 0.0, value: 0.0}], hover: 1.0}
977 draw_text: {down: [{time: 0.0, value: 0.0}], hover: 1.0}
978 }
979 }
980 down = {
981 from: {all: Forward {duration: 0.2}}
982 apply: {
983 draw_bg: {down: [{time: 0.0, value: 1.0}], hover: 1.0,}
984 draw_text: {down: [{time: 0.0, value: 1.0}], hover: 1.0,}
985 }
986 }
987 }
988
989 focus = {
990 default: off
991 off = {
992 from: {all: Snap}
993 apply: {
994 draw_bg: {focus: 0.0}
995 draw_text: {focus: 0.0}
996 }
997 }
998 on = {
999 from: {all: Snap}
1000 apply: {
1001 draw_bg: {focus: 1.0}
1002 draw_text: {focus: 1.0}
1003 }
1004 }
1005 }
1006 active = {
1007 default: off
1008 off = {
1009 ease: OutQuad
1010 from: {all: Forward {duration: 0.1}}
1011 apply: {
1012 draw_bg: {active: 0.0},
1013 draw_text: {active: 0.0},
1014 draw_icon: {active: 0.0},
1015 }
1016 }
1017 on = {
1018 ease: OutQuad
1019 from: {all: Forward {duration: 0.1}}
1020 apply: {
1021 draw_bg: {active: 1.0}
1022 draw_text: {active: 1.0}
1023 draw_icon: {active: 1.0},
1024 }
1025 }
1026 }
1027 }
1028 }
1029
1030 pub ToggleGradientY = <CheckBoxGradientY> {
1031 label_walk: {
1032 margin: <THEME_MSPACE_H_1> { left: (15.0 + THEME_SPACE_2) }
1033 }
1034
1035 draw_bg: {
1036 uniform size: 15.;
1037
1038 mark_color: (THEME_COLOR_LABEL_OUTER)
1039 mark_color_hover: (THEME_COLOR_LABEL_OUTER_ACTIVE)
1040 mark_color_down: (THEME_COLOR_LABEL_OUTER_DOWN)
1041
1042 fn pixel(self) -> vec4 {
1043 let sdf = Sdf2d::viewport(self.pos * self.rect_size);
1044 let dither = Math::random_2d(self.pos.xy) * 0.04 * self.color_dither;
1045
1046 let sz_px = vec2(
1047 self.size * 1.6,
1048 self.size
1049 );
1050 let sz_inner_px = vec2(
1051 sz_px.x - self.border_size * 2.,
1052 sz_px.y - self.border_size * 2.
1053 );
1054 let shift_px = vec2(0., 0.);
1055 let center_px = vec2(
1056 sz_px.x * 0.5,
1057 self.rect_size.y * 0.5
1058 )
1059
1060 let offset_px = vec2(
1061 shift_px.x,
1062 shift_px.y + center_px.y - sz_px.y * 0.5
1063 )
1064
1065 let offset_uv = vec2(
1066 offset_px.x / self.rect_size.x,
1067 offset_px.y / self.rect_size.y
1068 )
1069
1070 let border_sz_uv = vec2(
1071 self.border_size / self.rect_size.x,
1072 self.border_size / self.rect_size.y
1073 )
1074
1075 let scale_factor_border = vec2(
1076 self.rect_size.x / sz_px.x,
1077 self.rect_size.y / sz_px.y
1078 );
1079
1080 let gradient_border = vec2(
1081 (self.pos.x - offset_uv.x) * scale_factor_border.x + dither,
1082 (self.pos.y - offset_uv.y) * scale_factor_border.y + dither
1083 )
1084
1085 let scale_factor_fill = vec2(
1086 self.rect_size.x / sz_inner_px.x,
1087 self.rect_size.y / sz_inner_px.y
1088 );
1089
1090 let gradient_fill = vec2(
1091 (self.pos.x - offset_uv.x) * scale_factor_fill.x - border_sz_uv.x * 2. + dither,
1092 (self.pos.y - offset_uv.y) * scale_factor_fill.y - border_sz_uv.y * 2. + dither
1093 )
1094
1095 sdf.box(
1097 offset_px.x + self.border_size,
1098 offset_px.y + self.border_size,
1099 sz_px.x - self.border_size * 2.,
1100 sz_px.y - self.border_size * 2.,
1101 self.border_radius * self.size * 0.1
1102 );
1103
1104 sdf.stroke_keep(
1105 mix(
1106 mix(
1107 mix(
1108 mix(
1109 mix(self.border_color_1, self.border_color_2, gradient_border.y),
1110 mix(self.border_color_1_focus, self.border_color_2_focus, gradient_border.y),
1111 self.focus
1112 ),
1113 mix(
1114 mix(self.border_color_1_active, self.border_color_2_active, gradient_border.y),
1115 mix(self.border_color_1_focus, self.border_color_2_focus, gradient_border.y),
1116 self.focus
1117 ),
1118 self.active
1119 ),
1120 mix(
1121 mix(self.border_color_1_hover, self.border_color_2_hover, gradient_border.y),
1122 mix(self.border_color_1_down, self.border_color_2_down, gradient_border.y),
1123 self.down
1124 ),
1125 self.hover
1126 ),
1127 mix(self.border_color_1_disabled, self.border_color_2_disabled, gradient_border.y),
1128 self.disabled
1129 ), self.border_size
1130 )
1131
1132 sdf.fill(
1133 mix(
1134 mix(
1135 mix(
1136 mix(
1137 mix(self.color_1, self.color_2, gradient_fill.y),
1138 mix(self.color_1_active, self.color_2_active, gradient_fill.y),
1139 self.active
1140 ),
1141 mix(self.color_1_focus, self.color_2_focus, gradient_fill.y),
1142 self.focus
1143 ),
1144 mix(
1145 mix(self.color_1_hover, self.color_2_hover, gradient_fill.y),
1146 mix(self.color_1_down, self.color_2_down, gradient_fill.y),
1147 self.down
1148 ),
1149 self.hover
1150 ),
1151 mix(self.color_1_disabled, self.color_2_disabled, gradient_fill.y),
1152 self.disabled
1153 )
1154 )
1155
1156 let mark_padding = 1.5;
1158 let mark_size = sz_px.y * 0.5 - self.border_size - mark_padding;
1159 let mark_target_y = sz_px.y - sz_px.x + self.border_size + mark_padding;
1160 let mark_pos_y = sz_px.y * 0.5 + self.border_size - mark_target_y * self.active;
1161
1162 sdf.circle(
1163 mark_pos_y,
1164 center_px.y,
1165 mark_size
1166 );
1167 sdf.circle(
1168 mark_pos_y,
1169 center_px.y,
1170 mark_size * 0.45
1171 );
1172 sdf.subtract();
1173
1174 sdf.circle(
1175 mark_pos_y,
1176 center_px.y,
1177 mark_size
1178 );
1179
1180 sdf.blend(self.active)
1181
1182 sdf.fill(
1183 mix(
1184 mix(
1185 mix(self.mark_color, self.mark_color_hover, self.hover),
1186 mix(self.mark_color_active, self.mark_color_active_hover, self.hover),
1187 self.active
1188 ),
1189 self.mark_color_disabled,
1190 self.disabled
1191 )
1192 )
1193 return sdf.result
1194 }
1195 }
1196
1197 animator: {
1198 disabled = {
1199 default: off,
1200 off = {
1201 from: {all: Forward {duration: 0.}}
1202 apply: {
1203 draw_bg: {disabled: 0.0}
1204 draw_text: {disabled: 0.0}
1205 draw_icon: {disabled: 0.0}
1206 }
1207 }
1208 on = {
1209 from: {all: Forward {duration: 0.2}}
1210 apply: {
1211 draw_bg: {disabled: 1.0}
1212 draw_text: {disabled: 1.0}
1213 draw_icon: {disabled: 1.0}
1214 }
1215 }
1216 }
1217
1218 hover = {
1219 default: off
1220 off = {
1221 from: {all: Forward {duration: 0.15}}
1222 apply: {
1223 draw_bg: {down: [{time: 0.0, value: 0.0}], hover: 0.0}
1224 draw_text: {down: [{time: 0.0, value: 0.0}], hover: 0.0}
1225 }
1226 }
1227 on = {
1228 from: {all: Snap}
1229 apply: {
1230 draw_bg: {down: [{time: 0.0, value: 0.0}], hover: 1.0}
1231 draw_text: {down: [{time: 0.0, value: 0.0}], hover: 1.0}
1232 }
1233 }
1234 down = {
1235 from: {all: Forward {duration: 0.2}}
1236 apply: {
1237 draw_bg: {down: [{time: 0.0, value: 1.0}], hover: 1.0,}
1238 draw_text: {down: [{time: 0.0, value: 1.0}], hover: 1.0,}
1239 }
1240 }
1241 }
1242
1243 focus = {
1244 default: off
1245 off = {
1246 from: {all: Snap}
1247 apply: {
1248 draw_bg: {focus: 0.0}
1249 draw_text: {focus: 0.0}
1250 }
1251 }
1252 on = {
1253 from: {all: Snap}
1254 apply: {
1255 draw_bg: {focus: 1.0}
1256 draw_text: {focus: 1.0}
1257 }
1258 }
1259 }
1260 active = {
1261 default: off
1262 off = {
1263 ease: OutQuad
1264 from: {all: Forward {duration: 0.1}}
1265 apply: {
1266 draw_bg: {active: 0.0},
1267 draw_text: {active: 0.0},
1268 draw_icon: {active: 0.0},
1269 }
1270 }
1271 on = {
1272 ease: OutQuad
1273 from: {all: Forward {duration: 0.1}}
1274 apply: {
1275 draw_bg: {active: 1.0}
1276 draw_text: {active: 1.0}
1277 draw_icon: {active: 1.0},
1278 }
1279 }
1280 }
1281 }
1282 }
1283
1284 pub ToggleFlat = <Toggle> {
1285 draw_bg: {
1286 color: (THEME_COLOR_INSET)
1287 color_hover: (THEME_COLOR_INSET_HOVER)
1288 color_down: (THEME_COLOR_INSET_DOWN)
1289 color_active: (THEME_COLOR_INSET_ACTIVE)
1290 color_focus: (THEME_COLOR_INSET_FOCUS)
1291 color_down: (THEME_COLOR_INSET_DISABLED)
1292
1293 border_color_1: (THEME_COLOR_BEVEL)
1294 border_color_1_hover: (THEME_COLOR_BEVEL_HOVER)
1295 border_color_1_down: (THEME_COLOR_BEVEL_DOWN)
1296 border_color_1_active: (THEME_COLOR_BEVEL_ACTIVE)
1297 border_color_1_focus: (THEME_COLOR_BEVEL_FOCUS)
1298 border_color_1_disabled: (THEME_COLOR_BEVEL_DISABLED)
1299
1300 border_color_2: (THEME_COLOR_BEVEL)
1301 border_color_2_hover: (THEME_COLOR_BEVEL_HOVER)
1302 border_color_2_down: (THEME_COLOR_BEVEL_DOWN)
1303 border_color_2_active: (THEME_COLOR_BEVEL_ACTIVE)
1304 border_color_2_focus: (THEME_COLOR_BEVEL_FOCUS)
1305 border_color_2_disabled: (THEME_COLOR_BEVEL_DISABLED)
1306 }
1307 }
1308
1309 pub ToggleFlatter = <ToggleFlat> {
1310 draw_bg: {
1311 border_color_1: (THEME_COLOR_U_HIDDEN)
1312 border_color_1_hover: (THEME_COLOR_U_HIDDEN)
1313 border_color_1_down: (THEME_COLOR_U_HIDDEN)
1314 border_color_1_active: (THEME_COLOR_U_HIDDEN)
1315 border_color_1_focus: (THEME_COLOR_U_HIDDEN)
1316 border_color_1_disabled: (THEME_COLOR_U_HIDDEN)
1317
1318 border_color_2: (THEME_COLOR_U_HIDDEN)
1319 border_color_2_hover: (THEME_COLOR_U_HIDDEN)
1320 border_color_2_down: (THEME_COLOR_U_HIDDEN)
1321 border_color_2_active: (THEME_COLOR_U_HIDDEN)
1322 border_color_2_focus: (THEME_COLOR_U_HIDDEN)
1323 border_color_2_disabled: (THEME_COLOR_U_HIDDEN)
1324 }
1325 }
1326
1327 pub ToggleGradientX = <ToggleGradientY> {
1328 draw_bg: {
1329 uniform size: 15.;
1330
1331 fn pixel(self) -> vec4 {
1332 let sdf = Sdf2d::viewport(self.pos * self.rect_size);
1333 let dither = Math::random_2d(self.pos.xy) * 0.04 * self.color_dither;
1334
1335 let sz_px = vec2(
1336 self.size * 1.6,
1337 self.size
1338 );
1339 let sz_inner_px = vec2(
1340 sz_px.x - self.border_size * 2.,
1341 sz_px.y - self.border_size * 2.
1342 );
1343 let shift_px = vec2(0., 0.);
1344 let center_px = vec2(
1345 sz_px.x * 0.5,
1346 self.rect_size.y * 0.5
1347 )
1348
1349 let offset_px = vec2(
1350 shift_px.x,
1351 shift_px.y + center_px.y - sz_px.y * 0.5
1352 )
1353
1354 let offset_uv = vec2(
1355 offset_px.x / self.rect_size.x,
1356 offset_px.y / self.rect_size.y
1357 )
1358
1359 let border_sz_uv = vec2(
1360 self.border_size / self.rect_size.x,
1361 self.border_size / self.rect_size.y
1362 )
1363
1364 let scale_factor_border = vec2(
1365 self.rect_size.x / sz_px.x,
1366 self.rect_size.y / sz_px.y
1367 );
1368
1369 let gradient_border = vec2(
1370 (self.pos.x - offset_uv.x) * scale_factor_border.x + dither,
1371 (self.pos.y - offset_uv.y) * scale_factor_border.y + dither
1372 )
1373
1374 let scale_factor_fill = vec2(
1375 self.rect_size.x / sz_inner_px.x,
1376 self.rect_size.y / sz_inner_px.y
1377 );
1378
1379 let gradient_fill = vec2(
1380 (self.pos.x - offset_uv.x) * scale_factor_fill.x - border_sz_uv.x * 2. + dither,
1381 (self.pos.y - offset_uv.y) * scale_factor_fill.y - border_sz_uv.y * 2. + dither
1382 )
1383
1384 sdf.box(
1386 offset_px.x + self.border_size,
1387 offset_px.y + self.border_size,
1388 sz_px.x - self.border_size * 2.,
1389 sz_px.y - self.border_size * 2.,
1390 self.border_radius * self.size * 0.1
1391 );
1392
1393 sdf.fill_keep(
1394 mix(
1395 mix(
1396 mix(
1397 mix(
1398 mix(self.color_1, self.color_2, gradient_fill.x),
1399 mix(self.color_1_focus, self.color_2_focus, gradient_fill.x),
1400 self.focus
1401 ),
1402 mix(
1403 mix(self.color_1_active, self.color_2_active, gradient_fill.x),
1404 mix(self.color_1_focus, self.color_2_focus, gradient_fill.x),
1405 self.focus
1406 ),
1407 self.active
1408 ),
1409 mix(
1410 mix(self.color_1_hover, self.color_2_hover, gradient_fill.x),
1411 mix(self.color_1_down, self.color_2_down, gradient_fill.x),
1412 self.down
1413 ),
1414 self.hover
1415 ),
1416 mix(self.color_1_disabled, self.color_2_disabled, gradient_fill.x),
1417 self.disabled
1418 )
1419 )
1420
1421 sdf.stroke(
1422 mix(
1423 mix(
1424 mix(
1425 mix(
1426 mix(self.border_color_1, self.border_color_2, gradient_border.y),
1427 mix(self.border_color_1_focus, self.border_color_2_focus, gradient_border.y),
1428 self.focus
1429 ),
1430 mix(
1431 mix(self.border_color_1_active, self.border_color_2_active, gradient_border.y),
1432 mix(self.border_color_1_focus, self.border_color_2_focus, gradient_border.y),
1433 self.focus
1434 ),
1435 self.active
1436 ),
1437 mix(
1438 mix(self.border_color_1_hover, self.border_color_2_hover, gradient_border.y),
1439 mix(self.border_color_1_down, self.border_color_2_down, gradient_border.y),
1440 self.down
1441 ),
1442 self.hover
1443 ),
1444 mix(self.border_color_1_disabled, self.border_color_2_disabled, gradient_border.y),
1445 self.disabled
1446 ), self.border_size
1447 )
1448
1449
1450 let mark_padding = 1.5;
1452 let mark_size = sz_px.y * 0.5 - self.border_size - mark_padding;
1453 let mark_target_y = sz_px.y - sz_px.x + self.border_size + mark_padding;
1454 let mark_pos_y = sz_px.y * 0.5 + self.border_size - mark_target_y * self.active;
1455
1456 sdf.circle(
1457 mark_pos_y,
1458 center_px.y,
1459 mark_size
1460 );
1461 sdf.circle(
1462 mark_pos_y,
1463 center_px.y,
1464 mark_size * 0.45
1465 );
1466 sdf.subtract();
1467
1468 sdf.circle(
1469 mark_pos_y,
1470 center_px.y,
1471 mark_size
1472 );
1473
1474 sdf.blend(self.active)
1475
1476 sdf.fill(
1477 mix(
1478 mix(
1479 mix(self.mark_color, self.mark_color_hover, self.hover),
1480 mix(self.mark_color_active, self.mark_color_active_hover, self.hover),
1481 self.active
1482 ),
1483 self.mark_color_disabled,
1484 self.disabled
1485 )
1486 )
1487 return sdf.result
1488 }
1489 }
1490 }
1491
1492 pub CheckBoxCustom = <CheckBox> {
1493 draw_bg: { check_type: None }
1494 width: Fit, height: Fit,
1495
1496 padding: <THEME_MSPACE_2> {}
1497 align: { x: 0., y: 0.5 }
1498
1499 label_walk: {
1500 margin: <THEME_MSPACE_H_2> {}
1501 }
1502 }
1503}
1504
1505#[derive(Live, LiveHook, LiveRegister)]
1506#[repr(C)]
1507pub struct DrawCheckBox {
1508 #[deref] draw_super: DrawQuad,
1509 #[live] check_type: CheckType,
1510 #[live] hover: f32,
1511 #[live] focus: f32,
1512 #[live] active: f32
1513}
1514
1515#[derive(Live, LiveHook, LiveRegister)]
1516#[live_ignore]
1517#[repr(u32)]
1518pub enum CheckType {
1519 #[pick] Check = shader_enum(1),
1520 Radio = shader_enum(2),
1521 Toggle = shader_enum(3),
1522 None = shader_enum(4),
1523}
1524
1525#[derive(Live, Widget)]
1526pub struct CheckBox {
1527
1528 #[walk] walk: Walk,
1529 #[layout] layout: Layout,
1530 #[animator] animator: Animator,
1531
1532 #[live] icon_walk: Walk,
1533 #[live] label_walk: Walk,
1534 #[live] label_align: Align,
1535
1536 #[redraw] #[live] draw_bg: DrawCheckBox,
1537 #[live] draw_text: DrawText,
1538 #[live] draw_icon: DrawIcon,
1539
1540 #[live] text: ArcStringMut,
1541
1542 #[visible] #[live(true)]
1543 pub visible: bool,
1544
1545 #[live(None)]
1546 pub active: Option<bool>,
1547
1548 #[live] bind: String,
1549 #[action_data] #[rust] action_data: WidgetActionData,
1550}
1551
1552impl LiveHook for CheckBox{
1554 fn after_new_from_doc(&mut self, cx: &mut Cx){
1555 if let Some(active) = self.active.take() {
1556 self.animator_toggle(cx, active, Animate::No, id!(active.on), id!(active.off));
1557 }
1558 }
1559}
1560
1561#[derive(Clone, Debug, DefaultNone)]
1562pub enum CheckBoxAction {
1563 Change(bool),
1564 None
1565}
1566
1567impl CheckBox {
1568
1569 pub fn draw_walk(&mut self, cx: &mut Cx2d, walk: Walk) -> DrawStep {
1570 self.draw_bg.begin(cx, walk, self.layout);
1571 self.draw_icon.draw_walk(cx, self.icon_walk);
1572 self.draw_text.draw_walk(cx, self.label_walk, self.label_align, self.text.as_ref());
1573 self.draw_bg.end(cx);
1574 cx.add_nav_stop(self.draw_bg.area(), NavRole::TextInput, Margin::default());
1575 DrawStep::done()
1576 }
1577}
1578
1579impl Widget for CheckBox {
1580
1581 fn set_disabled(&mut self, cx:&mut Cx, disabled:bool){
1582 self.animator_toggle(cx, disabled, Animate::Yes, id!(disabled.on), id!(disabled.off));
1583 }
1584
1585 fn disabled(&self, cx:&Cx) -> bool {
1586 self.animator_in_state(cx, id!(disabled.on))
1587 }
1588
1589 fn widget_to_data(&self, _cx: &mut Cx, actions: &Actions, nodes: &mut LiveNodeVec, path: &[LiveId]) -> bool {
1590 match actions.find_widget_action_cast(self.widget_uid()) {
1591 CheckBoxAction::Change(v) => {
1592 nodes.write_field_value(path, LiveValue::Bool(v));
1593 true
1594 }
1595 _ => false
1596 }
1597 }
1598
1599 fn data_to_widget(&mut self, cx: &mut Cx, nodes: &[LiveNode], path: &[LiveId]) {
1600 if let Some(value) = nodes.read_field_value(path) {
1601 if let Some(value) = value.as_bool() {
1602 self.animator_toggle(cx, value, Animate::Yes, id!(active.on), id!(active.off));
1603 }
1604 }
1605 }
1606
1607 fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
1608 let uid = self.widget_uid();
1609 self.animator_handle_event(cx, event);
1610
1611 match event.hits(cx, self.draw_bg.area()) {
1612 Hit::KeyFocus(_) => {
1613 self.animator_play(cx, id!(focus.on));
1614 }
1615 Hit::KeyFocusLost(_) => {
1616 self.animator_play(cx, id!(focus.off));
1617 self.draw_bg.redraw(cx);
1618 }
1619 Hit::FingerHoverIn(_) => {
1620 cx.set_cursor(MouseCursor::Hand);
1621 self.animator_play(cx, id!(hover.on));
1622 }
1623 Hit::FingerHoverOut(_) => {
1624 self.animator_play(cx, id!(hover.off));
1625 },
1626 Hit::FingerDown(fe) if fe.is_primary_hit() => {
1627 self.set_key_focus(cx);
1628 if self.animator_in_state(cx, id!(active.on)) {
1629 self.animator_play(cx, id!(active.off));
1630 cx.widget_action_with_data(&self.action_data, uid, &scope.path, CheckBoxAction::Change(false));
1631 }
1632 else {
1633 self.animator_play(cx, id!(active.on));
1634 cx.widget_action_with_data(&self.action_data, uid, &scope.path, CheckBoxAction::Change(true));
1635 }
1636 },
1637 Hit::FingerUp(_fe) => {
1638
1639 }
1640 Hit::FingerMove(_fe) => {
1641
1642 }
1643 _ => ()
1644 }
1645 }
1646
1647 fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
1648 if !self.visible {
1649 return DrawStep::done();
1650 }
1651 self.draw_walk(cx, walk)
1652 }
1653
1654 fn text(&self) -> String {
1655 self.text.as_ref().to_string()
1656 }
1657
1658 fn set_text(&mut self, cx:&mut Cx, v: &str) {
1659 self.text.as_mut_empty().push_str(v);
1660 self.redraw(cx);
1661 }
1662}
1663
1664impl CheckBoxRef {
1665
1666 pub fn changed(&self, actions: &Actions) -> Option<bool> {
1667 if let CheckBoxAction::Change(b) = actions.find_widget_action_cast(self.widget_uid()) {
1668 return Some(b)
1669 }
1670 None
1671 }
1672
1673 pub fn set_text(&self, text: &str) {
1674 if let Some(mut inner) = self.borrow_mut() {
1675 let s = inner.text.as_mut_empty();
1676 s.push_str(text);
1677 }
1678 }
1679
1680 pub fn active(&self, cx: &Cx) -> bool {
1681 if let Some(inner) = self.borrow() {
1682 inner.animator_in_state(cx, id!(active.on))
1683 }
1684 else {
1685 false
1686 }
1687 }
1688
1689 pub fn set_active(&self, cx: &mut Cx, value: bool) {
1690 if let Some(mut inner) = self.borrow_mut() {
1691 inner.animator_toggle(cx, value, Animate::Yes, id!(active.on), id!(active.off));
1692 }
1693 }
1694}