mirror of
https://github.com/slint-ui/slint.git
synced 2025-12-23 09:19:32 +00:00
Some checks are pending
autofix.ci / lint_typecheck (push) Waiting to run
autofix.ci / format_fix (push) Waiting to run
CI / tree-sitter (push) Blocked by required conditions
CI / files-changed (push) Waiting to run
CI / build_and_test (--exclude ffmpeg --exclude gstreamer-player, macos-14, stable) (push) Blocked by required conditions
CI / python_test (windows-2022) (push) Blocked by required conditions
CI / build_and_test (--exclude ffmpeg --exclude gstreamer-player, windows-2022, 1.88) (push) Blocked by required conditions
CI / build_and_test (--exclude ffmpeg --exclude gstreamer-player, windows-2022, beta) (push) Blocked by required conditions
CI / build_and_test (--exclude ffmpeg --exclude gstreamer-player, windows-2022, stable) (push) Blocked by required conditions
CI / build_and_test (ubuntu-22.04, 1.88) (push) Blocked by required conditions
CI / build_and_test (ubuntu-22.04, nightly) (push) Blocked by required conditions
CI / node_test (macos-14) (push) Blocked by required conditions
CI / node_test (windows-2022) (push) Blocked by required conditions
CI / node_test (ubuntu-22.04) (push) Blocked by required conditions
CI / python_test (macos-14) (push) Blocked by required conditions
CI / python_test (ubuntu-22.04) (push) Blocked by required conditions
CI / cpp_test_driver (macos-14) (push) Blocked by required conditions
CI / cpp_test_driver (ubuntu-22.04) (push) Blocked by required conditions
CI / cpp_test_driver (windows-2022) (push) Blocked by required conditions
CI / cpp_cmake (macos-14, 1.88) (push) Blocked by required conditions
CI / cpp_cmake (ubuntu-22.04, stable) (push) Blocked by required conditions
CI / cpp_cmake (windows-2022, nightly) (push) Blocked by required conditions
CI / cpp_package_test (push) Blocked by required conditions
CI / vsce_build_test (push) Blocked by required conditions
CI / wasm_demo (push) Blocked by required conditions
CI / mcu (pico-st7789, thumbv6m-none-eabi) (push) Blocked by required conditions
CI / mcu (pico2-st7789, thumbv8m.main-none-eabihf) (push) Blocked by required conditions
CI / mcu (stm32h735g, thumbv7em-none-eabihf) (push) Blocked by required conditions
CI / mcu-embassy (push) Blocked by required conditions
CI / ffi_32bit_build (push) Blocked by required conditions
CI / docs (push) Blocked by required conditions
CI / wasm (push) Blocked by required conditions
CI / updater_test (0.3.0) (push) Blocked by required conditions
CI / fmt_test (push) Blocked by required conditions
CI / esp-idf-quick (push) Blocked by required conditions
CI / android (push) Blocked by required conditions
CI / miri (push) Blocked by required conditions
CI / test-figma-inspector (push) Blocked by required conditions
CI / material-components (push) Blocked by required conditions
133 lines
4.1 KiB
Text
133 lines
4.1 KiB
Text
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
export global AppState {
|
|
out property <int> totalLights: 35;
|
|
property <angle> degreesFilledWithLights: 360deg - (startAngle - endAngle);
|
|
out property <int> volume: (normalizeAngle(angle - startAngle) / degreesFilledWithLights) * (totalLights + 1);
|
|
out property <angle> startAngle: 120deg;
|
|
out property <angle> endAngle: 60deg;
|
|
out property <angle> angleGap: startAngle - endAngle;
|
|
in-out property <angle> angle: startAngle;
|
|
out property <length> elementRadius: 185px;
|
|
|
|
pure public function normalizeAngle(angle: angle) -> angle {
|
|
return (angle + 360deg).mod(360deg);
|
|
}
|
|
}
|
|
|
|
export component Light {
|
|
in property <int> index;
|
|
property <angle> gap: (360deg - (AppState.startAngle - AppState.endAngle)) / AppState.totalLights;
|
|
property <angle> angle: (index * gap) + AppState.startAngle;
|
|
property <bool> lightOn: index <= AppState.volume;
|
|
|
|
x: AppState.elementRadius * angle.cos();
|
|
y: AppState.elementRadius * angle.sin();
|
|
width: 0;
|
|
height: 0;
|
|
|
|
states [
|
|
lightOn when root.lightOn: {
|
|
blueLed.opacity: 0.6;
|
|
in {
|
|
animate blueLed.opacity {
|
|
duration: 100ms;
|
|
easing: ease-in-sine;
|
|
}
|
|
}
|
|
out {
|
|
animate blueLed.opacity {
|
|
duration: 600ms;
|
|
easing: ease-out-sine;
|
|
}
|
|
}
|
|
}
|
|
]
|
|
|
|
Image {
|
|
source: @image-url("images/light-hole.png");
|
|
}
|
|
|
|
blueLed := Image {
|
|
source: @image-url("images/light.png");
|
|
opacity: 0;
|
|
}
|
|
}
|
|
|
|
export component AppWindow inherits Window {
|
|
preferred-width: 500px;
|
|
preferred-height: 500px;
|
|
background: #1e1d27;
|
|
|
|
base := Image {
|
|
source: @image-url("images/dial-frame.png");
|
|
}
|
|
|
|
ta := TouchArea {
|
|
property <length> centerX: self.width / 2;
|
|
property <length> centerY: self.height / 2;
|
|
property <length> relativeX;
|
|
property <length> relativeY;
|
|
property <angle> lastAngle;
|
|
property <angle> nextAngle;
|
|
property <bool> hovering: Math.pow(relativeX / 1px, 2) + Math.pow(relativeY / 1px, 2) < metalKnob.width / 2px * metalKnob.height / 2px;
|
|
property <bool> touching: false;
|
|
width: base.width;
|
|
height: base.height;
|
|
|
|
mouse-cursor: touching ? move : hovering ? grab : default;
|
|
|
|
pointer-event(event) => {
|
|
relativeX = ta.mouse-x - centerX;
|
|
relativeY = ta.mouse-y - centerY;
|
|
let newAngle = AppState.normalizeAngle(atan2(relativeY / 1px, relativeX / 1px));
|
|
if event.kind == PointerEventKind.down {
|
|
if hovering {
|
|
touching = true;
|
|
lastAngle = newAngle;
|
|
}
|
|
} else if event.kind == PointerEventKind.up {
|
|
touching = false;
|
|
} else if event.kind == PointerEventKind.move {
|
|
if touching {
|
|
nextAngle = AppState.normalizeAngle(AppState.angle - lastAngle + newAngle);
|
|
// Check if the new angle is within the start and end angles
|
|
if nextAngle >= AppState.startAngle || nextAngle <= AppState.endAngle {
|
|
AppState.angle = nextAngle;
|
|
}
|
|
lastAngle = newAngle;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
metalKnob := Image {
|
|
source: @image-url("images/metal-dial.png");
|
|
transform-rotation: AppState.angle;
|
|
}
|
|
|
|
Image {
|
|
source: @image-url("images/metal-lights.png");
|
|
}
|
|
|
|
Image {
|
|
source: @image-url("images/dial-trim.png");
|
|
}
|
|
|
|
Rectangle {
|
|
x: parent.width / 2;
|
|
y: parent.height / 2;
|
|
|
|
Image {
|
|
property <float> r: 0.5;
|
|
x: r * root.width / 2 * AppState.angle.cos();
|
|
y: r * root.height / 2 * AppState.angle.sin();
|
|
source: @image-url("images/indicator.png");
|
|
}
|
|
|
|
for i in AppState.totalLights + 1: Light {
|
|
index: i;
|
|
}
|
|
}
|
|
}
|