1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: MIT
3import { Palette } from "../../common.slint";
4
5export global DialState {
6 out property <int> totalLights: 60;
7 out property <angle> degreesFilledWithLights: 360deg - (startAngle - endAngle);
8 out property <angle> startAngle: 104deg;
9 out property <angle> endAngle: -startAngle;
10 in-out property <length> elementRadius: 120px;
11}
12
13export component Dial {
14 pure public function normalizeAngle(angle: angle) -> angle {
15 return (angle + 360deg).mod(360deg);
16 }
17
18 in property <bool> interactive: true;
19 property <bool> moving: ta.firstTouch;
20 in-out property <angle> dialAngle: DialState.startAngle;
21 out property <int> volume: ((dialAngle - DialState.startAngle) / DialState.degreesFilledWithLights) * DialState.totalLights;
22
23 width: 212px;
24 height: 213px;
25 knob := Rectangle {
26 base := Rectangle {
27 Image {
28 x: 0px;
29 y: 9px;
30 source: @image-url("../../images/dial-frame.png");
31 }
32
33 Image {
34 source: @image-url("../../images/lines.png");
35 colorize: Palette.dark-color-scheme ? #fff : #000;
36 rotation-angle: root.dialAngle;
37 width: self.source.width * 0.55 * 1px;
38 height: self.source.height * 0.55 * 1px;
39 opacity: 0.03;
40 }
41
42 ta := TouchArea {
43 property <length> centerX: self.width / 2;
44 property <length> centerY: self.height / 2;
45 property <length> relativeX;
46 property <length> relativeY;
47 property <angle> newAngle;
48 property <angle> deltaDegrees;
49 property <bool> firstTouch: false;
50 width: parent.width;
51 height: parent.height;
52 enabled: root.interactive;
53
54 changed pressed => {
55 if !self.pressed {
56 firstTouch = false;
57 }
58 }
59
60 moved => {
61 relativeX = ta.mouse-x - centerX;
62 relativeY = ta.mouse-y - centerY;
63 newAngle = normalizeAngle(atan2(relativeY / 1px, relativeX / 1px));
64 if !firstTouch {
65 firstTouch = true;
66 deltaDegrees = normalizeAngle(root.dialAngle - newAngle);
67 } else {
68 root.dialAngle = normalizeAngle(deltaDegrees + newAngle).clamp(DialState.startAngle, 260deg);
69 }
70 }
71 }
72 }
73 }
74
75 Rectangle {
76 width: 1px;
77 height: 1px;
78 x: 106px;
79 y: 105px;
80 Rectangle {
81 width: 0px;
82 height: 0px;
83 x: 55px * root.dialAngle.cos();
84 y: 55px * root.dialAngle.sin();
85 Image {
86 source: @image-url("../../images/notch.png");
87 }
88 }
89 }
90}
91