1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
2 | // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 |
3 | |
4 | import { CosmicFontSettings, CosmicPalette } from "styling.slint" ; |
5 | import { StateLayer } from "components.slint" ; |
6 | |
7 | export component Button { |
8 | in property <string> text; |
9 | in property <image> icon; |
10 | in property <bool> primary; |
11 | in property <bool> enabled <=> state-layer.enabled; |
12 | in property <bool> checkable; |
13 | in property <bool> colorize-icon; |
14 | out property <bool> has-focus: state-layer.has-focus; |
15 | out property <bool> pressed: self.enabled && state-layer.pressed; |
16 | in-out property <bool> checked <=> state-layer.checked; |
17 | |
18 | callback clicked; |
19 | |
20 | private property <brush> text-color: primary ? CosmicPalette.accent-foreground : CosmicPalette.control-foreground; |
21 | |
22 | min-width: max(32px, layout.min-width); |
23 | min-height: max(32px, layout.min-height); |
24 | horizontal-stretch: 0; |
25 | vertical-stretch: 0; |
26 | forward-focus: state-layer; |
27 | |
28 | accessible-role: button; |
29 | accessible-enabled: root.enabled; |
30 | accessible-checkable: root.checkable; |
31 | accessible-checked: root.checked; |
32 | accessible-label: root.text; |
33 | accessible-action-default => { state-layer.clicked(); } |
34 | |
35 | states [ |
36 | disabled when !root.enabled : { |
37 | root.opacity: 0.5; |
38 | } |
39 | ] |
40 | |
41 | background := Rectangle { |
42 | border-radius: 16px; |
43 | background: root.primary ? CosmicPalette.accent-background : CosmicPalette.control-background; |
44 | |
45 | animate background, border-color { duration: 150ms; } |
46 | |
47 | layout := HorizontalLayout { |
48 | padding-left: 12px; |
49 | padding-right: 12px; |
50 | padding-top: 5px; |
51 | padding-bottom: 5px; |
52 | spacing: 4px; |
53 | alignment: center; |
54 | |
55 | if (root.icon.width > 0 && root.icon.height > 0) : Image { |
56 | y: (parent.height - self.height) / 2; |
57 | source <=> root.icon; |
58 | width: 20px; |
59 | colorize: root.colorize-icon ? root.text-color : transparent; |
60 | } |
61 | |
62 | if (root.text != "" ): Text { |
63 | font-size: CosmicFontSettings.body.font-size; |
64 | font-weight: CosmicFontSettings.body.font-weight; |
65 | horizontal-alignment: center; |
66 | vertical-alignment: center; |
67 | text: root.text; |
68 | color: root.text-color; |
69 | animate color { duration: 150ms; } |
70 | accessible-role: none; |
71 | } |
72 | } |
73 | } |
74 | |
75 | state-layer := StateLayer { |
76 | border-radius: background.border-radius; |
77 | |
78 | clicked => { |
79 | if (root.checkable) { |
80 | root.checked = !root.checked; |
81 | } |
82 | root.clicked(); |
83 | } |
84 | } |
85 | } |
86 | |