1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
2 | // SPDX-License-Identifier: MIT |
3 | |
4 | import { Theme } from "../theme.slint" ; |
5 | import { MenuButton } from "menu_button.slint" ; |
6 | import { MenuBackground } from "../components/menu_background.slint" ; |
7 | |
8 | export component Menu { |
9 | in-out property <bool> menu-button-visible; |
10 | in property <length> start-y; |
11 | in property <length> end-y; |
12 | in property <bool> stays-open; |
13 | in property <length> menu-width <=> i-menu-container.width; |
14 | in property <length> menu-height <=> i-menu-container.height; |
15 | out property <bool> open; |
16 | |
17 | callback opend(); |
18 | callback closed(); |
19 | |
20 | public function hide-button() { |
21 | menu-button-visible = false; |
22 | } |
23 | |
24 | public function open-menu() { |
25 | open = true; |
26 | } |
27 | |
28 | public function hide() { |
29 | menu-button-visible = false; |
30 | open = false; |
31 | closed(); |
32 | } |
33 | |
34 | private property <int> container-visibility; |
35 | |
36 | states [ |
37 | open when root.open : { |
38 | container-visibility: 1.0; |
39 | i-menu-container.y: end-y; |
40 | |
41 | in { |
42 | animate i-menu-container.y { duration: Theme.durations.medium; } |
43 | } |
44 | out { |
45 | animate container-visibility, i-menu-container.y { duration: Theme.durations.medium; } |
46 | } |
47 | } |
48 | ] |
49 | |
50 | if (open) : Rectangle { |
51 | background: Theme.palette.pure-black; |
52 | opacity: 0.5; |
53 | |
54 | TouchArea { |
55 | clicked => { |
56 | hide(); |
57 | } |
58 | } |
59 | } |
60 | |
61 | i-menu-container := Rectangle { |
62 | x: (parent.width - self.width) / 2; |
63 | y: parent.height - start-y; |
64 | width: root.width / 3; |
65 | height: root.height - 75px; |
66 | |
67 | i-container := MenuBackground { |
68 | visible: container-visibility == 1.0; |
69 | |
70 | // avoid click-through |
71 | TouchArea {} |
72 | |
73 | @children |
74 | } |
75 | |
76 | if(menu-button-visible || container-visibility == 1.0 || stays-open) : HorizontalLayout { |
77 | y: -i-menu-button.height / 2; |
78 | alignment: center; |
79 | |
80 | VerticalLayout { |
81 | alignment: start; |
82 | |
83 | i-menu-button := MenuButton { |
84 | clicked => { |
85 | if(open) { |
86 | hide(); |
87 | } else { |
88 | open-menu(); |
89 | } |
90 | } |
91 | } |
92 | } |
93 | } |
94 | } |
95 | } |
96 | |
97 | export component MobileMenu { |
98 | out property <bool> open; |
99 | in property <length> end-y; |
100 | in property <length> menu-x; |
101 | out property <length> menu-width: 200px; |
102 | |
103 | if (root.open) : Rectangle { |
104 | background: Theme.palette.pure-black; |
105 | opacity: 0.5; |
106 | |
107 | TouchArea { |
108 | clicked => { |
109 | hide(); |
110 | } |
111 | } |
112 | } |
113 | |
114 | public function open-menu() { |
115 | root.open = true; |
116 | } |
117 | |
118 | public function hide() { |
119 | root.open = false; |
120 | } |
121 | |
122 | Rectangle { |
123 | clip: true; |
124 | menu := Rectangle { |
125 | x: root.menu-x; |
126 | y: -self.height; |
127 | width: root.menu-width; |
128 | height: root.height / 2; |
129 | visible: visibility > 0.0; |
130 | |
131 | private property <float> visibility; |
132 | |
133 | MenuBackground { |
134 | // avoid click-through |
135 | TouchArea {} |
136 | |
137 | @children |
138 | } |
139 | |
140 | states [ |
141 | open when root.open : { |
142 | menu.y: end-y; |
143 | visibility: 1.0; |
144 | |
145 | out { |
146 | animate visibility { duration: Theme.durations.medium; } |
147 | } |
148 | } |
149 | ] |
150 | |
151 | animate y { duration: Theme.durations.fast; } |
152 | } |
153 | |
154 | } |
155 | } |
156 | |