From 7244831bb7f65350feed23161260e582d86fc3d2 Mon Sep 17 00:00:00 2001 From: zervo Date: Fri, 7 Nov 2025 14:04:55 +0100 Subject: [PATCH] Initial commit --- .cargo/config.toml | 12 + .gitignore | 21 + .vscode/extensions.json | 5 + .vscode/settings.json | 5 + Cargo.lock | 6069 +++++++++++++++++ Cargo.toml | 30 + LICENSE.txt | 9 + README.md | 7 + build.rs | 13 + index.html | 33 + material-1.0/LICENSE.md | 11 + material-1.0/README.md | 30 + material-1.0/material.slint | 66 + material-1.0/ui/components/app_bar.slint | 256 + material-1.0/ui/components/badge.slint | 36 + material-1.0/ui/components/base_button.slint | 72 + .../ui/components/base_navigation.slint | 51 + .../ui/components/bottom_app_bar.slint | 64 + material-1.0/ui/components/bottom_sheet.slint | 125 + material-1.0/ui/components/card.slint | 112 + material-1.0/ui/components/check_box.slint | 130 + material-1.0/ui/components/chip.slint | 205 + material-1.0/ui/components/date_picker.slint | 568 ++ material-1.0/ui/components/dialog.slint | 233 + material-1.0/ui/components/divider.slint | 28 + material-1.0/ui/components/drawer.slint | 89 + .../ui/components/drop_down_menu.slint | 125 + .../ui/components/elevated_button.slint | 45 + material-1.0/ui/components/elevation.slint | 108 + .../ui/components/extended_touch_area.slint | 57 + .../ui/components/filled_button.slint | 43 + .../ui/components/filled_icon_button.slint | 64 + .../components/floating_action_button.slint | 55 + material-1.0/ui/components/grid.slint | 10 + material-1.0/ui/components/horizontal.slint | 9 + material-1.0/ui/components/icon.slint | 11 + material-1.0/ui/components/icon_button.slint | 62 + material-1.0/ui/components/list.slint | 107 + material-1.0/ui/components/list_view.slint | 8 + .../ui/components/material_text.slint | 14 + .../ui/components/material_window.slint | 18 + material-1.0/ui/components/menu.slint | 136 + material-1.0/ui/components/modal.slint | 28 + .../ui/components/navigation_bar.slint | 150 + .../ui/components/navigation_drawer.slint | 211 + .../ui/components/navigation_rail.slint | 85 + .../ui/components/outline_button.slint | 42 + .../ui/components/outline_icon_button.slint | 78 + .../ui/components/progress_indicator.slint | 107 + material-1.0/ui/components/radio_button.slint | 99 + material-1.0/ui/components/scroll_view.slint | 166 + material-1.0/ui/components/search_bar.slint | 317 + .../ui/components/segmented_button.slint | 103 + material-1.0/ui/components/slider.slint | 136 + material-1.0/ui/components/snack_bar.slint | 88 + material-1.0/ui/components/state_layer.slint | 171 + material-1.0/ui/components/switch.slint | 151 + material-1.0/ui/components/tab_bar.slint | 210 + material-1.0/ui/components/text_button.slint | 33 + material-1.0/ui/components/text_field.slint | 209 + material-1.0/ui/components/time_picker.slint | 674 ++ material-1.0/ui/components/tonal_button.slint | 44 + .../ui/components/tonal_icon_button.slint | 63 + material-1.0/ui/components/tooltip.slint | 33 + material-1.0/ui/components/vertical.slint | 9 + material-1.0/ui/icons/account_box.svg | 1 + material-1.0/ui/icons/arrow_back.svg | 1 + material-1.0/ui/icons/arrow_drop_down.svg | 2 + material-1.0/ui/icons/arrow_drop_up.svg | 1 + material-1.0/ui/icons/arrow_right.svg | 1 + material-1.0/ui/icons/calendar_today.svg | 1 + material-1.0/ui/icons/check.svg | 1 + material-1.0/ui/icons/chevron_backward.svg | 1 + material-1.0/ui/icons/chevron_forward.svg | 1 + material-1.0/ui/icons/close.svg | 1 + material-1.0/ui/icons/cog.svg | 1 + material-1.0/ui/icons/edit.svg | 1 + material-1.0/ui/icons/home.svg | 1 + material-1.0/ui/icons/icons.slint | 27 + material-1.0/ui/icons/keyboard.svg | 1 + material-1.0/ui/icons/list_box.svg | 1 + material-1.0/ui/icons/menu.svg | 1 + material-1.0/ui/icons/package_variant.svg | 1 + material-1.0/ui/icons/remove.svg | 1 + material-1.0/ui/icons/schedule.svg | 1 + material-1.0/ui/icons/shape.svg | 1 + material-1.0/ui/items/list_item.slint | 12 + material-1.0/ui/items/menu_item.slint | 9 + material-1.0/ui/items/navigation_item.slint | 15 + .../ui/styling/material_animations.slint | 17 + .../ui/styling/material_palette.slint | 173 + .../ui/styling/material_schemes.slint | 59 + .../ui/styling/material_style_metrics.slint | 75 + .../ui/styling/material_typography.slint | 93 + src/lib.rs | 23 + src/main.rs | 6 + ui/home.slint | 19 + ui/main.slint | 61 + ui/slint-logo.svg | 4 + 99 files changed, 12973 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 build.rs create mode 100644 index.html create mode 100644 material-1.0/LICENSE.md create mode 100644 material-1.0/README.md create mode 100644 material-1.0/material.slint create mode 100644 material-1.0/ui/components/app_bar.slint create mode 100644 material-1.0/ui/components/badge.slint create mode 100644 material-1.0/ui/components/base_button.slint create mode 100644 material-1.0/ui/components/base_navigation.slint create mode 100644 material-1.0/ui/components/bottom_app_bar.slint create mode 100644 material-1.0/ui/components/bottom_sheet.slint create mode 100644 material-1.0/ui/components/card.slint create mode 100644 material-1.0/ui/components/check_box.slint create mode 100644 material-1.0/ui/components/chip.slint create mode 100644 material-1.0/ui/components/date_picker.slint create mode 100644 material-1.0/ui/components/dialog.slint create mode 100644 material-1.0/ui/components/divider.slint create mode 100644 material-1.0/ui/components/drawer.slint create mode 100644 material-1.0/ui/components/drop_down_menu.slint create mode 100644 material-1.0/ui/components/elevated_button.slint create mode 100644 material-1.0/ui/components/elevation.slint create mode 100644 material-1.0/ui/components/extended_touch_area.slint create mode 100644 material-1.0/ui/components/filled_button.slint create mode 100644 material-1.0/ui/components/filled_icon_button.slint create mode 100644 material-1.0/ui/components/floating_action_button.slint create mode 100644 material-1.0/ui/components/grid.slint create mode 100644 material-1.0/ui/components/horizontal.slint create mode 100644 material-1.0/ui/components/icon.slint create mode 100644 material-1.0/ui/components/icon_button.slint create mode 100644 material-1.0/ui/components/list.slint create mode 100644 material-1.0/ui/components/list_view.slint create mode 100644 material-1.0/ui/components/material_text.slint create mode 100644 material-1.0/ui/components/material_window.slint create mode 100644 material-1.0/ui/components/menu.slint create mode 100644 material-1.0/ui/components/modal.slint create mode 100644 material-1.0/ui/components/navigation_bar.slint create mode 100644 material-1.0/ui/components/navigation_drawer.slint create mode 100644 material-1.0/ui/components/navigation_rail.slint create mode 100644 material-1.0/ui/components/outline_button.slint create mode 100644 material-1.0/ui/components/outline_icon_button.slint create mode 100644 material-1.0/ui/components/progress_indicator.slint create mode 100644 material-1.0/ui/components/radio_button.slint create mode 100644 material-1.0/ui/components/scroll_view.slint create mode 100644 material-1.0/ui/components/search_bar.slint create mode 100644 material-1.0/ui/components/segmented_button.slint create mode 100644 material-1.0/ui/components/slider.slint create mode 100644 material-1.0/ui/components/snack_bar.slint create mode 100644 material-1.0/ui/components/state_layer.slint create mode 100644 material-1.0/ui/components/switch.slint create mode 100644 material-1.0/ui/components/tab_bar.slint create mode 100644 material-1.0/ui/components/text_button.slint create mode 100644 material-1.0/ui/components/text_field.slint create mode 100644 material-1.0/ui/components/time_picker.slint create mode 100644 material-1.0/ui/components/tonal_button.slint create mode 100644 material-1.0/ui/components/tonal_icon_button.slint create mode 100644 material-1.0/ui/components/tooltip.slint create mode 100644 material-1.0/ui/components/vertical.slint create mode 100644 material-1.0/ui/icons/account_box.svg create mode 100644 material-1.0/ui/icons/arrow_back.svg create mode 100644 material-1.0/ui/icons/arrow_drop_down.svg create mode 100644 material-1.0/ui/icons/arrow_drop_up.svg create mode 100644 material-1.0/ui/icons/arrow_right.svg create mode 100644 material-1.0/ui/icons/calendar_today.svg create mode 100644 material-1.0/ui/icons/check.svg create mode 100644 material-1.0/ui/icons/chevron_backward.svg create mode 100644 material-1.0/ui/icons/chevron_forward.svg create mode 100644 material-1.0/ui/icons/close.svg create mode 100644 material-1.0/ui/icons/cog.svg create mode 100644 material-1.0/ui/icons/edit.svg create mode 100644 material-1.0/ui/icons/home.svg create mode 100644 material-1.0/ui/icons/icons.slint create mode 100644 material-1.0/ui/icons/keyboard.svg create mode 100644 material-1.0/ui/icons/list_box.svg create mode 100644 material-1.0/ui/icons/menu.svg create mode 100644 material-1.0/ui/icons/package_variant.svg create mode 100644 material-1.0/ui/icons/remove.svg create mode 100644 material-1.0/ui/icons/schedule.svg create mode 100644 material-1.0/ui/icons/shape.svg create mode 100644 material-1.0/ui/items/list_item.slint create mode 100644 material-1.0/ui/items/menu_item.slint create mode 100644 material-1.0/ui/items/navigation_item.slint create mode 100644 material-1.0/ui/styling/material_animations.slint create mode 100644 material-1.0/ui/styling/material_palette.slint create mode 100644 material-1.0/ui/styling/material_schemes.slint create mode 100644 material-1.0/ui/styling/material_style_metrics.slint create mode 100644 material-1.0/ui/styling/material_typography.slint create mode 100644 src/lib.rs create mode 100644 src/main.rs create mode 100644 ui/home.slint create mode 100644 ui/main.slint create mode 100644 ui/slint-logo.svg diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..c971371 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,12 @@ +[target.x86_64-pc-windows-msvc] +# Increase default stack size to avoid running out of stack +# space in debug builds. The size matches Linux's default. +rustflags = [ + "-C", "link-arg=/STACK:8000000" +] +[target.aarch64-pc-windows-msvc] +# Increase default stack size to avoid running out of stack +# space in debug builds. The size matches Linux's default. +rustflags = [ + "-C", "link-arg=/STACK:8000000" +] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cfbeb4f --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +# Generated by cargo mutants +# Contains mutation testing data +**/mutants.out*/ + +# RustRover +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..8c44e99 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "Slint.slint" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..630d14d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "slint.libraryPaths": { + "material": "./material-1.0/material.slint" + } +} diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..a2f07a3 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,6069 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ab_glyph" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" + +[[package]] +name = "accesskit" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "553cd5f6b68b8c3dd07606447b91a12c044e8023d30decdc1554ecc313481d25" + +[[package]] +name = "accesskit_atspi_common" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe8f7e6cedea3731ad97d934cb85d89d930e34ade75a82aec3ec0adc9d834d0a" +dependencies = [ + "accesskit", + "accesskit_consumer", + "atspi-common", + "serde", + "thiserror 1.0.69", + "zvariant", +] + +[[package]] +name = "accesskit_consumer" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c964dad39d2e2d6977674abb9bf333a118a657dd5abb6d3b90ac44ab1f70951" +dependencies = [ + "accesskit", + "hashbrown 0.15.5", +] + +[[package]] +name = "accesskit_macos" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1aada7b0eec94ac456568d123ea32a4155cc7670c7d28c37d19843a4f00ba6" +dependencies = [ + "accesskit", + "accesskit_consumer", + "hashbrown 0.15.5", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "accesskit_unix" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31a205f8ef4ae2d1e1ad93cc616e27f93c471628787612ecaed565773bdfeb3c" +dependencies = [ + "accesskit", + "accesskit_atspi_common", + "async-channel", + "async-executor", + "async-task", + "atspi", + "futures-lite", + "futures-util", + "serde", + "zbus", +] + +[[package]] +name = "accesskit_windows" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b415603285ccd9db7a4c97bc4e4e450132e4dc5df639acc5aaa3b59cf607de5f" +dependencies = [ + "accesskit", + "accesskit_consumer", + "hashbrown 0.15.5", + "static_assertions", + "windows 0.61.3", + "windows-core 0.61.2", +] + +[[package]] +name = "accesskit_winit" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce4cc9d736f66d1b090a723a92e15336b06a095d6ad349b051ab04c3a2426432" +dependencies = [ + "accesskit", + "accesskit_macos", + "accesskit_unix", + "accesskit_windows", + "raw-window-handle", + "winit", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-activity" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" +dependencies = [ + "android-properties", + "bitflags 2.10.0", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk 0.8.0", + "ndk-context", + "ndk-sys 0.5.0+25.2.9519653", + "num_enum", + "thiserror 1.0.69", +] + +[[package]] +name = "android-activity" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +dependencies = [ + "android-properties", + "bitflags 2.10.0", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk 0.9.0", + "ndk-context", + "ndk-sys 0.6.0+11769913", + "num_enum", + "thiserror 1.0.69", +] + +[[package]] +name = "android-build" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cac4c64175d504608cf239756339c07f6384a476f97f20a7043f92920b0b8fd" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "android-properties" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 1.1.2", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "3.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 1.1.2", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-signal" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.1.2", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "atspi" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c83247582e7508838caf5f316c00791eee0e15c0bf743e6880585b867e16815c" +dependencies = [ + "atspi-common", + "atspi-connection", + "atspi-proxies", +] + +[[package]] +name = "atspi-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33dfc05e7cdf90988a197803bf24f5788f94f7c94a69efa95683e8ffe76cfdfb" +dependencies = [ + "enumflags2", + "serde", + "static_assertions", + "zbus", + "zbus-lockstep", + "zbus-lockstep-macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "atspi-connection" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4193d51303d8332304056ae0004714256b46b6635a5c556109b319c0d3784938" +dependencies = [ + "atspi-common", + "atspi-proxies", + "futures-lite", + "zbus", +] + +[[package]] +name = "atspi-proxies" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2eebcb9e7e76f26d0bcfd6f0295e1cd1e6f33bedbc5698a971db8dc43d7751c" +dependencies = [ + "atspi-common", + "serde", + "zbus", +] + +[[package]] +name = "auto_enums" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c170965892137a3a9aeb000b4524aa3cc022a310e709d848b6e1cdce4ab4781" +dependencies = [ + "derive_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom 8.0.0", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bincode" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" +dependencies = [ + "serde", + "unty", +] + +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags 2.10.0", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 2.1.1", + "shlex", + "syn", +] + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +dependencies = [ + "serde_core", +] + +[[package]] +name = "bitstream-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" + +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2 0.6.3", +] + +[[package]] +name = "blocking" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "borsh" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" +dependencies = [ + "cfg_aliases", +] + +[[package]] +name = "built" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + +[[package]] +name = "bytemuck" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "calloop" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.10.0", + "log", + "polling", + "rustix 0.38.44", + "slab", + "thiserror 1.0.69", +] + +[[package]] +name = "calloop" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e" +dependencies = [ + "bitflags 2.10.0", + "polling", + "rustix 1.1.2", + "slab", + "tracing", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +dependencies = [ + "calloop 0.13.0", + "rustix 0.38.44", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" +dependencies = [ + "calloop 0.14.3", + "rustix 1.1.2", + "wayland-backend", + "wayland-client", +] + +[[package]] +name = "cc" +version = "1.2.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom 7.1.3", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cgl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ced0551234e87afee12411d535648dd89d2e7f34c78b753395567aff3d447ff" +dependencies = [ + "libc", +] + +[[package]] +name = "chrono" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link 0.2.1", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading 0.8.9", +] + +[[package]] +name = "clipboard-win" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" +dependencies = [ + "error-code", +] + +[[package]] +name = "clru" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" + +[[package]] +name = "codemap" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e769b5c8c8283982a987c6e948e540254f1058d5a74b8794914d4ef5fc2a24" + +[[package]] +name = "codemap-diagnostic" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc20770be05b566a963bf91505e60412c4a2d016d1ef95c5512823bb085a8122" +dependencies = [ + "codemap", + "termcolor", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "const-field-offset" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91fcde4ca1211b5a94b573083c472ee19e86b19a441913f66e1cc5c41daf0255" +dependencies = [ + "const-field-offset-macro", + "field-offset", +] + +[[package]] +name = "const-field-offset-macro" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5387f5bbc9e9e6c96436ea125afa12614cebf8ac67f49abc08c1e7a891466c90" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "copypasta" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e6811e17f81fe246ef2bc553f76b6ee6ab41a694845df1d37e52a92b7bbd38a" +dependencies = [ + "clipboard-win", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "smithay-clipboard", + "x11-clipboard", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.10.1", + "core-graphics-types 0.2.0", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.10.1", + "libc", +] + +[[package]] +name = "core-text" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a593227b66cbd4007b2a050dfdd9e1d1318311409c8d600dc82ba1b15ca9c130" +dependencies = [ + "core-foundation 0.10.1", + "core-graphics 0.24.0", + "foreign-types", + "libc", +] + +[[package]] +name = "core_maths" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30" +dependencies = [ + "libm", +] + +[[package]] +name = "countme" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" + +[[package]] +name = "cpp" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bcac3d8234c1fb813358e83d1bb6b0290a3d2b3b5efc6b88bfeaf9d8eec17" +dependencies = [ + "cpp_macros", +] + +[[package]] +name = "cpp_build" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27f8638c97fbd79cc6fc80b616e0e74b49bac21014faed590bbc89b7e2676c90" +dependencies = [ + "cc", + "cpp_common", + "lazy_static", + "proc-macro2", + "regex", + "syn", + "unicode-xid", +] + +[[package]] +name = "cpp_common" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25fcfea2ee05889597d35e986c2ad0169694320ae5cc8f6d2640a4bb8a884560" +dependencies = [ + "lazy_static", + "proc-macro2", + "syn", +] + +[[package]] +name = "cpp_macros" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d156158fe86e274820f5a53bc9edb0885a6e7113909497aa8d883b69dd171871" +dependencies = [ + "aho-corasick", + "byteorder", + "cpp_common", + "lazy_static", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "ctor-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f791803201ab277ace03903de1594460708d2d54df6053f2d9e82f592b19e3b" + +[[package]] +name = "cursor-icon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" + +[[package]] +name = "data-url" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "derive_utils" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccfae181bab5ab6c5478b2ccb69e4c68a02f8c3ec72f6616bfec9dbc599d2ee0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading 0.8.9", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "drm" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f" +dependencies = [ + "bitflags 2.10.0", + "bytemuck", + "drm-ffi", + "drm-fourcc", + "libc", + "rustix 0.38.44", +] + +[[package]] +name = "drm-ffi" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e41459d99a9b529845f6d2c909eb9adf3b6d2f82635ae40be8de0601726e8b" +dependencies = [ + "drm-sys", + "rustix 0.38.44", +] + +[[package]] +name = "drm-fourcc" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" + +[[package]] +name = "drm-sys" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bafb66c8dbc944d69e15cfcc661df7e703beffbaec8bd63151368b06c5f9858c" +dependencies = [ + "libc", + "linux-raw-sys 0.6.5", +] + +[[package]] +name = "dwrote" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b35532432acc8b19ceed096e35dfa088d3ea037fe4f3c085f1f97f33b4d02" +dependencies = [ + "lazy_static", + "libc", + "serde", + "serde_derive", + "winapi", + "wio", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "error-code" +version = "3.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" + +[[package]] +name = "euclid" +version = "0.22.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +dependencies = [ + "num-traits", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "exr" +version = "1.73.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fax" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +dependencies = [ + "fax_derive", +] + +[[package]] +name = "fax_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "femtovg" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deda049f5a6dc3152b23263f72c575847f6aa0ace0045299d151f36af7aca136" +dependencies = [ + "bitflags 2.10.0", + "bytemuck", + "fnv", + "glow", + "image", + "imgref", + "log", + "lru", + "rgb", + "rustybuzz", + "slotmap", + "unicode-bidi", + "unicode-segmentation", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "filetime" +version = "0.2.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.60.2", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "fontconfig-parser" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" +dependencies = [ + "roxmltree", +] + +[[package]] +name = "fontdb" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser 0.25.1", +] + +[[package]] +name = "fontdue" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e57e16b3fe8ff4364c0661fdaac543fb38b29ea9bc9c2f45612d90adf931d2b" +dependencies = [ + "hashbrown 0.15.5", + "rayon", + "ttf-parser 0.21.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "gbm" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce852e998d3ca5e4a97014fb31c940dc5ef344ec7d364984525fd11e8a547e6a" +dependencies = [ + "bitflags 2.10.0", + "drm", + "drm-fourcc", + "gbm-sys", + "libc", +] + +[[package]] +name = "gbm-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13a5f2acc785d8fb6bf6b7ab6bfb0ef5dad4f4d97e8e70bb8e470722312f76f" +dependencies = [ + "libc", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix 1.1.2", + "windows-link 0.2.1", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "gif" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "glow" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e5ea60d70410161c8bf5da3fdfeaa1c72ed2c15f8bbb9d19fe3a4fad085f08" +dependencies = [ + "js-sys", + "slotmap", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "glutin" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12124de845cacfebedff80e877bb37b5b75c34c5a4c89e47e1cdd67fb6041325" +dependencies = [ + "bitflags 2.10.0", + "cfg_aliases", + "cgl", + "dispatch2", + "glutin_egl_sys", + "glutin_glx_sys", + "glutin_wgl_sys", + "libloading 0.8.9", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "once_cell", + "raw-window-handle", + "wayland-sys", + "windows-sys 0.52.0", + "x11-dl", +] + +[[package]] +name = "glutin-winit" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f" +dependencies = [ + "cfg_aliases", + "glutin", + "raw-window-handle", + "winit", +] + +[[package]] +name = "glutin_egl_sys" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2" +dependencies = [ + "gl_generator", + "windows-sys 0.52.0", +] + +[[package]] +name = "glutin_glx_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185" +dependencies = [ + "gl_generator", + "x11-dl", +] + +[[package]] +name = "glutin_wgl_sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" +dependencies = [ + "gl_generator", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", + "rayon", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "i-slint-backend-android-activity" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d13f3cc154a02e861e217e1b6c7e73cd5cc0ec6918be115e048d764961ed06" +dependencies = [ + "android-activity 0.5.2", + "android-activity 0.6.0", + "android-build", + "i-slint-core", + "i-slint-renderer-skia", + "jni", + "ndk 0.9.0", + "raw-window-handle", +] + +[[package]] +name = "i-slint-backend-linuxkms" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efe95e5c81a08027a03535d69aa025740275b11fb613abf555441ce074001119" +dependencies = [ + "bytemuck", + "calloop 0.14.3", + "drm", + "gbm", + "glutin", + "i-slint-common", + "i-slint-core", + "i-slint-renderer-femtovg", + "input", + "memmap2", + "nix", + "raw-window-handle", + "xkbcommon", +] + +[[package]] +name = "i-slint-backend-qt" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01922963d80f3e5ab38eec4cee7b8ae829b04d669fba9ffcd11e29a8397aed23" +dependencies = [ + "const-field-offset", + "cpp", + "cpp_build", + "i-slint-common", + "i-slint-core", + "i-slint-core-macros", + "lyon_path", + "pin-project", + "pin-weak", + "qttypes", + "vtable", +] + +[[package]] +name = "i-slint-backend-selector" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5c1525cd7a659b609600a7df79bb7d90092730d5c4de4f378f39ab9a023993" +dependencies = [ + "cfg-if", + "i-slint-backend-linuxkms", + "i-slint-backend-qt", + "i-slint-backend-winit", + "i-slint-common", + "i-slint-core", + "i-slint-core-macros", +] + +[[package]] +name = "i-slint-backend-winit" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba2a1f40bf70d4dfc5e7009673da72730ec32b4af680654975c6b39908bcd739" +dependencies = [ + "accesskit", + "accesskit_winit", + "bytemuck", + "cfg-if", + "cfg_aliases", + "copypasta", + "derive_more", + "futures", + "glutin", + "glutin-winit", + "i-slint-common", + "i-slint-core", + "i-slint-core-macros", + "i-slint-renderer-femtovg", + "i-slint-renderer-skia", + "imgref", + "lyon_path", + "muda", + "objc2-app-kit 0.3.2", + "pin-weak", + "raw-window-handle", + "rgb", + "scoped-tls-hkt", + "scopeguard", + "softbuffer", + "strum", + "vtable", + "wasm-bindgen", + "web-sys", + "windows 0.61.3", + "winit", + "zbus", +] + +[[package]] +name = "i-slint-common" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40862447fc6e177ab924f43fa2bcab4de3a10fe41596a2a2cb279c911f0ad5e9" +dependencies = [ + "cfg-if", + "derive_more", + "fontdb", + "libloading 0.8.9", + "ttf-parser 0.25.1", +] + +[[package]] +name = "i-slint-compiler" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7e35548ed4f437f7fcb7c2bb11bbd0f45c8271d1900b47b688e4eed89482d0" +dependencies = [ + "by_address", + "codemap", + "codemap-diagnostic", + "derive_more", + "fontdue", + "i-slint-common", + "image", + "itertools 0.14.0", + "linked_hash_set", + "lyon_extra", + "lyon_path", + "num_enum", + "polib", + "proc-macro2", + "quote", + "rayon", + "resvg", + "rowan", + "smol_str 0.3.2", + "strum", + "typed-index-collections", + "url", +] + +[[package]] +name = "i-slint-core" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68d10fc4c25a22e757784acf7da950223762477329f01d73e1c9cfa0749bf51a" +dependencies = [ + "auto_enums", + "bitflags 2.10.0", + "bytemuck", + "cfg-if", + "chrono", + "clru", + "const-field-offset", + "derive_more", + "euclid", + "fontdue", + "i-slint-common", + "i-slint-core-macros", + "image", + "integer-sqrt", + "lyon_algorithms", + "lyon_extra", + "lyon_geom", + "lyon_path", + "num-traits", + "once_cell", + "pin-project", + "pin-weak", + "portable-atomic", + "raw-window-handle", + "resvg", + "rgb", + "rustybuzz", + "scoped-tls-hkt", + "scopeguard", + "slab", + "strum", + "sys-locale", + "unicode-linebreak", + "unicode-script", + "unicode-segmentation", + "vtable", + "wasm-bindgen", + "web-sys", + "web-time", +] + +[[package]] +name = "i-slint-core-macros" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583ffd7589dc4e273cf25058b8f41fc8baeee40f28660b4539ee60f7ffc06c6b" +dependencies = [ + "quote", + "serde_json", + "syn", +] + +[[package]] +name = "i-slint-renderer-femtovg" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4ce7ca8b5316585f3db1ce902318c93980b09ab14aafc30846cad36da67acd" +dependencies = [ + "cfg-if", + "const-field-offset", + "core-foundation 0.10.1", + "core-text", + "derive_more", + "dwrote", + "femtovg", + "glow", + "i-slint-common", + "i-slint-core", + "i-slint-core-macros", + "imgref", + "lyon_path", + "pin-weak", + "rgb", + "scoped-tls-hkt", + "ttf-parser 0.25.1", + "unicode-script", + "unicode-segmentation", + "wasm-bindgen", + "web-sys", + "winapi", +] + +[[package]] +name = "i-slint-renderer-skia" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0848e46481abf3155d3aca7e4a9b07be5a5d55716cd90d891293e8698a07b679" +dependencies = [ + "bytemuck", + "cfg-if", + "cfg_aliases", + "const-field-offset", + "derive_more", + "glow", + "glutin", + "i-slint-common", + "i-slint-core", + "i-slint-core-macros", + "lyon_path", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", + "objc2-quartz-core 0.3.2", + "pin-weak", + "raw-window-handle", + "raw-window-metal", + "scoped-tls-hkt", + "skia-safe", + "softbuffer", + "unicode-segmentation", + "vtable", + "windows 0.58.0", + "windows 0.61.3", + "windows-core 0.58.0", + "windows-core 0.61.2", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image" +version = "0.25.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png 0.18.0", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imagesize" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285" + +[[package]] +name = "imgref" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" + +[[package]] +name = "indexmap" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +dependencies = [ + "equivalent", + "hashbrown 0.16.0", +] + +[[package]] +name = "input" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbdc09524a91f9cacd26f16734ff63d7dc650daffadd2b6f84d17a285bd875a9" +dependencies = [ + "bitflags 2.10.0", + "input-sys", + "libc", + "log", + "udev", +] + +[[package]] +name = "input-sys" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd4f5b4d1c00331c5245163aacfe5f20be75b564c7112d45893d4ae038119eb0" + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "java-locator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c46c1fe465c59b1474e665e85e1256c3893dd00927b8d55f63b09044c1e64f" +dependencies = [ + "glob", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "java-locator", + "jni-sys", + "libloading 0.7.4", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "keyboard-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.10.0", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "kurbo" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62026ae44756f8a599ba21140f350303d4f08dcdcc71b5ad9c9bb8128c13c62" +dependencies = [ + "arrayvec", + "euclid", + "smallvec", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5037190e1f70cbeef565bd267599242926f724d3b8a9f510fd7e0b540cfa4404" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link 0.2.1", +] + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags 2.10.0", + "libc", + "redox_syscall 0.5.18", +] + +[[package]] +name = "libudev-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "linereader" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d921fea6860357575519aca014c6e22470585accdd543b370c404a8a72d0dd1d" +dependencies = [ + "memchr", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linked_hash_set" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bae85b5be22d9843c80e5fc80e9b64c8a3b1f98f867c709956eca3efff4e92e2" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "lru" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" + +[[package]] +name = "lyon_algorithms" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c0829e28c4f336396f250d850c3987e16ce6db057ffe047ce0dd54aab6b647" +dependencies = [ + "lyon_path", + "num-traits", +] + +[[package]] +name = "lyon_extra" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ca94c7bf1e2557c2798989c43416822c12fc5dcc5e17cc3307ef0e71894a955" +dependencies = [ + "lyon_path", + "thiserror 1.0.69", +] + +[[package]] +name = "lyon_geom" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e16770d760c7848b0c1c2d209101e408207a65168109509f8483837a36cf2e7" +dependencies = [ + "arrayvec", + "euclid", + "num-traits", +] + +[[package]] +name = "lyon_path" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aeca86bcfd632a15984ba029b539ffb811e0a70bf55e814ef8b0f54f506fdeb" +dependencies = [ + "lyon_geom", + "num-traits", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "memmap2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "moxcms" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fbdd3d7436f8b5e892b8b7ea114271ff0fa00bc5acae845d53b07d498616ef6" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "muda" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a" +dependencies = [ + "crossbeam-channel", + "dpi", + "keyboard-types", + "objc2 0.6.3", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "once_cell", + "png 0.17.16", + "thiserror 2.0.17", + "windows-sys 0.60.2", +] + +[[package]] +name = "ndk" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +dependencies = [ + "bitflags 2.10.0", + "jni-sys", + "log", + "ndk-sys 0.5.0+25.2.9519653", + "num_enum", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.10.0", + "jni-sys", + "log", + "ndk-sys 0.6.0+11769913", + "num_enum", + "raw-window-handle", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_enum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.10.0", + "block2 0.6.2", + "libc", + "objc2 0.6.3", + "objc2-cloud-kit 0.3.2", + "objc2-core-data 0.3.2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image 0.3.2", + "objc2-core-text", + "objc2-core-video", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.10.0", + "dispatch2", + "objc2 0.6.3", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags 2.10.0", + "dispatch2", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-contacts", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-core-video" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-io-surface", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "dispatch", + "libc", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-metal" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-metal 0.2.2", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags 2.10.0", + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-metal 0.3.2", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-cloud-kit 0.2.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-core-location", + "objc2-foundation 0.2.2", + "objc2-link-presentation", + "objc2-quartz-core 0.2.2", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.10.0", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-core-location", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +dependencies = [ + "critical-section", + "portable-atomic", +] + +[[package]] +name = "orbclient" +version = "0.3.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "247ad146e19b9437f8604c21f8652423595cf710ad108af40e77d3ae6e96b827" +dependencies = [ + "libredox", +] + +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "owned_ttf_parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +dependencies = [ + "ttf-parser 0.25.1", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parts_rs" +version = "0.1.0" +dependencies = [ + "console_error_panic_hook", + "slint", + "slint-build", + "wasm-bindgen", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pin-weak" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b330c9d1b92dfe68442ca20b009c717d5f0b1e3cf4965e62f704c3c6e95a1305" + +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "png" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" +dependencies = [ + "bitflags 2.10.0", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "polib" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b393b155cf9be86249cba1b56cc81be0e6212c66d94ac0d76d37a1761f3bb1b" +dependencies = [ + "linereader", +] + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.5.2", + "pin-project-lite", + "rustix 1.1.2", + "windows-sys 0.61.2", +] + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +dependencies = [ + "critical-section", +] + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit 0.23.7", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "pxfm" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3cbdf373972bf78df4d3b518d07003938e2c7d1fb5891e55f9cb6df57009d84" +dependencies = [ + "num-traits", +] + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "qttypes" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7edf5b38c97ad8900ad2a8418ee44b4adceaa866a4a3405e2f1c909871d7ebd" +dependencies = [ + "cpp", + "cpp_build", + "semver", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "quick-xml" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools 0.12.1", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps", + "thiserror 1.0.69", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5825c26fddd16ab9f515930d49028a630efec172e903483c94796cfe31893e6b" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + +[[package]] +name = "raw-window-metal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" +dependencies = [ + "objc2 0.6.3", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "objc2-quartz-core 0.3.2", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "resvg" +version = "0.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8928798c0a55e03c9ca6c4c6846f76377427d2c1e1f7e6de3c06ae57942df43" +dependencies = [ + "gif", + "image-webp", + "log", + "pico-args", + "rgb", + "svgtypes", + "tiny-skia", + "usvg", + "zune-jpeg", +] + +[[package]] +name = "rgb" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "rowan" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "417a3a9f582e349834051b8a10c8d71ca88da4211e4093528e36b9845f6b5f21" +dependencies = [ + "countme", + "hashbrown 0.14.5", + "rustc-hash 1.1.0", + "text-size", +] + +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "rustybuzz" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702" +dependencies = [ + "bitflags 2.10.0", + "bytemuck", + "core_maths", + "log", + "smallvec", + "ttf-parser 0.25.1", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-properties", + "unicode-script", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scoped-tls-hkt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9603871ffe5df3ac39cb624790c296dbd47a400d202f56bf3e414045099524d" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sctk-adwaita" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit 0.19.2", + "tiny-skia", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +dependencies = [ + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "simplecss" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9c6883ca9c3c7c90e888de77b7a5c849c779d25d74a1269b0218b14e8b136c" +dependencies = [ + "log", +] + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + +[[package]] +name = "skia-bindings" +version = "0.87.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704242769235d2ffe66a2a0a3002661262fc4af08d32807c362d7b0160ee703c" +dependencies = [ + "bindgen", + "cc", + "flate2", + "heck", + "lazy_static", + "pkg-config", + "regex", + "serde_json", + "tar", + "toml", +] + +[[package]] +name = "skia-safe" +version = "0.87.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f7d94f3e7537c71ad4cf132eb26e3be8c8a886ed3649c4525c089041fc312b2" +dependencies = [ + "bitflags 2.10.0", + "lazy_static", + "skia-bindings", + "windows 0.61.3", +] + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "slint" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f467a64a49620e41807016dc1d519ba0ebb9d1322f734853059f93b8c3f3d2bd" +dependencies = [ + "const-field-offset", + "i-slint-backend-android-activity", + "i-slint-backend-qt", + "i-slint-backend-selector", + "i-slint-core", + "i-slint-core-macros", + "i-slint-renderer-femtovg", + "num-traits", + "once_cell", + "pin-weak", + "slint-macros", + "unicode-segmentation", + "vtable", +] + +[[package]] +name = "slint-build" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ea77b3786ae4e7549f924232a9d1ce427a320729334643a3ec1a76702d00d8" +dependencies = [ + "derive_more", + "i-slint-compiler", + "spin_on", + "toml_edit 0.23.7", +] + +[[package]] +name = "slint-macros" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e11f55a603d8bb037f0831d4f4e91a560cfe93d93ddf2f992aa375b620f4bca3" +dependencies = [ + "i-slint-compiler", + "proc-macro2", + "quote", + "spin_on", +] + +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "smithay-client-toolkit" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +dependencies = [ + "bitflags 2.10.0", + "calloop 0.13.0", + "calloop-wayland-source 0.3.0", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 0.38.44", + "thiserror 1.0.69", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-client-toolkit" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" +dependencies = [ + "bitflags 2.10.0", + "calloop 0.14.3", + "calloop-wayland-source 0.4.1", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix 1.1.2", + "thiserror 2.0.17", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-experimental", + "wayland-protocols-misc", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + +[[package]] +name = "smithay-clipboard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71704c03f739f7745053bde45fa203a46c58d25bc5c4efba1d9a60e9dba81226" +dependencies = [ + "libc", + "smithay-client-toolkit 0.20.0", + "wayland-backend", +] + +[[package]] +name = "smol_str" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +dependencies = [ + "serde", +] + +[[package]] +name = "smol_str" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9676b89cd56310a87b93dec47b11af744f34d5fc9f367b829474eec0a891350d" +dependencies = [ + "borsh", + "serde", +] + +[[package]] +name = "softbuffer" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" +dependencies = [ + "as-raw-xcb-connection", + "bytemuck", + "cfg_aliases", + "core-graphics 0.24.0", + "fastrand", + "foreign-types", + "js-sys", + "log", + "memmap2", + "objc2 0.5.2", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", + "raw-window-handle", + "redox_syscall 0.5.18", + "rustix 0.38.44", + "tiny-xlib", + "wasm-bindgen", + "wayland-backend", + "wayland-client", + "wayland-sys", + "web-sys", + "windows-sys 0.59.0", + "x11rb", +] + +[[package]] +name = "spin_on" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076e103ed41b9864aa838287efe5f4e3a7a0362dd00671ae62a212e5e4612da2" +dependencies = [ + "pin-utils", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +dependencies = [ + "float-cmp", +] + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "svgtypes" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c7541fff44b35860c1a7a47a7cadf3e4a304c457b58f9870d9706ece028afc" +dependencies = [ + "kurbo", + "siphasher", +] + +[[package]] +name = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "tar" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix 1.1.2", + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "text-size" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tiff" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "png 0.17.16", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + +[[package]] +name = "tiny-xlib" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0324504befd01cab6e0c994f34b2ffa257849ee019d3fb3b64fb2c858887d89e" +dependencies = [ + "as-raw-xcb-connection", + "ctor-lite", + "libloading 0.8.9", + "pkg-config", + "tracing", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime 0.6.11", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap", + "toml_datetime 0.7.3", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "toml_writer" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "ttf-parser" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" + +[[package]] +name = "ttf-parser" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" +dependencies = [ + "core_maths", +] + +[[package]] +name = "typed-index-collections" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fd393dbd1e7b23e0cab7396570309b4068aa504e9dac2cd41d827583b4e9ab7" +dependencies = [ + "bincode", + "serde", +] + +[[package]] +name = "udev" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af4e37e9ea4401fc841ff54b9ddfc9be1079b1e89434c1a6a865dd68980f7e9f" +dependencies = [ + "io-lifetimes", + "libc", + "libudev-sys", + "pkg-config", +] + +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-bidi-mirroring" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfa6e8c60bb66d49db113e0125ee8711b7647b5579dc7f5f19c42357ed039fe" + +[[package]] +name = "unicode-ccc" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce61d488bcdc9bc8b5d1772c404828b17fc481c0a582b5581e95fb233aef503e" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + +[[package]] +name = "unicode-script" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-vo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "usvg" +version = "0.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80be9b06fbae3b8b303400ab20778c80bbaf338f563afe567cf3c9eea17b47ef" +dependencies = [ + "base64", + "data-url", + "flate2", + "fontdb", + "imagesize", + "kurbo", + "log", + "pico-args", + "roxmltree", + "rustybuzz", + "simplecss", + "siphasher", + "strict-num", + "svgtypes", + "tiny-skia-path", + "unicode-bidi", + "unicode-script", + "unicode-vo", + "xmlwriter", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "vtable" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "753be81c38dff787d177b5939af1fa16f72f0d0d21a6b7d74ae56e29cd26f2a6" +dependencies = [ + "const-field-offset", + "portable-atomic", + "stable_deref_trait", + "vtable-macro", +] + +[[package]] +name = "vtable-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfcf6171aa2b0f85718ca5888ca32f6edf61d1849f8e4b3786ad890e5b68f68" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wayland-backend" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" +dependencies = [ + "cc", + "downcast-rs", + "rustix 1.1.2", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" +dependencies = [ + "bitflags 2.10.0", + "rustix 1.1.2", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.10.0", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29" +dependencies = [ + "rustix 1.1.2", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.32.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-experimental" +version = "20250721.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfe33d551eb8bffd03ff067a8b44bb963919157841a99957151299a6307d19c" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec" +dependencies = [ + "bitflags 2.10.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" +dependencies = [ + "proc-macro2", + "quick-xml 0.37.5", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" +dependencies = [ + "dlib", + "log", + "once_cell", + "pkg-config", +] + +[[package]] +name = "web-sys" +version = "0.3.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "weezl" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings 0.1.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winit" +version = "0.30.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" +dependencies = [ + "ahash", + "android-activity 0.6.0", + "atomic-waker", + "bitflags 2.10.0", + "block2 0.5.1", + "bytemuck", + "calloop 0.13.0", + "cfg_aliases", + "concurrent-queue", + "core-foundation 0.9.4", + "core-graphics 0.23.2", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "memmap2", + "ndk 0.9.0", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", + "objc2-ui-kit", + "orbclient", + "percent-encoding", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix 0.38.44", + "sctk-adwaita", + "smithay-client-toolkit 0.19.2", + "smol_str 0.2.2", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "x11-dl", + "x11rb", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + +[[package]] +name = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "x11-clipboard" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662d74b3d77e396b8e5beb00b9cad6a9eccf40b2ef68cc858784b14c41d535a3" +dependencies = [ + "libc", + "x11rb", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "as-raw-xcb-connection", + "gethostname", + "libc", + "libloading 0.8.9", + "once_cell", + "rustix 1.1.2", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix 1.1.2", +] + +[[package]] +name = "xcursor" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" + +[[package]] +name = "xkbcommon" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d66ca9352cbd4eecbbc40871d8a11b4ac8107cfc528a6e14d7c19c69d0e1ac9" +dependencies = [ + "libc", + "memmap2", + "xkeysym", +] + +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.10.0", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xml-rs" +version = "0.8.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" + +[[package]] +name = "xmlwriter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zbus" +version = "5.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b622b18155f7a93d1cd2dc8c01d2d6a44e08fb9ebb7b3f9e6ed101488bad6c91" +dependencies = [ + "async-broadcast", + "async-executor", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-lite", + "hex", + "nix", + "ordered-stream", + "serde", + "serde_repr", + "tracing", + "uds_windows", + "uuid", + "windows-sys 0.61.2", + "winnow", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus-lockstep" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e96e38ded30eeab90b6ba88cb888d70aef4e7489b6cd212c5e5b5ec38045b6" +dependencies = [ + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus-lockstep-macros" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6821851fa840b708b4cbbaf6241868cabc85a2dc22f426361b0292bfc0b836" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "zbus-lockstep", + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "5.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cdb94821ca8a87ca9c298b5d1cbd80e2a8b67115d99f6e4551ac49e42b6a314" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zbus_names", + "zvariant", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" +dependencies = [ + "serde", + "static_assertions", + "winnow", + "zvariant", +] + +[[package]] +name = "zbus_xml" +version = "5.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589e9a02bfafb9754bb2340a9e3b38f389772684c63d9637e76b1870377bec29" +dependencies = [ + "quick-xml 0.36.2", + "serde", + "static_assertions", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" +dependencies = [ + "zune-core", +] + +[[package]] +name = "zvariant" +version = "5.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2be61892e4f2b1772727be11630a62664a1826b62efa43a6fe7449521cb8744c" +dependencies = [ + "endi", + "enumflags2", + "serde", + "winnow", + "zvariant_derive", + "zvariant_utils", +] + +[[package]] +name = "zvariant_derive" +version = "5.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58575a1b2b20766513b1ec59d8e2e68db2745379f961f86650655e862d2006" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6949d142f89f6916deca2232cf26a8afacf2b9fdc35ce766105e104478be599" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn", + "winnow", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..6b018ba --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "parts_rs" +version = "0.1.0" +edition = "2024" + +[lib] +crate-type = ["lib", "cdylib"] +path = "src/lib.rs" +name = "parts_rs_lib" + +[[bin]] +path = "src/main.rs" +name = "parts_rs" + +[dependencies] +slint = { version = "1.13", features = ["backend-android-activity-06"] } + +[target.'cfg(target_arch = "wasm32")'.dependencies] +wasm-bindgen = { version = "0.2" } +console_error_panic_hook = "0.1.5" + +[build-dependencies] +slint-build = { version = "1.13" } + +[package.metadata.android] +package = "org.zervo.partsrs" +apk_name = "parts_rs" + +[package.metadata.android.application] +label = "PartsRS" diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..2071b23 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..47126e2 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# PartsRS + +PartsRS is a simple desktop parts management / inventory tracking system intended for use by hobbyists and smaller companies. + +It is designed for tracking inventory of electronic components but can probably be used for other stuff as well. + +NOTE: Early WIP, does not work yet. \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..913e5da --- /dev/null +++ b/build.rs @@ -0,0 +1,13 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +fn main() { + let config = slint_build::CompilerConfiguration::new().with_library_paths( + std::collections::HashMap::from([( + "material".to_string(), + std::path::Path::new(&std::env::var_os("CARGO_MANIFEST_DIR").unwrap()) + .join("material-1.0/material.slint"), + )]), + ); + slint_build::compile_with_config("ui/main.slint", config).unwrap(); +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..7d5a6b5 --- /dev/null +++ b/index.html @@ -0,0 +1,33 @@ + + + + + PartsRS + + + + + + + + + diff --git a/material-1.0/LICENSE.md b/material-1.0/LICENSE.md new file mode 100644 index 0000000..49468b5 --- /dev/null +++ b/material-1.0/LICENSE.md @@ -0,0 +1,11 @@ + + +MIT License + +Copyright (c) 2025 SixtyFPS GmbH + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/material-1.0/README.md b/material-1.0/README.md new file mode 100644 index 0000000..9d2fe19 --- /dev/null +++ b/material-1.0/README.md @@ -0,0 +1,30 @@ + + +# Material Design 3 component set for Slint + +[![Gallery image](https://material.slint.dev/tablet-material.webp)](examples/gallery) + +Welcome to the official Material Design 3 component set for [Slint](https://slint.dev). These UI components adhere to [Material Design 3 guidelines](https://m3.material.io/). +The components are intended to use for development of user interfaces with Slint for Android apps, touch friendly interfaces for embedded devices and even for desktop application development. +Contributions and feedback from the community are welcome. + + +## Demos + +[WebAssembly build in the web browser](https://material.slint.dev/wasm/) + +Download and install the [APK for android](https://material.slint.dev/apk/slint_material.apk) + +## Documentation + +View the documentation online at https://material.slint.dev/getting-started/ + +### Get Started + +Clone one of our Material Components for Slint templates and follow the instruction from their README: + + - Rust: https://github.com/slint-ui/material-rust-template + - C++: https://github.com/slint-ui/material-cpp-template + - Node.js/Deno: https://github.com/slint-ui/material-nodejs-template + - Python: https://github.com/slint-ui/material-python-template + diff --git a/material-1.0/material.slint b/material-1.0/material.slint new file mode 100644 index 0000000..4b5316f --- /dev/null +++ b/material-1.0/material.slint @@ -0,0 +1,66 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +// components +export { AppBar, SmallAppBar, MediumAppBar, LargeAppBar } from "./ui/components/app_bar.slint"; +export { Badge } from "./ui/components/badge.slint"; +export { BottomAppBar } from "./ui/components/bottom_app_bar.slint"; +export { CheckState, CheckBox, CheckBoxTile } from "./ui/components/check_box.slint"; +export { ActionChip, FilterChip, InputChip } from "./ui/components/chip.slint"; +export { DatePickerPopup, DatePickerAdapter } from "./ui/components/date_picker.slint"; +export { Dialog, FullscreenDialog } from "./ui/components/dialog.slint"; +export { Drawer, ModalDrawer } from "./ui/components/drawer.slint"; +export { DropDownMenu } from "./ui/components/drop_down_menu.slint"; +export { VerticalDivider, HorizontalDivider } from "./ui/components/divider.slint"; +export { ModalBottomSheet } from "./ui/components/bottom_sheet.slint"; +export { ElevatedCard, FilledCard, OutlinedCard } from "./ui/components/card.slint"; +export { ElevatedButton } from "./ui/components/elevated_button.slint"; +export { Elevation } from "./ui/components/elevation.slint"; +export { ExtendedTouchArea } from "./ui/components/extended_touch_area.slint"; +export { FilledButton } from "./ui/components/filled_button.slint"; +export { FilledIconButton } from "./ui/components/filled_icon_button.slint"; +export { FloatingActionButton, FABStyle } from "./ui/components/floating_action_button.slint"; +export { Grid } from "./ui/components/grid.slint"; +export { Horizontal } from "./ui/components/horizontal.slint"; +export { Icon } from "./ui/components/icon.slint"; +export { IconButton } from "./ui/components/icon_button.slint"; +export { OutlineButton } from "./ui/components/outline_button.slint"; +export { OutlineIconButton } from "./ui/components/outline_icon_button.slint"; +export { Avatar, ListTile } from "./ui/components/list.slint"; +export { ListView } from "./ui/components/list_view.slint"; +export { MaterialText } from "./ui/components/material_text.slint"; +export { MaterialWindow, MaterialWindowAdapter } from "./ui/components/material_window.slint"; +export { PopupMenu } from "./ui/components/menu.slint"; +export { NavigationBar } from "./ui/components/navigation_bar.slint"; +export { NavigationDrawer, ModalNavigationDrawer } from "./ui/components/navigation_drawer.slint"; +export { NavigationRail } from "./ui/components/navigation_rail.slint"; +export { CircularProgressIndicator, LinearProgressIndicator } from "./ui/components/progress_indicator.slint"; +export { RadioButton, RadioButtonTile } from "./ui/components/radio_button.slint"; +export { SearchBar } from "./ui/components/search_bar.slint"; +export { ScrollView } from "./ui/components/scroll_view.slint"; +export { Slider } from "./ui/components/slider.slint"; +export { SnackBar } from "./ui/components/snack_bar.slint"; +export { StateLayerArea, StateLayer, Ripple } from "./ui/components/state_layer.slint"; +export { SegmentedButton } from "./ui/components/segmented_button.slint"; +export { Switch } from "./ui/components/switch.slint"; +export { TabBar, SecondaryTabBar } from "./ui/components/tab_bar.slint"; +export { TextButton } from "./ui/components/text_button.slint"; +export { TextField } from "./ui/components/text_field.slint"; +export { TimePickerPopup, Time } from "./ui/components/time_picker.slint"; +export { TonalButton } from "./ui/components/tonal_button.slint"; +export { TonalIconButton } from "./ui/components/tonal_icon_button.slint"; +export { ToolTip } from "./ui/components/tooltip.slint"; +export { Vertical } from "./ui/components/vertical.slint"; +export { Modal } from "./ui/components/modal.slint"; + +// items +export { ListItem } from "./ui/items/list_item.slint"; +export { NavigationItem, NavigationGroup } from "./ui/items/navigation_item.slint"; +export { MenuItem } from "./ui/items/menu_item.slint"; + +// styles +export { MaterialAnimations } from "./ui/styling/material_animations.slint"; +export { MaterialScheme, MaterialSchemes } from "./ui/styling/material_schemes.slint"; +export { MaterialStyleMetrics } from "./ui/styling/material_style_metrics.slint"; +export { MaterialPalette } from "./ui/styling/material_palette.slint"; +export { MaterialTypography } from "./ui/styling/material_typography.slint"; diff --git a/material-1.0/ui/components/app_bar.slint b/material-1.0/ui/components/app_bar.slint new file mode 100644 index 0000000..774e15e --- /dev/null +++ b/material-1.0/ui/components/app_bar.slint @@ -0,0 +1,256 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { IconButton } from "./icon_button.slint"; +import { MaterialText } from "./material_text.slint"; +import { MaterialTypography, TextStyle } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { IconButtonItem } from "./bottom_app_bar.slint"; + +component BaseAppBar { + in property title; + in property leading_button; + in property show_background; + in property <[IconButtonItem]> trailing_buttons; + in property horizontal_alignment; + in property spacing; + in property vertical_spacing; + in property two_rows; + in property text_style; + in property text_padding; + in property appbar_padding_right: 0; + in property appbar_padding_top: 0; + in property appbar_padding_bottom: 0; + + callback leading_button_clicked(); + callback trailing_button_clicked(index: int); + + min_width: layout.min_width; + min_height: layout.min_height; + + Rectangle { + background: root.show_background ? MaterialPalette.surface_container : MaterialPalette.surface; + + layout := VerticalLayout { + padding_top: root.appbar_padding_top; + padding_bottom: root.appbar_padding_bottom; + min_width: top_layout.min_width; + spacing: root.vertical_spacing; + + top_layout := HorizontalLayout { + padding_left: root.spacing; + padding_right: root.appbar_padding_right; + spacing: MaterialStyleMetrics.spacing_6; + + if root.leading_button.icon.width > 0 && root.leading_button.icon.height > 0 : VerticalLayout { + alignment: center; + + IconButton { + icon: root.leading_button.icon; + enabled: root.leading_button.enabled; + tooltip: root.leading_button.tooltip; + + clicked => { + root.leading_button_clicked(); + } + } + } + + if !root.two_rows : MaterialText { + horizontal_stretch: 1; + text: root.title; + vertical_alignment: center; + horizontal_alignment: root.horizontal_alignment; + color: MaterialPalette.on_surface; + overflow: elide; + style: root.text_style; + } + + // spacer + if root.two_rows : Rectangle { + horizontal_stretch: 1; + } + + if root.trailing_buttons.length > 0 : VerticalLayout { + alignment: center; + + HorizontalLayout { + spacing: top_layout.spacing; + + for item[index] in root.trailing_buttons : IconButton { + icon: item.icon; + enabled: item.enabled; + tooltip: item.tooltip; + + clicked => { + root.trailing_button_clicked(index); + } + } + } + } + } + + if root.two_rows && root.title != "" : HorizontalLayout { + padding_left: root.text_padding; + padding_right: self.padding_left; + + MaterialText { + text: root.title; + horizontal_alignment: root.horizontal_alignment; + color: MaterialPalette.on_surface; + overflow: elide; + style: root.text_style; + } + } + } + } +} + +export component AppBar { + in property title; + in property leading_button; + in property trailing_button; + in property show_background; + + callback leading_button_clicked(); + callback trailing_button_clicked(); + + min_height: max(MaterialStyleMetrics.size_64, base.min_height); + + HorizontalLayout { + base := BaseAppBar { + title: root.title; + horizontal_alignment: center; + + leading_button: root.leading_button; + trailing_buttons: [root.trailing_button]; + show_background: root.show_background; + + appbar_padding_right: self.padding_left; + appbar_padding_top: MaterialStyleMetrics.padding_8; + appbar_padding_bottom: self.padding_top; + spacing: MaterialStyleMetrics.spacing_6; + text_style: MaterialTypography.title_large; + + leading_button_clicked => { + root.leading_button_clicked(); + } + + trailing_button_clicked(index) => { + root.trailing_button_clicked(); + } + } + } +} + +export component SmallAppBar { + in property title; + in property leading_button; + in property <[IconButtonItem]> trailing_buttons; + in property show_background; + + callback leading_button_clicked(); + callback trailing_button_clicked(index: int); + + min_height: max(MaterialStyleMetrics.size_64, base.min_height); + + HorizontalLayout { + base := BaseAppBar { + title: root.title; + horizontal_alignment: left; + leading_button: root.leading_button; + trailing_buttons: root.trailing_buttons; + show_background: root.show_background; + appbar_padding_right: self.padding_left; + appbar_padding_top: MaterialStyleMetrics.padding_8; + appbar_padding_bottom: self.padding_top; + spacing: MaterialStyleMetrics.spacing_4; + text_style: MaterialTypography.title_large; + + leading_button_clicked => { + root.leading_button_clicked(); + } + + trailing_button_clicked(index) => { + root.trailing_button_clicked(index); + } + } + } +} + +export component MediumAppBar { + in property title; + in property leading_button; + in property <[IconButtonItem]> trailing_buttons; + in property show_background; + + callback leading_button_clicked(); + callback trailing_button_clicked(index: int); + + min_height: max(MaterialStyleMetrics.size_64, base.min_height); + + HorizontalLayout { + base := BaseAppBar { + title: root.title; + horizontal_alignment: left; + leading_button: root.leading_button; + trailing_buttons: root.trailing_buttons; + show_background: root.show_background; + appbar_padding_right: self.padding_left; + appbar_padding_top: MaterialStyleMetrics.padding_8; + appbar_padding_bottom: MaterialStyleMetrics.padding_24; + vertical_spacing: MaterialStyleMetrics.spacing_4; + spacing: MaterialStyleMetrics.spacing_4; + two_rows: true; + text_style: MaterialTypography.headline_small; + text_padding: MaterialStyleMetrics.padding_16; + + leading_button_clicked => { + root.leading_button_clicked(); + } + + trailing_button_clicked(index) => { + root.trailing_button_clicked(index); + } + } + } +} + +export component LargeAppBar { + in property title; + in property leading_button; + in property <[IconButtonItem]> trailing_buttons; + in property show_background; + + callback leading_button_clicked(); + callback trailing_button_clicked(index: int); + + min_height: max(MaterialStyleMetrics.size_64, base.min_height); + + HorizontalLayout { + base := BaseAppBar { + title: root.title; + horizontal_alignment: left; + leading_button: root.leading_button; + trailing_buttons: root.trailing_buttons; + show_background: root.show_background; + appbar_padding_right: self.padding_left; + appbar_padding_top: MaterialStyleMetrics.padding_8; + appbar_padding_bottom: MaterialStyleMetrics.padding_28; + vertical_spacing: MaterialStyleMetrics.spacing_40; + spacing: MaterialStyleMetrics.spacing_4; + two_rows: true; + text_style: MaterialTypography.headline_medium; + text_padding: MaterialStyleMetrics.padding_16; + + leading_button_clicked => { + root.leading_button_clicked(); + } + + trailing_button_clicked(index) => { + root.trailing_button_clicked(index); + } + } + } +} diff --git a/material-1.0/ui/components/badge.slint b/material-1.0/ui/components/badge.slint new file mode 100644 index 0000000..eacae3e --- /dev/null +++ b/material-1.0/ui/components/badge.slint @@ -0,0 +1,36 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialText } from "material_text.slint"; + +export component Badge { + in property text; + + width: max(MaterialStyleMetrics.size_16, label.width + 2 * MaterialStyleMetrics.padding_4); + height: max(MaterialStyleMetrics.size_16, label.height); + + background_layer := Rectangle { + width: parent.width; + height: parent.height; + border_radius: self.height / 2; + background: MaterialPalette.error; + } + + label := MaterialText { + text: root.text; + color: MaterialPalette.on_error; + vertical_alignment: center; + horizontal_alignment: center; + style: MaterialTypography.label_small; + } + + states [ + small when root.text == "" : { + background_layer.width: MaterialStyleMetrics.size_6; + background_layer.height: MaterialStyleMetrics.size_6; + } + ] +} diff --git a/material-1.0/ui/components/base_button.slint b/material-1.0/ui/components/base_button.slint new file mode 100644 index 0000000..950e734 --- /dev/null +++ b/material-1.0/ui/components/base_button.slint @@ -0,0 +1,72 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { StateLayerArea } from "./state_layer.slint"; +import { MaterialText } from "./material_text.slint"; +import { Icon } from "./icon.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { Avatar } from "./list.slint"; + +export component BaseButton inherits StateLayerArea { + in property icon; + in property icon_color: self.color; + in property text; + in property button_horizontal_padding: MaterialStyleMetrics.padding_24; + in property button_vertical_padding: MaterialStyleMetrics.padding_10; + in property button_padding_left: self.button_horizontal_padding; + in property button_padding_right: self.button_horizontal_padding; + in property button_padding_top: self.button_vertical_padding; + in property button_padding_bottom: self.button_vertical_padding; + in property spacing: MaterialStyleMetrics.spacing_8; + in property min_layout_width: MaterialStyleMetrics.size_40; + in property min_layout_height: MaterialStyleMetrics.size_40; + in property icon_size: MaterialStyleMetrics.icon_size_18; + in property avatar_icon; + in property avatar_size; + in property avatar_background: #00000000; + out property has_icon: root.icon.width > 0 && root.icon.height > 0; + out property has_avatar: root.avatar_icon.width > 0 && root.avatar_icon.height > 0; + + min_width: max(root.min_layout_width, layout.min_width); + min_height: max(root.min_layout_height, layout.min_height); + tooltip_offset: root.height / 2 + root.icon_size / 2 + MaterialStyleMetrics.padding_14; + + layout := HorizontalLayout { + padding_left: root.button_padding_left; + padding_right: root.button_padding_right; + padding_top: root.button_padding_top; + padding_bottom: root.button_padding_bottom; + spacing: root.spacing; + alignment: center; + + if root.has_icon || root.has_avatar : VerticalLayout { + alignment: center; + + if root.has_avatar && root.avatar_size > 0 : Avatar { + width: root.avatar_size; + height: self.width; + image: root.avatar_icon; + background: root.avatar_background; + } + + if root.has_icon : Icon { + source: root.icon; + colorize: root.icon_color; + opacity: root.enabled ? 100% : 38%; + width: root.icon_size; + } + } + + if root.text != "" : MaterialText { + text: root.text; + style: MaterialTypography.label_large; + color: root.color; + opacity: root.enabled ? 100% : 38%; + overflow: clip; + vertical_alignment: center; + } + + @children + } +} diff --git a/material-1.0/ui/components/base_navigation.slint b/material-1.0/ui/components/base_navigation.slint new file mode 100644 index 0000000..a8a4100 --- /dev/null +++ b/material-1.0/ui/components/base_navigation.slint @@ -0,0 +1,51 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { NavigationItem } from "../items/navigation_item.slint"; + +export component BaseNavigationItemTemplate { + in property icon; + in property selected_icon; + in property text; + in property index; + in property selected; + in property show_badge; + in property badge; + + callback clicked; + callback pointer_event(event: PointerEvent, position: Point); + + accessible-role: tab; + accessible-label: root.text; + accessible-item-index: root.index; + accessible-item-selectable: true; + accessible-item-selected: root.selected; + accessible-action-default => { self.clicked(); } + + @children + +} + +export component BaseNavigation { + in property <[NavigationItem]> items; + in_out property current_index; + + callback index_changed(index: int); + + accessible-role: tab-list; + // accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-index; + // accessible-label: root.title; + accessible-item-count: root.items.length; + + @children + + protected function select(index: int) { + if index < 0 || index >= root.items.length { + return; + } + + root.current_index = index; + root.index_changed(index); + } + +} diff --git a/material-1.0/ui/components/bottom_app_bar.slint b/material-1.0/ui/components/bottom_app_bar.slint new file mode 100644 index 0000000..daea6ac --- /dev/null +++ b/material-1.0/ui/components/bottom_app_bar.slint @@ -0,0 +1,64 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { IconButton } from "./icon_button.slint"; +import { FloatingActionButton, FABStyle } from "./floating_action_button.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; + +export struct IconButtonItem { + icon: image, + tooltip: string, + enabled: bool +} + +export component BottomAppBar { + in property <[IconButtonItem]> icon_buttons; + in property fab_icon; + + callback fab_clicked(); + callback icon_button_clicked(index: int); + + min_height: max(MaterialStyleMetrics.size_80, layout.min_height); + + Rectangle { + background: MaterialPalette.surface_container; + + layout := HorizontalLayout { + padding_left: MaterialStyleMetrics.padding_4; + padding_right: MaterialStyleMetrics.padding_16; + + VerticalLayout { + alignment: center; + + HorizontalLayout { + for button[index] in root.icon_buttons : IconButton { + icon: button.icon; + enabled: button.enabled; + tooltip: button.tooltip; + + clicked => { + root.icon_button_clicked(index); + } + } + } + } + + // spacer + Rectangle {} + + if root.fab_icon.width > 0 && root.fab_icon.height > 0 : VerticalLayout { + alignment: center; + + FloatingActionButton { + icon: root.fab_icon; + style: FABStyle.standard; + + clicked => { + root.fab_clicked(); + } + } + } + } + } +} diff --git a/material-1.0/ui/components/bottom_sheet.slint b/material-1.0/ui/components/bottom_sheet.slint new file mode 100644 index 0000000..0883352 --- /dev/null +++ b/material-1.0/ui/components/bottom_sheet.slint @@ -0,0 +1,125 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { Elevation } from "./elevation.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { Horizontal } from "./horizontal.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; +import { Modal } from "./modal.slint"; + +component BottomSheet { + callback drag_moved(offset_y: length); + callback pressed(); + callback released(); + + elevation := Elevation { + width: 100%; + height: 100%; + level: 3; + border_radius: MaterialStyleMetrics.border_radius_16; + } + + TouchArea { + Rectangle { + background: MaterialPalette.surface_container_low; + border_top_left_radius: MaterialStyleMetrics.border_radius_16; + border_top_right_radius: self.border_top_left_radius; + + VerticalLayout { + alignment: start; + + drag_handle := TouchArea { + height: MaterialStyleMetrics.size_36; + + Rectangle { + width: MaterialStyleMetrics.size_32; + height: MaterialStyleMetrics.size_4; + background: MaterialPalette.outline; + border_radius: self.height / 2; + } + + moved => { + root.drag_moved(self.pressed_y - self.mouse_y); + } + + changed pressed => { + if self.pressed { + root.pressed(); + return; + } + + root.released(); + } + } + + Horizontal { + @children + } + } + } + } +} + +export component ModalBottomSheet inherits PopupWindow { + close_policy: no_auto_close; + + property drag_margin: MaterialStyleMetrics.padding_56; + + modal := Modal { + width: 100%; + height: 100%; + + sheet := BottomSheet { + property y_duration: MaterialAnimations.standard_accelerate_duration; + property y_drag_start; + property height_drag_start; + + x: (parent.width - self.width) / 2; + y: parent.height; + width: min(MaterialStyleMetrics.size_640, parent.width - 2 * MaterialStyleMetrics.padding_56); + + @children + + drag_moved(offset_y) => { + self.y_duration = 0; + self.y = max(self.y - offset_y, self.y_drag_start); + self.height += offset_y; + } + + pressed => { + self.y_drag_start = self.y; + self.height_drag_start = self.height; + } + + released => { + if self.y >= root.height - root.drag_margin { + root.close(); + return; + } + + self.y_duration = MaterialAnimations.standard_accelerate_duration; + self.height = self.height_drag_start; + self.y = self.y_drag_start; + } + + animate y, height { + duration: self.y_duration; + easing: MaterialAnimations.standard_easing; + } + } + + clicked => { + root.close(); + } + } + + Timer { + interval: 50ms; + + triggered => { + sheet.y = modal.height - sheet.height; + self.running = false; + } + } +} diff --git a/material-1.0/ui/components/card.slint b/material-1.0/ui/components/card.slint new file mode 100644 index 0000000..6afebef --- /dev/null +++ b/material-1.0/ui/components/card.slint @@ -0,0 +1,112 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { Elevation } from "./elevation.slint"; +import { StateLayerArea } from "./state_layer.slint"; + +component BaseCard { + in property clickable; + in property has_elevation; + in property background; + in property border_color; + in property border_width; + + callback clicked(); + + forward_focus: state_layer; + + if root.has_elevation : Elevation { + width: 100%; + height: 100%; + border_radius: background_layer.border_radius; + level: 1; + } + + background_layer := Rectangle { + background: root.background; + border_radius: MaterialStyleMetrics.border_radius_12; + border_width: root.border_width; + border_color: root.border_color; + } + + state_layer := StateLayerArea { + width: 100%; + height: 100%; + border_radius: background_layer.border_radius; + visible: root.clickable; + enabled: root.visible; + + clicked => { + root.clicked(); + } + } + + Rectangle { + clip: true; + border_radius: MaterialStyleMetrics.border_radius_12; + + @children + } +} + +export component ElevatedCard { + in property clickable <=> base.clickable; + + callback clicked <=> base.clicked; + + forward_focus: base; + accessible-role: button; + accessible-enabled: root.clickable; + accessible-action-default => { base.clicked(); } + + base := BaseCard { + width: 100%; + height: 100%; + has_elevation: true; + background: MaterialPalette.surface; + + @children + } +} + +export component FilledCard { + in property clickable <=> base.clickable; + + callback clicked <=> base.clicked; + + forward_focus: base; + accessible-role: button; + accessible-enabled: root.clickable; + accessible-action-default => { base.clicked(); } + + base := BaseCard { + width: 100%; + height: 100%; + background: MaterialPalette.surface_container_highest; + + @children + } +} + +export component OutlinedCard { + in property clickable <=> base.clickable; + + callback clicked <=> base.clicked; + + forward_focus: base; + accessible-role: button; + accessible-enabled: root.clickable; + accessible-action-default => { base.clicked(); } + + base := BaseCard { + width: 100%; + height: 100%; + background: MaterialPalette.surface_container_low; + border_width: 1px; + border_color: MaterialPalette.outline; + + @children + } +} diff --git a/material-1.0/ui/components/check_box.slint b/material-1.0/ui/components/check_box.slint new file mode 100644 index 0000000..227a1db --- /dev/null +++ b/material-1.0/ui/components/check_box.slint @@ -0,0 +1,130 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; +import { Icons } from "../icons/icons.slint"; +import { ListTile } from "./list.slint"; +import { StateLayerArea } from "./state_layer.slint"; +import { Icon } from "./icon.slint"; + +export enum CheckState { + unchecked, + partially_checked, + checked, +} + +export component CheckBox { + + in_out property check_state; + in_out property tristate; + in property has_error; + in property enabled <=> state_area.enabled; + + property checked: root.check_state == CheckState.checked || root.check_state == CheckState.partially_checked; + + callback checked_state_changed(check_state: CheckState); + + min_width: MaterialStyleMetrics.size_48; + min_height: self.min_width; + accessible-enabled: root.enabled; + accessible-checkable: true; + accessible-checked <=> root.checked; + accessible-role: checkbox; + accessible-action-default => { state_area.clicked(); } + forward_focus: state_area; + + state_area := StateLayerArea { + width: 100%; + height: 100%; + border_radius: max(self.width, self.height) / 2; + color: MaterialPalette.on_surface; + + background_layer := Rectangle { + width: MaterialStyleMetrics.size_18; + height: self.width; + border_radius: MaterialStyleMetrics.border_radius_2; + border_width: root.checked ? 0 : 2px; + border_color: root.has_error ? MaterialPalette.error : MaterialPalette.on_surface_variant; + + if root.checked : Icon { + colorize: MaterialPalette.on_primary; + source: Icons.check; + + states [ + partial_checked when root.check_state == CheckState.partially-checked : { + source: Icons.remove; + } + ] + } + + animate background, border_width { + duration: MaterialAnimations.opacity_duration; + easing: MaterialAnimations.opacity_easing; + } + } + + clicked => { + root.toggle(); + } + } + + changed check_state => { + root.checked_state_changed(root.check_state); + } + + public function toggle() { + if !root.tristate { + root.check_state = root.check_state != CheckState.checked ? CheckState.checked : CheckState.unchecked; + return; + } + + root.check_state = root.check_state == CheckState.checked ? CheckState.partially_checked : + root.check_state == CheckState.partially_checked ? CheckState.unchecked : CheckState.checked; + } + + public function set_check_state(check_state: CheckState) { + if check_state == CheckState.partially-checked { + root.tristate = true; + } + root.check_state = check_state; + } + + states [ + disabled when !root.enabled : { + state_area.display_background: false; + background_layer.border_color: root.checked ? transparent : MaterialPalette.on_surface.with_alpha(38%); + background_layer.background: root.checked ? MaterialPalette.on_surface.with_alpha(38%) : transparent; + } + checked when root.checked : { + background_layer.border_width: 0; + background_layer.background: root.has_error ? MaterialPalette.error : MaterialPalette.primary; + state_area.color: background_layer.background; + } + ] +} + +export component CheckBoxTile inherits ListTile { + in_out property check_state <=> check_box.check_state; + in_out property tristate <=> check_box.tristate; + in property has_error <=> check_box.has_error; + + callback checked_state_changed <=> check_box.checked_state_changed; + + Rectangle { + horizontal-stretch: 0; + + check_box := CheckBox { + enabled: root.enabled; + } + } + + clicked => { + check_box.toggle(); + } + + public function set_check_state(check-state: CheckState) { + check_box.set_check_state(check_state); + } +} diff --git a/material-1.0/ui/components/chip.slint b/material-1.0/ui/components/chip.slint new file mode 100644 index 0000000..4182279 --- /dev/null +++ b/material-1.0/ui/components/chip.slint @@ -0,0 +1,205 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { BaseButton } from "./base_button.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { Icons } from "../icons/icons.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; +import { IconButton } from "icon_button.slint"; + +export component ActionChip { + in property icon <=> base.icon; + in property text <=> base.text; + in property enabled <=> base.enabled; + in property tooltip <=> base.tooltip; + in property avatar_icon <=> base.avatar-icon; + in property avatar_background <=> base.avatar_background; + + callback clicked <=> base.clicked; + + forward-focus: base; + accessible-role: button; + accessible-enabled: root.enabled; + accessible-label: root.text == "" ? root.tooltip : root.text; + accessible-action-default => { base.clicked(); } + + + border := Rectangle { + border_radius: base.border_radius; + border_width: 1px; + border_color: MaterialPalette.outline; + + base := BaseButton { + min_layout_height: MaterialStyleMetrics.size_32; + border_radius: MaterialStyleMetrics.border_radius_8; + color: MaterialPalette.on_surface; + icon_color: MaterialPalette.primary; + spacing: MaterialStyleMetrics.spacing_8; + button_padding_left: self.has_icon ? MaterialStyleMetrics.padding_8 : MaterialStyleMetrics.padding_16; + button_padding_right:MaterialStyleMetrics.padding_16; + button_vertical_padding: MaterialStyleMetrics.padding_6; + avatar_size: MaterialStyleMetrics.size_18; + } + } + + states [ + disabled when !root.enabled : { + base.display_background: false; + base.icon_color: MaterialPalette.on_surface; + } + ] +} + +export component FilterChip { + in property icon <=> base.icon; + in property text <=> base.text; + in property enabled <=> base.enabled; + in property tooltip <=> base.tooltip; + in_out property checked; + + forward-focus: base; + accessible-role: button; + accessible-enabled: root.enabled; + accessible-label: root.text == "" ? root.tooltip : root.text; + accessible-checkable: true; + accessible-checked: root.checked; + accessible-action-default => { base.clicked(); } + + border := Rectangle { + border_radius: base.border_radius; + border_width: 1px; + border_color: MaterialPalette.outline; + + + base := BaseButton { + min_layout_height: MaterialStyleMetrics.size_32; + border_radius: MaterialStyleMetrics.border_radius_8; + color: MaterialPalette.on_surface; + icon_color: MaterialPalette.primary; + spacing: MaterialStyleMetrics.spacing_8; + button_padding_left: self.has_icon ? MaterialStyleMetrics.padding_8 : MaterialStyleMetrics.padding_16; + button_padding_right:MaterialStyleMetrics.padding_16; + button_vertical_padding: MaterialStyleMetrics.padding_6; + avatar_size: MaterialStyleMetrics.size_18; + + clicked => { + root.toggle(); + } + } + + states [ + checked when root.checked : { + base.icon: Icons.check; + base.icon_color: MaterialPalette.on_secondary_container; + base.color: MaterialPalette.on_secondary_container; + border.border_width: 0; + border.background: MaterialPalette.secondary_container; + } + ] + + animate width { duration: MaterialAnimations.standard_accelerate_duration; easing: MaterialAnimations.standard_easing; } + } + + function toggle() { + root.checked = !root.checked; + } + + states [ + disabled when !root.enabled : { + base.display_background: false; + base.icon_color: MaterialPalette.on_surface; + } + ] +} + +export component InputChip { + in property leading_icon <=> base.icon; + in property trailing_icon; + in property avatar <=> base.avatar-icon; + in property avatar_background <=> base.avatar_background; + in property text <=> base.text; + in property enabled <=> base.enabled; + in property tooltip <=> base.tooltip; + in property checkable; + in_out property checked; + + property has_avatar: root.avatar.width > 0 && root.avatar.height > 0; + + callback clicked(); + callback trailing_icon_clicked(); + + forward-focus: base; + accessible-role: button; + accessible-enabled: root.enabled; + accessible-label: root.text == "" ? root.tooltip : root.text; + accessible-checkable: root.checkable; + accessible-checked: root.checked; + accessible-action-default => { base.clicked(); } + + border := Rectangle { + border_radius: base.border_radius; + border_width: 1px; + border_color: MaterialPalette.outline; + clip: true; + + base := BaseButton { + min_layout_height: MaterialStyleMetrics.size_32; + border_radius: root.has_avatar ? self.height / 2 : MaterialStyleMetrics.border_radius_8; + color: MaterialPalette.on_surface; + icon_color: MaterialPalette.primary; + spacing: MaterialStyleMetrics.spacing_8; + button_padding_left: root.has_avatar ? MaterialStyleMetrics.padding_4 : self.has_icon ? MaterialStyleMetrics.padding_8 : MaterialStyleMetrics.padding_12; + button_padding_right: root.trailing_icon.width > 0 && root.trailing_icon.height > 0 ? MaterialStyleMetrics.padding_8 : MaterialStyleMetrics.padding_12; + button_vertical_padding: MaterialStyleMetrics.padding_6; + avatar_size: MaterialStyleMetrics.size_18; + + if root.trailing_icon.width > 0 && root.trailing_icon.height > 0 : VerticalLayout { + alignment: center; + + IconButton { + icon: root.trailing_icon; + inline: true; + enabled: root.enabled; + + clicked => { + root.trailing_icon_clicked(); + } + } + } + + clicked => { + root.clicked(); + root.toggle(); + } + } + + states [ + checked when root.checked : { + base.icon_color: MaterialPalette.on_secondary_container; + base.color: MaterialPalette.on_secondary_container; + border.border_width: 0; + border.background: MaterialPalette.secondary_container; + } + ] + + animate width { duration: MaterialAnimations.standard_accelerate_duration; easing: MaterialAnimations.standard_easing; } + } + + function toggle() { + if !root.checkable { + return; + } + + root.checked = !root.checked; + } + + states [ + disabled when !root.enabled : { + base.display_background: false; + base.icon_color: MaterialPalette.on_surface; + } + ] +} + diff --git a/material-1.0/ui/components/date_picker.slint b/material-1.0/ui/components/date_picker.slint new file mode 100644 index 0000000..ec102e5 --- /dev/null +++ b/material-1.0/ui/components/date_picker.slint @@ -0,0 +1,568 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { BaseDialog } from "./dialog.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { Icons } from "../icons/icons.slint"; +import { MaterialText } from "./material_text.slint"; +import { StateLayer } from "./state_layer.slint"; +import { ScrollView } from "./scroll_view.slint"; +import { IconButton } from "./icon_button.slint"; +import { TextField } from "./text_field.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { ExtendedTouchArea } from "./extended_touch_area.slint"; + +// defines the interface to get the data for the DatePicker from native code. +export global DatePickerAdapter { + // returns the number of days for the given month in the given year. + pure callback month_day_count(month: int, year: int) -> int; + + // return the numbers of day to the first monday of the month. + pure callback month_offset(month: int, year: int) -> int; + + // used to format a date that is defined by day month and year. + pure callback format_date(format: string, day: int, month: int, year: int) -> string; + + // parses the given date string and returns a list of day, month and year. + pure callback parse_date(date: string, format: string) -> [int]; + + // returns true if the given date is valid. + pure callback valid_date(date: string, format: string) -> bool; + + // returns the current date as list of day, month and year. + pure callback date_now() -> [int]; +} + +export struct Date { + year: int, + month: int, + day: int, +} + +component CalendarHeaderDelegate { + in property text <=> text_label.text; + + min_width: max(MaterialStyleMetrics.size_40, content_layer.min_width); + min_height: max(MaterialStyleMetrics.size_40, content_layer.min_height); + + content_layer := VerticalLayout { + text_label := MaterialText { + vertical_alignment: center; + horizontal_alignment: center; + style: MaterialTypography.body_large; + color: MaterialPalette.on_surface; + } + } +} + +component CalendarDelegate { + in property selected; + in property today; + in property text <=> text_label.text; + in property enabled: true; + + callback clicked <=> touch_area.clicked; + + min_width: max(MaterialStyleMetrics.size_40, content_layer.min_width); + min_height: max(MaterialStyleMetrics.size_40, content_layer.min_height); + forward_focus: focus_scope; + + accessible_role: button; + accessible_checkable: true; + accessible_checked: root.selected; + accessible_label: root.text; + accessible_action_default => { touch_area.clicked(); } + + touch_area := TouchArea { + enabled: root.enabled; + } + + focus_scope := FocusScope { + width: 0px; + enabled: root.enabled; + + key_pressed(event) => { + if (event.text == " " || event.text == "\n") { + touch_area.clicked(); + return accept; + } + + return reject; + } + } + + background_layer := Rectangle { + border_radius: self.height / 2; + } + + content_layer := HorizontalLayout { + text_label := MaterialText { + vertical_alignment: center; + horizontal_alignment: center; + style: MaterialTypography.body_large; + color: MaterialPalette.on_surface; + } + } + + state_layer := StateLayer { + enabled: root.enabled; + border_radius: background_layer.border_radius; + pressed: touch_area.pressed; + has_hover: touch_area.has_hover; + has_focus: focus_scope.has_focus; + } + + states [ + // FIXME: states + disabled when !root.enabled : { + root.opacity: 0.38; + } + selected when root.selected : { + background_layer.background: MaterialPalette.primary; + text_label.color: MaterialPalette.on_primary; + } + today when root.today : { + background_layer.border_width: 1px; + background_layer.border_color: MaterialPalette.primary; + } + ] +} + +export component Calendar { + in property column_count; + in property row_count; + in property delegate_size; + in property start_column; + in property <[string]> header_model; + in property month_count; + in property today; + in property selected_date; + in property display_month; + in property display_year; + + callback select_date(date: Date); + + // header + for day[index] in root.header_model : CalendarHeaderDelegate { + x: root.delegate_x(index); + y: root.delegate_y(index); + text: day; + } + + // items + for index in root.month_count : CalendarDelegate { + property d: { day: index + 1, month: root.display_month, year: root.display_year }; + + x: root.delegate_x(root.index_on_calendar(index)); + y: root.delegate_y(root.index_on_calendar(index)); + width: root.delegate_size; + height: root.delegate_size; + text: index + 1; + selected: root.selected_date == self.d; + today: root.today == self.d; + + clicked => { + root.select_date(self.d); + } + } + + function index_on_calendar(index: int) -> int { + // add column count because items starts after header row + root.column_count + root.start_column + index + } + + function row_for_index(index: int) -> int { + floor(index / root.column_count) + } + + function column_for_index(index: int) -> int { + mod(index, root.column_count) + } + + function delegate_x(index: int) -> length { + root.column_for_index(index) * root.delegate_size + root.column_for_index(index) * 1px /* * root.style.spacing */ + } + + function delegate_y(index: int) -> length { + root.row_for_index(index) * root.delegate_size + root.row_for_index(index) * 1px /* * root.style.spacing */ + } +} + +component YearSelection { + in property <[int]> model; + in property spacing; + in property visible_row_count; + in property column_count; + in property delegate_width; + in property delegate_height; + in property selected_year; + in property today_year; + + callback select_year(year: int); + + property row_height: root.height / root.visible_row_count; + property row_count: root.model.length / root.column_count; + property viewport_height: root.row_count * root.row_height; + property start_x: root.width / (root.column_count + 1); + property start_y: root.height / (root.visible_row_count + 1); + + ScrollView { + width: 100%; + height: 100%; + viewport_width: root.width; + viewport_height: root.viewport_height; + + for year[index] in root.model: CalendarDelegate { + x: root.delegate_center_x(index) - self.width / 2; + y: root.delegate_center_y(index) - self.height / 2; + width: root.delegate_width; + height: root.delegate_height; + text: year; + selected: year == root.selected_year; + today: year == root.today_year; + + clicked => { + root.select_year(year); + } + } + } + + function delegate_center_x(index: int) -> length { + root.start_x * (root.column_for_index(index) + 1) + } + + function delegate_center_y(index: int) -> length { + root.start_y * (root.row_for_index(index) + 1) + } + + function row_for_index(index: int) -> int { + floor(index / root.column_count) + } + + function column_for_index(index: int) -> int { + mod(index, root.column_count) + } +} + +export component SelectionButton { + in property text <=> text-label.text; + in property icon <=> icon-image.source; + in property enabled: true; + in-out property checked; + + callback clicked(); + + min-width: content-layer.min-width; + min-height: max(40px, content-layer.min-height); + accessible-label: root.text; + accessible-role: button; + accessible-checkable: true; + accessible-checked: root.checked; + accessible-action-default => { touch-area.clicked(); } + forward-focus: touch-area; + + touch-area := ExtendedTouchArea { + width: 100%; + height: 100%; + enabled: root.enabled; + + clicked => { + root.checked = !root.checked; + root.clicked(); + } + } + + state-layer := StateLayer { + enabled: root.enabled; + pressed: touch-area.pressed; + has-hover: touch-area.has-hover; + has-focus: touch-area.has-focus; + background: text_label.color; + } + + content-layer := HorizontalLayout { + alignment: center; + padding-left: 8px; + padding-right: 8px; + spacing: 8px; + + text-label := MaterialText { + vertical-alignment: center; + color: MaterialPalette.on_surface_variant; + style: MaterialTypography.label_large; + } + + icon-image := Image { + y: (parent.height - self.height) / 2; + width: MaterialStyleMetrics.size_18; + colorize: MaterialPalette.on_surface_variant; + rotation-angle: root.checked ? 180deg : 0; + rotation-origin-x: self.width / 2; + rotation-origin-y: self.height / 2; + + animate rotation-angle { duration: 250ms; } + } + } + + states [ + disabled when !root.enabled : { + root.opacity: 0.38; + } + ] +} + + +export component DatePickerPopup inherits PopupWindow { + in property title; + in property date : { day: today[0], month: today[1], year: today[2] }; + + callback canceled(); + callback accepted(date: Date); + + // this is used for the navigation between months + property input_title: @tr("Enter date"); + property input_placeholder_text: "mm/dd/yyyy"; + property input_format: "%m/%d/%Y"; + property cancel_text: @tr("Cancel"); + property ok_text: @tr("Ok"); + property display_date: root.date; + property current_date: root.date; + property delegate_size: 40px; + property year_delegate_width: 72px; + property calendar_column_count: 7; + property calendar_row_count: 6; + property calendar_min_width: root.delegate_size * root.calendar_column_count + (root.calendar_column_count - 1) * 1px; + property calendar_min_height: root.delegate_size *(root.calendar_row_count + 1) + (root.calendar_row_count - 1) * 1px; + property year_selection_column_count: 3; + property year_selection_row_count: 5; + property year_selection; + property selection_mode: true; + property current_input; + + property calendar_month_count: DatePickerAdapter.month_day_count(root.display_date.month, root.display_date.year); + property <[string]> calendar_header_model: [ + @tr("One-letter abbrev for Sunday" => "S"), + @tr("One-letter abbrev for Monday" => "M"), + @tr("One-letter abbrev for Tuesday" => "T"), + @tr("One-letter abbrev for Wednesday" => "W"), + @tr("One-letter abbrev for Thursday" => "T"), + @tr("One-letter abbrev for Friday" => "F"), + @tr("One-letter abbrev for Saturday" => "S"), + ]; + property <[int]> today: DatePickerAdapter.date_now(); + property start_column: DatePickerAdapter.month_offset(root.display_date.month, root.display_date.year); + property current_month: DatePickerAdapter.format_date("%B %Y", root.display_date.day, root.display_date.month, root.display_date.year); + property <[int]> year_model: [2024, 2025, 2026, 2027, 2028, 2029, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043]; + property selected_year: root.display_date.year; + property today_year: root.today[2]; + property current_day: DatePickerAdapter.format_date("%a, %b %d", root.current_date.day, root.current_date.month, root.current_date.year); + property <[int]> input_formatted: DatePickerAdapter.parse_date(root.current_input, root.input_format); + + close_policy: no_auto_close; + forward_focus: base; + + base := BaseDialog { + width: 100%; + height: 100%; + title: root.title; + actions: [ + root.cancel_text, + root.ok_text + ]; + + content_layer := VerticalLayout { + spacing: MaterialStyleMetrics.spacing_12; + + header := HorizontalLayout { + MaterialText { + text: root.selection_mode ? root.current_day : root.input_title; + horizontal_alignment: left; + vertical_alignment: center; + style: MaterialTypography.headline_large; + } + + if root.selection_mode : IconButton { + icon: Icons.edit; + accessible_label: "Toggle selection mode"; + + clicked => { + root.toggle_selection_mode(); + } + } + } + + Rectangle { + height: 1px; + background: MaterialPalette.outline; + } + + if root.selection_mode : HorizontalLayout { + // FIXME: spacing + + VerticalLayout { + horizontal_stretch: 0; + alignment: center; + + SelectionButton { + text: root.current_month; + icon: Icons.arrow_drop_down; + checked <=> root.year_selection; + } + } + + Rectangle {} + + IconButton { + icon: Icons.chevron_backward; + accessible_label: "Previous month"; + + clicked => { + root.show_previous(); + } + } + + IconButton { + icon: Icons.chevron_forward; + accessible_label: "Next month"; + + clicked => { + root.show_next(); + } + } + } + + if root.selection_mode : VerticalLayout { + if !root.year_selection : Calendar { + min_width: root.calendar_min_width; + min_height: root.calendar_min_height; + column_count: root.calendar_column_count; + row_count: root.calendar_row_count; + delegate_size: root.delegate_size; + header_model: root.calendar_header_model; + month_count: root.calendar_month_count; + today: { day: root.today[0], month: root.today[1], year: root.today[2] }; + selected_date <=> root.current_date; + start_column: root.start_column; + display_month: root.display_date.month; + display_year: root.display_date.year; + + select_date(date) => { + root.select_date(date); + } + } + + if root.year_selection : YearSelection { + min_width: root.calendar_min_width; + min_height: root.calendar_min_height; + column_count: root.year_selection_column_count; + visible_row_count: root.year_selection_row_count; + delegate_width: root.year_delegate_width; + delegate_height: root.delegate_size; + model: root.year_model; + selected_year: root.selected_year; + today_year: root.today_year; + + select_year(year) => { + root.select_year(year); + } + } + } + + Rectangle { + height: 1px; + visible: root.year_selection; + background: MaterialPalette.outline; + } + + if !root.selection_mode : TextField { + text <=> root.current_input; + placeholder_text: root.input_placeholder_text; + trailing_icon: Icons.calendar_today; + + trailing_icon_clicked => { + root.toggle_selection_mode(); + } + } + } + + action_clicked(index) => { + // cancel + if index == 0 { + root.close(); + root.canceled(); + } else if index == 1 { + root.accepted(root.date); + } + } + + close => { + root.close(); + } + } + + changed date => { + root.display_date = root.date; + root.current_date = root.date; + } + + changed selection_mode => { + // check switch from input mode if input is valid + if root.selection_mode && root.current_input_valid() { + root.current_date = root.input_as_date(); + root.display_date = root.current_date; + } + } + + pure public function ok_enabled() -> bool { + root.selection_mode || root.current_input_valid() + } + + public function get_current_date() -> Date { + if root.selection_mode { + return root.current_date; + } + + root.input_as_date() + } + + pure function current_input_valid() -> bool { + DatePickerAdapter.valid_date(root.current_input, root.input_format) + } + + pure function input_as_date() -> Date { + { day: root.input_formatted[0], month: root.input_formatted[1], year: root.input_formatted[2] } + } + + function select_date(date: Date) { + root.current_date = date; + } + + function select_year(year: int) { + root.current_date = { day: 1, month: 1, year: year }; + root.display_date = root.current_date; + root.year_selection = false; + } + + function show_next() { + if root.display_date.month >= 12 { + root.display_date = { day: 1, month: 1, year: root.display_date.year + 1 }; + return; + } + + root.display_date = { day: 1, month: root.display_date.month + 1, year: root.display_date.year }; + } + + function show_previous() { + if root.display_date.month <= 1 { + root.display_date = { day: 1, month: 12, year: root.display_date.year - 1 }; + return; + } + + root.display_date = { day: 1, month: root.display_date.month - 1, year: root.display_date.year }; + } + + function toggle_selection_mode() { + root.selection_mode = !root.selection_mode; + } +} diff --git a/material-1.0/ui/components/dialog.slint b/material-1.0/ui/components/dialog.slint new file mode 100644 index 0000000..fcdd916 --- /dev/null +++ b/material-1.0/ui/components/dialog.slint @@ -0,0 +1,233 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { TextButton } from "./text_button.slint"; +import { FilledButton } from "./filled_button.slint"; +import { MaterialText } from "./material_text.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; +import { Modal } from "./modal.slint"; +import { Icon } from "./icon.slint"; +import { IconButton } from "./icon_button.slint"; +import { Icons } from "../icons/icons.slint"; + +export component FullscreenDialog inherits PopupWindow { + in property title; + in property <[string]> actions; + + callback action_clicked(index: int); + + close_policy: no_auto_close; + forward_focus: focus_scope; + + focus_scope := FocusScope { + x: 0; + width: 0; + + key_pressed(event) => { + if event.text == Key.Escape { + root.close(); + return accept; + } + + reject + } + } + + background_layer := Rectangle { + width: 100%; + height: 100%; + opacity: 0; + background: MaterialPalette.surface; + + VerticalLayout { + spacing: MaterialStyleMetrics.spacing_16; + + HorizontalLayout { + padding: MaterialStyleMetrics.padding_24; + spacing: MaterialStyleMetrics.spacing_16; + vertical_stretch: 0; + + IconButton { + icon: Icons.close; + + clicked => { + root.close(); + } + } + + MaterialText { + text: root.title; + style: MaterialTypography.headline_small; + color: MaterialPalette.on_surface; + vertical_alignment: center; + } + + for action[index] in root.actions : TextButton { + text: action; + + clicked => { + root.action_clicked(index); + } + } + } + + @children + + } + } + + Timer { + interval: 50ms; + + triggered => { + background_layer.opacity = 1; + self.running = false; + } + } +} + +export component BaseDialog { + in property title; + in property icon; + in property <[image]> action_button_icons; + in property default_action_text; + in property <[string]> actions; + + property has_icon: root.icon.width > 0 && root.icon.height > 0; + + callback default_action_clicked(); + callback action_button_clicked(index: int); + callback action_clicked(index: int); + callback close(); + + forward_focus: focus_scope; + + focus_scope := FocusScope { + x: 0; + width: 0; + + key_pressed(event) => { + if event.text == Key.Return && root.default_action_text != "" { + root.default_action_clicked(); + return accept; + } + + if event.text == Key.Escape { + root.close(); + return accept; + } + + reject + } + } + + modal := Modal { + width: 100%; + height: 100%; + + background_layer := Rectangle { + x: (parent.width - self.width) / 2; + y: (parent.height - self.height) / 2; + width: layout.min_width; + height: layout.min_height; + opacity: 0; + border_radius: MaterialStyleMetrics.border_radius_28; + background: MaterialPalette.surface_container_high; + + TouchArea { + layout := VerticalLayout { + padding: MaterialStyleMetrics.padding_24; + spacing: MaterialStyleMetrics.spacing_16; + + if root.has_icon : Icon { + x: (parent.width - self.width) / 2; + colorize: MaterialPalette.on_surface; + source: root.icon; + } + + if root.title != "" : MaterialText { + horizontal_alignment: root.has_icon ? center : left; + text: root.title; + style: MaterialTypography.headline_small; + color: MaterialPalette.on_surface; + } + + @children + + HorizontalLayout { + spacing: MaterialStyleMetrics.spacing_8; + + for action_button[index] in root.action_button_icons : IconButton { + icon: action_button; + + clicked => { + root.action_button_clicked(index); + } + } + + // Spacer + Rectangle {} + + for action[index] in root.actions : TextButton { + text: action; + + clicked => { + root.action_clicked(index); + } + } + + if root.default_action_text != "" : FilledButton { + text: root.default_action_text; + + clicked => { + root.default_action_clicked(); + } + } + } + } + } + + animate opacity { duration: MaterialAnimations.opacity_duration; easing: MaterialAnimations.opacity_easing; } + } + + clicked => { + root.close(); + } + } + + Timer { + interval: 50ms; + + triggered => { + background_layer.opacity = 1; + self.running = false; + } + } +} + +export component Dialog inherits PopupWindow { + in property title <=> base.title; + in property icon <=> base.icon; + in property default_action_text <=> base.default_action_text; + in property <[string]> actions <=> base.actions; + + callback default_action_clicked <=> base.default_action_clicked; + callback action_clicked <=> base.action_clicked; + + close_policy: no_auto_close; + forward_focus: base; + + base := BaseDialog { + width: 100%; + height: 100%; + + @children + + close => { + root.close(); + } + } +} diff --git a/material-1.0/ui/components/divider.slint b/material-1.0/ui/components/divider.slint new file mode 100644 index 0000000..c7b9498 --- /dev/null +++ b/material-1.0/ui/components/divider.slint @@ -0,0 +1,28 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialPalette } from "../styling/material_palette.slint"; + +component BaseDivider { + Rectangle { + background: MaterialPalette.outline_variant; + } +} + +export component VerticalDivider { + width: 1px; + + BaseDivider { + width: 100%; + height: 100%; + } +} + +export component HorizontalDivider { + height: 1px; + + BaseDivider { + width: 100%; + height: 100%; + } +} diff --git a/material-1.0/ui/components/drawer.slint b/material-1.0/ui/components/drawer.slint new file mode 100644 index 0000000..5938d44 --- /dev/null +++ b/material-1.0/ui/components/drawer.slint @@ -0,0 +1,89 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialText } from "./material_text.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; +import { Modal } from "./modal.slint"; + +export component DrawerHeader { + in property title; + + min_height: max(MaterialStyleMetrics.size_56, title_label.min_width); + + title_label := MaterialText { + x: MaterialStyleMetrics.padding_16; + width: root.width - MaterialStyleMetrics.padding_16; + text: root.title; + color: MaterialPalette.on_surface_variant; + vertical_alignment: center; + style: MaterialTypography.title_small; + } +} + +export component Drawer { + in property title; + + min_width: max(MaterialStyleMetrics.size_360, layout.min_width); + + TouchArea { + + Rectangle { + background: MaterialPalette.surface_container_low; + border_radius: MaterialStyleMetrics.border_radius_16; + + layout := VerticalLayout { + alignment: start; + padding: MaterialStyleMetrics.padding_12; + + if root.title != "" : DrawerHeader { + width: 100%; + title: root.title; + } + + @children + } + } + } +} + +export component ModalDrawer inherits PopupWindow { + in property position_right; + in property title; + + close_policy: no_auto_close; + + modal := Modal { + width: 100%; + height: 100%; + + drawer := Drawer { + x: root.position_right ? parent.width : -self.width; + y: 0; + height: 100%; + title: root.title; + + @children + + animate x { + duration: MaterialAnimations.standard_accelerate_duration; + easing: MaterialAnimations.standard_easing; + } + } + + clicked => { + root.close(); + } + } + + Timer { + interval: 50ms; + + triggered => { + drawer.x = root.position_right ? root.width - drawer.width : 0; + self.running = false; + } + } +} diff --git a/material-1.0/ui/components/drop_down_menu.slint b/material-1.0/ui/components/drop_down_menu.slint new file mode 100644 index 0000000..7f96101 --- /dev/null +++ b/material-1.0/ui/components/drop_down_menu.slint @@ -0,0 +1,125 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { TextField } from "./text_field.slint"; +import { MenuItem } from "../items/menu_item.slint"; +import { Icons } from "../icons/icons.slint"; +import { MenuInner } from "./menu.slint"; +import { StateLayer } from "./state_layer.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { ScrollView } from "./scroll_view.slint"; + +export component DropDownMenu { + in property label <=> text_field.label; + in property enabled <=> text_field.enabled; + in property leading_icon <=> text_field.leading_icon; + in property <[MenuItem]> items; + in_out property current_index: -1; + + callback selected(index: int); + + property item_height: MaterialStyleMetrics.size_56; + property max_displayed_items: 6; + property text <=> text_field.text; + + min_width: text_field.min_width; + min_height: text_field.min_height; + forward_focus: text_field; accessible-role: combobox; + accessible_enabled: root.enabled; + accessible_expandable: true; + accessible_value <=> text_field.text; + accessible_action_expand => { menu.show(); } + + text_field := TextField { + width: 100%; + height: 100%; + trailing_icon: Icons.arrow_drop_down; + read_only: true; + } + + state_layer := StateLayer { + width: 100%; + height: 100%; + background: MaterialPalette.on_surface; + has_hover: touch_area.has_hover; + enabled: root.enabled; + } + + touch_area := TouchArea { + width: 100%; + height: 100%; + enabled: root.enabled; + + clicked => { + menu.show(); + } + } + + menu := PopupWindow { + x: 0; + width: root.width; + close_policy: close_on_click_outside; + forward_focus: inner_text_field; + + VerticalLayout { + alignment: start; + + inner_text_field := TextField { + width: root.width; + leading_icon: root.leading_icon; + trailing_icon: Icons.arrow_drop_up; + text: root.text; + label: root.label; + read_only: true; + + leading_icon_clicked => { + menu.close(); + } + + trailing_icon_clicked => { + menu.close(); + } + } + + Rectangle { + width: 100%; + height: min(max(root.item_height, items.length * root.item_height), root.max_displayed_items * root.item_height); + background: MaterialPalette.surface_container; + + ScrollView { + VerticalLayout { + menu_inner := MenuInner { + current_index: root.current_index; + items: root.items; + + activated(index) => { + root.update_selection(index); + } + } + } + } + } + } + } + + function update_selection(index: int) { + root.update_text(index); + root.current_index = index; + menu.close(); + root.selected(index); + } + + function update_text(index: int) { + if index < 0 || root.current_index >= root.items.length { + text_field.text = ""; + return; + } + + text_field.text = root.items[index].text; + } + + changed current_index => { + root.update_text(root.current_index); + } +} diff --git a/material-1.0/ui/components/elevated_button.slint b/material-1.0/ui/components/elevated_button.slint new file mode 100644 index 0000000..fbfb809 --- /dev/null +++ b/material-1.0/ui/components/elevated_button.slint @@ -0,0 +1,45 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { Elevation } from "./elevation.slint"; +import { BaseButton } from "./base_button.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; + +export component ElevatedButton { + in property icon <=> base.icon; + in property text <=> base.text; + in property tooltip <=> base.tooltip; + in property enabled <=> base.enabled; + + callback clicked <=> base.clicked; + + accessible-role: button; + accessible-enabled: root.enabled; + accessible-label: root.text == "" ? root.tooltip : root.text; + accessible-action-default => { base.clicked(); } + + elevation := Elevation { + border_radius: root.height / 2; + background: MaterialPalette.surface_container_low; + level: 1; + width: 100%; + height: 100%; + } + + base := BaseButton { + border_radius: elevation.border_radius; + color: MaterialPalette.primary; + } + + states [ + disabled when !root.enabled : { + elevation.background: transparent; + elevation.level: 0; + base.color: MaterialPalette.on_surface; + } + hover when base.has_hover && !base.pressed && !base.enter_pressed : { + elevation.level: 3; + } + ] +} diff --git a/material-1.0/ui/components/elevation.slint b/material-1.0/ui/components/elevation.slint new file mode 100644 index 0000000..9fc8596 --- /dev/null +++ b/material-1.0/ui/components/elevation.slint @@ -0,0 +1,108 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { Palette } from "std-widgets.slint"; +import { MaterialWindow } from "material_window.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; + +export component Elevation { + in property background; + in property border_radius; + in property level; + + property dark: Palette.color_scheme == ColorScheme.dark; + + outer_shadow := Rectangle { + border_radius: root.border_radius; + + inner_shadow := Rectangle { + border_radius: root.border_radius; + background: root.background; + + @children + } + } + + states [ + level_1_light when root.level == 1 && !root.dark: { + outer_shadow.drop_shadow_offset_y: 1px; + outer_shadow.drop_shadow_blur: 2px; + outer_shadow.drop_shadow_color: MaterialPalette.shadow_30; + inner_shadow.drop_shadow_offset_y: 1px; + inner_shadow.drop_shadow_blur: 2px; + inner_shadow.drop_shadow_color: MaterialPalette.shadow_15; + } + level_2_light when root.level == 2 && !root.dark: { + outer_shadow.drop_shadow_offset_y: 1px; + outer_shadow.drop_shadow_blur: 2px; + outer_shadow.drop_shadow_color: MaterialPalette.shadow_30; + inner_shadow.drop_shadow_offset_y: 2px; + inner_shadow.drop_shadow_blur: 6px; + inner_shadow.drop_shadow_color: MaterialPalette.shadow_15; + } + level_3_light when root.level == 3 && !root.dark: { + outer_shadow.drop_shadow_offset_y: 4px; + outer_shadow.drop_shadow_blur: 8px; + outer_shadow.drop_shadow_color: MaterialPalette.shadow_15; + inner_shadow.drop_shadow_offset_y: 1px; + inner_shadow.drop_shadow_blur: 3px; + inner_shadow.drop_shadow_color: MaterialPalette.shadow_30; + } + level_4_light when root.level == 4 && !root.dark: { + outer_shadow.drop_shadow_offset_y: 6px; + outer_shadow.drop_shadow_blur: 10px; + outer_shadow.drop_shadow_color: MaterialPalette.shadow_15; + inner_shadow.drop_shadow_offset_y: 2px; + inner_shadow.drop_shadow_blur: 3px; + inner_shadow.drop_shadow_color: MaterialPalette.shadow_30; + } + level_5_light when root.level == 5 && !root.dark: { + outer_shadow.drop_shadow_offset_y: 8px; + outer_shadow.drop_shadow_blur: 12px; + outer_shadow.drop_shadow_color: MaterialPalette.shadow_15; + inner_shadow.drop_shadow_offset_y: 4px; + inner_shadow.drop_shadow_blur: 4px; + inner_shadow.drop_shadow_color: MaterialPalette.shadow_30; + } + level_1_dark when root.level == 1 && root.dark: { + outer_shadow.drop_shadow_offset_y: 1px; + outer_shadow.drop_shadow_blur: 3px; + outer_shadow.drop_shadow_color: MaterialPalette.shadow_15; + inner_shadow.drop_shadow_offset_y: 1px; + inner_shadow.drop_shadow_blur: 2px; + inner_shadow.drop_shadow_color: MaterialPalette.shadow_30; + } + level_2_dark when root.level == 2 && root.dark: { + outer_shadow.drop_shadow_offset_y: 2px; + outer_shadow.drop_shadow_blur: 6px; + outer_shadow.drop_shadow_color: MaterialPalette.shadow_15; + inner_shadow.drop_shadow_offset_y: 1px; + inner_shadow.drop_shadow_blur: 2px; + inner_shadow.drop_shadow_color: MaterialPalette.shadow_30; + } + level_3_dark when root.level == 3 && root.dark: { + outer_shadow.drop_shadow_offset_y: 4px; + outer_shadow.drop_shadow_blur: 8px; + outer_shadow.drop_shadow_color: MaterialPalette.shadow_15; + inner_shadow.drop_shadow_offset_y: 1px; + inner_shadow.drop_shadow_blur: 3px; + inner_shadow.drop_shadow_color: MaterialPalette.shadow_30; + } + level_4_dark when root.level == 4 && root.dark: { + outer_shadow.drop_shadow_offset_y: 6px; + outer_shadow.drop_shadow_blur: 10px; + outer_shadow.drop_shadow_color: MaterialPalette.shadow_15; + inner_shadow.drop_shadow_offset_y: 2px; + inner_shadow.drop_shadow_blur: 3px; + inner_shadow.drop_shadow_color: MaterialPalette.shadow_30; + } + level_5_dark when root.level == 5 && root.dark: { + outer_shadow.drop_shadow_offset_y: 8px; + outer_shadow.drop_shadow_blur: 12px; + outer_shadow.drop_shadow_color: MaterialPalette.shadow_15; + inner_shadow.drop_shadow_offset_y: 4px; + inner_shadow.drop_shadow_blur: 4px; + inner_shadow.drop_shadow_color: MaterialPalette.shadow_30; + } + ] +} diff --git a/material-1.0/ui/components/extended_touch_area.slint b/material-1.0/ui/components/extended_touch_area.slint new file mode 100644 index 0000000..5108c7c --- /dev/null +++ b/material-1.0/ui/components/extended_touch_area.slint @@ -0,0 +1,57 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialAnimations } from "../styling/material_animations.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { ToolTip } from "tooltip.slint"; + +export component ExtendedTouchArea inherits TouchArea { + in property tooltip; + in property tooltip_offset; + out property has_focus <=> focus_scope.has_focus; + out property enter_pressed; + + callback key_pressed(KeyEvent) -> EventResult; + + forward-focus: focus-scope; + + focus_scope := FocusScope { + x: 0; + width: 0px; + enabled: root.enabled; + + key_pressed(event) => { + if !root.enabled { + return reject; + } + + if (event.text == " " || event.text == "\n") && !root.enter_pressed { + root.enter_pressed = true; + root.clicked(); + return accept; + } + + root.key_pressed(event) + } + + key_released(event) => { + if !root.enabled { + return reject; + } + + if (event.text == " " || event.text == "\n") && root.enter_pressed { + root.enter_pressed = false; + return accept; + } + + reject + } + } + + @children + + if root.tooltip != "" && root.has-hover && !root.pressed : ToolTip { + y: root.tooltip_offset; + text: root.tooltip; + } +} diff --git a/material-1.0/ui/components/filled_button.slint b/material-1.0/ui/components/filled_button.slint new file mode 100644 index 0000000..e2b503f --- /dev/null +++ b/material-1.0/ui/components/filled_button.slint @@ -0,0 +1,43 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { Elevation } from "./elevation.slint"; +import { BaseButton } from "./base_button.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; + +export component FilledButton { + in property icon <=> base.icon; + in property text <=> base.text; + in property tooltip <=> base.tooltip; + in property enabled <=> base.enabled; + + callback clicked <=> base.clicked; + + accessible-role: button; + accessible-enabled: root.enabled; + accessible-label: root.text == "" ? root.tooltip : root.text; + accessible-action-default => { base.clicked(); } + + elevation := Elevation { + border_radius: root.height / 2; + background: MaterialPalette.primary; + width: 100%; + height: 100%; + } + + base := BaseButton { + border_radius: elevation.border_radius; + color: MaterialPalette.on_primary; + } + + states [ + disabled when !root.enabled : { + elevation.background: transparent; + base.color: MaterialPalette.on_surface; + } + hover when base.has_hover && !base.pressed && !base.enter_pressed : { + elevation.level: 1; + } + ] +} diff --git a/material-1.0/ui/components/filled_icon_button.slint b/material-1.0/ui/components/filled_icon_button.slint new file mode 100644 index 0000000..0f6f096 --- /dev/null +++ b/material-1.0/ui/components/filled_icon_button.slint @@ -0,0 +1,64 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { Elevation } from "./elevation.slint"; +import { BaseButton } from "./base_button.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; + +export component FilledIconButton { + in property icon; + in property checked_icon: root.icon; + in property checkable; + in_out property checked; + in property tooltip <=> base.tooltip; + in property enabled <=> base.enabled; + + callback clicked(); + + accessible-role: button; + accessible-enabled: true; + accessible-label: root.tooltip; + accessible-checkable: root.checkable; + accessible-checked: root.checked; + accessible-action-default => { base.clicked(); } + + background_layer := Rectangle { + width: 100%; + height: 100%; + border_radius: base.border_radius; + background: root.checkable ? MaterialPalette.surface_container_highest : MaterialPalette.primary; + visible: root.enabled; + } + + base := BaseButton { + icon: root.checked ? root.checked_icon : root.icon; + border_radius: self.height / 2; + color: !root.enabled ? MaterialPalette.on_surface_variant : root.checkable ? MaterialPalette.primary : MaterialPalette.on_primary; + button_horizontal_padding: 0; + button_vertical_padding: 0; + width: self.height; + icon_size: MaterialStyleMetrics.icon_size_24; + + clicked => { + root.toggle(); + root.clicked(); + } + } + + function toggle() { + if !root.checkable { + return; + } + + root.checked = !root.checked; + } + + states [ + checked when root.enabled && root.checked : { + base.color: MaterialPalette.on_primary; + background_layer.background: MaterialPalette.primary; + } + ] +} diff --git a/material-1.0/ui/components/floating_action_button.slint b/material-1.0/ui/components/floating_action_button.slint new file mode 100644 index 0000000..32077f7 --- /dev/null +++ b/material-1.0/ui/components/floating_action_button.slint @@ -0,0 +1,55 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { Elevation } from "./elevation.slint"; +import { BaseButton } from "./base_button.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; + +export enum FABStyle { + small, + standard, + large +} + +export component FloatingActionButton { + in property icon <=> base.icon; + in property text <=> base.text; + in property tooltip <=> base.tooltip; + in property style; + + callback clicked <=> base.clicked; + + accessible-role: button; + accessible-enabled: true; + accessible-label: root.text == "" ? root.tooltip : root.text; + accessible-action-default => { base.clicked(); } + + elevation := Elevation { + border_radius: root.style == FABStyle.small ? MaterialStyleMetrics.border_radius_12 : + root.style == FABStyle.standard ? MaterialStyleMetrics.border_radius_16 : MaterialStyleMetrics.border_radius_28; + background: MaterialPalette.primary; + level: 3; + width: 100%; + height: 100%; + } + + base := BaseButton { + border_radius: elevation.border_radius; + color: MaterialPalette.on_primary; + button_vertical_padding: root.style == FABStyle.small ? MaterialStyleMetrics.padding_10 : + root.style == FABStyle.standard ? MaterialStyleMetrics.padding_14 : MaterialStyleMetrics.padding_30; + button_horizontal_padding: self.button_vertical_padding; + min_layout_width: self.min_layout_height; + min_layout_height: root.style == FABStyle.small ? MaterialStyleMetrics.size_40 : + root.style == FABStyle.standard ? MaterialStyleMetrics.size_56 : MaterialStyleMetrics.size_90; + icon_size: root.style != FABStyle.large ? MaterialStyleMetrics.icon_size_24 : MaterialStyleMetrics.icon_size_36; + } + + states [ + hover when base.has_hover : { + elevation.level: 4; + } + ] +} diff --git a/material-1.0/ui/components/grid.slint b/material-1.0/ui/components/grid.slint new file mode 100644 index 0000000..9c82f56 --- /dev/null +++ b/material-1.0/ui/components/grid.slint @@ -0,0 +1,10 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; + +export component Grid inherits GridLayout { + padding: MaterialStyleMetrics.padding_8; + spacing_vertical: MaterialStyleMetrics.spacing_8; + spacing_horizontal: MaterialStyleMetrics.spacing_8; +} diff --git a/material-1.0/ui/components/horizontal.slint b/material-1.0/ui/components/horizontal.slint new file mode 100644 index 0000000..bddf801 --- /dev/null +++ b/material-1.0/ui/components/horizontal.slint @@ -0,0 +1,9 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; + +export component Horizontal inherits HorizontalLayout { + padding: MaterialStyleMetrics.padding_8; + spacing: MaterialStyleMetrics.spacing_8; +} diff --git a/material-1.0/ui/components/icon.slint b/material-1.0/ui/components/icon.slint new file mode 100644 index 0000000..4d23105 --- /dev/null +++ b/material-1.0/ui/components/icon.slint @@ -0,0 +1,11 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; + +export component Icon inherits Image { + width: MaterialStyleMetrics.icon_size_18; + height: self.width; + colorize: MaterialPalette.on_background; +} diff --git a/material-1.0/ui/components/icon_button.slint b/material-1.0/ui/components/icon_button.slint new file mode 100644 index 0000000..9b2625a --- /dev/null +++ b/material-1.0/ui/components/icon_button.slint @@ -0,0 +1,62 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { Elevation } from "./elevation.slint"; +import { BaseButton } from "./base_button.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; + +export component IconButton { + in property icon; + in property checked_icon: root.icon; + in property checkable; + in_out property checked; + in property tooltip <=> base.tooltip; + in property enabled <=> base.enabled; + in property inverse; + in property inline: false; + in property has_error; + + callback clicked(); + + accessible-role: button; + accessible-enabled: true; + accessible-label: root.tooltip; + accessible-checkable: root.checkable; + accessible-checked: root.checked; + accessible-action-default => { base.clicked(); } + + base := BaseButton { + icon: root.checked ? root.checked_icon : root.icon; + border_radius: self.height / 2; + color: root.has_error ? MaterialPalette.error : root.inverse ? MaterialPalette.inverse_on_surface : MaterialPalette.on_surface_variant; + button_horizontal_padding: 0; + button_vertical_padding: 0; + width: self.height; + display_background: false; + icon_size: root.inline ? MaterialStyleMetrics.icon_size_18 : MaterialStyleMetrics.icon_size_24; + min_layout_width: root.inline ? MaterialStyleMetrics.icon_size_18 : MaterialStyleMetrics.size_40; + min_layout_height: self.min_layout_width; + clip_ripple: !root.inline; + + clicked => { + root.toggle(); + root.clicked(); + } + } + + function toggle() { + if !root.checkable { + return; + } + + root.checked = !root.checked; + } + + states [ + checked when root.enabled && root.checked : { + base.color: MaterialPalette.primary; + } + ] +} diff --git a/material-1.0/ui/components/list.slint b/material-1.0/ui/components/list.slint new file mode 100644 index 0000000..8e7bd68 --- /dev/null +++ b/material-1.0/ui/components/list.slint @@ -0,0 +1,107 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { StateLayerArea } from "./state_layer.slint"; +import { MaterialText } from "./material_text.slint"; +import { Icon } from "./icon.slint"; + +export component Avatar { + in property image; + in property background: MaterialPalette.primary; + + width: MaterialStyleMetrics.size_32; + height: self.width; + + Rectangle { + width: 100%; + height: 100%; + border_radius: self.width / 2; + background: root.background; + clip: true; + + Image { + source: root.image; + } + } +} + +export component ListTile { + in property text; + in property supporting_text; + in property avatar_icon; + in property avatar_text; + in property avatar_background; + in property avatar_foreground; + in property enabled <=> state_layer.enabled; + + property color: MaterialPalette.on_surface; + + callback clicked <=> state_layer.clicked; + + min_height: max(MaterialStyleMetrics.size_72, layout.min_height); + + state_layer := StateLayerArea { + color: root.color; + + layout := HorizontalLayout { + padding_left: MaterialStyleMetrics.padding_16; + padding_right: MaterialStyleMetrics.padding_24; + padding_top: MaterialStyleMetrics.padding_8; + padding_bottom: self.padding_top; + spacing: MaterialStyleMetrics.spacing_16; + + if root.avatar_background != #00000000 || root.avatar_text != "" || (root.avatar_icon.width > 0 && root.avatar_icon.height > 0) : Rectangle { + width: self.height; + border_radius: self.height / 2; + background: root.avatar_background; + clip: true; + + if root.avatar_text != "" : MaterialText { + text: root.avatar_text; + vertical_alignment: center; + horizontal_alignment: center; + color: root.avatar_foreground; + style: MaterialTypography.title_medium; + } + + if root.avatar_icon.width > 0 && root.avatar_icon.height > 0 : Icon { + width: parent.width; + source: root.avatar_icon; + colorize: root.avatar_foreground; + } + } + + title_layout := VerticalLayout { + alignment: center; + horizontal_stretch: 1; + + MaterialText { + text: root.text; + color: root.color; + overflow: elide; + style: MaterialTypography.body_large; + } + + if root.supporting_text != "" : MaterialText { + text: root.supporting_text; + color: root.color; + overflow: elide; + style: MaterialTypography.body_medium; + } + } + + @children + } + } + + states [ + disabled when !root.enabled : { + state_layer.display_background: false; + title_layout.opacity: 38%; + } + ] +} + diff --git a/material-1.0/ui/components/list_view.slint b/material-1.0/ui/components/list_view.slint new file mode 100644 index 0000000..aeb847f --- /dev/null +++ b/material-1.0/ui/components/list_view.slint @@ -0,0 +1,8 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { ScrollView } from "./scroll_view.slint"; + +export component ListView inherits ScrollView { + +} diff --git a/material-1.0/ui/components/material_text.slint b/material-1.0/ui/components/material_text.slint new file mode 100644 index 0000000..4aa5c20 --- /dev/null +++ b/material-1.0/ui/components/material_text.slint @@ -0,0 +1,14 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialTypography, TextStyle } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; + +export component MaterialText inherits Text { + in property style: MaterialTypography.body_medium; + + font_size: root.style.font_size; + font_weight: root.style.font_weight; + color: MaterialPalette.on_background; + overflow: elide; +} diff --git a/material-1.0/ui/components/material_window.slint b/material-1.0/ui/components/material_window.slint new file mode 100644 index 0000000..a861ac0 --- /dev/null +++ b/material-1.0/ui/components/material_window.slint @@ -0,0 +1,18 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialPalette } from "../styling/material_palette.slint"; + +export global MaterialWindowAdapter { + in property disable_hover; +} + +export component MaterialWindow inherits Window { + in property disable_hover; + + background: MaterialPalette.background; + + changed disable_hover => { + MaterialWindowAdapter.disable_hover = root.disable_hover; + } +} diff --git a/material-1.0/ui/components/menu.slint b/material-1.0/ui/components/menu.slint new file mode 100644 index 0000000..f04da7a --- /dev/null +++ b/material-1.0/ui/components/menu.slint @@ -0,0 +1,136 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { Elevation } from "elevation.slint"; +import { StateLayerArea } from "./state_layer.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { Icon } from "./icon.slint"; +import { MenuItem } from "../items/menu_item.slint"; +import { MaterialText } from "./material_text.slint"; +import { Icons } from "../icons/icons.slint"; + +component MenuItemTemplate { + in property icon; + in property text; + in property trailing_text; + in property enabled <=> state_area.enabled; + in property selected; + + callback clicked(); + + property has_icon: root.icon.width > 0 && root.icon.height > 0; + property color: MaterialPalette.on_surface; + property color_variant: MaterialPalette.on_surface_variant; + + min_height: max(MaterialStyleMetrics.size_56, layout.min_height); + + background_layer := Rectangle { + state_area := StateLayerArea { + color: root.color; + + layout := HorizontalLayout { + padding_left: MaterialStyleMetrics.padding_12; + padding_right: self.padding_left; + padding_top: MaterialStyleMetrics.padding_8; + padding_bottom: self.padding_top; + spacing: MaterialStyleMetrics.spacing_12; + + if root.has_icon : VerticalLayout { + alignment: center; + + Icon { + source: root.icon; + colorize: root.color; + } + } + + MaterialText { + horizontal_stretch: 1; + text: root.text; + style: MaterialTypography.body_large; + color: root.color; + vertical_alignment: center; + } + + if root.trailing_text != "" : MaterialText { + text: root.trailing_text; + style: MaterialTypography.body_large; + color: root.color_variant; + vertical_alignment: center; + } + } + + clicked => { + root.clicked(); + } + } + } + + states [ + disabled when !root.enabled : { + state_area.opacity: MaterialPalette.disable_opacity; + } + selected when root.selected : { + background_layer.background: MaterialPalette.surface_container_highest; + } + ] +} + +export component MenuInner { + in property <[MenuItem]> items; + in_out property current_index: -1; + + callback activated(index: int); + + // used to fix clipping of shadows + out property elevation: 2; + + menu := Elevation { + width: 100%; + level: root.elevation; + height: layout.min_height + root.elevation * 1px; + border_radius: MaterialStyleMetrics.border_radius_4; + background: MaterialPalette.surface_container; + + layout := VerticalLayout { + width: root.width; + padding_top: MaterialStyleMetrics.padding_8; + padding_bottom: self.padding_top; + + for item[index] in root.items : MenuItemTemplate { + icon: item.icon; + text: item.text; + trailing_text: item.trailing_text; + enabled: item.enabled; + selected: index == root.current_index; + + clicked => { + root.activated(index); + } + } + } + } +} + +export component PopupMenu inherits PopupWindow { + in property <[MenuItem]> items; + + callback activated(index: int); + + width: MaterialStyleMetrics.size_200; + close_policy: close_on_click_outside; + + VerticalLayout { + padding: inner.elevation * 1px; + + inner := MenuInner { + items: root.items; + + activated(index) => { + root.activated(index); + } + } + } +} diff --git a/material-1.0/ui/components/modal.slint b/material-1.0/ui/components/modal.slint new file mode 100644 index 0000000..b14a4a6 --- /dev/null +++ b/material-1.0/ui/components/modal.slint @@ -0,0 +1,28 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; + +export component Modal { + callback clicked <=> touch_area.clicked; + + background_layer := Rectangle { + clip: true; + + touch_area := TouchArea { + @children + } + + animate background { duration: MaterialAnimations.opacity_duration; easing: MaterialAnimations.opacity_easing; } + } + + Timer { + interval: 50ms; + + triggered => { + background_layer.background = MaterialPalette.background_modal; + self.running = false; + } + } +} diff --git a/material-1.0/ui/components/navigation_bar.slint b/material-1.0/ui/components/navigation_bar.slint new file mode 100644 index 0000000..2705ef3 --- /dev/null +++ b/material-1.0/ui/components/navigation_bar.slint @@ -0,0 +1,150 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { Badge } from "./badge.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialText } from "./material_text.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { ExtendedTouchArea } from "./extended_touch_area.slint"; +import { StateLayer, Ripple } from "./state_layer.slint"; +import { Icon } from "./icon.slint"; +import { NavigationItem } from "../items/navigation_item.slint"; +import { BaseNavigationItemTemplate, BaseNavigation } from "./base_navigation.slint"; + +export component NavigationItemTemplate inherits BaseNavigationItemTemplate { + property has_icon: root.icon.width > 0 && root.icon.height > 0; + property has_selected_icon: root.selected_icon.width > 0 || root.selected_icon.height > 0; + property color: MaterialPalette.on_surface; + + in property navitem_padding_top: MaterialStyleMetrics.padding_12; + in property navitem_padding_bottom: MaterialStyleMetrics.padding_16; + + Rectangle { + width: 100%; + height: 100%; + } + + touch_area := ExtendedTouchArea { + HorizontalLayout { + alignment: center; + + VerticalLayout { + alignment: start; + spacing: MaterialStyleMetrics.spacing_4; + padding_top: root.navitem_padding_top; + padding_bottom: root.navitem_padding_bottom; + + HorizontalLayout { + alignment: center; + + background_layer := Rectangle { + min_width: state_layout.min_width; + min_height: max(MaterialStyleMetrics.size_32, state_layout.min_height); + border_radius: self.height / 2; + + state_layer := StateLayer { + background: root.color; + border_radius: parent.border_radius; + enabled: true; + has_focus: touch_area.has_focus; + has_hover: touch_area.has_hover; + pressed: touch_area.pressed || touch_area.enter_pressed; + width: 100%; + height: 100%; + + if touch_area.pressed && !root.selected : Ripple { + width: root.width; + height: root.height; + pressed_x: touch_area.pressed_x; + pressed_y: touch_area.pressed_y; + color: root.color; + } + + state_layout := HorizontalLayout { + padding_left: MaterialStyleMetrics.padding_20; + padding_right: self.padding_left; + alignment: center; + + VerticalLayout { + alignment: center; + + if !root.has_icon && !root.has_selected_icon : Rectangle { + width: 12px; + height: self.width; + border_radius: self.width / 2; + background: root.color; + } + + if root.has_icon || root.has_selected_icon : Icon { + source: root.icon; + colorize: root.color; + + states [ + selected when root.selected && root.has_selected_icon : { + source: root.selected_icon; + } + ] + } + } + } + } + + if root.show_badge || root.badge != "" : Badge { + x: parent.width / 2; + y: 0; + text: root.badge; + } + } + } + + label := MaterialText { + text: root.text; + style: MaterialTypography.label_medium; + color: root.color; + horizontal_alignment: center; + } + } + } + + clicked => { + root.clicked(); + } + } + + states [ + selected when root.selected : { + background_layer.background: MaterialPalette.secondary_container; + state_layer.background: transparent; + label.style: MaterialTypography.label_medium_prominent; + } + ] +} + +export component NavigationBar inherits BaseNavigation { + min_height: max(MaterialStyleMetrics.size_80, layout.min_height); + + Rectangle { + background: MaterialPalette.surface_container; + + layout := HorizontalLayout { + padding_left: MaterialStyleMetrics.padding_8; + padding_right: self.padding_left; + spacing: MaterialStyleMetrics.spacing_8; + + for item[index] in root.items : NavigationItemTemplate { + icon: item.icon; + selected_icon: item.selected_icon; + text: item.text; + index: index; + selected: index == root.current_index; + show_badge: item.show_badge; + badge: item.badge; + + clicked => { + root.select(index); + } + } + } + } +} diff --git a/material-1.0/ui/components/navigation_drawer.slint b/material-1.0/ui/components/navigation_drawer.slint new file mode 100644 index 0000000..bc42756 --- /dev/null +++ b/material-1.0/ui/components/navigation_drawer.slint @@ -0,0 +1,211 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { Drawer, ModalDrawer, DrawerHeader } from "./drawer.slint"; +import { NavigationItem, NavigationGroup } from "../items/navigation_item.slint"; +import { HorizontalDivider } from "./divider.slint"; +import { StateLayerArea } from "./state_layer.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { Icon } from "./icon.slint"; +import { MaterialText } from "./material_text.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; +import { BaseNavigationItemTemplate } from "./base_navigation.slint"; + +component NavigationItemTemplate inherits BaseNavigationItemTemplate { + property has_icon: root.icon.width > 0 && root.icon.height > 0; + property has_selected_icon: root.selected_icon.width > 0 || root.selected_icon.height > 0; + property color: MaterialPalette.on_surface_variant; + + min_height: max(MaterialStyleMetrics.size_56, layout.min_height); + + background_layer := Rectangle { + border_radius: self.height / 2; + + state_layer := StateLayerArea { + border_radius: parent.border_radius; + color: root.selected ? transparent : root.color; + + layout := HorizontalLayout { + padding_left: MaterialStyleMetrics.padding_16; + padding_right: MaterialStyleMetrics.padding_24; + padding_top: MaterialStyleMetrics.padding_16; + padding_bottom: self.padding_top; + spacing: MaterialStyleMetrics.spacing_12; + + VerticalLayout { + alignment: center; + + if !root.has_icon && !root.has_selected_icon : Rectangle { + width: MaterialStyleMetrics.icon_size_24; + height: self.width; + + Rectangle { + width: 12px; + height: self.width; + border_radius: self.width / 2; + background: root.color; + } + } + + if root.has_icon || root.has_selected_icon : Icon { + source: root.icon; + colorize: root.color; + + states [ + selected when root.selected && root.has_selected_icon : { + source: root.selected_icon; + } + ] + } + } + + MaterialText { + horizontal_stretch: 1; + text: root.text; + style: MaterialTypography.label_large; + color: root.color; + vertical_alignment: center; + } + + if root.badge != "" : MaterialText { + text: root.badge; + style: MaterialTypography.label_large; + color: root.color; + vertical_alignment: center; + } + } + + clicked => { + root.clicked(); + } + + pointer_event(event) => { + root.pointer_event(event, { + x: self.mouse_x, + y: self.mouse_y, + }); + } + } + + animate background { duration: MaterialAnimations.opacity_duration; easing: MaterialAnimations.opacity_easing; } + } + + states [ + selected when root.selected : { + background_layer.background: MaterialPalette.secondary_container; + root.color: MaterialPalette.on_secondary_container; + } + ] + + animate color { duration: MaterialAnimations.opacity_duration; easing: MaterialAnimations.opacity_easing; } +} + +component NavigationGroupTemplate { + in property title; + in property <[NavigationItem]> items; + in property current_index: -1; + in property has_divider; + + callback select(index: int); + callback item_pointer_event(index: int, event: PointerEvent, position: Point); + + VerticalLayout { + alignment: start; + + if root.title != 0 : DrawerHeader { + title: root.title; + } + + for item[index] in root.items : NavigationItemTemplate { + icon: item.icon; + selected_icon: item.selected_icon; + text: item.text; + badge: item.badge; + selected: index == root.current_index; + index: index; + + clicked => { + root.select(index); + } + pointer_event(event, position) => { + root.item_pointer_event(index, event, { + x: self.x + position.x, + y: self.y + position.y, + }); + } + } + + if root.has_divider : HorizontalDivider {} + } +} + +export component NavigationDrawer inherits Drawer { + callback selected(group-index: int, item_index: int); + callback item_pointer_event(group_index: int, item_index: int, event: PointerEvent, position: Point); + in property <[NavigationGroup]> groups; + in_out property current_group; + in_out property current_index; + + accessible-role: tab-list; + // accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-index; + // accessible-label: root.title; + accessible-item-count: root.groups.length; + + for group[group_index] in root.groups : NavigationGroupTemplate { + title: group.title; + items: group.items; + current_index: group_index == root.current_group ? root.current_index : -1; + has_divider: root.groups.length > 1 && group_index < root.groups.length - 1; + + select(index) => { + root.select(group_index, index); + } + item_pointer_event(index, event, position) => { + root.item_pointer_event(group_index, index, event, { x: self.x + position.x, y: self.y + position.y }); + } + } + + function select(group_index: int, item_index: int) { + if group_index < 0 || group_index >= root.groups.length || item_index < 0 || item_index >= root.groups[group_index].items.length { + return; + } + + root.current_group = group_index; + root.current_index = item_index; + root.selected(group_index, item_index); + } +} + +export component ModalNavigationDrawer inherits ModalDrawer { + in property <[NavigationGroup]> groups; + in_out property current_group; + in_out property current_index; + + accessible-role: tab-list; + // accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-index; + // accessible-label: root.title; + accessible-item-count: root.groups.length; + + for group[group_index] in root.groups : NavigationGroupTemplate { + title: group.title; + items: group.items; + current_index: group_index == root.current_group ? root.current_index : -1; + has_divider: root.groups.length > 1 && group_index < root.groups.length - 1; + + select(index) => { + root.select(group_index, index); + } + } + + function select(group_index: int, item_index: int) { + if group_index < 0 || group_index >= root.groups.length || item_index < 0 || item_index >= root.groups[group_index].items.length { + return; + } + + root.current_group = group_index; + root.current_index = item_index; + root.close(); + } +} diff --git a/material-1.0/ui/components/navigation_rail.slint b/material-1.0/ui/components/navigation_rail.slint new file mode 100644 index 0000000..ae2be9e --- /dev/null +++ b/material-1.0/ui/components/navigation_rail.slint @@ -0,0 +1,85 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { NavigationItem } from "../items/navigation_item.slint"; +import { FloatingActionButton, FABStyle } from "./floating_action_button.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { IconButton } from "icon_button.slint"; +import { Icons } from "../icons/icons.slint"; +import { NavigationItemTemplate } from "navigation_bar.slint"; +import { BaseNavigation } from "./base_navigation.slint"; + +export component NavigationRail inherits BaseNavigation { + in property has_menu; + in property fab_icon; + in property alignment; + + callback menu_clicked(); + callback fab_clicked(); + + min_width: max(MaterialStyleMetrics.size_80, layout.min_width); + + Rectangle { + background: MaterialPalette.surface; + border-radius: 5px; + + layout := VerticalLayout { + padding_top: MaterialStyleMetrics.padding_44; + padding_bottom: MaterialStyleMetrics.padding_56; + spacing: MaterialStyleMetrics.spacing_4; + + if root.has_menu : IconButton { + icon: Icons.menu; + + clicked => { + root.menu_clicked(); + } + } + + + if root.fab_icon.width > 0 && root.fab_icon.height > 0 : HorizontalLayout { + alignment: center; + + FloatingActionButton { + icon: root.fab_icon; + style: FABStyle.standard; + + clicked => { + root.fab_clicked(); + } + } + } + + // helper to place fab at the top if no items are present + if root.items.length == 0 : Rectangle { + horizontal_stretch: 1; + } + + HorizontalLayout { + vertical_stretch: 1; + alignment: center; + + VerticalLayout { + alignment: root.alignment; + + for item[index] in root.items : NavigationItemTemplate { + icon: item.icon; + selected_icon: item.selected_icon; + text: item.text; + index: index; + selected: index == root.current_index; + show_badge: item.show_badge; + badge: item.badge; + navitem_padding_top: 0; + navitem_padding_bottom: MaterialStyleMetrics.padding_4; + + clicked => { + root.select(index); + } + } + } + } + } + } +} diff --git a/material-1.0/ui/components/outline_button.slint b/material-1.0/ui/components/outline_button.slint new file mode 100644 index 0000000..e40db92 --- /dev/null +++ b/material-1.0/ui/components/outline_button.slint @@ -0,0 +1,42 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { BaseButton } from "./base_button.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; + +export component OutlineButton { + in property icon <=> base.icon; + in property text <=> base.text; + in property enabled <=> base.enabled; + in property tooltip <=> base.tooltip; + + callback clicked <=> base.clicked; + + accessible-role: button; + accessible-enabled: root.enabled; + accessible-label: root.text == "" ? root.tooltip : root.text; + accessible-action-default => { base.clicked(); } + + base := BaseButton { + border_radius: border.border_radius; + color: MaterialPalette.primary; + } + + border := Rectangle { + border_radius: root.height / 2; + border_width: 1px; + border_color: MaterialPalette.outline; + width: 100%; + height: 100%; + } + + states [ + disabled when !root.enabled : { + base.color: MaterialPalette.on_surface; + base.transparent_background: true; + border.border_color: MaterialPalette.on_surface; + border.opacity: MaterialPalette.state_layer_opacity_hover; + } + ] +} diff --git a/material-1.0/ui/components/outline_icon_button.slint b/material-1.0/ui/components/outline_icon_button.slint new file mode 100644 index 0000000..142b11a --- /dev/null +++ b/material-1.0/ui/components/outline_icon_button.slint @@ -0,0 +1,78 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { Elevation } from "./elevation.slint"; +import { BaseButton } from "./base_button.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; + +export component OutlineIconButton { + in property icon; + in property checked_icon: root.icon; + in property checkable; + in_out property checked; + in property tooltip <=> base.tooltip; + in property enabled <=> base.enabled; + + callback clicked(); + + accessible-role: button; + accessible-enabled: true; + accessible-label: root.tooltip; + accessible-checkable: root.checkable; + accessible-checked: root.checked; + accessible-action-default => { base.clicked(); } + + background_layer := Rectangle { + width: 100%; + height: 100%; + border_radius: base.border_radius; + border_width: 1px; + border_color: MaterialPalette.outline; + } + + base := BaseButton { + icon: root.checked ? root.checked_icon : root.icon; + border_radius: self.height / 2; + color: !root.enabled ? MaterialPalette.on_surface_variant : MaterialPalette.on_surface_variant; + button_horizontal_padding: 0; + button_vertical_padding: 0; + width: self.height; + icon_size: MaterialStyleMetrics.icon_size_24; + display_background: false; + + clicked => { + root.toggle(); + root.clicked(); + } + } + + function toggle() { + if !root.checkable { + return; + } + + root.checked = !root.checked; + } + + states [ + disabled when !root.enabled : { + base.color: MaterialPalette.on_surface; + base.transparent_background: true; + background_layer.border_color: root.checked ? transparent : MaterialPalette.on_surface; + background_layer.background: root.checked ? MaterialPalette.on_surface : transparent; + background_layer.opacity: MaterialPalette.state_layer_opacity_hover; + } + checked when root.enabled && root.checked : { + base.color: MaterialPalette.inverse_on_surface; + background_layer.background: MaterialPalette.inverse_surface; + background_layer.border_width: 0; + } + checked_disabled when root.enabled && root.checked : { + base.color: MaterialPalette.inverse_on_surface; + background_layer.background: MaterialPalette.inverse_on_surface; + background_layer.border_width: 0; + } + ] +} diff --git a/material-1.0/ui/components/progress_indicator.slint b/material-1.0/ui/components/progress_indicator.slint new file mode 100644 index 0000000..b32567c --- /dev/null +++ b/material-1.0/ui/components/progress_indicator.slint @@ -0,0 +1,107 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; + +export component LinearProgressIndicator { + in property progress; + in property indeterminate; + + height: MaterialStyleMetrics.size_4; + + Rectangle { + width: 100%; + height: 100%; + clip: true; + background: MaterialPalette.primary_container; + border_radius: MaterialStyleMetrics.border_radius_2; + + track := Rectangle { + x: 0; + y: 0; + width: parent.width * root.progress; + height: 100%; + border_radius: parent.border_radius; + background: MaterialPalette.primary; + } + } +} + +export component CircularProgressIndicator { + in property progress; + in property indeterminate; + + property bar_height: MaterialStyleMetrics.size_4; + + width: self.height; + min_height: MaterialStyleMetrics.size_40; + + background_layer := Rectangle { + width: root.width; + height: root.height; + border_width: root.bar_height; + border_color: root.progress == 1 ? MaterialPalette.primary : MaterialPalette.primary_container; + border_radius: max(self.width, self.height) / 2; + } + + track := Path { + property radius: min(self.viewbox_width, self.viewbox_height) / 2; + property start_x: self.viewbox_width / 2; + property start_y: self.viewbox_height / 2; + property inner_radius: self.radius - (root.bar_height * (self.viewbox_height / self.height)); + property start: !root.indeterminate ? 0 : 1 * mod(animation-tick(), 1.5s) / 1.5s; + property progress: !root.indeterminate ? root.progress : 0.5; + + x: background_layer.x; + y: background_layer.y; + viewbox_width: 100; + viewbox_height: 100; + width: background_layer.width; + height: background_layer.height; + fill: MaterialPalette.primary; + visible: self.progress > 0 && self.progress < 1; + + MoveTo { + x: !root.indeterminate ? track.start_x : track.start_x - track.radius * sin(-track.start * 360deg); + y: !root.indeterminate ? 0 : track.start_y - track.radius * cos(-track.start * 360deg); + } + + ArcTo { + radius_x: 1; + radius_y: 1; + x: !root.indeterminate ? track.start_x : track.start_x - track.inner-radius * sin(-track.start * 360deg); + y: !root.indeterminate ? root.bar_height * (track.viewbox_height / track.height) : track.start_y - track.inner_radius * cos(-track.start * 360deg); + } + + ArcTo { + radius_x: track.inner_radius; + radius_y: track.inner_radius; + x: start_x - track.inner_radius * sin(-(track.start + track.progress) * 360deg); + y: start_y - track.inner_radius * cos(-(track.start + track.progress) * 360deg); + sweep: track.progress > 0; + large-arc: track.progress > 0.5; + } + + ArcTo { + radius_x: 1; + radius_y: 1; + x: start_x - radius * sin(-(track.start + track.progress) * 360deg); + y: start_y - radius * cos(-(track.start + track.progress) * 360deg); + } + + ArcTo { + radius_x: radius; + radius_y: radius; + x: start_x - radius * sin(-track.start * 360deg); + y: start_y - radius * cos(-track.start * 360deg); + sweep: track.progress < 0; + large-arc: track.progress > 0.5; + } + + LineTo { + x: start_x - radius * sin(-track.start * 360deg); + y: start_y - radius * cos(-track.start * 360deg); + } + } +} diff --git a/material-1.0/ui/components/radio_button.slint b/material-1.0/ui/components/radio_button.slint new file mode 100644 index 0000000..4dab0bd --- /dev/null +++ b/material-1.0/ui/components/radio_button.slint @@ -0,0 +1,99 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; +import { StateLayerArea } from "./state_layer.slint"; +import { ListTile } from "./list.slint"; +import { ListView } from "./list_view.slint"; + +export component RadioButton { + in property checked; + in property enabled; + + callback clicked(); + + min_width: MaterialStyleMetrics.size_40; + min_height: self.min_width; + accessible-enabled: root.enabled; + accessible-checkable: true; + accessible-checked <=> root.checked; + accessible-role: checkbox; + accessible-action-default => { state_area.clicked(); } + forward_focus: state_area; + + state_area := StateLayerArea { + width: 100%; + height: 100%; + border_radius: max(self.width, self.height) / 2; + color: MaterialPalette.on_surface; + + border := Rectangle { + width: MaterialStyleMetrics.size_20; + height: self.width; + border_radius: max(self.width, self.height) / 2; + border_color: MaterialPalette.on_surface_variant; + border_width: MaterialStyleMetrics.size_2; + + indicator := Rectangle { + width: parent.width / 2; + height: self.width; + border_radius: max(self.width, self.height) / 2; + background: MaterialPalette.primary; + opacity: !root.checked ? 0 : 1; + + animate opacity { + duration: MaterialAnimations.opacity_duration; + easing: MaterialAnimations.opacity_easing; + } + } + + animate border_color { + duration: MaterialAnimations.opacity_duration; + easing: MaterialAnimations.opacity_easing; + } + } + + clicked => { + root.clicked(); + } + } + + states [ + disabled when !root.enabled : { + border.border_color: MaterialPalette.on_surface; + border.opacity: MaterialPalette.disable_opacity; + indicator.background: MaterialPalette.on_surface; + indicator.opacity: root.checked ? MaterialPalette.disable_opacity : 0; + } + highlighted when !root.checked && (state_area.pressed || state_area.has_focus || state_area.has_hover) : { + border.border_color: MaterialPalette.on_surface; + } + checked when root.checked : { + border.border_color: MaterialPalette.primary; + } + ] +} + +export component RadioButtonTile inherits ListTile { + in_out property checked <=> radio_button.checked; + + callback radio_button_clicked(); + + Rectangle { + horizontal_stretch: 0; + + radio_button := RadioButton { + enabled: root.enabled; + + clicked => { + root.radio_button_clicked(); + } + } + } + + clicked => { + radio_button.clicked(); + } +} diff --git a/material-1.0/ui/components/scroll_view.slint b/material-1.0/ui/components/scroll_view.slint new file mode 100644 index 0000000..dd783c3 --- /dev/null +++ b/material-1.0/ui/components/scroll_view.slint @@ -0,0 +1,166 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialPalette } from "../styling/material_palette.slint"; + +export component ScrollBar { + in property enabled; + out property has_hover: touch_area.has_hover; + in_out property horizontal; + in_out property maximum; + in_out property page_size; + in_out property value; + in property policy: ScrollBarPolicy.as_needed; + + property track_size: root.horizontal ? root.width - 2 * root.offset : root.height - 2 * offset; + property step_size: 10px; + property offset: 2px; + property state_opacity: 40%; + + visible: (self.policy == ScrollBarPolicy.always_on) || (self.policy == ScrollBarPolicy.as_needed && self.maximum > 0); + + Rectangle { + clip: true; + + thumb := Rectangle { + width: !root.horizontal ? parent.width : root.maximum <= 0phx ? 0phx : max(min(32px, root.width), root.track-size * root.page-size / (root.maximum + root.page-size)); + height: root.horizontal ? parent.height : root.maximum <= 0phx ? 0phx : max(min(32px, root.height), root.track-size * (root.page-size / (root.maximum + root.page-size))); + x: !root.horizontal ? (parent.width - self.width) / 2 : root.offset + (root.track-size - thumb.width) * (-root.value / root.maximum); + y: root.horizontal ? (parent.height - self.height) / 2 : root.offset + (root.track-size - thumb.height) * (-root.value / root.maximum); + border-radius: (root.horizontal ? self.height : self.width) / 2; + background: MaterialPalette.on_background; + opacity: hide_timer.running || touch_area.has_hover || touch_area.pressed ? root.state_opacity : 0; + + animate opacity { duration: 150ms; } + } + } + + touch_area := TouchArea { + property pressed_value; + + width: parent.width; + height: parent.height; + + pointer-event(event) => { + if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) { + self.pressed-value = -root.value; + } + } + + moved => { + if (self.enabled && self.pressed) { + root.value = -max(0px, min(root.maximum, self.pressed-value + ( + root.horizontal ? (touch-area.mouse-x - touch-area.pressed-x) * (root.maximum / (root.track-size - thumb.width)) + : (touch-area.mouse-y - touch-area.pressed-y) * (root.maximum / (root.track-size - thumb.height)) + ))); + } + } + + scroll-event(event) => { + if (root.horizontal && event.delta-x != 0) { + root.value = max(-root.maximum, min(0px, root.value + event.delta-x)); + return accept; + } else if (!root.horizontal && event.delta-y != 0) { + root.value = max(-root.maximum, min(0px, root.value + event.delta-y)); + return accept; + } + + reject + } + + changed has_hover => { + if !self.has_hover && !hide_timer.running { + hide_timer.running = true; + } + } + + changed pressed => { + if self.pressed && hide_timer.running { + hide_timer.running = false; + } + } + } + + changed value => { + if !self.has_hover && !hide_timer.running { + hide_timer.running = true; + } + } + + hide_timer := Timer { + interval: 1.5s; + running: false; + + triggered => { + self.running = false; + } + } + + states [ + pressed when touch_area.pressed : { + root.state_opacity: 80%; + } + hover when root.has_hover : { + root.state_opacity: 70%; + } + ] +} + +export component ScrollView { + in property enabled: true; + out property visible_width <=> flickable.width; + out property visible_height <=> flickable.height; + in_out property viewport_width <=> flickable.viewport_width; + in_out property viewport_height <=> flickable.viewport_height; + in_out property viewport_x <=> flickable.viewport_x; + in_out property viewport_y <=> flickable.viewport_y; + in property vertical_scrollbar_policy <=> vertical_bar.policy; + in property horizontal_scrollbar_policy <=> horizontal_bar.policy; + // FIXME: remove. This property is currently set by the ListView and is used by the native style to draw the scrollbar differently when it has focus + in_out property has_focus; + + callback scrolled <=> flickable.flicked; + + property scroll_bar_size: 8px; + property scroll_bar_padding: 1px; + + min_height: 50px; + min_width: 50px; + horizontal_stretch: 1; + vertical_stretch: 1; + preferred_height: 100%; + preferred_width: 100%; + + flickable := Flickable { + x: 0; + y: 0; + viewport_y <=> vertical_bar.value; + viewport_x <=> horizontal_bar.value; + width: root.width - (root.vertical_scrollbar_policy != ScrollBarPolicy.always_off ? root.scroll_bar_size - 2 * root.scroll_bar_padding : 0); + height: root.height - (root.horizontal_scrollbar_policy != ScrollBarPolicy.always_off ? root.scroll_bar_size : 0); + + @children + } + + vertical_bar := ScrollBar { + enabled: root.enabled; + x: flickable.width + root.scroll_bar_padding; + y: 0; + width: root.visible ? root.scroll_bar_size : 0; + height: root.vertical_scrollbar_policy != ScrollBarPolicy.always_off ? parent.height - horizontal_bar.height : parent.height; + horizontal: false; + maximum: flickable.viewport_height - flickable.height; + page-size: flickable.height; + } + + horizontal_bar := ScrollBar { + enabled: root.enabled; + width: vertical_bar.visible ? parent.width - vertical_bar.width : parent.width; + height: root.horizontal_scrollbar_policy != ScrollBarPolicy.always_off ? root.scroll_bar_size : 0; + x: 0; + y: flickable.height + root.scroll_bar_padding; + horizontal: true; + maximum: flickable.viewport_width - flickable.width; + page_size: flickable.width; + } +} diff --git a/material-1.0/ui/components/search_bar.slint b/material-1.0/ui/components/search_bar.slint new file mode 100644 index 0000000..3ea343b --- /dev/null +++ b/material-1.0/ui/components/search_bar.slint @@ -0,0 +1,317 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { ListItem } from "../items/list_item.slint"; +import { Avatar, ListTile } from "./list.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { StateLayerArea } from "./state_layer.slint"; +import { MaterialText } from "./material_text.slint"; +import { Icon } from "./icon.slint"; +import { IconButton } from "./icon_button.slint"; +import { Icons } from "../icons/icons.slint"; +import { HorizontalDivider } from "./divider.slint"; +import { ListView } from "./list_view.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; + +component SearchTile inherits ListTile { + in property action_button_icon; + + callback action_button_clicked(); + + if root.action_button_icon.width > 0 && root.action_button_icon.height > 0 : IconButton { + icon: root.action_button_icon; + + clicked => { + root.action_button_clicked(); + } + } +} + +component SearchIcon { + in property icon; + in property color; + + VerticalLayout { + alignment: center; + padding_left: MaterialStyleMetrics.padding_8; + padding_right: self.padding_left; + + Icon { + source: root.icon; + colorize: root.color; + } + } +} + +component SearchTextInput { + in_out property text <=> text_input.text; + in property placeholder_text; + property computed_x; + + callback accepted(text: string); + callback edited(text: string); + callback key_pressed(event: KeyEvent) -> EventResult; + callback key_released(event: KeyEvent) -> EventResult; + + forward_focus: text_input; + horizontal_stretch: 1; + + Rectangle { + clip: true; + + text_input := TextInput { + x: min(0px, max(parent.width - self.width - self.text_cursor_width, root.computed_x)); + width: max(parent.width - self.text-cursor-width, self.preferred-width); + height: 100%; + font_size: MaterialTypography.body_large.font_size; + font_weight: MaterialTypography.body_large.font_weight; + vertical_alignment: center; + single_line: true; + color: MaterialPalette.on_surface; + selection_background_color: MaterialPalette.secondary_container; + selection_foreground_color: self.color; + // Disable TextInput's built-in accessibility support as the component takes care of that. + accessible-role: none; + + cursor_position_changed(cursor_position) => { + if cursor_position.x + root.computed_x < 0 { + root.computed_x = - cursor_position.x; + } else if cursor-position.x + root.computed_x > parent.width - self.text-cursor-width { + root.computed_x = parent.width - cursor_position.x - self.text-cursor-width; + } + } + + accepted => { + root.accepted(self.text); + } + + edited => { + root.edited(self.text); + } + + key_pressed(event) => { + root.key_pressed(event) + } + + key_released(event) => { + root.key_released(event) + } + + init => { + if root.text.character_count > 0 { + self.set_selection_offsets(root.text.character_count, root.text.character_count); + } + } + } + if root.text == "" && root.placeholder_text != "" : MaterialText { + width: 100%; + height: 100%; + text: root.placeholder_text; + color: MaterialPalette.on_surface_variant; + vertical_alignment: center; + style: MaterialTypography.body_large; + } + } +} + +export component SearchBar { + in property leading_icon: Icons.menu; + in property trailing_icon; + in property avatar_icon; + in property avatar_background: #00000000; + in property placeholder_text; + in property empty_text; + in_out property text; + in_out property current_index; + in property <[ListItem]> items; + + callback accepted(text: string); + callback edited(text: string); + callback action_button_clicked(index: int); + callback key_pressed(event: KeyEvent) -> EventResult; + callback key_released(event: KeyEvent) -> EventResult; + + property color: MaterialPalette.on_surface_variant; + property item_height: MaterialStyleMetrics.size_72; + + min_height: max(MaterialStyleMetrics.size_56, layout.min_height); + forward_focus: state_layer; + + Rectangle { + background: MaterialPalette.surface_container_high; + border_radius: MaterialStyleMetrics.border_radius_28; + + state_layer := StateLayerArea { + border_radius: parent.border_radius; + color: root.color; + + layout := HorizontalLayout { + padding: MaterialStyleMetrics.padding_4; + spacing: MaterialStyleMetrics.spacing_4; + + SearchIcon { + icon: root.leading_icon; + color: root.color; + } + + MaterialText { + text: root.text; + font_size: MaterialTypography.body_large.font_size; + font_weight: MaterialTypography.body_large.font_weight; + vertical_alignment: center; + color: MaterialPalette.on_surface; + + states [ + placeholder when root.text == "" : { + text: root.placeholder_text; + color: MaterialPalette.on_surface; + } + ] + } + + SearchIcon { + icon: root.trailing_icon; + color: root.color; + } + + if (root.avatar_icon.width > 0 && root.avatar_icon.height > 0) || root.avatar_background != #00000000 : VerticalLayout { + alignment: center; + + Avatar { + image: root.avatar_icon; + background: root.avatar_background; + } + } + } + + changed has_focus => { + if self.has_focus { + popup.show(); + } + } + + clicked => { + popup.show(); + } + } + } + + popup := PopupWindow { + x: 0; + y: 0; + width: root.width; + height: root.height + clamp(root.item_height * root.items.length, 3 * root.item_height, 6 * root.item_height); + close_policy: close_on_click_outside; + forward-focus: popup_input; + + background_layer := Rectangle { + x: 0; + y: 0; + width: 100%; + height: root.height; + background: MaterialPalette.surface_container_high; + border_radius: MaterialStyleMetrics.border_radius_28; + clip: true; + + VerticalLayout { + HorizontalLayout { + padding: MaterialStyleMetrics.padding_4; + spacing: MaterialStyleMetrics.spacing_4; + + IconButton { + icon: Icons.arrow_back; + + clicked => { + popup.close(); + } + } + + popup_input := SearchTextInput { + placeholder_text: root.placeholder_text; + text: root.text; + + accepted => { + root.accepted(self.text); + } + + edited => { + root.text = self.text; + root.edited(self.text); + } + + key_pressed(event) => { + root.key_pressed(event) + } + + key_released(event) => { + root.key_released(event) + } + + changed text => { + root.text = text; + } + } + + IconButton { + icon: Icons.close; + + clicked => { + root.text = ""; + popup.close(); + } + } + } + + HorizontalDivider {} + + if root.items.length == 0 : MaterialText { + text: root.empty_text; + color: root.color; + horizontal_alignment: center; + style: MaterialTypography.label_small; + } + + if root.items.length == 0 : Rectangle {} + + if root.items.length > 0 : ListView { + horizontal_stretch: 1; + + for item[index] in root.items : SearchTile { + text: item.text; + supporting_text: item.supporting_text; + avatar_icon: item.avatar_icon; + avatar_text: item.avatar_text; + avatar_background: item.avatar_background; + avatar_foreground: item.avatar_foreground; + action_button_icon: item.action_button_icon; + + clicked => { + root.text = self.text; + popup.close(); + } + + action_button_clicked => { + root.action_button_clicked(index); + } + } + } + } + + animate height { + duration: MaterialAnimations.standard_accelerate_duration; + easing: MaterialAnimations.standard_easing; + } + } + + Timer { + interval: 50ms; + + triggered => { + background_layer.height = popup.height; + self.running = false; + } + } + } +} diff --git a/material-1.0/ui/components/segmented_button.slint b/material-1.0/ui/components/segmented_button.slint new file mode 100644 index 0000000..21acf94 --- /dev/null +++ b/material-1.0/ui/components/segmented_button.slint @@ -0,0 +1,103 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { BaseButton } from "base_button.slint"; +import { Icons } from "../icons/icons.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; + +export struct SegmentedItem { + icon: image, + text: string +} + +component SegmentedItemTemplate { + in property icon; + in property text; + in property index; + in property selected; + in property last; + + callback clicked <=> base.clicked; + + accessible-role: list-item; + accessible-label: root.text; + accessible-item-selectable: true; + accessible-item-selected: root.selected; + accessible-item-index: root.index; + + if root.selected : Rectangle { + background: MaterialPalette.secondary_container; + } + + base := BaseButton { + min_layout_width: 0; + min_layout_height: 0; + color: MaterialPalette.on_surface; + button_vertical_padding: MaterialStyleMetrics.padding_10; + button_horizontal_padding: MaterialStyleMetrics.padding_24; + spacing: MaterialStyleMetrics.spacing_8; + icon: root.icon; + text: root.text; + + + animate width { duration: MaterialAnimations.standard_accelerate_duration; easing: MaterialAnimations.standard_easing; } + } + + if !root.last : Rectangle { + x: parent.width - self.width; + width: 1px; + height: 100%; + background: MaterialPalette.outline; + } + + states [ + selected when root.selected : { + base.icon: Icons.check; + } + ] +} + +export component SegmentedButton { + in property <[SegmentedItem]> items; + in_out property current_index; + + callback index_changed(index: int); + + min_width: max(2 * MaterialStyleMetrics.size_40, layout.min_width); + min_height: max(MaterialStyleMetrics.size_40, layout.min_height); + + accessible-role: list; + accessible-item-count: root.items.length; + + Rectangle { + clip: true; + border_width: 1px; + border_radius: self.height / 2; + border_color: MaterialPalette.outline; + + layout := HorizontalLayout { + for item[index] in root.items : SegmentedItemTemplate { + icon: item.icon; + text: item.text; + index: index; + last: index == root.items.length - 1; + selected: index == root.current_index; + + clicked => { + root.select(index); + } + } + } + } + + function select(index: int) { + if index < 0 || index >= root.items.length { + return; + } + + root.current_index = index; + root.index_changed(index); + } +} diff --git a/material-1.0/ui/components/slider.slint b/material-1.0/ui/components/slider.slint new file mode 100644 index 0000000..cc846b6 --- /dev/null +++ b/material-1.0/ui/components/slider.slint @@ -0,0 +1,136 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT +// +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { StateLayer } from "./state_layer.slint"; + +export component Slider { + in property enabled; + in_out property value; + in property minimum; + in property stop_count: 0; + in property maximum: 100; + + callback released(value: float); + callback value_changed(value: float); + + property steps: root.stop_count > 0 ? (root.maximum - root.minimum) / root.stop_count : 1; + + min_height: 20px; + accessible-role: slider; + accessible-enabled: root.enabled; + accessible-value: root.value; + accessible-value-minimum: root.minimum; + accessible-value-maximum: root.maximum; + accessible-value-step: min(steps, (root.maximum - root.minimum) / 100); + forward-focus: focus_scope; + + focus_scope := FocusScope { + touch_area := TouchArea { + track := Rectangle { + x: 0; + height: MaterialStyleMetrics.size_16; + background: MaterialPalette.surface_container_highest; + border_radius: self.height / 2; + + Rectangle { + x: 0; + width: state_layer.x - MaterialStyleMetrics.size_6; + border-top-left-radius: track.border_radius; + border-bottom-left-radius: track.border_radius; + border-top-right-radius: MaterialStyleMetrics.size_1; + border-bottom-right-radius: MaterialStyleMetrics.size_1; + background: thumb.background; + } + + if root.stop_count > 0: Rectangle { + width: 100%; + height: 100%; + + for i in (root.maximum - root.minimum) / root.steps: Rectangle { + x: root.value_to_length(track.width, (i + 1) * root.steps) - self.width / 2; + height: MaterialStyleMetrics.size_4; + width: self.height; + border_radius: self.height / 2; + background: MaterialPalette.outline; + } + } + } + + state_layer := Rectangle { + x: root.value_to_length(track.width, root.value) - (self.width) / 2; + width: 0; + height: track.height + (MaterialStyleMetrics.size_14 * 2); + StateLayer { + height: track.height + (MaterialStyleMetrics.size_16 * 2); + width: thumb.width + (MaterialStyleMetrics.size_2 * 2); + border_radius: self.width / 2; + pressed: touch_area.pressed; + has_hover: touch_area.has_hover; + has_focus: focus_scope.has_focus; + enabled: root.enabled; + background: thumb.background; + display_background: thumb_area.pressed || thumb_area.has_hover || focus_scope.has_focus; + + thumb_area := TouchArea { + height: track.height + (MaterialStyleMetrics.size_14 * 2); + width: self.height; + thumb := Rectangle { + width: MaterialStyleMetrics.size_4; + border_radius: self.width / 2; + background: MaterialPalette.primary; + } + + moved => { + root.set_value(root.length_to_value(state_layer.x + self.mouse_x, track.width)); + } + + pointer_event(event) => { + if event.kind == PointerEventKind.up { + root.released(root.value); + } + } + } + } + } + + pointer_event(event) => { + if event.kind == PointerEventKind.down && event.button == PointerEventButton.left { + root.set_value(root.length_to_value(self.mouse_x, track.width)); + } + if event.kind == PointerEventKind.up { + root.released(root.value); + } + } + } + + key_pressed(event) => { + if event.text == Key.LeftArrow { + root.set_value(root.value - root.steps); + return accept; + } + if event.text == Key.RightArrow { + root.set_value(root.value + root.steps); + return accept; + } + reject + } + } + + changed value => { + root.value_changed(root.value); + } + + pure function value_to_length(width: length, value: float) -> length { + clamp(width * (value - root.minimum) / (root.maximum - root.minimum), 0, width) + } + + pure function length_to_value(x: length, width: length) -> float { + x * (root.maximum - root.minimum) / width + } + + function set_value(value: float) { + root.value = clamp(round(value / root.steps) * root.steps, root.minimum, root.maximum) + } +} diff --git a/material-1.0/ui/components/snack_bar.slint b/material-1.0/ui/components/snack_bar.slint new file mode 100644 index 0000000..962c742 --- /dev/null +++ b/material-1.0/ui/components/snack_bar.slint @@ -0,0 +1,88 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { Elevation } from "elevation.slint"; +import { MaterialText } from "./material_text.slint"; +import { TextButton } from "./text_button.slint"; +import { IconButton } from "./icon_button.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { Icons } from "../icons/icons.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; + +export component SnackBar inherits PopupWindow { + in property text; + in property action_text; + in property has_close_button; + + close_policy: no_auto_close; + + callback action_clicked(); + + snack_bar := Elevation { + x: (parent.width - self.width) / 2; + y: parent.height - self.height; + width: MaterialStyleMetrics.size_344; + level: 3; + + background_layer := Rectangle { + background: MaterialPalette.inverse_surface; + border_radius: MaterialStyleMetrics.border_radius_4; + + HorizontalLayout { + padding_left: MaterialStyleMetrics.padding_16; + padding_right: self.padding_left; + padding_top: MaterialStyleMetrics.padding_10; + padding_bottom: self.padding_top; + spacing: MaterialStyleMetrics.spacing_4; + + MaterialText { + text: root.text; + vertical_alignment: center; + horizontal_alignment: left; + wrap: word_wrap; + style: MaterialTypography.body_medium; + color: MaterialPalette.inverse_on_surface; + } + + if root.action_text != "" : TextButton { + text: root.action_text; + inverse: true; + + clicked => { + root.raise_action(); + } + } + + if root.has_close_button : IconButton { + icon: Icons.close; + inverse: true; + + clicked => { + root.close(); + } + } + } + } + + animate y, height { + duration: MaterialAnimations.standard_accelerate_duration; + easing: MaterialAnimations.standard_easing; + } + } + + Timer { + interval: 50ms; + + triggered => { + snack_bar.y = root.height - snack_bar.height - MaterialStyleMetrics.padding_30; + self.running = false; + } + } + + function raise_action() { + root.action_clicked(); + root.close(); + } +} diff --git a/material-1.0/ui/components/state_layer.slint b/material-1.0/ui/components/state_layer.slint new file mode 100644 index 0000000..ee50f74 --- /dev/null +++ b/material-1.0/ui/components/state_layer.slint @@ -0,0 +1,171 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialAnimations } from "../styling/material_animations.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { ToolTip } from "./tooltip.slint"; +import { MaterialWindowAdapter } from "./material_window.slint"; + +export component Ripple { + in property border_radius; + in property pressed_x; + in property pressed_y; + in property color; + in property clip_ripple: true; + + Rectangle { + width: 100%; + height: 100%; + border_radius: root.border_radius; + clip: root.clip_ripple; + + ripple := Rectangle { + x: root.pressed_x - self.width / 2; + y: root.pressed_y - self.height / 2; + height: self.width; + border_radius: self.width / 2; + opacity: MaterialPalette.state_layer_opacity_press; + background: root.color; + + init => { + self.width = root.width * 2 * 1.4142; + } + + animate width { duration: MaterialAnimations.ripple_duration; easing: MaterialAnimations.ripple_easing; } + } + } +} + +export component StateLayer { + in property background; + in property border_radius; + in property display_background: true; + in property enabled; + in property pressed; + in property has_focus; + in property has_hover; + + property state_layer_opacity; + + Rectangle { + width: 100%; + height: 100%; + opacity: root.state_layer_opacity; + background: root.background; + border_radius: root.border_radius; + } + + Rectangle { + width: 100%; + height: 100%; + clip: true; + border_radius: root.border_radius; + + @children + } + + states [ + disabled when !root.enabled && root.display_background : { + root.state_layer_opacity: MaterialPalette.state_layer_opacity_focus; + } + focus when root.enabled && root.has_focus : { + root.state_layer_opacity: MaterialPalette.state_layer_opacity_focus; + } + pressed when root.enabled && root.pressed : { + root.state_layer_opacity: MaterialPalette.state_layer_opacity_press; + } + hover when root.enabled && root.has_hover && !MaterialWindowAdapter.disable_hover : { + root.state_layer_opacity: MaterialPalette.state_layer_opacity_hover; + } + ] + + animate state_layer_opacity { duration: MaterialAnimations.opacity_duration; easing: MaterialAnimations.opacity_easing; } +} + +export component FocusTouchArea inherits TouchArea { + out property has_focus <=> focus_scope.has_focus; + out property enter_pressed; + in property tooltip; + in property tooltip_offset; + + callback key_pressed(KeyEvent) -> EventResult; + + forward_focus: focus_scope; + + focus_scope := FocusScope { + x: 0; + width: 0px; + enabled: root.enabled; + + key_pressed(event) => { + if !root.enabled { + return reject; + } + + if (event.text == " " || event.text == "\n") && !root.enter_pressed { + root.enter_pressed = true; + root.clicked(); + return accept; + } + + root.key_pressed(event) + } + + key_released(event) => { + if !root.enabled { + return reject; + } + + if (event.text == " " || event.text == "\n") && root.enter_pressed { + root.enter_pressed = false; + return accept; + } + + reject + } + } + + @children + + + if root.tooltip != "" && root.has_hover && !MaterialWindowAdapter.disable_hover && !root.pressed : ToolTip { + y: root.tooltip_offset; + text: root.tooltip; + } +} + +export component StateLayerArea inherits FocusTouchArea { + in property color; + in property border_radius; + in property transparent_background; + in property display_background: true; + in property clip_ripple: true; + + property popup_open; + property has_h: root.mouse-x > 0 && root.mouse-x < root.width && root.mouse-y > 0 && root.mouse-y < root.height; + + if !root.enabled || (root.enabled && (root.has_focus || root.pressed || root.enter_pressed || root.has_hover)) : StateLayer { + width: 100%; + height: 100%; + background: root.transparent_background ? transparent : root.color; + border_radius: root.border_radius; + enabled: root.enabled; + pressed: root.pressed || root.enter_pressed; + has_focus: root.has_focus; + has_hover: root.has_hover; + display_background: root.display_background; + } + + // ripple + if root.enabled && (root.pressed || root.enter_pressed) : Ripple { + pressed_x: root.pressed_x; + pressed_y: root.pressed_y; + width: 100%; + height: 100%; + border_radius: root.border_radius; + color: root.color; + clip_ripple: root.clip_ripple; + } + + @children +} diff --git a/material-1.0/ui/components/switch.slint b/material-1.0/ui/components/switch.slint new file mode 100644 index 0000000..9409ecc --- /dev/null +++ b/material-1.0/ui/components/switch.slint @@ -0,0 +1,151 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { FocusTouchArea, StateLayer, Ripple } from "./state_layer.slint"; +import { Icon } from "./icon.slint"; + +export component Switch { + in_out property checked; + in property enabled: true; + in property tooltip <=> touch_area.tooltip; + in property on_icon; + in property off_icon; + + property has_icon: (root.checked && root.on_icon.width > 0 && root.on_icon.height > 0) || (root.off_icon.width > 0 && root.off_icon.height > 0); + property foreground: root.checked ? MaterialPalette.on_primary_container : MaterialPalette.surface_container_highest; + + callback checked_state_changed(checked: bool); + + min_width: MaterialStyleMetrics.size_52; + min_height: MaterialStyleMetrics.size_32; + + accessible-enabled: root.enabled; + accessible-checkable: true; + accessible-checked <=> root.checked; + accessible-role: checkbox; + accessible-action-default => { touch_area.clicked(); } + forward_focus: touch_area; + + touch_area := FocusTouchArea { + enabled: root.enabled; + + background_layer := Rectangle { + background: root.checked ? MaterialPalette.primary : MaterialPalette.surface_container_highest; + border_radius: self.height / 2; + border_width: root.checked ? 0 : 2px; + border_color: MaterialPalette.outline; + + state_layer := StateLayer { + x: indicator.x + (indicator.width - self.width) / 2; + width: self.height; + height: root.height + MaterialStyleMetrics.size_8; + border_radius: self.height / 2; + has_hover: touch_area.has_hover; + has_focus: touch_area.has_focus; + pressed: touch_area.pressed; + enabled: root.enabled; + + // ripple + if root.enabled && (touch_area.pressed || touch_area.enter_pressed) : Ripple { + pressed_x: touch_area.pressed_x; + pressed_y: touch_area.pressed_y; + width: 100%; + height: 100%; + border_radius: state_layer.border_radius; + color: state_layer.background; + clip_ripple: true; + } + } + + indicator := Rectangle { + property indicator-padding: root.checked || root.has_icon ? MaterialStyleMetrics.padding_4 : MaterialStyleMetrics.padding_8; + + property default_height: background_layer.height - 2 * self.indicator-padding; + + x: self.indicator-padding - (self.height - self.default_height) / 2; + width: self.height; + height: self.default_height; + border_radius: self.height / 2; + background: root.checked ? MaterialPalette.primary_container : MaterialPalette.outline; + + if root.has_icon : Icon { + source: root.checked ? root.on_icon : root.off_icon; + colorize: root.foreground; + + animate colorize { + duration: MaterialAnimations.opacity_duration; + easing: MaterialAnimations.opacity_easing; + } + } + + animate height { + duration: MaterialAnimations.emphasized_accelerate_duration; + easing: MaterialAnimations.emphasized_easing; + } + + animate background { + duration: MaterialAnimations.opacity_duration; + easing: MaterialAnimations.opacity_easing; + } + + states [ + checked when root.checked : { + x: background_layer.width - self.indicator-padding - self.width; + + in { + animate x { + duration: MaterialAnimations.emphasized_accelerate_duration; + easing: MaterialAnimations.emphasized_easing; + } + } + + out { + animate x { + duration: MaterialAnimations.emphasized_accelerate_duration; + easing: MaterialAnimations.emphasized_easing; + } + } + } + ] + } + + animate background, border_color { + duration: MaterialAnimations.opacity_duration; + easing: MaterialAnimations.opacity_easing; + } + } + + clicked => { + root.toggle(); + } + } + + function toggle() { + root.checked = !root.checked; + } + + changed checked => { + root.checked_state_changed(root.checked); + } + + states [ + disabled when !root.enabled : { + state_layer.display_background: false; + indicator.background: root.checked ? MaterialPalette.surface : MaterialPalette.outline.with_alpha(MaterialPalette.disable_opacity); + background_layer.background: (root.checked ? MaterialPalette.on_surface : MaterialPalette.surface_variant).with_alpha(MaterialPalette.state_layer_opacity_disabled); + background_layer.border_color: MaterialPalette.on_surface.with_alpha(MaterialPalette.state_layer_opacity_disabled); + foreground: root.checked ? MaterialPalette.on_surface.with_alpha(MaterialPalette.disable_opacity) : MaterialPalette.surface_container_highest; + } + pressed when touch_area.pressed: { + state_layer.background: indicator.background; + indicator.height: background_layer.height - 2px; + indicator.background: root.checked ? MaterialPalette.primary_container : MaterialPalette.on_surface_variant; + } + hover when touch_area.has_hover: { + state_layer.background: indicator.background; + } + ] +} diff --git a/material-1.0/ui/components/tab_bar.slint b/material-1.0/ui/components/tab_bar.slint new file mode 100644 index 0000000..0be204b --- /dev/null +++ b/material-1.0/ui/components/tab_bar.slint @@ -0,0 +1,210 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { NavigationItem } from "../items/navigation_item.slint"; +import { BaseNavigationItemTemplate, BaseNavigation } from "./base_navigation.slint"; +import { StateLayerArea } from "./state_layer.slint"; +import { MaterialText } from "./material_text.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; +import { Icon } from "./icon.slint"; + +component TabItemTemplate inherits BaseNavigationItemTemplate { + out property label_width: label.width; + + property has_selected_icon: root.selected_icon.width > 0 || root.selected_icon.height > 0; + + StateLayerArea { + color: MaterialPalette.primary; + + VerticalLayout { + padding_top: MaterialStyleMetrics.padding_10; + padding_bottom: MaterialStyleMetrics.padding_8; + spacing: MaterialStyleMetrics.spacing_2; + + if root.icon.width > 0 && root.icon.height > 0 : HorizontalLayout { + alignment: center; + + Icon { + source: root.icon; + colorize: label.color; + + states [ + selected when root.selected && root.has_selected_icon : { + source: root.selected_icon; + } + ] + } + } + + HorizontalLayout { + alignment: center; + + label := MaterialText { + text: root.text; + style: MaterialTypography.title_small; + color: MaterialPalette.on_surface_variant; + } + } + } + + clicked => { + root.clicked(); + } + } + + states [ + selected when root.selected : { + label.color: MaterialPalette.primary; + } + ] +} + +component SecondaryTabItemTemplate inherits BaseNavigationItemTemplate { + property has_selected_icon: root.selected_icon.width > 0 || root.selected_icon.height > 0; + + StateLayerArea { + color: label.color; + + HorizontalLayout { + alignment: center; + spacing: MaterialStyleMetrics.spacing_8; + + if root.icon.width > 0 && root.icon.height > 0 : VerticalLayout { + alignment: center; + + Icon { + source: root.icon; + colorize: label.color; + + states [ + selected when root.selected && root.has_selected_icon : { + source: root.selected_icon; + } + ] + } + } + + + label := MaterialText { + text: root.text; + style: MaterialTypography.title_small; + color: MaterialPalette.on_surface_variant; + vertical_alignment: center; + } + } + + clicked => { + root.clicked(); + } + } + + states [ + selected when root.selected : { + label.color: MaterialPalette.on_surface; + } + ] +} + +export component TabBar inherits BaseNavigation { + property indicator_width; + property item_width: root.width / root.items.length; + property current_x: root.item_width * self.current_index; + + min_height: max(MaterialStyleMetrics.size_49, layout.min_height); + + Rectangle { + background: MaterialPalette.surface; + + layout := HorizontalLayout { + for item[index] in root.items : tab_item := TabItemTemplate { + icon: item.icon; + selected_icon: item.selected_icon; + text: item.text; + index: index; + selected: index == root.current_index; + show_badge: item.show_badge; + badge: item.badge; + + clicked => { + root.select(index); + root.set_indicator_width(index, self.label_width); + } + + Timer { + interval: 50ms; + + triggered => { + root.set_indicator_width(index, tab_item.label_width); + self.running = false; + } + } + } + } + + indicator := Rectangle { + x: root.current_x + (root.item_width - self.width) / 2; + y: parent.height - self.height; + width: root.indicator_width; + height: MaterialStyleMetrics.size_3; + border_top_left_radius: self.height / 2; + border_top_right_radius: self.border_top_left_radius; + background: MaterialPalette.primary; + + animate x, width { + duration: MaterialAnimations.standard_accelerate_duration; + easing: MaterialAnimations.standard_easing; + } + } + } + + function set_indicator_width(index: int, width: length) { + if index != root.current_index { + return; + } + + root.indicator_width = width; + } +} + +export component SecondaryTabBar inherits BaseNavigation { + property item_width: root.width / root.items.length; + property current_x: root.item_width * self.current_index; + + min_height: max(MaterialStyleMetrics.size_49, layout.min_height); + + Rectangle { + background: MaterialPalette.surface; + + layout := HorizontalLayout { + for item[index] in root.items : SecondaryTabItemTemplate { + icon: item.icon; + selected_icon: item.selected_icon; + text: item.text; + index: index; + selected: index == root.current_index; + show_badge: item.show_badge; + badge: item.badge; + + clicked => { + root.select(index); + } + } + } + + indicator := Rectangle { + x: root.current_x; + y: parent.height - self.height; + width: root.item_width; + height: MaterialStyleMetrics.size_2; + background: MaterialPalette.primary; + + animate x { + duration: MaterialAnimations.standard_accelerate_duration; + easing: MaterialAnimations.standard_easing; + } + } + } +} diff --git a/material-1.0/ui/components/text_button.slint b/material-1.0/ui/components/text_button.slint new file mode 100644 index 0000000..e04e513 --- /dev/null +++ b/material-1.0/ui/components/text_button.slint @@ -0,0 +1,33 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { BaseButton } from "./base_button.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; + +export component TextButton { + in property icon <=> base.icon; + in property text <=> base.text; + in property enabled <=> base.enabled; + in property tooltip <=> base.tooltip; + in property inverse; + + callback clicked <=> base.clicked; + + accessible-role: button; + accessible-enabled: root.enabled; + accessible-label: root.text == "" ? root.tooltip : root.text; + accessible-action-default => { base.clicked(); } + + base := BaseButton { + border_radius: root.height / 2; + color: root.inverse ? MaterialPalette.inverse_primary : MaterialPalette.primary; + } + + states [ + disabled when !root.enabled : { + base.color: MaterialPalette.on_surface; + base.transparent_background: true; + } + ] +} diff --git a/material-1.0/ui/components/text_field.slint b/material-1.0/ui/components/text_field.slint new file mode 100644 index 0000000..320eb01 --- /dev/null +++ b/material-1.0/ui/components/text_field.slint @@ -0,0 +1,209 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialAnimations } from "../styling/material_animations.slint"; +import { MaterialText } from "./material_text.slint"; +import { IconButton } from "./icon_button.slint"; +import { Icon } from "./icon.slint"; + +export component TextField { + in property label; + in property placeholder_text; + in property supporting_text; + in property has_error; + in property leading_icon; + in property trailing_icon; + in property enabled: true; + in property read_only <=> input.read_only; + out property has_focus: input.has_focus; + in_out property text <=> input.text; + + callback leading_icon_clicked(); + callback trailing_icon_clicked(); + callback accepted(text: string); + callback edited(text: string); + callback key_pressed(event: KeyEvent) -> EventResult; + callback key_released(event: KeyEvent) -> EventResult; + + property has_leading: root.leading_icon.width > 0 && root.leading_icon.height > 0; + property has_trailing: root.trailing_icon.width > 0 && root.trailing_icon.height > 0; + property computed_x; + property highlight: root.enabled && root.has_error ? MaterialPalette.error : root.has_focus ? MaterialPalette.primary : MaterialPalette.on_surface_variant; + + forward_focus: input; + accessible-role: text-input; + accessible-enabled: root.enabled; + accessible-value <=> text; + accessible-placeholder-text: root.text == "" ? placeholder_text : ""; + accessible-action-set-value(v) => { text = v; edited(v); } + + layout := VerticalLayout { + spacing: MaterialStyleMetrics.spacing_4; + + background_layer := Rectangle { + border_top_left_radius: MaterialStyleMetrics.border_radius_4; + border_top_right_radius: MaterialStyleMetrics.border_radius_4; + background: MaterialPalette.surface_container_highest; + min_height: max(MaterialStyleMetrics.size_56, inner_layout.min_height); + + inner_layout := HorizontalLayout { + padding_left: root.has_leading ? MaterialStyleMetrics.padding_4 : MaterialStyleMetrics.padding_16; + padding_right: root.has_trailing ? MaterialStyleMetrics.padding_4 : MaterialStyleMetrics.padding_16; + padding_top: MaterialStyleMetrics.padding_4; + padding_bottom: self.padding_top; + spacing: MaterialStyleMetrics.spacing_2; + + if root.has_leading : IconButton { + icon: root.leading_icon; + enabled: root.enabled; + + clicked => { + root.leading_icon_clicked(); + } + } + + HorizontalLayout { + padding_top: MaterialStyleMetrics.padding_4; + padding_bottom: self.padding_top; + + Rectangle { + horizontal_stretch: 1; + clip: true; + min_height: input.min_height; + + input := TextInput { + x: min(0px, max(parent.width - self.width - self.text_cursor_width, root.computed_x)); + width: max(parent.width - self.text-cursor-width, self.preferred-width); + font_size: MaterialTypography.body_large.font_size; + font_weight: MaterialTypography.body_large.font_weight; + text_cursor_width: MaterialStyleMetrics.size_3; + vertical_alignment: bottom; + single_line: true; + color: MaterialPalette.on_surface; + selection_background_color: MaterialPalette.primary.with_alpha(0.5); + selection_foreground_color: self.color; + enabled: root.enabled; + // Disable TextInput's built-in accessibility support as the component takes care of that. + accessible-role: none; + + cursor_position_changed(cursor_position) => { + if cursor_position.x + root.computed_x < 0 { + root.computed_x = - cursor_position.x; + } else if cursor-position.x + root.computed_x > parent.width - self.text-cursor-width { + root.computed_x = parent.width - cursor_position.x - self.text-cursor-width; + } + } + + accepted => { + root.accepted(self.text); + } + + edited => { + root.edited(self.text); + } + + key_pressed(event) => { + root.key_pressed(event) + } + + key_released(event) => { + root.key_released(event) + } + } + + text_label := MaterialText { + y: (parent.height - self.height) / 2; + width: 100%; + text: root.label; + color: root.highlight; + style: MaterialTypography.body_large; + + states [ + on_top when root.text != "" || input.has_focus : { + y: 0; + style: MaterialTypography.body_small; + } + ] + + animate font_size, y { + duration: MaterialAnimations.standard_fast_duration; + easing: MaterialAnimations.standard_easing; + } + } + } + } + + if root.trailing_icon.width > 0 && root.trailing_icon.height > 0 : IconButton { + icon: root.trailing_icon; + enabled: root.enabled; + has_error: root.has_error; + + clicked => { + root.trailing_icon_clicked(); + } + } + } + + active_indicator := Rectangle { + y: parent.height - self.height; + height: MaterialStyleMetrics.size_1; + background: root.highlight; + + animate height { + duration: MaterialAnimations.standard_fast_duration; + easing: MaterialAnimations.standard_easing; + } + } + } + + if root.supporting_text != "" : HorizontalLayout { + padding_left: MaterialStyleMetrics.padding_16; + padding_right: self.padding_left; + + supporting_text := MaterialText { + text: root.supporting_text; + style: MaterialTypography.body_small; + color: root.highlight; + opacity: root.enabled ? 1 : MaterialPalette.disable_opacity; + } + } + } + + public function set_selection_offsets(start: int, end: int) { + input.set_selection_offsets(start, end); + } + + public function select_all() { + input.select_all(); + } + + public function clear_selection() { + input.clear_selection(); + } + + public function cut() { + input.cut(); + } + + public function copy() { + input.copy(); + } + + public function paste() { + input.paste(); + } + + states [ + disabled when !root.enabled : { + background_layer.background: MaterialPalette.surface_container_highest.with_alpha(MaterialPalette.disable_opacity); + text_label.opacity: MaterialPalette.disable_opacity; + input.opacity: MaterialPalette.disable_opacity; + } + focused when input.has_focus : { + active_indicator.height: MaterialStyleMetrics.size_3; + } + ] +} diff --git a/material-1.0/ui/components/time_picker.slint b/material-1.0/ui/components/time_picker.slint new file mode 100644 index 0000000..5109e62 --- /dev/null +++ b/material-1.0/ui/components/time_picker.slint @@ -0,0 +1,674 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: MIT + +import { BaseDialog } from "./dialog.slint"; +import { Icons } from "../icons/icons.slint"; +import { MaterialText } from "./material_text.slint"; +import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint"; +import { MaterialTypography } from "../styling/material_typography.slint"; +import { MaterialPalette } from "../styling/material_palette.slint"; +import { StateLayerArea } from "state_layer.slint"; + +component TimeSelector inherits Rectangle { + in property selected; + in property value; + + callback clicked <=> touch_area.clicked; + + width: max(MaterialStyleMetrics.size_48, text_label.min_width); + height: max(MaterialStyleMetrics.size_48, text_label.min_height); + border_radius: max(root.width, root.height) / 2; + vertical_stretch: 0; + horizontal_stretch: 0; + + touch_area := TouchArea { + text_label := MaterialText { + text: root.value; + vertical_alignment: center; + horizontal_alignment: center; + style: MaterialTypography.body_large; + color: MaterialPalette.on_surface; + } + } + + states [ + selected when root.selected: { + text_label.color: MaterialPalette.on_primary; + } + ] +} + +component Clock { + in property <[int]> model; + in property two_columns; + in property total; + in_out property current_index; + in property current_value; + + callback current_index_changed(index: int); + + property radius: max(root.width, root.height) / 2; + property picker_ditameter: MaterialStyleMetrics.size_48; + property center: root.radius - root.picker_ditameter / 2; + property outer_padding: 2px; + property inner_padding: 32px; + property radius_outer: root.center - root.outer_padding; + property radius_inner: root.center - root.inner_padding; + property half_total: root.total / 2; + property rotation: 0.25turn; + property current_x: get_index_x(root.current_value); + property current_y: get_index_y(root.current_value); + + min_width: MaterialStyleMetrics.size_256; + min_height: self.min_width; + vertical_stretch: 0; + horizontal_stretch: 0; + + background_layer := Rectangle { + border_radius: max(self.width, self.height) / 2; + background: MaterialPalette.surface_container_highest; + + if root.current_index >= 0 || root.current_index < root.model.length: Path { + stroke: MaterialPalette.primary; + stroke_width: 2px; + viewbox_width: self.width / 1px; + viewbox_height: self.height / 1px; + + MoveTo { + x: root.width / 2px; + y: root.height / 2px; + } + + LineTo { + x: (root.current_x + root.picker_ditameter / 2) / 1px; + y: (root.current_y + root.picker_ditameter / 2) / 1px; + } + } + + Rectangle { + width: MaterialStyleMetrics.size_8; + height: self.width; + background: MaterialPalette.primary; + border_radius: self.width / 2; + } + + if root.current_index < root.model.length: Rectangle { + x: root.current_x; + y: root.current_y; + width: root.picker_ditameter; + height: root.picker_ditameter; + border_radius: root.picker_ditameter / 2; + background: MaterialPalette.primary; + + if root.current_index < 0: Rectangle { + width: MaterialStyleMetrics.size_4; + height: self.width; + border_radius: self.width / 2; + background: MaterialPalette.on_primary; + } + } + + for val[index] in root.model: TimeSelector { + x: get_index_x(val); + y: get_index_y(val); + width: root.picker_ditameter; + height: root.picker_ditameter; + value: val; + selected: index == root.current_index; + accessible_role: button; + accessible_label: @tr("{} Hours or minutes of {}", val, root.total); + accessible_action_default => { + self.clicked(); + } + + clicked => { + root.set_current_index(index); + } + } + } + + + pure function value_to_angle(value: int) -> angle { + if root.two_columns { + if value >= root.half_total { + return clamp((value - root.half_total) / root.half_total * 1turn, 0, 0.999999turn) - root.rotation; + } + return clamp(value / root.half_total * 1turn, 0, 0.99999turn) - root.rotation; + } + + clamp(value / root.total * 1turn, 0, 0.99999turn) - root.rotation + } + + pure function get_index_x(value: int) -> length { + if root.two_columns && value >= root.half_total { + return root.center + (root.radius_inner / 1px * cos(root.value_to_angle(value))) * 1px; + } + + root.center + (root.radius_outer / 1px * cos(root.value_to_angle(value))) * 1px + } + + pure function get_index_y(value: int) -> length { + // this is only for 24 mode + if root.total == 24 && value == 0 { + return root.center + (root.radius_inner / 1px * sin(root.value_to_angle(value))) * 1px; + } + if root.total == 24 && value == 12 { + return root.center + (root.radius_outer / 1px * sin(root.value_to_angle(value))) * 1px; + } + if root.two_columns && value >= root.half_total { + return root.center + (root.radius_inner / 1px * sin(root.value_to_angle(value))) * 1px; + } + + root.center + (root.radius_outer / 1px * sin(root.value_to_angle(value))) * 1px + } + + function set_current_index(index: int) { + root.current_index_changed(index); + } +} + +component TimePickerInput { + in property read_only <=> text_input.read_only; + in property checked; + in_out property text <=> text_input.text; + + callback clicked; + callback edited(value: int); + + width: MaterialStyleMetrics.size_90; + min_height: max(MaterialStyleMetrics.size_80, layout.min_height); + vertical_stretch: 0; + horizontal_stretch: 0; + + forward_focus: text_input; + + background_layer := Rectangle { + border_radius: MaterialStyleMetrics.border_radius_8; + background: MaterialPalette.surface_container_highest; + clip: true; + + layout := HorizontalLayout { + padding: MaterialStyleMetrics.padding_8; + + text_input := TextInput { + vertical_alignment: center; + horizontal_alignment: center; + color: MaterialPalette.on_surface; + font_size: MaterialTypography.display_large.font_size; + font_weight: MaterialTypography.display_large.font_weight; + input_type: number; + visible: !root.read_only; + + edited => { + root.edited(self.text.to_float()); + } + } + } + + if root.read_only : StateLayerArea { + border_radius: background_layer.border_radius; + color: MaterialPalette.on_surface; + + HorizontalLayout { + padding: MaterialStyleMetrics.padding_8; + + MaterialText { + text: root.text.to_float() >= 10 ? root.text : "0" + root.text; + style: MaterialTypography.display_large; + color: MaterialPalette.on_surface; + horizontal_alignment: center; + vertical_alignment: center; + } + } + + clicked => { + root.clicked(); + } + } + } + + states [ + has_focus when text_input.has_focus && !root.read_only: { + background_layer.background: MaterialPalette.primary_container; + background_layer.border_width: 2px; + background_layer.border_color: MaterialPalette.primary; + text_input.color: MaterialPalette.on_primary_container; + } + checked when root.checked: { + background_layer.background: MaterialPalette.primary_container; + text_input.color: MaterialPalette.on_primary_container; + } + ] +} + +component PeriodSelectorItem { + in property text <=> label.text; + in property checked; + + callback clicked <=> state_layer.clicked; + + background_layer := Rectangle { + state_layer := StateLayerArea { + color: label.color; + + label := MaterialText { + color: MaterialPalette.on_surface_variant; + horizontal_alignment: center; + } + } + } + + states [ + checked when root.checked: { + background_layer.background: MaterialPalette.tertiary_container; + label.color: MaterialPalette.on_tertiary_container; + } + ] +} + + +component PeriodSelector { + in property am_selected; + in property horizontal; + + callback update_period(am_selected: bool); + + min_width: max(MaterialStyleMetrics.size_52, layout.min_width); + min_height: max(root.horizontal ? MaterialStyleMetrics.size_38 : MaterialStyleMetrics.size_80, layout.min_height); + accessible_label: "AM or PM"; + accessible_role: checkbox; + accessible_checked: root.am_selected; + + Rectangle { + border_radius: border.border_radius; + clip: true; + + layout := VerticalLayout { + if root.horizontal : HorizontalLayout { + PeriodSelectorItem { + text: "AM"; + checked: root.am_selected; + + clicked => { + if root.am_selected { + return; + } + root.update_period(true); + } + } + + Rectangle { + width: 1px; + background: border.border_color; + vertical_stretch: 0; + } + + PeriodSelectorItem { + text: "PM"; + checked: !root.am_selected; + + clicked => { + if !root.am_selected { + return; + } + root.update_period(false); + } + } + } + + if !root.horizontal : VerticalLayout { + PeriodSelectorItem { + text: "AM"; + checked: root.am_selected; + + clicked => { + if root.am_selected { + return; + } + root.update_period(true); + } + } + + Rectangle { + height: 1px; + background: border.border_color; + vertical_stretch: 0; + } + + PeriodSelectorItem { + text: "PM"; + checked: !root.am_selected; + + clicked => { + if !root.am_selected { + return; + } + root.update_period(false); + } + } + } + } + } + + border := Rectangle { + border_radius: MaterialStyleMetrics.border_radius_8; + border_width: 1px; + border_color: MaterialPalette.outline; + } +} + +export struct Time { + hour: int, + minute: int, + second: int +} + +export component TimePickerPopup inherits PopupWindow { + in property use_24_hour_format: true; + in property title: @tr("Select time"); + in property cancel_text: @tr("Cancel"); + in property ok_text: @tr("Ok"); + in property