From 3eec86e5ed6e8290a17a3adb0a77f939a3c01297 Mon Sep 17 00:00:00 2001 From: onyx-and-iris <75868496+onyx-and-iris@users.noreply.github.com> Date: Mon, 11 Apr 2022 18:35:28 +0100 Subject: [PATCH] initial commit initial commit --- .gitignore | 1 + __main__.py | 12 + configs/app.toml | 15 + configs/vban.toml | 12 + profiles/banana/example.toml | 30 + profiles/basic/example.toml | 15 + profiles/potato/example.toml | 48 ++ setup.py | 25 + vmcompact/__init__.py | 3 + vmcompact/app.py | 177 ++++++ vmcompact/banner.py | 37 ++ vmcompact/channels.py | 376 +++++++++++++ vmcompact/config.py | 458 +++++++++++++++ vmcompact/configurations.py | 20 + vmcompact/data.py | 35 ++ vmcompact/errors.py | 4 + vmcompact/gainlayer.py | 244 ++++++++ vmcompact/img/cat.ico | Bin 0 -> 112922 bytes vmcompact/menu.py | 316 +++++++++++ vmcompact/navigation.py | 156 ++++++ vmcompact/sun-valley-theme/LICENSE | 21 + vmcompact/sun-valley-theme/sun-valley.tcl | 88 +++ vmcompact/sun-valley-theme/theme/dark.tcl | 521 +++++++++++++++++ .../theme/dark/arrow-down.png | Bin 0 -> 270 bytes .../theme/dark/arrow-right.png | Bin 0 -> 261 bytes .../sun-valley-theme/theme/dark/arrow-up.png | Bin 0 -> 274 bytes .../theme/dark/button-accent-disabled.png | Bin 0 -> 262 bytes .../theme/dark/button-accent-hover.png | Bin 0 -> 373 bytes .../theme/dark/button-accent-pressed.png | Bin 0 -> 363 bytes .../theme/dark/button-accent-rest.png | Bin 0 -> 377 bytes .../theme/dark/button-close-hover.png | Bin 0 -> 274 bytes .../theme/dark/button-close-pressed.png | Bin 0 -> 274 bytes .../theme/dark/button-disabled.png | Bin 0 -> 301 bytes .../theme/dark/button-hover.png | Bin 0 -> 276 bytes .../theme/dark/button-pressed.png | Bin 0 -> 288 bytes .../theme/dark/button-rest.png | Bin 0 -> 301 bytes .../theme/dark/button-titlebar-hover.png | Bin 0 -> 245 bytes .../theme/dark/button-titlebar-pressed.png | Bin 0 -> 238 bytes .../sun-valley-theme/theme/dark/card.png | Bin 0 -> 386 bytes .../theme/dark/check-disabled.png | Bin 0 -> 383 bytes .../theme/dark/check-hover.png | Bin 0 -> 474 bytes .../theme/dark/check-pressed.png | Bin 0 -> 460 bytes .../theme/dark/check-rest.png | Bin 0 -> 475 bytes .../theme/dark/check-tri-disabled.png | Bin 0 -> 294 bytes .../theme/dark/check-tri-hover.png | Bin 0 -> 362 bytes .../theme/dark/check-tri-pressed.png | Bin 0 -> 358 bytes .../theme/dark/check-tri-rest.png | Bin 0 -> 363 bytes .../theme/dark/check-unsel-disabled.png | Bin 0 -> 312 bytes .../theme/dark/check-unsel-hover.png | Bin 0 -> 353 bytes .../theme/dark/check-unsel-pressed.png | Bin 0 -> 302 bytes .../theme/dark/check-unsel-rest.png | Bin 0 -> 353 bytes .../sun-valley-theme/theme/dark/empty.png | Bin 0 -> 129 bytes .../theme/dark/entry-disabled.png | Bin 0 -> 273 bytes .../theme/dark/entry-focus.png | Bin 0 -> 335 bytes .../theme/dark/entry-hover.png | Bin 0 -> 269 bytes .../theme/dark/entry-invalid.png | Bin 0 -> 324 bytes .../theme/dark/entry-rest.png | Bin 0 -> 297 bytes .../theme/dark/notebook-border.png | Bin 0 -> 337 bytes .../sun-valley-theme/theme/dark/notebook.png | Bin 0 -> 186 bytes .../theme/dark/progress-pbar-hor.png | Bin 0 -> 193 bytes .../theme/dark/progress-pbar-vert.png | Bin 0 -> 214 bytes .../theme/dark/progress-trough-hor.png | Bin 0 -> 157 bytes .../theme/dark/progress-trough-vert.png | Bin 0 -> 160 bytes .../theme/dark/radio-disabled.png | Bin 0 -> 553 bytes .../theme/dark/radio-hover.png | Bin 0 -> 853 bytes .../theme/dark/radio-pressed.png | Bin 0 -> 786 bytes .../theme/dark/radio-rest.png | Bin 0 -> 830 bytes .../theme/dark/radio-unsel-disabled.png | Bin 0 -> 552 bytes .../theme/dark/radio-unsel-hover.png | Bin 0 -> 602 bytes .../theme/dark/radio-unsel-pressed.png | Bin 0 -> 616 bytes .../theme/dark/radio-unsel-rest.png | Bin 0 -> 621 bytes .../theme/dark/scale-thumb-disabled.png | Bin 0 -> 724 bytes .../theme/dark/scale-thumb-hover.png | Bin 0 -> 808 bytes .../theme/dark/scale-thumb-pressed.png | Bin 0 -> 735 bytes .../theme/dark/scale-thumb-rest.png | Bin 0 -> 771 bytes .../theme/dark/scale-trough-hor.png | Bin 0 -> 216 bytes .../theme/dark/scale-trough-vert.png | Bin 0 -> 215 bytes .../theme/dark/scroll-down.png | Bin 0 -> 226 bytes .../theme/dark/scroll-hor-thumb.png | Bin 0 -> 254 bytes .../theme/dark/scroll-hor-trough.png | Bin 0 -> 338 bytes .../theme/dark/scroll-left.png | Bin 0 -> 233 bytes .../theme/dark/scroll-right.png | Bin 0 -> 227 bytes .../sun-valley-theme/theme/dark/scroll-up.png | Bin 0 -> 236 bytes .../theme/dark/scroll-vert-thumb.png | Bin 0 -> 264 bytes .../theme/dark/scroll-vert-trough.png | Bin 0 -> 343 bytes .../sun-valley-theme/theme/dark/separator.png | Bin 0 -> 128 bytes .../sun-valley-theme/theme/dark/sizegrip.png | Bin 0 -> 276 bytes .../theme/dark/switch-off-disabled.png | Bin 0 -> 733 bytes .../theme/dark/switch-off-hover.png | Bin 0 -> 945 bytes .../theme/dark/switch-off-pressed.png | Bin 0 -> 963 bytes .../theme/dark/switch-off-rest.png | Bin 0 -> 895 bytes .../theme/dark/switch-on-disabled.png | Bin 0 -> 623 bytes .../theme/dark/switch-on-hover.png | Bin 0 -> 927 bytes .../theme/dark/switch-on-pressed.png | Bin 0 -> 936 bytes .../theme/dark/switch-on-rest.png | Bin 0 -> 859 bytes .../sun-valley-theme/theme/dark/tab-hover.png | Bin 0 -> 265 bytes .../sun-valley-theme/theme/dark/tab-rest.png | Bin 0 -> 164 bytes .../theme/dark/tab-selected.png | Bin 0 -> 319 bytes .../theme/dark/treeheading-hover.png | Bin 0 -> 295 bytes .../theme/dark/treeheading-pressed.png | Bin 0 -> 317 bytes .../theme/dark/treeheading-rest.png | Bin 0 -> 321 bytes vmcompact/sun-valley-theme/theme/light.tcl | 526 ++++++++++++++++++ .../theme/light/arrow-down.png | Bin 0 -> 278 bytes .../theme/light/arrow-right.png | Bin 0 -> 273 bytes .../sun-valley-theme/theme/light/arrow-up.png | Bin 0 -> 285 bytes .../theme/light/button-accent-disabled.png | Bin 0 -> 271 bytes .../theme/light/button-accent-hover.png | Bin 0 -> 374 bytes .../theme/light/button-accent-pressed.png | Bin 0 -> 367 bytes .../theme/light/button-accent-rest.png | Bin 0 -> 384 bytes .../theme/light/button-close-hover.png | Bin 0 -> 326 bytes .../theme/light/button-close-pressed.png | Bin 0 -> 316 bytes .../theme/light/button-disabled.png | Bin 0 -> 307 bytes .../theme/light/button-hover.png | Bin 0 -> 306 bytes .../theme/light/button-pressed.png | Bin 0 -> 289 bytes .../theme/light/button-rest.png | Bin 0 -> 303 bytes .../theme/light/button-titlebar-hover.png | Bin 0 -> 238 bytes .../theme/light/button-titlebar-pressed.png | Bin 0 -> 225 bytes .../sun-valley-theme/theme/light/card.png | Bin 0 -> 394 bytes .../theme/light/check-disabled.png | Bin 0 -> 381 bytes .../theme/light/check-hover.png | Bin 0 -> 476 bytes .../theme/light/check-pressed.png | Bin 0 -> 467 bytes .../theme/light/check-rest.png | Bin 0 -> 473 bytes .../theme/light/check-tri-disabled.png | Bin 0 -> 299 bytes .../theme/light/check-tri-hover.png | Bin 0 -> 365 bytes .../theme/light/check-tri-pressed.png | Bin 0 -> 362 bytes .../theme/light/check-tri-rest.png | Bin 0 -> 367 bytes .../theme/light/check-unsel-disabled.png | Bin 0 -> 324 bytes .../theme/light/check-unsel-hover.png | Bin 0 -> 334 bytes .../theme/light/check-unsel-pressed.png | Bin 0 -> 302 bytes .../theme/light/check-unsel-rest.png | Bin 0 -> 333 bytes .../sun-valley-theme/theme/light/empty.png | Bin 0 -> 129 bytes .../theme/light/entry-disabled.png | Bin 0 -> 289 bytes .../theme/light/entry-focus.png | Bin 0 -> 331 bytes .../theme/light/entry-hover.png | Bin 0 -> 302 bytes .../theme/light/entry-invalid.png | Bin 0 -> 324 bytes .../theme/light/entry-rest.png | Bin 0 -> 308 bytes .../theme/light/notebook-border.png | Bin 0 -> 298 bytes .../sun-valley-theme/theme/light/notebook.png | Bin 0 -> 185 bytes .../theme/light/progress-pbar-hor.png | Bin 0 -> 192 bytes .../theme/light/progress-pbar-vert.png | Bin 0 -> 216 bytes .../theme/light/progress-trough-hor.png | Bin 0 -> 158 bytes .../theme/light/progress-trough-vert.png | Bin 0 -> 161 bytes .../theme/light/radio-disabled.png | Bin 0 -> 523 bytes .../theme/light/radio-hover.png | Bin 0 -> 837 bytes .../theme/light/radio-pressed.png | Bin 0 -> 764 bytes .../theme/light/radio-rest.png | Bin 0 -> 773 bytes .../theme/light/radio-unsel-disabled.png | Bin 0 -> 521 bytes .../theme/light/radio-unsel-hover.png | Bin 0 -> 573 bytes .../theme/light/radio-unsel-pressed.png | Bin 0 -> 636 bytes .../theme/light/radio-unsel-rest.png | Bin 0 -> 576 bytes .../theme/light/scale-thumb-disabled.png | Bin 0 -> 658 bytes .../theme/light/scale-thumb-hover.png | Bin 0 -> 749 bytes .../theme/light/scale-thumb-pressed.png | Bin 0 -> 675 bytes .../theme/light/scale-thumb-rest.png | Bin 0 -> 701 bytes .../theme/light/scale-trough-hor.png | Bin 0 -> 208 bytes .../theme/light/scale-trough-vert.png | Bin 0 -> 214 bytes .../theme/light/scroll-down.png | Bin 0 -> 229 bytes .../theme/light/scroll-hor-thumb.png | Bin 0 -> 234 bytes .../theme/light/scroll-hor-trough.png | Bin 0 -> 321 bytes .../theme/light/scroll-left.png | Bin 0 -> 232 bytes .../theme/light/scroll-right.png | Bin 0 -> 223 bytes .../theme/light/scroll-up.png | Bin 0 -> 237 bytes .../theme/light/scroll-vert-thumb.png | Bin 0 -> 262 bytes .../theme/light/scroll-vert-trough.png | Bin 0 -> 324 bytes .../theme/light/separator.png | Bin 0 -> 128 bytes .../sun-valley-theme/theme/light/sizegrip.png | Bin 0 -> 272 bytes .../theme/light/switch-off-disabled.png | Bin 0 -> 726 bytes .../theme/light/switch-off-hover.png | Bin 0 -> 867 bytes .../theme/light/switch-off-pressed.png | Bin 0 -> 880 bytes .../theme/light/switch-off-rest.png | Bin 0 -> 814 bytes .../theme/light/switch-on-disabled.png | Bin 0 -> 590 bytes .../theme/light/switch-on-hover.png | Bin 0 -> 906 bytes .../theme/light/switch-on-pressed.png | Bin 0 -> 916 bytes .../theme/light/switch-on-rest.png | Bin 0 -> 857 bytes .../theme/light/tab-hover.png | Bin 0 -> 295 bytes .../sun-valley-theme/theme/light/tab-rest.png | Bin 0 -> 164 bytes .../theme/light/tab-selected.png | Bin 0 -> 318 bytes .../theme/light/treeheading-hover.png | Bin 0 -> 338 bytes .../theme/light/treeheading-pressed.png | Bin 0 -> 318 bytes .../theme/light/treeheading-rest.png | Bin 0 -> 330 bytes 180 files changed, 3140 insertions(+) create mode 100644 __main__.py create mode 100644 configs/app.toml create mode 100644 configs/vban.toml create mode 100644 profiles/banana/example.toml create mode 100644 profiles/basic/example.toml create mode 100644 profiles/potato/example.toml create mode 100644 setup.py create mode 100644 vmcompact/__init__.py create mode 100644 vmcompact/app.py create mode 100644 vmcompact/banner.py create mode 100644 vmcompact/channels.py create mode 100644 vmcompact/config.py create mode 100644 vmcompact/configurations.py create mode 100644 vmcompact/data.py create mode 100644 vmcompact/errors.py create mode 100644 vmcompact/gainlayer.py create mode 100644 vmcompact/img/cat.ico create mode 100644 vmcompact/menu.py create mode 100644 vmcompact/navigation.py create mode 100644 vmcompact/sun-valley-theme/LICENSE create mode 100644 vmcompact/sun-valley-theme/sun-valley.tcl create mode 100644 vmcompact/sun-valley-theme/theme/dark.tcl create mode 100644 vmcompact/sun-valley-theme/theme/dark/arrow-down.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/arrow-right.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/arrow-up.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/button-accent-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/button-accent-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/button-accent-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/button-accent-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/button-close-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/button-close-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/button-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/button-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/button-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/button-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/button-titlebar-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/button-titlebar-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/card.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/check-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/check-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/check-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/check-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/check-tri-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/check-tri-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/check-tri-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/check-tri-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/check-unsel-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/check-unsel-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/check-unsel-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/check-unsel-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/empty.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/entry-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/entry-focus.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/entry-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/entry-invalid.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/entry-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/notebook-border.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/notebook.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/progress-pbar-hor.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/progress-pbar-vert.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/progress-trough-hor.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/progress-trough-vert.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/radio-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/radio-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/radio-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/radio-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/radio-unsel-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/radio-unsel-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/radio-unsel-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/radio-unsel-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scale-thumb-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scale-thumb-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scale-thumb-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scale-thumb-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scale-trough-hor.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scale-trough-vert.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scroll-down.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scroll-hor-thumb.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scroll-hor-trough.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scroll-left.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scroll-right.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scroll-up.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scroll-vert-thumb.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/scroll-vert-trough.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/separator.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/sizegrip.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/switch-off-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/switch-off-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/switch-off-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/switch-off-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/switch-on-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/switch-on-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/switch-on-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/switch-on-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/tab-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/tab-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/tab-selected.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/treeheading-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/treeheading-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/dark/treeheading-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light.tcl create mode 100644 vmcompact/sun-valley-theme/theme/light/arrow-down.png create mode 100644 vmcompact/sun-valley-theme/theme/light/arrow-right.png create mode 100644 vmcompact/sun-valley-theme/theme/light/arrow-up.png create mode 100644 vmcompact/sun-valley-theme/theme/light/button-accent-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/light/button-accent-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/button-accent-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/button-accent-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light/button-close-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/button-close-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/button-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/light/button-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/button-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/button-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light/button-titlebar-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/button-titlebar-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/card.png create mode 100644 vmcompact/sun-valley-theme/theme/light/check-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/light/check-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/check-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/check-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light/check-tri-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/light/check-tri-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/check-tri-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/check-tri-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light/check-unsel-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/light/check-unsel-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/check-unsel-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/check-unsel-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light/empty.png create mode 100644 vmcompact/sun-valley-theme/theme/light/entry-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/light/entry-focus.png create mode 100644 vmcompact/sun-valley-theme/theme/light/entry-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/entry-invalid.png create mode 100644 vmcompact/sun-valley-theme/theme/light/entry-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light/notebook-border.png create mode 100644 vmcompact/sun-valley-theme/theme/light/notebook.png create mode 100644 vmcompact/sun-valley-theme/theme/light/progress-pbar-hor.png create mode 100644 vmcompact/sun-valley-theme/theme/light/progress-pbar-vert.png create mode 100644 vmcompact/sun-valley-theme/theme/light/progress-trough-hor.png create mode 100644 vmcompact/sun-valley-theme/theme/light/progress-trough-vert.png create mode 100644 vmcompact/sun-valley-theme/theme/light/radio-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/light/radio-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/radio-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/radio-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light/radio-unsel-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/light/radio-unsel-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/radio-unsel-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/radio-unsel-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scale-thumb-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scale-thumb-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scale-thumb-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scale-thumb-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scale-trough-hor.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scale-trough-vert.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scroll-down.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scroll-hor-thumb.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scroll-hor-trough.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scroll-left.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scroll-right.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scroll-up.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scroll-vert-thumb.png create mode 100644 vmcompact/sun-valley-theme/theme/light/scroll-vert-trough.png create mode 100644 vmcompact/sun-valley-theme/theme/light/separator.png create mode 100644 vmcompact/sun-valley-theme/theme/light/sizegrip.png create mode 100644 vmcompact/sun-valley-theme/theme/light/switch-off-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/light/switch-off-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/switch-off-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/switch-off-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light/switch-on-disabled.png create mode 100644 vmcompact/sun-valley-theme/theme/light/switch-on-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/switch-on-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/switch-on-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light/tab-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/tab-rest.png create mode 100644 vmcompact/sun-valley-theme/theme/light/tab-selected.png create mode 100644 vmcompact/sun-valley-theme/theme/light/treeheading-hover.png create mode 100644 vmcompact/sun-valley-theme/theme/light/treeheading-pressed.png create mode 100644 vmcompact/sun-valley-theme/theme/light/treeheading-rest.png diff --git a/.gitignore b/.gitignore index b6e4761..181c079 100644 --- a/.gitignore +++ b/.gitignore @@ -109,6 +109,7 @@ venv/ ENV/ env.bak/ venv.bak/ +venv_vmcompact/ # Spyder project settings .spyderproject diff --git a/__main__.py b/__main__.py new file mode 100644 index 0000000..280f7c5 --- /dev/null +++ b/__main__.py @@ -0,0 +1,12 @@ +import voicemeeter +import vmcompact + + +if __name__ == "__main__": + kind_id = "banana" + + voicemeeter.launch(kind_id, hide=False) + + with voicemeeter.remote(kind_id) as vmr: + app = vmcompact.connect(kind_id, vmr) + app.mainloop() diff --git a/configs/app.toml b/configs/app.toml new file mode 100644 index 0000000..7e11b7c --- /dev/null +++ b/configs/app.toml @@ -0,0 +1,15 @@ +# load with themes enabled? set the default mode +[theme] +enabled=true +mode="light" +# load in extended mode? if so which orientation +[extends] +extended=true +extends_horizontal=false +# default dimensions for channel label frames +[channel] +width=80 +height=130 +# default submix bus +[submixes] +default=6 diff --git a/configs/vban.toml b/configs/vban.toml new file mode 100644 index 0000000..231acf1 --- /dev/null +++ b/configs/vban.toml @@ -0,0 +1,12 @@ +# example connections +[connection-1] +kind = 'banana' +ip = '' +streamname = 'Command1' +port = 6990 + +[connection-2] +kind = 'potato' +ip = '' +streamname = 'Command1' +port = 6990 diff --git a/profiles/banana/example.toml b/profiles/banana/example.toml new file mode 100644 index 0000000..7201251 --- /dev/null +++ b/profiles/banana/example.toml @@ -0,0 +1,30 @@ +extends = 'blank' +[strip-0] +label = "PhysStrip0" + +[strip-1] +label = "PhysStrip1" + +[strip-2] +label = "PhysStrip2" + +[strip-3] +label = "VirtStrip0" + +[strip-4] +label = "VirtStrip1" + +[bus-0] +label = "PhysBus0" + +[bus-1] +label = "PhysBus1" + +[bus-2] +label = "PhysBus2" + +[bus-3] +label = "VirtBus0" + +[bus-4] +label = "VirtBus1" diff --git a/profiles/basic/example.toml b/profiles/basic/example.toml new file mode 100644 index 0000000..6aa196d --- /dev/null +++ b/profiles/basic/example.toml @@ -0,0 +1,15 @@ +extends = 'blank' +[strip-0] +label = "PhysStrip0" + +[strip-1] +label = "PhysStrip1" + +[strip-2] +label = "VirtStrip0" + +[bus-0] +label = "PhysBus0" + +[bus-1] +label = "PhysBus1" diff --git a/profiles/potato/example.toml b/profiles/potato/example.toml new file mode 100644 index 0000000..af47002 --- /dev/null +++ b/profiles/potato/example.toml @@ -0,0 +1,48 @@ +extends = 'blank' +[strip-0] +label = "PhysStrip0" + +[strip-1] +label = "PhysStrip1" + +[strip-2] +label = "PhysStrip2" + +[strip-3] +label = "PhysStrip3" + +[strip-4] +label = "PhysStrip4" + +[strip-5] +label = "VirtStrip0" + +[strip-6] +label = "VirtStrip1" + +[strip-7] +label = "VirtStrip2" + +[bus-0] +label = "PhysBus0" + +[bus-1] +label = "PhysBus1" + +[bus-2] +label = "PhysBus2" + +[bus-3] +label = "PhysBus3" + +[bus-4] +label = "PhysBus4" + +[bus-5] +label = "VirtBus0" + +[bus-6] +label = "VirtBus1" + +[bus-7] +label = "VirtBus2" diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..31d0644 --- /dev/null +++ b/setup.py @@ -0,0 +1,25 @@ +import setuptools + +with open("README.md", "r", encoding="utf-8") as fh: + long_description = fh.read() + +setuptools.setup( + name='vmcompact', + version='0.0.1', + author='Onyx and Iris', + author_email='code@onyxandiris.online', + description='Compact Tkinter Voicemeeter Remote App', + long_description=long_description, + long_description_content_type="text/markdown", + url='https://github.com/onyx-and-iris/voicemeeter-compact', + project_urls = { + "Bug Tracker": "https://github.com/onyx-and-iris/voicemeeter-compact/issues" + }, + license='MIT', + packages=['vmcompact'], + install_requires=[ + 'toml', + 'voicemeeter@git+https://github.com/onyx-and-iris/voicemeeter-api-python#egg=voicemeeter', + 'vbancmd@git+https://github.com/onyx-and-iris/vban-cmd-python#egg=vbancmd', + ], +) diff --git a/vmcompact/__init__.py b/vmcompact/__init__.py new file mode 100644 index 0000000..f78dec4 --- /dev/null +++ b/vmcompact/__init__.py @@ -0,0 +1,3 @@ +from .app import connect + +__ALL__ = ["connect"] diff --git a/vmcompact/app.py b/vmcompact/app.py new file mode 100644 index 0000000..f77b89e --- /dev/null +++ b/vmcompact/app.py @@ -0,0 +1,177 @@ +import tkinter as tk +from tkinter import ttk +from typing import NamedTuple +from functools import partial +from pathlib import Path + +from .errors import VMCompactErrors +from .data import _base_vals, _kinds_all +from .channels import ChannelFrame +from .navigation import Navigation +from .menu import Menus +from .banner import Banner +from .configurations import configuration + + +class App(tk.Tk): + """Topmost Level of App""" + + @classmethod + def make(cls, kind: NamedTuple): + """ + Factory function for App + + Returns an App class of a kind + """ + APP_cls = type( + f"Voicemeeter{kind.name}.Compact", + (cls,), + { + "kind": kind, + }, + ) + return APP_cls + + def __init__(self, vmr): + super().__init__() + defaults = { + "theme": { + "mode": "light", + }, + "extends": { + "extended": False, + "extends_horizontal": True, + }, + } + self.configuration = defaults | self.configuration + _base_vals.themes_enabled = self.configuration["theme"]["enabled"] + _base_vals.extends_horizontal = self.configuration["extends"][ + "extends_horizontal" + ] + _base_vals.submixes = self.configuration["submixes"]["default"] + + # create menus + self.menus = Menus(self, vmr) + self.styletable = ttk.Style() + self._vmr = vmr + + # start pdirty watcher + self.upd_pdirty() + + self.resizable(False, False) + if _base_vals.themes_enabled: + self.apply_theme() + self._make_app(self.kind) + + self.drag_id = "" + self.bind("", self.dragging) + + self.iconbitmap(Path.cwd() / "vmcompact" / "img" / "cat.ico") + + @property + def target(self): + """returns the current interface""" + return self._vban if _base_vals.vban_connected else self._vmr + + @property + def pdirty(self): + return self._pdirty + + @pdirty.setter + def pdirty(self, val): + self._pdirty = val + + @property + def configuration(self): + return configuration["app"] + + @configuration.setter + def configuration(self, val): + self.configuration["app"] = val + + @property + def configframes(self): + """returns a tuple of current config frame addresses""" + return tuple( + frame + for frame in self.winfo_children() + if isinstance(frame, ttk.Frame) + and "!stripconfig" in str(frame) + or "!busconfig" in str(frame) + ) + + def apply_theme(self): + _base_vals.using_theme = True + self.tk.call("source", "./vmcompact/sun-valley-theme/sun-valley.tcl") + self.tk.call("set_theme", self.configuration["theme"]["mode"]) + + def _make_app(self, kind, vban=None): + self.title( + f'Voicemeeter{kind.name}.Compact [{"Local" if not vban else "Network"} Connection]' + ) + self._vban = vban + self.kind = kind + + self._make_top_level_frames() + + def _make_top_level_frames(self): + # initialize bus frame variable + self.bus_frame = None + # channel_frame, left aligned + self.channel_frame = ChannelFrame.make_strips(self) + self.channel_frame.grid(row=0, column=0, sticky=(tk.W)) + # separator + self.sep = ttk.Separator(self, orient="vertical") + self.sep.grid(row=0, column=1, sticky=(tk.S, tk.N)) + self.columnconfigure(1, minsize=15) + + # navigation frame + self.nav_frame = Navigation(self) + self.nav_frame.grid(row=0, column=3) + + if self.configuration["extends"]["extended"]: + self.nav_frame.extend.set(True) + self.nav_frame.extend_frame() + + self.banner = Banner(self) + self.banner.grid(row=4, column=0, columnspan=3) + + def _destroy_top_level_frames(self): + [ + frame.destroy() + for frame in self.winfo_children() + if isinstance(frame, ttk.Frame) + ] + + def upd_pdirty(self): + self.after(1, self.upd_pdirty_step) + + def upd_pdirty_step(self): + self.pdirty = self.target.pdirty + self.after(1, self.upd_pdirty_step) + + def dragging(self, event, *args): + if event.widget is self: + if self.drag_id == "": + _base_vals.in_scale_button_1 = True + _base_vals.dragging = True + else: + self.after_cancel(self.drag_id) + self.drag_id = self.after(100, self.stop_drag) + + def stop_drag(self): + _base_vals.dragging = False + _base_vals.in_scale_button_1 = False + self.drag_id = "" + + +_apps = {kind.id: App.make(kind) for kind in _kinds_all} + + +def connect(kind_id: str, vmr) -> App: + """return App of the kind requested""" + try: + VMMIN_cls = _apps[kind_id] + return VMMIN_cls(vmr) + except KeyError: + raise VMCompactErrors(f"Invalid kind: {kind_id}") diff --git a/vmcompact/banner.py b/vmcompact/banner.py new file mode 100644 index 0000000..d9dfb7a --- /dev/null +++ b/vmcompact/banner.py @@ -0,0 +1,37 @@ +import tkinter as tk +from tkinter import ttk + +from .data import _base_vals + + +class Banner(ttk.Frame): + def __init__(self, parent): + super().__init__() + self._parent = parent + self.web = "onyxandiris.online" + self.submix = tk.StringVar() + if self._parent.kind.name == "Potato": + self.submix.set(self.target.bus[_base_vals.submixes].label) + + if self._parent.kind.name == "Potato": + self.label = ttk.Label( + self, + text=f"SUBMIX: {self.submix.get().upper()}", + ) + self.label.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.W, tk.E)) + + self.upd_submix() + + @property + def target(self): + """use the correct interface""" + return self._parent.target + + def upd_submix(self): + self.after(1, self.upd_submix_step) + + def upd_submix_step(self): + if not _base_vals.dragging: + self.submix.set(self.target.bus[_base_vals.submixes].label) + self.label["text"] = f"SUBMIX: {self.submix.get().upper()}" + self.after(100, self.upd_submix_step) diff --git a/vmcompact/channels.py b/vmcompact/channels.py new file mode 100644 index 0000000..21cbe44 --- /dev/null +++ b/vmcompact/channels.py @@ -0,0 +1,376 @@ +import tkinter as tk +from tkinter import ttk +from functools import partial + +from .data import _base_vals +from .config import StripConfig, BusConfig + + +class Channel(ttk.LabelFrame): + """Base class for a single channel""" + + def __init__(self, parent, index, id): + super().__init__(parent) + self._parent = parent + self.index = index + self.id = id + self.s = self._parent._parent.styletable + self.config_frame = None + + self.gain = tk.DoubleVar() + self.level = tk.DoubleVar() + self.mute = tk.BooleanVar() + self.conf = tk.BooleanVar() + + self.sync() + self._make_widgets() + + self.col_row_configure() + self.watch_pdirty() + self.watch_levels() + + @property + def identifier(self): + return self.id + + @property + def target(self): + """use the correct interface""" + return self._parent.target + + def getter(self, param): + if param in dir(self.target): + return getattr(self.target, param) + + def setter(self, param, value): + if param in dir(self.target): + setattr(self.target, param, value) + + def toggle_mute(self, *args): + self.target.mute = self.mute.get() + if not _base_vals.using_theme: + self.s.configure( + f"{self.identifier}Mute{self.index}.TButton", + background=f'{"red" if self.mute.get() else "white"}', + ) + + def reset_gain(self, *args): + self.setter("gain", 0) + self.gain.set(0) + self._parent._parent.nav_frame.info_text.set(0) + + def scale_enter(self, *args): + self._parent._parent.nav_frame.info_text.set(round(self.gain.get(), 1)) + + def scale_leave(self, *args): + self._parent._parent.nav_frame.info_text.set("") + + def scale_press(self, *args): + _base_vals.in_scale_button_1 = True + + def scale_release(self, *args): + _base_vals.in_scale_button_1 = False + + def scale_callback(self, *args): + """callback function for scale widget""" + self.setter("gain", self.gain.get()) + self._parent._parent.nav_frame.info_text.set(round(self.gain.get(), 1)) + + def _make_widgets(self): + """Creates a progressbar, scale, mute button and config button for a single channel""" + # Progress bar + self.pb = ttk.Progressbar( + self, + maximum=100, + orient="vertical", + mode="determinate", + variable=self.level, + ) + self.pb.grid(column=0, row=0) + + # Scale + self.scale = ttk.Scale( + self, + from_=12.0, + to=-60.0, + orient="vertical", + variable=self.gain, + command=self.scale_callback, + length=self._parent.height, + ) + self.scale.grid(column=1, row=0) + self.scale.bind("", self.reset_gain) + self.scale.bind("", self.scale_press) + self.scale.bind("", self.scale_enter) + self.scale.bind("", self.scale_release) + self.scale.bind("", self.scale_leave) + + # Mute button + self.button_mute = ttk.Checkbutton( + self, + text="MUTE", + command=partial(self.toggle_mute, "mute"), + style=f"{'Toggle.TButton' if _base_vals.using_theme else f'{self.identifier}Mute{self.index}.TButton'}", + variable=self.mute, + ) + self.button_mute.grid(column=0, row=1, columnspan=2) + + self.button_conf = ttk.Checkbutton( + self, + text="CONFIG", + command=self.open_config, + style=f"{'Toggle.TButton' if _base_vals.using_theme else f'{self.identifier}Conf{self.index}.TButton'}", + variable=self.conf, + ) + self.button_conf.grid(column=0, row=2, columnspan=2) + + def watch_pdirty(self): + self.after(1, self.watch_pdirty_step) + + def watch_pdirty_step(self): + """keeps params synced but ensures sliders are responsive""" + if self._parent._parent.pdirty and not _base_vals.in_scale_button_1: + self.sync() + self.after(1, self.watch_pdirty_step) + + def sync(self): + """sync params with voicemeeter""" + retval = self.getter("label") + if len(retval) > 10: + retval = f"{retval[:8]}.." + self.configure(text=retval) + self.gain.set(self.getter("gain")) + self.mute.set(self.getter("mute")) + if not _base_vals.using_theme: + self.s.configure( + f"{self.identifier}Mute{self.index}.TButton", + background=f'{"red" if self.mute.get() else "white"}', + ) + self.s.configure( + f"{self.identifier}Conf{self.index}.TButton", background="white" + ) + + def col_row_configure(self): + self.grid(sticky=(tk.N, tk.S)) + [ + child.grid_configure(padx=1, pady=1, sticky=(tk.W, tk.E)) + for child in self.winfo_children() + if isinstance(child, ttk.Checkbutton) + ] + [ + child.grid_configure(padx=1, pady=1, sticky=(tk.N, tk.S)) + for child in self.winfo_children() + if isinstance(child, ttk.Progressbar) or isinstance(child, ttk.Scale) + ] + + +class Strip(Channel): + """Concrete class representing a single""" + + def __init__(self, parent, index, id): + super().__init__(parent, index, id) + + @property + def target(self): + """use the correct interface""" + _target = super(Strip, self).target + return getattr(_target, self.identifier)[self.index] + + def open_config(self): + if self.conf.get(): + self.config_frame = StripConfig( + self._parent._parent, + self.index, + self.identifier, + ) + self.config_frame.grid(column=0, row=1, columnspan=4) + self._parent._parent.channel_frame.reset_config_buttons(self) + if self._parent._parent.bus_frame is not None: + self._parent._parent.bus_frame.reset_config_buttons(self) + else: + self.config_frame.destroy() + + if not _base_vals.using_theme: + self.s.configure( + f"{self.identifier}Conf{self.index}.TButton", + background=f'{"yellow" if self.conf.get() else "white"}', + ) + + def watch_levels(self): + self.after(1, self.watch_levels_step) + + def watch_levels_step(self): + if not _base_vals.dragging: + vals = self.target.levels.prefader + val = vals[0] if vals[0] > vals[1] else vals[0] + self.level.set(val) + self.level.set( + (0 if self.mute.get() else 100 + (val - 18) + self.gain.get()) + ) + self.after( + 25 if not _base_vals.in_scale_button_1 else 100, self.watch_levels_step + ) + + +class Bus(Channel): + """Concrete bus class representing a single bus""" + + def __init__(self, parent, index, id): + super().__init__(parent, index, id) + + @property + def target(self): + """use the correct interface""" + _target = super(Bus, self).target + return getattr(_target, self.identifier)[self.index] + + def open_config(self): + if self.conf.get(): + self.config_frame = BusConfig( + self._parent._parent, + self.index, + self.identifier, + ) + if _base_vals.extends_horizontal: + self.config_frame.grid(column=0, row=1, columnspan=3) + else: + self.config_frame.grid(column=0, row=3, columnspan=3) + self._parent._parent.channel_frame.reset_config_buttons(self) + self._parent._parent.bus_frame.reset_config_buttons(self) + else: + self.config_frame.destroy() + + if not _base_vals.using_theme: + self.s.configure( + f"{self.identifier}Conf{self.index}.TButton", + background=f'{"yellow" if self.conf.get() else "white"}', + ) + + def watch_levels(self): + self.after(1, self.watch_levels_step) + + def watch_levels_step(self): + if not _base_vals.dragging: + vals = self.target.levels.all + val = vals[0] if vals[0] > vals[1] else vals[0] + self.level.set(val) + self.level.set( + (0 if self.mute.get() else 100 + (val - 18) + self.gain.get()) + ) + self.after( + 25 if not _base_vals.in_scale_button_1 else 100, self.watch_levels_step + ) + + +class ChannelFrame(ttk.Frame): + @classmethod + def make_strips(cls, parent): + return cls(parent, is_strip=True) + + @classmethod + def make_buses(cls, parent): + return cls(parent, is_strip=False) + + def __init__(self, parent, is_strip: bool = True): + super().__init__(parent) + self._parent = parent + self._is_strip = is_strip + self.phys_in, self.virt_in = parent.kind.ins + self.phys_out, self.virt_out = parent.kind.outs + + defaults = { + "width": 80, + "height": 150, + } + self.configuration = defaults | self.configuration + self.width = self.configuration["width"] + self.height = self.configuration["height"] + + self.watch_pdirty() + + # create labelframes + if is_strip: + self.strips = [ + Strip(self, i, self.identifier) + for i in range(self.phys_in + self.virt_in) + ] + else: + self.buses = [ + Bus(self, i, self.identifier) + for i in range(self.phys_out + self.virt_out) + ] + + # position label frames. destroy any without label text + self.labelframes = self.strips if is_strip else self.buses + + self.col_row_configure() + + for i, labelframe in enumerate(self.labelframes): + labelframe.grid(row=0, column=i) + if not labelframe.cget("text"): + self.columnconfigure(i, minsize=0) + labelframe.grid_remove() + + @property + def target(self): + """returns the current interface""" + return self._parent.target + + @property + def configuration(self): + return self._parent.configuration["channel"] + + @configuration.setter + def configuration(self, val): + self._parent.configuration["channel"] = val + + @property + def identifier(self): + return "strip" if self._is_strip else "bus" + + def reset_config_buttons(self, current): + if not _base_vals.using_theme: + [ + labelframe.s.configure( + f"{labelframe.identifier}Conf{labelframe.index}.TButton", + background="white", + ) + for labelframe in self.labelframes + if labelframe is not None + ] + [ + labelframe.conf.set(False) + for labelframe in self.labelframes + if labelframe is not None and labelframe != current + ] + [ + labelframe.config_frame.destroy() + for labelframe in self.labelframes + if labelframe is not None + and labelframe.config_frame + and labelframe != current + ] + + def col_row_configure(self): + [ + self.columnconfigure(i, minsize=self.width) + for i, _ in enumerate(self.labelframes) + ] + [self.rowconfigure(0, minsize=130) for i, _ in enumerate(self.labelframes)] + + def watch_pdirty(self): + self.after(1, self.watch_pdirty_step) + + def watch_pdirty_step(self): + if self._parent.pdirty: + self.watch_labels() + self.after(1, self.watch_pdirty_step) + + def watch_labels(self): + for i, labelframe in enumerate(self.labelframes): + if not labelframe.getter("label"): + self.columnconfigure(i, minsize=0) + labelframe.grid_remove() + else: + self.columnconfigure(i, minsize=self.width) + labelframe.grid() diff --git a/vmcompact/config.py b/vmcompact/config.py new file mode 100644 index 0000000..4a0cea0 --- /dev/null +++ b/vmcompact/config.py @@ -0,0 +1,458 @@ +import tkinter as tk +from tkinter import ttk +from functools import partial + +from .data import _base_vals + + +class Config(ttk.Frame): + def __init__(self, parent, index, _id): + super().__init__(parent) + self._parent = parent + self.index = index + self.id = _id + self.s = parent.styletable + + self.phys_in, self.virt_in = parent.kind.ins + self.phys_out, self.virt_out = parent.kind.outs + + self.watch_pdirty() + + @property + def identifier(self): + return self.id + + @property + def target(self): + """returns the current interface""" + return self._parent.target + + def getter(self, param): + if param in dir(self.target): + return getattr(self.target, param) + + def setter(self, param, value): + if param in dir(self.target): + setattr(self.target, param, value) + + def scale_enter(self, *args): + _base_vals.in_scale_button_1 = True + + def scale_leave(self, *args): + _base_vals.in_scale_button_1 = False + self._parent.nav_frame.info_text.set("") + + def scale_callback(self, param, *args): + """callback function for scale widget""" + val = self.slider_vars[self.slider_params.index(param)].get() + self.setter(param, val) + self._parent.nav_frame.info_text.set(round(val, 1)) + + def reset_scale(self, param, val, *args): + self.setter(param, val) + self.slider_vars[self.slider_params.index(param)].set(val) + + def col_row_configure(self): + [ + child.grid_configure(padx=1, pady=1, sticky=(tk.W, tk.E)) + for child in self.winfo_children() + if isinstance(child, ttk.Checkbutton) + ] + self.grid(sticky=(tk.W)) + + def watch_pdirty(self): + self.after(1, self.watch_pdirty_step) + + def watch_pdirty_step(self): + """keeps params synced but ensures sliders are responsive""" + if self._parent.pdirty and not _base_vals.in_scale_button_1: + self.sync() + self.after(1, self.watch_pdirty_step) + + +class StripConfig(Config): + def __init__(self, parent, index, _id): + super().__init__(parent, index, _id) + + # create parameter variables + if self._parent.kind.name == "Basic": + self.slider_params = ("audibility",) + self.slider_vars = (tk.DoubleVar(),) + else: + self.slider_params = ("comp", "gate", "limit") + self.slider_vars = [ + tk.DoubleVar() for i, _ in enumerate(self.slider_params) + ] + + self.phys_out_params = [f"A{i+1}" for i in range(self.phys_out)] + self.phys_out_params_vars = [ + tk.BooleanVar() for i, _ in enumerate(self.phys_out_params) + ] + + self.virt_out_params = [f"B{i+1}" for i in range(self.virt_out)] + self.virt_out_params_vars = [ + tk.BooleanVar() for i, _ in enumerate(self.virt_out_params) + ] + + self.params = ("mono", "solo") + self.param_vars = list(tk.BooleanVar() for i, _ in enumerate(self.params)) + + self.make_row0() + self.make_row1() + self.make_row2() + + # sync all parameters + self.sync() + self.sync_sliders() + + self.col_row_configure() + + @property + def target(self): + """use the correct interface""" + _target = super(StripConfig, self).target + return getattr(_target, self.identifier)[self.index] + + def make_row0(self): + # Create sliders + if self.index < self.phys_in: + if self._parent.kind.name == "Basic": + # audibility + aud_label = ttk.Label(self, text="Audibility") + aud_scale = ttk.Scale( + self, + from_=0.0, + to=10.0, + orient="horizontal", + length=_base_vals.level_width, + variable=self.slider_vars[self.slider_params.index("audibility")], + command=partial(self.scale_callback, "audibility"), + ) + aud_scale.bind( + "", partial(self.reset_scale, "audibility", 0) + ) + aud_scale.bind("", self.scale_enter) + aud_scale.bind("", self.scale_leave) + + aud_label.grid(column=0, row=0) + aud_scale.grid(column=1, row=0) + else: + # comp + comp_label = ttk.Label(self, text="Comp") + comp_scale = ttk.Scale( + self, + from_=0.0, + to=10.0, + orient="horizontal", + length=_base_vals.level_width, + variable=self.slider_vars[self.slider_params.index("comp")], + command=partial(self.scale_callback, "comp"), + ) + comp_scale.bind( + "", partial(self.reset_scale, "comp", 0) + ) + comp_scale.bind("", self.scale_enter) + comp_scale.bind("", self.scale_leave) + + # gate + gate_label = ttk.Label(self, text="Gate") + gate_scale = ttk.Scale( + self, + from_=0.0, + to=10.0, + orient="horizontal", + length=_base_vals.level_width, + variable=self.slider_vars[self.slider_params.index("gate")], + command=partial(self.scale_callback, "gate"), + ) + gate_scale.bind( + "", partial(self.reset_scale, "gate", 0) + ) + gate_scale.bind("", self.scale_enter) + gate_scale.bind("", self.scale_leave) + + # limit + limit_label = ttk.Label(self, text="Limit") + limit_scale = ttk.Scale( + self, + from_=-40, + to=12, + orient="horizontal", + length=_base_vals.level_width, + variable=self.slider_vars[self.slider_params.index("limit")], + command=partial(self.scale_callback, "limit"), + ) + limit_scale.bind( + "", partial(self.reset_scale, "limit", 12) + ) + limit_scale.bind("", self.scale_enter) + limit_scale.bind("", self.scale_leave) + + # Position sliders + comp_label.grid(column=0, row=0) + comp_scale.grid(column=1, row=0) + gate_label.grid(column=2, row=0) + gate_scale.grid(column=3, row=0) + limit_label.grid(column=4, row=0) + limit_scale.grid(column=5, row=0) + + def make_row1(self): + # create buttons + self.a_buttons = [ + ttk.Checkbutton( + self, + text=param, + command=partial(self.toggle_a, param), + style=f"{'Toggle.TButton' if _base_vals.using_theme else f'{param}.TButton'}", + variable=self.phys_out_params_vars[self.phys_out_params.index(param)], + ) + for param in self.phys_out_params + ] + self.b_buttons = [ + ttk.Checkbutton( + self, + text=param, + command=partial(self.toggle_b, param), + style=f"{'Toggle.TButton' if _base_vals.using_theme else f'{param}.TButton'}", + variable=self.virt_out_params_vars[self.virt_out_params.index(param)], + ) + for param in self.virt_out_params + ] + + # set button positions + [ + button.grid( + column=self.a_buttons.index(button), + row=1, + ) + for button in self.a_buttons + ] + [ + button.grid( + column=len(self.a_buttons) + self.b_buttons.index(button), + row=1, + ) + for button in self.b_buttons + ] + + def toggle_a(self, param): + val = self.phys_out_params_vars[self.phys_out_params.index(param)].get() + self.setter(param, val) + if not _base_vals.using_theme: + self.s.configure( + f"{param}.TButton", background=f'{"green" if val else "white"}' + ) + + def toggle_b(self, param): + val = self.virt_out_params_vars[self.virt_out_params.index(param)].get() + self.setter(param, val) + if not _base_vals.using_theme: + self.s.configure( + f"{param}.TButton", background=f'{"green" if val else "white"}' + ) + + def make_row2(self): + if self._parent.kind.name in ("Banana", "Potato"): + if self.index == self.phys_in: + self.params = list(map(lambda x: x.replace("mono", "mc"), self.params)) + if self._parent.kind.name == "Banana": + pass + # karaoke modes not in RT Packet yet. May implement in future + """ + if self.index == self.phys_in + 1: + self.params = list( + map(lambda x: x.replace("mono", "k"), self.params) + ) + self.param_vars[self.params.index("k")] = tk.IntVar + """ + else: + if self.index == self.phys_in + self.virt_in - 1: + self.params = list( + map(lambda x: x.replace("mono", "mc"), self.params) + ) + + param_buttons = [ + ttk.Checkbutton( + self, + text=param, + command=partial(self.toggle_p, param), + style=f"{'Toggle.TButton' if _base_vals.using_theme else f'{param}.TButton'}", + variable=self.param_vars[self.params.index(param)], + ) + for param in self.params + ] + [ + button.grid( + column=param_buttons.index(button), + row=2, + ) + for button in param_buttons + ] + + def toggle_p(self, param): + val = self.param_vars[self.params.index(param)].get() + self.setter(param, val) + if not _base_vals.using_theme: + self.s.configure( + f"{param}.TButton", background=f'{"green" if val else "white"}' + ) + + def sync(self): + [ + self.phys_out_params_vars[self.phys_out_params.index(param)].set( + self.getter(param) + ) + for param in self.phys_out_params + ] + [ + self.virt_out_params_vars[self.virt_out_params.index(param)].set( + self.getter(param) + ) + for param in self.virt_out_params + ] + [ + self.param_vars[self.params.index(param)].set(self.getter(param)) + for param in self.params + ] + if not _base_vals.using_theme: + [ + self.s.configure( + f"{param}.TButton", + background=f'{"green" if self.phys_out_params_vars[self.phys_out_params.index(param)].get() else "white"}', + ) + for param in self.phys_out_params + ] + [ + self.s.configure( + f"{param}.TButton", + background=f'{"green" if self.virt_out_params_vars[self.virt_out_params.index(param)].get() else "white"}', + ) + for param in self.virt_out_params + ] + [ + self.s.configure( + f"{param}.TButton", + background=f'{"green" if self.param_vars[self.params.index(param)].get() else "white"}', + ) + for param in self.params + ] + + def sync_sliders(self): + [ + self.slider_vars[self.slider_params.index(param)].set(self.getter(param)) + for param in self.slider_params + ] + + def col_row_configure(self): + super(StripConfig, self).col_row_configure() + [ + self.columnconfigure(i, minsize=80) + for i in range(self.phys_out + self.virt_out) + ] + + +class BusConfig(Config): + def __init__(self, parent, index, _id): + super().__init__(parent, index, _id) + # fmt: off + # create parameter variables + self.bus_modes = ( + "normal", "Amix", "Bmix", "Repeat", "Composite", "TVMix", "UpMix21", + "UpMix41", "UpMix61", "CenterOnly", "LFEOnly", "RearOnly", + ) + # fmt: on + self.params = ("mono", "eq", "eq_ab") + self.param_vars = [tk.BooleanVar() for i, _ in enumerate(self.params)] + + self.make_row0() + self.make_row1() + + # sync all parameters + self.sync() + + self.col_row_configure() + + @property + def target(self): + """returns the current interface""" + _target = super(BusConfig, self).target + return getattr(_target, self.identifier)[self.index] + + def make_row0(self): + self._cur_bus_mode = tk.StringVar() + self._cur_bus_mode.set(f"Bus Mode: {self.bus_modes[self.get_current_index()]}") + self.busmode_button = ttk.Button(self, textvariable=self._cur_bus_mode) + self.busmode_button.grid(column=0, row=0, columnspan=2, sticky=(tk.W)) + self.busmode_button.bind("", self.rotate_bus_modes_right) + self.busmode_button.bind("", self.rotate_bus_modes_left) + + def get_current_index(self): + for mode in self.bus_modes: + if getattr(self.target.mode, mode.lower()): + return self.bus_modes.index(mode) + + def rotate_bus_modes_right(self, *args): + current_index = self.get_current_index() + if current_index + 1 < len(self.bus_modes): + next = self.bus_modes[current_index + 1] + else: + next = self.bus_modes[0] + setattr(self.target.mode, next.lower(), True) + self._cur_bus_mode.set(f"Bus Mode: {next}") + + def rotate_bus_modes_left(self, *args): + current_index = self.get_current_index() + if current_index == 0: + next = self.bus_modes[-1] + else: + next = self.bus_modes[current_index - 1] + setattr(self.target.mode, next.lower(), True) + self._cur_bus_mode.set(f"Bus Mode: {next}") + + def make_row1(self): + param_buttons = [ + ttk.Checkbutton( + self, + text=param, + command=partial(self.toggle_p, param), + style=f"{'Toggle.TButton' if _base_vals.using_theme else f'{param}.TButton'}", + variable=self.param_vars[self.params.index(param)], + ) + for param in self.params + ] + [ + button.grid( + column=param_buttons.index(button), + row=1, + ) + for button in param_buttons + ] + + def toggle_p(self, param): + val = self.param_vars[self.params.index(param)].get() + self.setter(param, val) + if not _base_vals.using_theme: + self.s.configure( + f"{param}.TButton", background=f'{"green" if val else "white"}' + ) + + def col_row_configure(self): + super(BusConfig, self).col_row_configure() + [ + self.columnconfigure(i, minsize=80) + for i in range(self.phys_out + self.virt_out) + ] + + def sync(self): + [ + self.param_vars[self.params.index(param)].set(self.getter(param)) + for param in self.params + ] + if not _base_vals.using_theme: + [ + self.s.configure( + f"{param}.TButton", + background=f'{"green" if self.param_vars[self.params.index(param)].get() else "white"}', + ) + for param in self.params + ] diff --git a/vmcompact/configurations.py b/vmcompact/configurations.py new file mode 100644 index 0000000..d064fba --- /dev/null +++ b/vmcompact/configurations.py @@ -0,0 +1,20 @@ +import toml +from pathlib import Path + +configuration = {} + +config_path = [Path.cwd() / "configs"] +for path in config_path: + if path.is_dir(): + filenames = list(path.glob("*.toml")) + configs = {} + for filename in filenames: + name = filename.with_suffix("").stem + try: + configs[name] = toml.load(filename) + except toml.TomlDecodeError: + print(f"Invalid TOML profile: configs/{filename.stem}") + + for name, cfg in configs.items(): + print(f"Loaded profile configs/{name}") + configuration[name] = cfg diff --git a/vmcompact/data.py b/vmcompact/data.py new file mode 100644 index 0000000..200ef78 --- /dev/null +++ b/vmcompact/data.py @@ -0,0 +1,35 @@ +from dataclasses import dataclass +from voicemeeter import kinds + + +@dataclass +class BaseValues: + level_height: int = 100 + level_width: int = 80 + + # are we dragging a scale with mouse 1 + in_scale_button_1: bool = False + # are we dragging main window with mouse 1 + dragging: bool = False + # direction the gui extends + extends_horizontal: bool = True + # a vban connection established + vban_connected: bool = False + # are themes enabled + themes_enabled: bool = True + # are we using a theme + using_theme: bool = False + # bus assigned as current submix + submixes: int = 0 + + +_base_vals = BaseValues() + + +_kinds = {kind.id: kind for kind in kinds.all} + +_kinds_all = _kinds.values() + + +def kind_get(kind_id): + return _kinds[kind_id] diff --git a/vmcompact/errors.py b/vmcompact/errors.py new file mode 100644 index 0000000..abd1b38 --- /dev/null +++ b/vmcompact/errors.py @@ -0,0 +1,4 @@ +class VMCompactErrors(Exception): + """Base classs for VMCompact Errors""" + + pass diff --git a/vmcompact/gainlayer.py b/vmcompact/gainlayer.py new file mode 100644 index 0000000..88422e0 --- /dev/null +++ b/vmcompact/gainlayer.py @@ -0,0 +1,244 @@ +import tkinter as tk +from tkinter import ttk, messagebox as msg +from functools import partial + +from .data import _base_vals + + +class GainLayer(ttk.LabelFrame): + """Concrete class representing a single gainlayer""" + + def __init__(self, parent, index, j): + super().__init__(parent) + self._parent = parent + self.index = index + self.j = j + self.gain = tk.DoubleVar() + self.level = tk.DoubleVar() + self.on = tk.BooleanVar() + self.s = self._parent._parent.styletable + + self.sync() + self._make_widgets() + + self.col_row_configure() + self.watch_pdirty() + self.watch_levels() + + @property + def target(self): + """returns the current interface""" + _target = self._parent.target + return _target.strip[self.index].gainlayer[self.j] + + def getter(self, param): + if param in dir(self.target): + return getattr(self.target, param) + + def setter(self, param, value): + if param in dir(self.target): + setattr(self.target, param, value) + + def reset_gain(self, *args): + self.setter("gain", 0) + self.gain.set(0) + self._parent._parent.nav_frame.info_text.set(0) + + def scale_enter(self, *args): + self._parent._parent.nav_frame.info_text.set(round(self.gain.get(), 1)) + + def scale_leave(self, *args): + self._parent._parent.nav_frame.info_text.set("") + + def scale_press(self, *args): + _base_vals.in_scale_button_1 = True + + def scale_release(self, *args): + _base_vals.in_scale_button_1 = False + + def scale_callback(self, *args): + """callback function for scale widget""" + self.setter("gain", self.gain.get()) + self._parent._parent.nav_frame.info_text.set(round(self.gain.get(), 1)) + + def set_on(self): + """enables a gainlayer. sets its button colour""" + setattr( + self._parent.target.strip[self.index], + self._parent.buses[self.j], + self.on.get(), + ) + if not _base_vals.using_theme: + self.s.configure( + f"On.TButton", + background=f'{"green" if self.on.get() else "white"}', + ) + + def _make_widgets(self): + """Creates a progressbar, scale, on button and config button for a single channel""" + # Progress bar + self.pb = ttk.Progressbar( + self, + maximum=100, + orient="vertical", + mode="determinate", + variable=self.level, + ) + self.pb.grid(column=0, row=0) + + # Scale + self.scale = ttk.Scale( + self, + from_=12.0, + to=-60.0, + orient="vertical", + variable=self.gain, + command=self.scale_callback, + length=self._parent.height, + ) + self.scale.grid(column=1, row=0) + self.scale.bind("", self.reset_gain) + self.scale.bind("", self.scale_press) + self.scale.bind("", self.scale_enter) + self.scale.bind("", self.scale_release) + self.scale.bind("", self.scale_leave) + + # On button + self.button_on = ttk.Checkbutton( + self, + text="ON", + command=self.set_on, + style=f"{'Toggle.TButton' if _base_vals.using_theme else 'On.TButton'}", + variable=self.on, + ) + self.button_on.grid(column=0, row=1, columnspan=2) + + def col_row_configure(self): + [ + child.grid_configure(padx=1, pady=1, sticky=(tk.N, tk.S, tk.W, tk.E)) + for child in self.winfo_children() + if isinstance(child, ttk.Checkbutton) + ] + [ + child.grid_configure(padx=1, pady=1, sticky=(tk.N, tk.S)) + for child in self.winfo_children() + if isinstance(child, ttk.Progressbar) or isinstance(child, ttk.Scale) + ] + self.columnconfigure(0, minsize=36) + self.columnconfigure(1, minsize=36) + self.rowconfigure(1, minsize=70) + + def watch_pdirty(self): + self.after(1, self.watch_pdirty_step) + + def watch_pdirty_step(self): + """keeps params synced but ensures sliders are responsive""" + if self._parent._parent.pdirty and not _base_vals.in_scale_button_1: + self.sync() + self.after(1, self.watch_pdirty_step) + + def sync(self): + """sync params with voicemeeter""" + retval = self.getter("label") + if len(retval) > 10: + retval = f"{retval[:8]}.." + self.configure(text=retval) + self.gain.set(self.getter("gain")) + self.on.set( + getattr( + self._parent.target.strip[self.index], + self._parent.buses[self.j], + ) + ) + + def watch_levels(self): + self.after(1, self.watch_levels_step) + + def watch_levels_step(self): + if not _base_vals.dragging: + vals = self._parent.target.strip[self.index].levels.prefader + val = vals[0] if vals[0] > vals[1] else vals[0] + self.level.set(val) + self.level.set( + ( + 0 + if self._parent._parent.channel_frame.strips[self.index].mute.get() + else 100 + (val - 18) + self.gain.get() + ) + ) + self.after( + 25 if not _base_vals.in_scale_button_1 else 100, self.watch_levels_step + ) + + +class SubMixFrame(ttk.Frame): + def __init__(self, parent): + super().__init__(parent) + self._parent = parent + self.phys_out, self.virt_out = parent.kind.outs + self.buses = tuple(f"A{i+1}" for i in range(self.phys_out)) + tuple( + f"B{i+1}" for i in range(self.virt_out) + ) + defaults = { + "width": 80, + "height": 150, + } + self.configuration = defaults | self.configuration + self.width = self.configuration["width"] + self.height = self.configuration["height"] + + self.gainlayers = [ + GainLayer(self, index, _base_vals.submixes) for index in range(8) + ] + [ + gainlayer.grid(row=0, column=self.gainlayers.index(gainlayer)) + for gainlayer in self.gainlayers + ] + + self.col_row_configure() + + # destroy any without label text + for i, gainlayer in enumerate(self.gainlayers): + gainlayer.grid(row=0, column=i) + if not gainlayer.cget("text"): + self.columnconfigure(i, minsize=0) + gainlayer.grid_remove() + + self.watch_pdirty() + + @property + def target(self): + """returns the current interface""" + return self._parent.target + + @property + def configuration(self): + return self._parent.configuration["channel"] + + @configuration.setter + def configuration(self, val): + self._parent.configuration["channel"] = val + + def col_row_configure(self): + [ + self.columnconfigure(i, minsize=self.width) + for i, _ in enumerate(self.gainlayers) + ] + [self.rowconfigure(0, minsize=130) for i, _ in enumerate(self.gainlayers)] + + def watch_pdirty(self): + self.after(1, self.watch_pdirty_step) + + def watch_pdirty_step(self): + if self._parent.pdirty: + self.watch_labels() + self.after(1, self.watch_pdirty_step) + + def watch_labels(self): + for i, gainlayer in enumerate(self.gainlayers): + if not self.target.strip[gainlayer.index].label: + self.columnconfigure(i, minsize=0) + gainlayer.grid_remove() + else: + self.columnconfigure(i, minsize=80) + gainlayer.grid() diff --git a/vmcompact/img/cat.ico b/vmcompact/img/cat.ico new file mode 100644 index 0000000000000000000000000000000000000000..254c6e117877d78f7cc8864d5c3c1c6ed1525363 GIT binary patch literal 112922 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

JxYtWrt@TsZ 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 literal 0 HcmV?d00001 diff --git a/vmcompact/menu.py b/vmcompact/menu.py new file mode 100644 index 0000000..c8d762c --- /dev/null +++ b/vmcompact/menu.py @@ -0,0 +1,316 @@ +import tkinter as tk +from tkinter import ttk, messagebox +from functools import partial +import webbrowser + +import vbancmd + +from .configurations import configuration +from .data import _base_vals, kind_get +from .gainlayer import SubMixFrame + + +class Menus(tk.Menu): + def __init__(self, parent, vmr): + super().__init__() + self._parent = parent + self._vmr = vmr + self.vban_conns = [None for i, _ in enumerate(self.configuration_vban)] + self.menubar = tk.Menu(self, tearoff=0) + parent["menu"] = self.menubar + self._is_topmost = tk.BooleanVar() + self._selected_bus = list(tk.BooleanVar() for _ in range(8)) + + # voicemeeter menu + self.menu_voicemeeter = tk.Menu(self.menubar, tearoff=0) + self.menubar.add_cascade(menu=self.menu_voicemeeter, label="Voicemeeter") + self.menu_voicemeeter.add_checkbutton( + label="Always On Top", + onvalue=1, + offvalue=0, + variable=self._is_topmost, + command=self.always_on_top, + ) + self.menu_voicemeeter.add_separator() + self.menu_voicemeeter.add_command( + label="Show", + underline=0, + command=partial(self.action_invoke_voicemeeter, "show"), + ) + self.menu_voicemeeter.add_command( + label="Hide", + underline=0, + command=partial(self.action_invoke_voicemeeter, "hide"), + ) + self.menu_voicemeeter.add_command( + label="Restart", + underline=0, + command=partial(self.action_invoke_voicemeeter, "restart"), + ) + self.menu_voicemeeter.add_command( + label="Shutdown", + underline=0, + command=partial(self.action_invoke_voicemeeter, "shutdown"), + ) + self.menu_voicemeeter.add_separator() + self.menu_lock = tk.Menu(self.menu_voicemeeter, tearoff=0) + self.menu_voicemeeter.add_cascade( + menu=self.menu_lock, label="GUI Lock", underline=0 + ) + self.menu_lock.add_command( + label="Lock", command=partial(self.action_set_voicemeeter, "lock") + ) + self.menu_lock.add_command( + label="Unlock", command=partial(self.action_set_voicemeeter, "lock", False) + ) + + # profiles menu + menu_profiles = tk.Menu(self.menubar, tearoff=0) + self.menubar.add_cascade(menu=menu_profiles, label="Profiles") + self.menu_profiles_load = tk.Menu(menu_profiles, tearoff=0) + menu_profiles.add_cascade(menu=self.menu_profiles_load, label="Load profile") + defaults = {"base", "blank"} + if len(vmr.profiles) > len(defaults) and all( + key in vmr.profiles for key in defaults + ): + [ + self.menu_profiles_load.add_command( + label=profile, command=partial(self.load_profile, profile) + ) + for profile in vmr.profiles.keys() + if profile not in defaults + ] + else: + menu_profiles.entryconfig(0, state="disabled") + menu_profiles.add_separator() + menu_profiles.add_command(label="Reset to defaults", command=self.load_defaults) + + # vban connect menu + self.menu_vban = tk.Menu(self.menubar, tearoff=0) + self.menubar.add_cascade(menu=self.menu_vban, label="VBAN Connect") + for i, _ in enumerate(self.configuration_vban): + setattr(self, f"menu_vban_{i+1}", tk.Menu(self.menu_vban, tearoff=0)) + target_menu = getattr(self, f"menu_vban_{i+1}") + self.menu_vban.add_cascade( + menu=target_menu, label=f"VBAN Connect #{i+1}", underline=0 + ) + target_menu.add_command( + label="Connect", command=partial(self.vban_connect, i) + ) + target_menu.add_command( + label="Disconnect", command=partial(self.vban_disconnect, i) + ) + target_menu.entryconfig(1, state="disabled") + + # extends menu + self.menu_extends = tk.Menu(self.menubar, tearoff=0) + self.menubar.add_cascade(menu=self.menu_extends, label="Extends") + self.menu_extends.add_command( + label="horizontal", + underline=0, + command=partial(self.switch_orientation, extends_horizontal=True), + ) + self.menu_extends.add_command( + label="vertical", + underline=0, + command=partial(self.switch_orientation, extends_horizontal=False), + ) + self.menu_extends.entryconfig( + 0 if _base_vals.extends_horizontal else 1, state="disabled" + ) + + # submixes menu + # here we build menu regardless of kind but disable if not Potato + buses = tuple(f"A{i+1}" for i in range(5)) + tuple(f"B{i+1}" for i in range(3)) + self.menu_submixes = tk.Menu(self.menubar, tearoff=0) + self.menubar.add_cascade(menu=self.menu_submixes, label="Submixes") + [ + self.menu_submixes.add_checkbutton( + label=f"Bus {buses[i]}", + underline=0, + onvalue=1, + offvalue=0, + variable=self._selected_bus[i], + command=partial(self.set_submix, i), + ) + for i in range(8) + ] + self._selected_bus[_base_vals.submixes].set(True) + if self._parent.kind.name != "Potato": + self.menubar.entryconfig(4, state="disabled") + + # themes menu + self.menu_themes = tk.Menu(self.menubar, tearoff=0) + self.menubar.add_cascade(menu=self.menu_themes, label="Themes") + tcl_themes = [ + "light", + "dark", + ] + [ + self.menu_themes.add_command( + label=theme.capitalize(), + command=partial(self.load_theme, theme), + ) + for theme in tcl_themes + ] + self.menu_themes.entryconfig( + 0 if self.configuration_app["theme"]["mode"] == "light" else 1, + state="disabled", + ) + if not _base_vals.themes_enabled: + self.menubar.entryconfig(6, state="disabled") + + # Help menu + self.menu_help = tk.Menu(self.menubar, tearoff=0) + self.menubar.add_cascade(menu=self.menu_help, label="Help") + self.menu_help.add_command( + label="Voicemeeter Site", + command=self.documentation, + ) + self.menu_help.add_command( + label="Source Code", + command=self.github, + ) + self.menu_help.add_command( + label="App Creator", + command=self.onyxandiris, + ) + + @property + def target(self): + """use the correct interface""" + return self._parent.target + + @property + def configuration_app(self): + return configuration["app"] + + @configuration_app.setter + def configuration_app(self, val): + self.configuration_app = val + + @property + def configuration_vban(self): + return configuration["vban"] + + def action_invoke_voicemeeter(self, cmd): + getattr(self.target.command, cmd)() + + def action_set_voicemeeter(self, cmd, val=True): + setattr(self.target.command, cmd, val) + + def load_profile(self, profile): + self.target.apply_profile(profile) + + def load_defaults(self): + resp = messagebox.askyesno( + message="Are you sure you want to Reset values to defaults?\nPhysical strips B1, Virtual strips A1\nMono, Solo, Mute, EQ all OFF" + ) + if resp: + self.target.apply_profile("base") + + def always_on_top(self): + self._parent.attributes("-topmost", self._is_topmost.get()) + self._parent.update() + + def switch_orientation(self, extends_horizontal: bool = True, *args): + _base_vals.extends_horizontal = extends_horizontal + if extends_horizontal: + self.menu_extends.entryconfig(0, state="disabled") + self.menu_extends.entryconfig(1, state="normal") + else: + self.menu_extends.entryconfig(1, state="disabled") + self.menu_extends.entryconfig(0, state="normal") + + def set_submix(self, i): + if _base_vals.submixes != i: + _base_vals.submixes = i + if self._parent.submix_frame is not None: + self._parent.submix_frame.destroy() + self._parent.nav_frame.show_submix() + for j, var in enumerate(self._selected_bus): + var.set(True if i == j else False) + + def load_theme(self, theme): + self.tk.call("set_theme", theme) + self.configuration_app["theme"]["mode"] = theme + self.menu_themes.entryconfig( + 0, + state=f"{'disabled' if theme == 'light' else 'normal'}", + ) + self.menu_themes.entryconfig( + 1, + state=f"{'disabled' if theme == 'dark' else 'normal'}", + ) + [ + menu.config(bg=f"{'black' if theme == 'dark' else 'white'}") + for menu in self.menubar.winfo_children() + if isinstance(menu, tk.Menu) + ] + self.menu_lock.config(bg=f"{'black' if theme == 'dark' else 'white'}") + self.menu_profiles_load.config(bg=f"{'black' if theme == 'dark' else 'white'}") + [ + menu.config(bg=f"{'black' if theme == 'dark' else 'white'}") + for menu in self.menu_vban.winfo_children() + if isinstance(menu, tk.Menu) + ] + + def vban_connect(self, i): + [ + self.menu_vban.entryconfig(j, state="disabled") + for j, _ in enumerate(self.menu_vban.winfo_children()) + if j != i + ] + + opts = {} + opts |= self.configuration_vban[f"connection-{i+1}"] + kind_id = opts.pop("kind") + self.vban_conns[i] = vbancmd.connect(kind_id, **opts) + # login to vban interface + self.vban_conns[i].login() + # destroy the current App frames + self._parent._destroy_top_level_frames() + _base_vals.vban_connected = True + # build new app frames according to a kind + kind = kind_get(kind_id) + self._parent._make_app(kind, self.vban_conns[i]) + target_menu = getattr(self, f"menu_vban_{i+1}") + target_menu.entryconfig(0, state="disabled") + target_menu.entryconfig(1, state="normal") + self.menubar.entryconfig( + 4, state=f"{'normal' if kind.name == 'Potato' else 'disabled'}" + ) + + def vban_disconnect(self, i): + # destroy the current App frames + self._parent._destroy_top_level_frames() + _base_vals.vban_connected = False + # logout of vban interface + i_to_close = self.vban_conns[i] + self.vban_conns[i] = None + i_to_close.logout() + # build new app frames according to a kind + kind = kind_get(self._vmr.type) + # destroy the current App frames + self._parent._destroy_top_level_frames() + self._parent._make_app(kind, None) + target_menu = getattr(self, f"menu_vban_{i+1}") + target_menu.entryconfig(0, state="normal") + target_menu.entryconfig(1, state="disabled") + + self.after(15000, self.enable_vban_menus) + + def enable_vban_menus(self): + [ + self.menu_vban.entryconfig(j, state="normal") + for j, _ in enumerate(self.menu_vban.winfo_children()) + ] + + def documentation(self): + webbrowser.open_new(r"https://voicemeeter.com/") + + def github(self): + webbrowser.open_new(r"https://github.com/onyx-and-iris") + + def onyxandiris(self): + webbrowser.open_new(r"https://onyxandiris.online") diff --git a/vmcompact/navigation.py b/vmcompact/navigation.py new file mode 100644 index 0000000..7d933c9 --- /dev/null +++ b/vmcompact/navigation.py @@ -0,0 +1,156 @@ +import tkinter as tk +from tkinter import ttk + +from .channels import ChannelFrame +from .gainlayer import SubMixFrame +from .data import _base_vals + + +class Navigation(ttk.Frame): + def __init__(self, parent): + super().__init__(parent) + self._parent = parent + self.s = parent.styletable + + self.submix = tk.BooleanVar() + self.channel = tk.BooleanVar() + self.extend = tk.BooleanVar() + self.info = tk.BooleanVar() + + self.channel_text = tk.StringVar() + self.channel_text.set(parent.channel_frame.identifier.upper()) + self.extend_text = tk.StringVar() + self.extend_text.set("EXTEND") + self.info_text = tk.StringVar() + self._parent.submix_frame = None + + self._make_widgets() + + self.col_row_configure() + + def _make_widgets(self): + """Creates the navigation buttons""" + self.submix_button = ttk.Checkbutton( + self, + text="SUBMIX", + command=self.show_submix, + style=f"{'Toggle.TButton' if _base_vals.using_theme else f'Submix.TButton'}", + variable=self.submix, + ) + self.channel_button = ttk.Checkbutton( + self, + textvariable=self.channel_text, + command=self.switch_channel, + style=f"{'Toggle.TButton' if _base_vals.using_theme else f'Channel.TButton'}", + variable=self.channel, + ) + self.extend_button = ttk.Checkbutton( + self, + textvariable=self.extend_text, + command=self.extend_frame, + style=f"{'Toggle.TButton' if _base_vals.using_theme else f'Extend.TButton'}", + variable=self.extend, + ) + self.info_button = ttk.Checkbutton( + self, + textvariable=self.info_text, + style=f"{'Toggle.TButton' if _base_vals.using_theme else f'Rec.TButton'}", + variable=self.info, + ) + self.info_button["state"] = "active" + + """ Position navigation buttons """ + self.submix_button.grid(column=0, row=0) + self.channel_button.grid(column=0, row=1, rowspan=1) + self.extend_button.grid(column=0, row=2) + self.info_button.grid(column=0, row=3) + + if self._parent.kind.name != "Potato": + self.submix_button["state"] = "disabled" + + def show_submix(self): + if self.submix.get(): + if _base_vals.extends_horizontal: + self._parent.submix_frame = SubMixFrame(self._parent) + self._parent.submix_frame.grid(row=0, column=2) + if self._parent.bus_frame: + self._parent.bus_frame.grid_remove() + else: + self._parent.submix_frame = SubMixFrame(self._parent) + self._parent.submix_frame.grid(row=2, column=0, sticky=(tk.W)) + if self._parent.bus_frame: + self._parent.bus_frame.grid_remove() + else: + if _base_vals.extends_horizontal: + self._parent.submix_frame.destroy() + if self._parent.bus_frame: + self._parent.bus_frame.grid() + else: + self._parent.columnconfigure(1, weight=0) + else: + self._parent.submix_frame.destroy() + if self._parent.bus_frame: + self._parent.bus_frame.grid() + else: + self._parent.rowconfigure(2, weight=0, minsize=0) + + if not _base_vals.using_theme: + self.s.configure( + f"Submix.TButton", + background=f'{"purple" if self.submix.get() else "white"}', + ) + + def switch_channel(self): + if self.channel_text.get() == "STRIP": + self._parent.bus_frame = ChannelFrame.make_buses(self._parent) + self._parent.bus_frame.grid(row=0, column=0) + self._parent.channel_frame.destroy() + else: + self._parent.channel_frame = ChannelFrame.make_strips(self._parent) + self._parent.channel_frame.grid(row=0, column=0) + self._parent.bus_frame.destroy() + + self.extend_button["state"] = ( + "disabled" if self.channel_text.get() == "STRIP" else "normal" + ) + [frame.destroy() for frame in self._parent.configframes] + self.channel_text.set("BUS" if self.channel_text.get() == "STRIP" else "STRIP") + + def extend_frame(self): + if self.extend.get(): + self.channel_button["state"] = "disabled" + self._parent.bus_frame = ChannelFrame.make_buses(self._parent) + if _base_vals.extends_horizontal: + self._parent.bus_frame.grid(row=0, column=2) + else: + self._parent.bus_frame.grid(row=2, column=0, sticky=(tk.W)) + else: + [ + frame.destroy() + for frame in self._parent.configframes + if "!busconfig" in str(frame) + ] + self._parent.bus_frame.destroy() + self._parent.bus_frame = None + self.channel_button["state"] = "normal" + + if self._parent.submix_frame: + self._parent.submix_frame.destroy() + self.submix.set(False) + if not _base_vals.using_theme: + self.s.configure( + f"Submix.TButton", + background=f'{"purple" if self.submix.get() else "white"}', + ) + + self.extend_text.set("REDUCE" if self.extend.get() else "EXTEND") + + def col_row_configure(self): + [ + child.grid_configure(padx=1, pady=1, sticky=(tk.N, tk.S, tk.W, tk.E)) + for child in self.winfo_children() + if isinstance(child, ttk.Checkbutton) + ] + + self.rowconfigure(1, minsize=self._parent.channel_frame.height - 18) + self.grid(sticky=(tk.N)) diff --git a/vmcompact/sun-valley-theme/LICENSE b/vmcompact/sun-valley-theme/LICENSE new file mode 100644 index 0000000..0212030 --- /dev/null +++ b/vmcompact/sun-valley-theme/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 rdbende + +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/vmcompact/sun-valley-theme/sun-valley.tcl b/vmcompact/sun-valley-theme/sun-valley.tcl new file mode 100644 index 0000000..a1b55d2 --- /dev/null +++ b/vmcompact/sun-valley-theme/sun-valley.tcl @@ -0,0 +1,88 @@ +# Copyright © 2021 rdbende + +source [file join [file dirname [info script]] theme light.tcl] +source [file join [file dirname [info script]] theme dark.tcl] + +option add *tearOff 0 + +proc set_theme {mode} { + if {$mode == "dark"} { + ttk::style theme use "sun-valley-dark" + + array set colors { + -fg "#ffffff" + -bg "#1c1c1c" + -disabledfg "#595959" + -selectfg "#ffffff" + -selectbg "#2f60d8" + } + + ttk::style configure . \ + -background $colors(-bg) \ + -foreground $colors(-fg) \ + -troughcolor $colors(-bg) \ + -focuscolor $colors(-selectbg) \ + -selectbackground $colors(-selectbg) \ + -selectforeground $colors(-selectfg) \ + -insertwidth 1 \ + -insertcolor $colors(-fg) \ + -fieldbackground $colors(-selectbg) \ + -font {"Segoe UI" 10} \ + -borderwidth 0 \ + -relief flat + + tk_setPalette \ + background [ttk::style lookup . -background] \ + foreground [ttk::style lookup . -foreground] \ + highlightColor [ttk::style lookup . -focuscolor] \ + selectBackground [ttk::style lookup . -selectbackground] \ + selectForeground [ttk::style lookup . -selectforeground] \ + activeBackground [ttk::style lookup . -selectbackground] \ + activeForeground [ttk::style lookup . -selectforeground] + + ttk::style map . -foreground [list disabled $colors(-disabledfg)] + + option add *font [ttk::style lookup . -font] + option add *Menu.selectcolor $colors(-fg) + option add *Menu.background #2f2f2f + + } elseif {$mode == "light"} { + ttk::style theme use "sun-valley-light" + + array set colors { + -fg "#202020" + -bg "#fafafa" + -disabledfg "#a0a0a0" + -selectfg "#ffffff" + -selectbg "#2f60d8" + } + + ttk::style configure . \ + -background $colors(-bg) \ + -foreground $colors(-fg) \ + -troughcolor $colors(-bg) \ + -focuscolor $colors(-selectbg) \ + -selectbackground $colors(-selectbg) \ + -selectforeground $colors(-selectfg) \ + -insertwidth 1 \ + -insertcolor $colors(-fg) \ + -fieldbackground $colors(-selectbg) \ + -font {"Segoe UI" 10} \ + -borderwidth 0 \ + -relief flat + + tk_setPalette background [ttk::style lookup . -background] \ + foreground [ttk::style lookup . -foreground] \ + highlightColor [ttk::style lookup . -focuscolor] \ + selectBackground [ttk::style lookup . -selectbackground] \ + selectForeground [ttk::style lookup . -selectforeground] \ + activeBackground [ttk::style lookup . -selectbackground] \ + activeForeground [ttk::style lookup . -selectforeground] + + ttk::style map . -foreground [list disabled $colors(-disabledfg)] + + option add *font [ttk::style lookup . -font] + option add *Menu.selectcolor $colors(-fg) + option add *Menu.background #e7e7e7 + } +} diff --git a/vmcompact/sun-valley-theme/theme/dark.tcl b/vmcompact/sun-valley-theme/theme/dark.tcl new file mode 100644 index 0000000..2363eca --- /dev/null +++ b/vmcompact/sun-valley-theme/theme/dark.tcl @@ -0,0 +1,521 @@ +# Copyright © 2021 rdbende + +# A stunning dark theme for ttk based on Microsoft's Sun Valley visual style + +package require Tk 8.6 + +namespace eval ttk::theme::sun-valley-dark { + variable version 1.0 + package provide ttk::theme::sun-valley-dark $version + + ttk::style theme create sun-valley-dark -parent clam -settings { + proc load_images {imgdir} { + variable images + foreach file [glob -directory $imgdir *.png] { + set images([file tail [file rootname $file]]) \ + [image create photo -file $file -format png] + } + } + + load_images [file join [file dirname [info script]] dark] + + array set colors { + -fg "#ffffff" + -bg "#1c1c1c" + -disabledfg "#595959" + -selectfg "#ffffff" + -selectbg "#2f60d8" + } + + ttk::style layout TButton { + Button.button -children { + Button.padding -children { + Button.label -side left -expand 1 + } + } + } + + ttk::style layout Toolbutton { + Toolbutton.button -children { + Toolbutton.padding -children { + Toolbutton.label -side left -expand 1 + } + } + } + + ttk::style layout TMenubutton { + Menubutton.button -children { + Menubutton.padding -children { + Menubutton.label -side left -expand 1 + Menubutton.indicator -side right -sticky nsew + } + } + } + + ttk::style layout TOptionMenu { + OptionMenu.button -children { + OptionMenu.padding -children { + OptionMenu.label -side left -expand 1 + OptionMenu.indicator -side right -sticky nsew + } + } + } + + ttk::style layout Accent.TButton { + AccentButton.button -children { + AccentButton.padding -children { + AccentButton.label -side left -expand 1 + } + } + } + + ttk::style layout Titlebar.TButton { + TitlebarButton.button -children { + TitlebarButton.padding -children { + TitlebarButton.label -side left -expand 1 + } + } + } + + ttk::style layout Close.Titlebar.TButton { + CloseButton.button -children { + CloseButton.padding -children { + CloseButton.label -side left -expand 1 + } + } + } + + ttk::style layout TCheckbutton { + Checkbutton.button -children { + Checkbutton.padding -children { + Checkbutton.indicator -side left + Checkbutton.label -side right -expand 1 + } + } + } + + ttk::style layout Switch.TCheckbutton { + Switch.button -children { + Switch.padding -children { + Switch.indicator -side left + Switch.label -side right -expand 1 + } + } + } + + ttk::style layout Toggle.TButton { + ToggleButton.button -children { + ToggleButton.padding -children { + ToggleButton.label -side left -expand 1 + } + } + } + + ttk::style layout TRadiobutton { + Radiobutton.button -children { + Radiobutton.padding -children { + Radiobutton.indicator -side left + Radiobutton.label -side right -expand 1 + } + } + } + + ttk::style layout Vertical.TScrollbar { + Vertical.Scrollbar.trough -sticky ns -children { + Vertical.Scrollbar.uparrow -side top + Vertical.Scrollbar.downarrow -side bottom + Vertical.Scrollbar.thumb -expand 1 + } + } + + ttk::style layout Horizontal.TScrollbar { + Horizontal.Scrollbar.trough -sticky ew -children { + Horizontal.Scrollbar.leftarrow -side left + Horizontal.Scrollbar.rightarrow -side right + Horizontal.Scrollbar.thumb -expand 1 + } + } + + ttk::style layout TSeparator { + TSeparator.separator -sticky nsew + } + + ttk::style layout TCombobox { + Combobox.field -sticky nsew -children { + Combobox.padding -expand 1 -sticky nsew -children { + Combobox.textarea -sticky nsew + } + } + null -side right -sticky ns -children { + Combobox.arrow -sticky nsew + } + } + + ttk::style layout TSpinbox { + Spinbox.field -sticky nsew -children { + Spinbox.padding -expand 1 -sticky nsew -children { + Spinbox.textarea -sticky nsew + } + + } + null -side right -sticky nsew -children { + Spinbox.uparrow -side left -sticky nsew + Spinbox.downarrow -side right -sticky nsew + } + } + + ttk::style layout Card.TFrame { + Card.field { + Card.padding -expand 1 + } + } + + ttk::style layout TLabelframe { + Labelframe.border { + Labelframe.padding -expand 1 -children { + Labelframe.label -side left + } + } + } + + ttk::style layout TNotebook { + Notebook.border -children { + TNotebook.Tab -expand 1 + Notebook.client -sticky nsew + } + } + + ttk::style layout Treeview.Item { + Treeitem.padding -sticky nsew -children { + Treeitem.image -side left -sticky {} + Treeitem.indicator -side left -sticky {} + Treeitem.text -side left -sticky {} + } + } + + # Button + ttk::style configure TButton -padding {8 4} -anchor center -foreground $colors(-fg) + + ttk::style map TButton -foreground \ + [list disabled #7a7a7a \ + pressed #d0d0d0] + + ttk::style element create Button.button image \ + [list $images(button-rest) \ + {selected disabled} $images(button-disabled) \ + disabled $images(button-disabled) \ + selected $images(button-rest) \ + pressed $images(button-pressed) \ + active $images(button-hover) \ + ] -border 4 -sticky nsew + + # Toolbutton + ttk::style configure Toolbutton -padding {8 4} -anchor center + + ttk::style element create Toolbutton.button image \ + [list $images(empty) \ + {selected disabled} $images(button-disabled) \ + selected $images(button-rest) \ + pressed $images(button-pressed) \ + active $images(button-hover) \ + ] -border 4 -sticky nsew + + # Menubutton + ttk::style configure TMenubutton -padding {8 4 0 4} + + ttk::style element create Menubutton.button \ + image [list $images(button-rest) \ + disabled $images(button-disabled) \ + pressed $images(button-pressed) \ + active $images(button-hover) \ + ] -border 4 -sticky nsew + + ttk::style element create Menubutton.indicator image $images(arrow-down) -width 28 -sticky {} + + # OptionMenu + ttk::style configure TOptionMenu -padding {8 4 0 4} + + ttk::style element create OptionMenu.button \ + image [list $images(button-rest) \ + disabled $images(button-disabled) \ + pressed $images(button-pressed) \ + active $images(button-hover) \ + ] -border 4 -sticky nsew + + ttk::style element create OptionMenu.indicator image $images(arrow-down) -width 28 -sticky {} + + # Accent.TButton + ttk::style configure Accent.TButton -padding {8 4} -anchor center -foreground #000000 + + ttk::style map Accent.TButton -foreground \ + [list pressed #25536a \ + disabled #a5a5a5] + + ttk::style element create AccentButton.button image \ + [list $images(button-accent-rest) \ + {selected disabled} $images(button-accent-disabled) \ + disabled $images(button-accent-disabled) \ + selected $images(button-accent-rest) \ + pressed $images(button-accent-pressed) \ + active $images(button-accent-hover) \ + ] -border 4 -sticky nsew + + # Titlebar.TButton + ttk::style configure Titlebar.TButton -padding {8 4} -anchor center -foreground #ffffff + + ttk::style map Titlebar.TButton -foreground \ + [list disabled #6f6f6f \ + pressed #d1d1d1 \ + active #ffffff] + + ttk::style element create TitlebarButton.button image \ + [list $images(empty) \ + disabled $images(empty) \ + pressed $images(button-titlebar-pressed) \ + active $images(button-titlebar-hover) \ + ] -border 4 -sticky nsew + + # Close.Titlebar.TButton + ttk::style configure Close.Titlebar.TButton -padding {8 4} -anchor center -foreground #ffffff + + ttk::style map Close.Titlebar.TButton -foreground \ + [list disabled #6f6f6f \ + pressed #e8bfbb \ + active #ffffff] + + ttk::style element create CloseButton.button image \ + [list $images(empty) \ + disabled $images(empty) \ + pressed $images(button-close-pressed) \ + active $images(button-close-hover) \ + ] -border 4 -sticky nsew + + # Checkbutton + ttk::style configure TCheckbutton -padding 4 + + ttk::style element create Checkbutton.indicator image \ + [list $images(check-unsel-rest) \ + {alternate disabled} $images(check-tri-disabled) \ + {selected disabled} $images(check-disabled) \ + disabled $images(check-unsel-disabled) \ + {pressed alternate} $images(check-tri-hover) \ + {active alternate} $images(check-tri-hover) \ + alternate $images(check-tri-rest) \ + {pressed selected} $images(check-hover) \ + {active selected} $images(check-hover) \ + selected $images(check-rest) \ + {pressed !selected} $images(check-unsel-pressed) \ + active $images(check-unsel-hover) \ + ] -width 26 -sticky w + + # Switch.TCheckbutton + ttk::style element create Switch.indicator image \ + [list $images(switch-off-rest) \ + {selected disabled} $images(switch-on-disabled) \ + disabled $images(switch-off-disabled) \ + {pressed selected} $images(switch-on-pressed) \ + {active selected} $images(switch-on-hover) \ + selected $images(switch-on-rest) \ + {pressed !selected} $images(switch-off-pressed) \ + active $images(switch-off-hover) \ + ] -width 46 -sticky w + + # Toggle.TButton + ttk::style configure Toggle.TButton -padding {8 4 8 4} -anchor center -foreground $colors(-fg) + + ttk::style map Toggle.TButton -foreground \ + [list {selected disabled} #a5a5a5 \ + {selected pressed} #d0d0d0 \ + selected #000000 \ + pressed #25536a \ + disabled #7a7a7a + ] + + ttk::style element create ToggleButton.button image \ + [list $images(button-rest) \ + {selected disabled} $images(button-accent-disabled) \ + disabled $images(button-disabled) \ + {pressed selected} $images(button-rest) \ + {active selected} $images(button-accent-hover) \ + selected $images(button-accent-rest) \ + {pressed !selected} $images(button-accent-rest) \ + active $images(button-hover) \ + ] -border 4 -sticky nsew + + # Radiobutton + ttk::style configure TRadiobutton -padding 4 + + ttk::style element create Radiobutton.indicator image \ + [list $images(radio-unsel-rest) \ + {selected disabled} $images(radio-disabled) \ + disabled $images(radio-unsel-disabled) \ + {pressed selected} $images(radio-pressed) \ + {active selected} $images(radio-hover) \ + selected $images(radio-rest) \ + {pressed !selected} $images(radio-unsel-pressed) \ + active $images(radio-unsel-hover) \ + ] -width 26 -sticky w + + # Scrollbar + ttk::style element create Horizontal.Scrollbar.trough image $images(scroll-hor-trough) -sticky ew -border 6 + ttk::style element create Horizontal.Scrollbar.thumb image $images(scroll-hor-thumb) -sticky ew -border 3 + + ttk::style element create Horizontal.Scrollbar.rightarrow image $images(scroll-right) -sticky {} -width 12 + ttk::style element create Horizontal.Scrollbar.leftarrow image $images(scroll-left) -sticky {} -width 12 + + ttk::style element create Vertical.Scrollbar.trough image $images(scroll-vert-trough) -sticky ns -border 6 + ttk::style element create Vertical.Scrollbar.thumb image $images(scroll-vert-thumb) -sticky ns -border 3 + + ttk::style element create Vertical.Scrollbar.uparrow image $images(scroll-up) -sticky {} -height 12 + ttk::style element create Vertical.Scrollbar.downarrow image $images(scroll-down) -sticky {} -height 12 + + # Scale + ttk::style element create Horizontal.Scale.trough image $images(scale-trough-hor) \ + -border 5 -padding 0 + + ttk::style element create Vertical.Scale.trough image $images(scale-trough-vert) \ + -border 5 -padding 0 + + ttk::style element create Scale.slider \ + image [list $images(scale-thumb-rest) \ + disabled $images(scale-thumb-disabled) \ + pressed $images(scale-thumb-pressed) \ + active $images(scale-thumb-hover) \ + ] -sticky {} + + # Progressbar + ttk::style element create Horizontal.Progressbar.trough image $images(progress-trough-hor) \ + -border 1 -sticky ew + + ttk::style element create Horizontal.Progressbar.pbar image $images(progress-pbar-hor) \ + -border 2 -sticky ew + + ttk::style element create Vertical.Progressbar.trough image $images(progress-trough-vert) \ + -border 1 -sticky ns + + ttk::style element create Vertical.Progressbar.pbar image $images(progress-pbar-vert) \ + -border 2 -sticky ns + + # Entry + ttk::style configure TEntry -foreground $colors(-fg) + + ttk::style map TEntry -foreground \ + [list disabled #757575 \ + pressed #cfcfcf + ] + + ttk::style element create Entry.field \ + image [list $images(entry-rest) \ + {focus hover !invalid} $images(entry-focus) \ + invalid $images(entry-invalid) \ + disabled $images(entry-disabled) \ + {focus !invalid} $images(entry-focus) \ + hover $images(entry-hover) \ + ] -border 5 -padding 8 -sticky nsew + + # Combobox + ttk::style configure TCombobox -foreground $colors(-fg) + + ttk::style map TCombobox -foreground \ + [list disabled #757575 \ + pressed #cfcfcf + ] + + ttk::style configure ComboboxPopdownFrame -borderwidth 1 -relief solid + + ttk::style map TCombobox -selectbackground [list \ + {readonly hover} $colors(-selectbg) \ + {readonly focus} $colors(-selectbg) \ + ] -selectforeground [list \ + {readonly hover} $colors(-selectfg) \ + {readonly focus} $colors(-selectfg) \ + ] + + ttk::style element create Combobox.field \ + image [list $images(entry-rest) \ + {readonly disabled} $images(button-disabled) \ + {readonly pressed} $images(button-pressed) \ + {readonly hover} $images(button-hover) \ + readonly $images(button-rest) \ + invalid $images(entry-invalid) \ + disabled $images(entry-disabled) \ + focus $images(entry-focus) \ + hover $images(entry-hover) \ + ] -border 5 -padding {8 8 28 8} + + ttk::style element create Combobox.arrow image $images(arrow-down) -width 35 -sticky {} + + # Spinbox + ttk::style configure TSpinbox -foreground $colors(-fg) + + ttk::style map TSpinbox -foreground \ + [list disabled #757575 \ + pressed #cfcfcf + ] + + ttk::style element create Spinbox.field \ + image [list $images(entry-rest) \ + invalid $images(entry-invalid) \ + disabled $images(entry-disabled) \ + focus $images(entry-focus) \ + hover $images(entry-hover) \ + ] -border 5 -padding {8 8 54 8} -sticky nsew + + ttk::style element create Spinbox.uparrow image $images(arrow-up) -width 35 -sticky {} + ttk::style element create Spinbox.downarrow image $images(arrow-down) -width 35 -sticky {} + + # Sizegrip + ttk::style element create Sizegrip.sizegrip image $images(sizegrip) \ + -sticky nsew + + # Separator + ttk::style element create TSeparator.separator image $images(separator) + + # Card + ttk::style element create Card.field image $images(card) \ + -border 10 -padding 4 -sticky nsew + + # Labelframe + ttk::style element create Labelframe.border image $images(card) \ + -border 5 -padding 4 -sticky nsew + + # Notebook + ttk::style configure TNotebook -padding 1 + + ttk::style element create Notebook.border \ + image $images(notebook-border) -border 5 -padding 5 + + ttk::style element create Notebook.client image $images(notebook) + + ttk::style element create Notebook.tab \ + image [list $images(tab-rest) \ + selected $images(tab-selected) \ + active $images(tab-hover) \ + ] -border 13 -padding {16 14 16 6} -height 32 + + # Treeview + ttk::style element create Treeview.field image $images(card) \ + -border 5 + + ttk::style element create Treeheading.cell \ + image [list $images(treeheading-rest) \ + pressed $images(treeheading-pressed) \ + active $images(treeheading-hover) + ] -border 5 -padding 15 -sticky nsew + + ttk::style element create Treeitem.indicator \ + image [list $images(arrow-right) \ + user2 $images(empty) \ + user1 $images(arrow-down) \ + ] -width 26 -sticky {} + + ttk::style configure Treeview -background $colors(-bg) -rowheight [expr {[font metrics font -linespace] + 2}] + ttk::style map Treeview \ + -background [list selected #292929] \ + -foreground [list selected $colors(-selectfg)] + + # Panedwindow + # Insane hack to remove clam's ugly sash + ttk::style configure Sash -gripcount 0 + } +} \ No newline at end of file diff --git a/vmcompact/sun-valley-theme/theme/dark/arrow-down.png b/vmcompact/sun-valley-theme/theme/dark/arrow-down.png new file mode 100644 index 0000000000000000000000000000000000000000..122ee4599d9d9eee5a4c8fb73d0f428ae7076c1e GIT binary patch literal 270 zcmeAS@N?(olHy`uVBq!ia0vp^AT}!p8<4C?sm%aVoCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt;1XT^vI=X6E)9avgFIad|#F zS8UrSy>DSo4GEO|ZY$F%aCih3j5Ro_y@0xmC4t-Ks1@rL&%K3~yK%_I$sr;+d!7Upepi{4FY#0bXl2=~SQk zpm+LG##-eD4W;?}-kZl>U)#N?g0bPx@>$C+=H8BDJRmVSD*OK7Z>*L))>mKT@N5G* Olfl!~&t;ucLK6U9iewxB literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/arrow-right.png b/vmcompact/sun-valley-theme/theme/dark/arrow-right.png new file mode 100644 index 0000000000000000000000000000000000000000..2638d885eb9be2833b009ef5b88081a4b22b34b2 GIT binary patch literal 261 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1g!3HF2ETDGVhgXJ?3QcUSGUi&$t1y1Z}2x(bF22!HCMuQ zI$p3OWUj4!E%8|9z|yT|74PF25?r3-^xU+1J}>zd^VQSFKbf9auLQb|!PC{xWt~$( F697n>UrPW0 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/arrow-up.png b/vmcompact/sun-valley-theme/theme/dark/arrow-up.png new file mode 100644 index 0000000000000000000000000000000000000000..f935a0d32a699308758f10b1ccee21c92e7c6b64 GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^AT}!p8<4C?sm%aVoCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt=OCT^vI=X2$jzavgFIVSTQi z*}{5|xk5}oLD5M{aRSQ`Y(kAvd{KEfjKk-)x RB?6tw;OXk;vd$@?2>=XyVnF}^ literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/button-accent-disabled.png b/vmcompact/sun-valley-theme/theme/dark/button-accent-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..bf7bd9ba70f9371a9c3d98b8f97039e611018479 GIT binary patch literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|;*h7sn8b-nZur`3@@xxLiDW z!YS&7&*{JVX}8u2I5|~J?otbV6Yxv^!OQ(YUir^ul6nLLCmfl2hG(tm3azU5H|7+3 zXvVgssR%kXbSOOMIVO>xeE-9~_X|4y^q$@G{Xy4mNzXNx)qXYb|7h6XkhYD-*m%R% zZ9HqXHm&Lso&LPiDfHky>!Ncjw%%(x%d=EO=6Itao1J61{YF2TkV2sI7(8A5T-G@y GGywpYLS~o% literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/button-accent-hover.png b/vmcompact/sun-valley-theme/theme/dark/button-accent-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..8aea9dd682773a2a5ed32f6a9c14a4db8f2c00ac GIT binary patch literal 373 zcmV-*0gC>KP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10Rl-x zK~y-6?bN+W!%!TC@#mZrlbRw0K~Ro^QncWv1YEoUXX)bTF1-OKZ$JkJXGg`wJ8*C) z4h}*mv5QFkz*dZslX(8l-Avjs&jtK=r&k$cB%EKO(P~p~MpUXHdCGobKDr$q&X0(n zd#KfDOEwP9aDENz1j)sL0;aUWOJZ&hchQYj8|T+Z3Sa;NBu>bJkma3ybiEm2r3f`z z>V(;~O?0IiG64?}@PZIMJ~dhimS73~3$*bkY66f_kbVu(Z}&HN?sxoUE~9^UjqY8Z zkPco@nWfO}h@dh{`rha9;uvL&kzj6-h3!3NR@Tw}bS}>&-weAQo~}-@gIE3l45nSi T5+#gb00000NkvXXu0mjf@z|C; literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/button-accent-pressed.png b/vmcompact/sun-valley-theme/theme/dark/button-accent-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..edc1114e5e03094ebe8796dd528ca5fb932ec9eb GIT binary patch literal 363 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|*)h7sn8b-nUn6{g@nO+CDzF zx9*;udEr#r)!YL?N^{c#^cI$c$sIY?*5W;(fLphNmz7r~>{yG(qSJL}`&z|jMeIn} zd7iQEWb|I4wuQ#O+g`s687wYMU0!lt z4%JQPuG`#;Tf8_<{9(Jro53Y5417}iTRn$ z_kpST7yD~>(}-r%AL<)ClBVSFb0$nKzmjF$cdf6(yaQPpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10R~A# zK~y-6?bN+W13?sq;df?N$>0*f%3{PuB$bt@SXo&HyaDk7(pq>0iU@Z0f>_yDiC`o6 zgBBKIBg7`4kOXx#8{C~uW-P1}3)iIF_W~Y1PH}|R+68)o$>lXhrsnZgK$bcm5ihsr z-0!Z_etbZb<`&%S<{`FFB(>l&aUg&J310lpGEAgY~T(%)uP|6KJA0L?0jlm{y2v-kc)4Y0sdvDfR0U zWOaWF^IS)m1l&KKqO*`DB+VzPdm9L?wNsmmtT}V`<;yxP||PQeIruR^2&q!!i^gZ;ubuSeW1DTk+ISuZ}w2O*5*3` zQ^PZ=R#;nnPcYNI_*W)v;)U|Hhu*PmJJpsf(38uxt>ExR|JN)zZ_@UkVzibMpLKw9 z&Vl_7>mMhsZOZ-i@xW!_oV%=*8R4ymWqUea9CDoMG_!@f>m>7W_XB$R70j*T>ISDz Sf8_%@mBG{1&t;ucLK6Vt7;0ev literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/button-close-pressed.png b/vmcompact/sun-valley-theme/theme/dark/button-close-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..6023dc1435a0288cf824533d496312b237fdf8b8 GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|Ya0=^f37C6--m5nQu|q!)78&qol`;+0K4&D_W%F@ literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/button-disabled.png b/vmcompact/sun-valley-theme/theme/dark/button-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..27eb0058c85c4bbcadb7df94d81f257102e2bae5 GIT binary patch literal 301 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|+?=7sn8b-nUn**Bvq7alWYC zX%>^hdGkM4tVE}Mu^?#5Q&%xNvF6_YE-E-BXhO@(LiKFjs`p#2NhB}mNVsiQ zbk5~Sa)8j*un;fB=RGP_@6TA~H@@@p;xt}7rO8`KNiLD0*ston3yY@eoihfT-EYKy z`K?vI=FepDnuFqhIAgLmUOV)6=i7HNe((R@+N{1}w{oW;+w;mr*Q6#fOend#|C#lM ummtT}V`<;yxP|-q97sn8b-nUl{u4*O1 zsC*))jVhBP;;;%B={W8H-&&gXs@sj0Mt`_R8PZ22G9 z?3wQVH9B+GbL+L!2WszoE)}`+ce%W}QbDF^6Uc VrPTJsX8;|`;OXk;vd$@?2>?~eZKMDI literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/button-pressed.png b/vmcompact/sun-valley-theme/theme/dark/button-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..a1c525723e796c3070b3c319e7e9e70a06435650 GIT binary patch literal 288 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|;dX7sn8b-nUmAyILH0+#ZTg zZsL$T_Zj!g-yInS;MwD{tse`FwiUx|OSTSf{mh7zCvW32wReVsG-QQ=4>L zSbp!DJkxnW#|N{lwKH}L3%VQ;_)@vBIyZMN?9Bi75GgYw&Fx8DakoWax8&t;ucLK6VlYj_|4 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/button-rest.png b/vmcompact/sun-valley-theme/theme/dark/button-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..ec427edba67de887bffcb0673518c072742c194d GIT binary patch literal 301 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|+?=7sn8b-nUaX_O%%Bu--2g zYMH`T_3!_84F^G$8~fgEiF)fPzAd$?|5)$Y)JU6S9dnF>yc9a+?#Qk+ee;_y)V0Sj zX_ndwt*GpR?|O=!EdmDTjjxrup0RWeUAQWC(e*>GcL_K-oRgds)HL(%q`gUL5^ao5 zo2t+5_wsbwXSVkvhx|k3KhrOq*_Ho5-Q&<1g{@&7HS%6U&nun0Gz-c*POJ@@w7+<% uh)d|vZMhQ1KVIWzXo%A8d)zSdAv-rqX!7?9^YVbcVDNPHb6Mw<&;$TnqIMJj literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/button-titlebar-hover.png b/vmcompact/sun-valley-theme/theme/dark/button-titlebar-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..fcb37512f76d28becbc7ece0f26be88ee16892d2 GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP*Iboi(`mI@7r_UT!#$=ST4@v z=Xt@i??11tK}1k>Do5nejnmdK+jwouUA#(3DIrZj@J^@7F^LsgXDlDC>biC-_l1|s zgLekTDQYH4|Bmf@*wHZSX7Za;cNc2Ev%9?X7Wcjf-2b>H#c=l-PD?yq=&+hgThDXR oss+Vk`_Fx=W%r!(;E1_J(xH`AK-VyMy85}Sb4q9e063~!+5i9m literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/button-titlebar-pressed.png b/vmcompact/sun-valley-theme/theme/dark/button-titlebar-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..2ed0623e8d5bed5e8a24d960b49a3a9e7c6f5ddd GIT binary patch literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP*Js~i(`mI@7oI-d6^A)oCCYM z8l?~YKCj`hZN{S@mP{sfy}#@g3sUx$Pjt!VRY^>X@Dy6bHM4Wop=OnJucMsq85{4g zz9TEhxb0fqF}v#6ler6aH?Ow;eQjSQyUhc}a0k!ogR5?}^%@>HbEnDEDeWG&GE?!n f{nK1oR335`J~weWWB$Vc=nMu=S3j3^P6uJzMwL zoHxJENia7s73_@@6b$+Lzp-4&>AkG6bLh#fVJTn>W<9 z>iY4x_2O$yi!`5xn18%0(Hz8e^Y`I@ol}HQZu?(LO%ZZ0>r@fsgK^Y8EV spwMS?V)VrGw%^XQo3~OcjqQN=osEgJ*1Y451co1jr>mdKI;Vst06Ai#e*gdg literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/check-disabled.png b/vmcompact/sun-valley-theme/theme/dark/check-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..f766ebafa3c9fa5b7dcf944e0a8c14961cb9c35a GIT binary patch literal 383 zcmV-_0f7FAP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10Srk* zK~y-6t!pis{hQtTpX$cm-iIH|HLr4a>Y{eFvb$3Kgdvm}1 ziF0nsvW%iAu+}0XypyWZ_dVWwLI|W;mf@Ux8=4alw%aY%TH3ZnilSJI{e*YB9b&Eh z7@N!U99d)CoQSZVHls_Pj4>Pzhjl<>3}soe-|s&MjWL`~C#GqlX_|QOcs!D(>91Il zB-C}yIF9k4bB?ksztLFiC3v}97>0rK`OIdsiN;=ns!G!|gb=8zDjItU&S+iN+-|pM z3?TjMsH$AA*C^=Ug-a7vT@6!Jr0@IHz^>~M?>%d*9LEvwJrY8oZCkpoTLh~rkH>@i d{m%3GpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10cS}> zK~y-6tm>%sQxjsVJvc0EU6MnKcjAF7lwN(ubAy zmZ8%w!pUQ>oXb4ec(}%WYT*|(iy4CA#vxd@7sbRpR9P~O8G^*&L})t;=co@?t22P6 zA+nPnh#7)ED2Gtu2xH+ngp)ZCCpQoS0493=uA7=Pnf*V7DlOYE+HQi#)v|5i=VKA1 zUdVv9Wy@H%`GNZBKG+eWrKHLYIDY^xe*lcb+%BS6Dv Q3;+NC07*qoM6N<$f;?EuF#rGn literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/check-pressed.png b/vmcompact/sun-valley-theme/theme/dark/check-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..4f9d1fc42c780c8e259064075cbd9860a8364fea GIT binary patch literal 460 zcmV;-0WpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10a-~z zK~y-6t*@gx0wzLfh4$rF{$OD)z^;@p5ti${WpvF#upG3B0}sD&>m{W78~cZh=O<*?*y8 z8Z z2=(vc3+f+zsEYiHhQ(%r*-{NuNMLY#0oO7^V>3Yz3SO#$B}MdZ&L>#85s1wO0T9Z- zOEpM*V}dajhyej#CX``qXEziS*l^xZ$1-BWTvG=fciXXnqvw0jq1=LF>I-AGF@kz| z3ML6S)E*QhGRsJ2RzQSAB*?W4Xpais&W`Y{ec=a+8+x@xd5_ru0000pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10cc4? zK~y-6t21Mxu(0 zQZ|KLECMC}3TAA2PMr)V!1neTg4*C}8P5SPnE8ECbxbXEh5aTyUW4)7R8*rgwW5j) zVipDftW5whP5bFzAZ^s}etBpPNENXs$fjZRvjS4erc48i zPq!esSOm0M?iy=WipU)W!P*(RBV|PJ4kxUGP7sba1W`rCM@Ga;bOUv%fNy)~je;~? RX`%oC002ovPDHLkV1i|U#n%7; literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/check-tri-disabled.png b/vmcompact/sun-valley-theme/theme/dark/check-tri-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..a9d31c760240a0deceaf99ab0f3a622de75aab08 GIT binary patch literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|;>j7sn8b-lrE0xegofv_1?M z1bVY|fRyO!+&Ofw{1T8w8(7M&9i zoDy`w^0`2=4e!+sj(gPx#z9^S1P-OXk(6s=JaQ&KdF#ISj=I-?a&NbE{gb~TD|@W4 z<$K-tWvgZ^%l!UrXRAAR+}FSUKN&BanU$EvcFNM6IaE|dDPv>NZLmmtT}V`<;yxP|rq34lPpgIb0nC7z*t?s*(ZUIS$KV$=Fzr;4Ev|CG7GOvY~wd5EHE|*JZmyz zq4IeLu^1uqX=TPW^}m@`%Pil(((G2E8D{w@=ERAPXsv?Zum7h=b}{q(^N?g>`}gmmtT}V`<;yxP|;^k7sn8b-sCA0C;mLIsCHW6 z<8Y+ z<0bR_&!s0!`r@_hh5;K8r19mkd7gJ+Q_D-O?c!}_j0<&UQwuuGBcG7;JSkz(tV{!E z_j!#vJ5=t)S)cvz{CN1ASr$7aTekXaJT>vTliQsji`b6StStu~^iNStcyNFI{S|39 z_5-b%vG2}K2UBMIyEcape5tu@)3)D2$UyVK`R)EZ=eM0nN_du*nDL|HsRXn3egkId z{T$57+}fUOe}Dh%efaolG7rC)so|f0KiU`>bV3~Ue19Dl26~^t)78&qol`;+0A4kZ AaR2}S literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/check-tri-rest.png b/vmcompact/sun-valley-theme/theme/dark/check-tri-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..26edcdb13c66fa429b933f7af6a8ae04a2cc17a2 GIT binary patch literal 363 zcmV-x0hIoUP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10QgBn zK~y-6W0aAR`OhV-!XO`0$-u8;#lXzT!$1o7`~3^U$IC|<9xQEV`2O@R1EZR`!+*WD zjSS4(d?Xo!Ver>a3>T~X7#LkA@BA-h>PC@aF!1)|b_T|f{h$An>P=kW@AoeZOw=-r zfq{X6nUjZsiE5@n!3Z>v1((FtIgJe8-#o)A$0;Jkpq)~WRgOFtGBVmmtT}V`<;yxP|;CO7sn8b-nUmbcC{D?G(4;@Y%WV|Kvzc#YHU*Gwy`4hsSJu7x(f%gS@eiVSnbVeY@5vw=@{C2|n~%YwD$W zM8dL<`EIG~`R9|T2%X*(kiC~hYw3n-M!v$IZ5BIoESVB<{j1QI;I&hy2r)diP&y{@ zt+t-~_uXx|Uuye1PCPaJzv^07N5NYr{gP($ie~-BwWd>osw!q^?+1E_!PC{xWt~$( F69Ag1dV&A| literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/check-unsel-hover.png b/vmcompact/sun-valley-theme/theme/dark/check-unsel-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..6d00402ad42910895fa8ec5617d5e50f9244e6b5 GIT binary patch literal 353 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|-V27sn8b-nVBA``jED*e>Mf zBz0X}IN9fq>{XW?4d)bN4sm|d;(NgMh)GCR^yC&UR!$?4ZU0w`t}SnHmpQ&u=d_c| z@dtC7gSxDz1WgE9v`Wk8GK*5nj!P!4mrY*m;(NX89+zbD2OIuG38nMJ6Le0mE0hVm z{&nq(Xc5;9xzbY4WpZ!Zonly!8(m{3pD`sU=k_;?JKK17t#hunsjWP0UURs<)l1Xh zn4EiCqJt)@uNUX}&vNbi-X}}2{dx2I-)t354#gSIC7)N`>yk(oa8lr45^-gGWN|Ka wmf9nWw%5BZl>QB?kYWF|&pmQl#5C6WJ;|Y;8LQ-;1AWfm>FVdQ&MBb@0B_=m>i_@% literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/check-unsel-pressed.png b/vmcompact/sun-valley-theme/theme/dark/check-unsel-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..67d6bb246ff2d2e9d072f90480c5ebb3279d6faf GIT binary patch literal 302 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|{9^wwTk8g#epjQs&&4#vZqbaG|fmrN0GVh~)YzBO!xmJ7@A z!i0$HThD&(3F11#v-O(ZgpLDe64G*Rw?%t#E)`jkCH^Jq;lB47YZGUw1#mE?eG~mA zW$fG|=;CrWci-wM9T&_S`HLFGD;nh+&&&Rith&Pz6l(DK{DSXtmgzvFs{19B=M>+a tP|T;uVqomTa@ao3;hdyW(`TDPb|;olzx`f~a902T literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/check-unsel-rest.png b/vmcompact/sun-valley-theme/theme/dark/check-unsel-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..10cd31b102682ca0b2fcef0f6057191833ce7194 GIT binary patch literal 353 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|-V27sn8b-nVBA``jED*e>Mf z7|jX{>~#6_x5G(kN>q9Qr}~Z677fxJ)5LT;U33KvCtkeqZ++O7dyH}$bzU3sFc-=k z-j=&!RhRXWDKnOFhK43aiV2+myw1e;q6zP>eaH8`-|low!s0o{VS&nd%_)&(XFvDs zT9@y7f00I0=B$96+iurO`;8bfZi~%7&)&6am4K5CU#q}^DNdC(wUvj>YYx}926-7A zlXIW7%+ZT8b(UJeIr;W=uajil|HvHwI9r92LowpI=<~{ZT@uM3YULdT7HDt@oZh4t vdtLCjq0Di{rC-7-=Bc+OIz&#pv5mLh-5^ZFF6mDy(B}-Eu6{1-oD!M literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/empty.png b/vmcompact/sun-valley-theme/theme/dark/empty.png new file mode 100644 index 0000000000000000000000000000000000000000..22183634d5e36298e12ed067750da6c7d2fcdea9 GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4aTa()7BevL9R^{>lpinR(g8$%zH2dih1^v)|cB0TuCix;TbNOifOZU~Lv=U|^iZ Vz$kX=awbrQ!PC{xWt~$(699LkAlU!_ literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/entry-disabled.png b/vmcompact/sun-valley-theme/theme/dark/entry-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..9d25dc8b95a58511cf0912ec600abf356eeaee56 GIT binary patch literal 273 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|-Y37sn8b-nSPF`C1HkSTA-8 zPw19u{5{{mL$LGh+7;!Ex-;+j$NSyh=6X&tbm|-;b-0VZrr)2mKTH2dll~8F3Bmft zATJjdqvtM9eg+68_B4LEchb_{>HP0|)<@4|tX;Tj&Fd;|o4)4S`-SCp?;YJTqj(mB PT*~0->gTe~DWM4fa`k4= literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/entry-focus.png b/vmcompact/sun-valley-theme/theme/dark/entry-focus.png new file mode 100644 index 0000000000000000000000000000000000000000..30310fb37156559369b5e99bdfc34f7eb568be5b GIT binary patch literal 335 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|+Pv7sn8b-nUl_y;uxI+CRQm zohhIy)}^3R+-2J;{*mLGnc2N#VISCr@zsC%IyB-?1z4~z5Bv+dF$G>zZ>s#PX5BpY literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/entry-hover.png b/vmcompact/sun-valley-theme/theme/dark/entry-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..6b93830ab5908d7af96c755acd111761524e0f4e GIT binary patch literal 269 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|++;7sn8b-nUmaiZ&bYv^<>L zs&QolLx1LsTc<17q(oob^b(#GQuyf7e}?{99(~(L!!-< zWzueb=J&tdjEs9CZbmiFOkBCOX=dR(^}fdr@9lS4dug7qT)eeSyndef6wjY#F+f)` Nc)I$ztaD0e0suTIW;6f* literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/entry-invalid.png b/vmcompact/sun-valley-theme/theme/dark/entry-invalid.png new file mode 100644 index 0000000000000000000000000000000000000000..7304b247cd136a2042d9ef347406655172be6537 GIT binary patch literal 324 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|-zC7sn8b-nUl{`W`V5aC>OJ zEx9tX`*fT|M2Lg`76;iY4#86x+4%%El_jO`SSR2yBjz*Lk1yv_RhBNf7UjfY@mxT# zDkwB-?UOl~Yag!JdPL%+rLnK@s#~mG9QUe|dU_sra4SwIUN+?tYpkBmQU#?J0fTdv z&no|kmqlu}CQ2A6U8;SS@6C87?Pav}j%Mp0>H(p<>mT$_FkGRv>{{3NI^!36(<8<1 zyi9)b@oDesYi5m$x7ys9Ghxc4d+Sd9{jFXe{A|Oz*b6r$=Jm7BTi3sbtA_D~anSBl Ths@^zJ;&hb>gTe~DWM4f{>_9> literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/entry-rest.png b/vmcompact/sun-valley-theme/theme/dark/entry-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..e8767526ae057387f873d60cc1ec1ae578b77cec GIT binary patch literal 297 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|-F|7sn8b-nUma_O>|iv_4Fi zR`<(bxX5RFna6a3#es^NlZt|K{H%9Ne|rA;WhT>Q6JJ#&1LGB19UQiyqDoBf`pz6t zP?9(a0>V{Rj@*l(t3a;Xk5lr}3qhb8mf^Wm_=9!90`MP`gbOaCHHB3=+VL81i pVP5)*EO80J8{2qa?^?9AP2QBpXKBq|V~{r)JYD@<);T3K0RWGPZ215H literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/notebook-border.png b/vmcompact/sun-valley-theme/theme/dark/notebook-border.png new file mode 100644 index 0000000000000000000000000000000000000000..0827a074e2330c873964133f877788a1fb4cbeb1 GIT binary patch literal 337 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-&H|6fVg?4G5)fv*mnL5U6qGD+ zjVKAuPb(=;EJ|f4FE7{2%*!rLPAo{(%P&fw{mw=TsOX-ji(^PepF;&n47$?_anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt=AJE{-7)t#8j6G9FM6U@&wz z{(F0*O38@}eB!J(jX$rEw~lAOClbOM>KGazijyj340+DDcylDb50q$YKTtzQZ8Qcszea3Q$n8 z#5JNMI6tkVJh3R1p}f3YFEcN@I61K(RWH9NefB#WDWD=hPZ!4!iK)p`CQkf$-of?2 zBB|(e3h$>MI&k8U*F?wv|No>_Y$z0CPJXkn|9_;#&XtdL+27x9U|@T1Tf@Wu^Y4pD mfBSzvzwLOmxPd{CH4kI2rj)?bY!MZp$qb&ZelF{r5}E)bNJUcs literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/progress-pbar-vert.png b/vmcompact/sun-valley-theme/theme/dark/progress-pbar-vert.png new file mode 100644 index 0000000000000000000000000000000000000000..3d0cb29758f0c6b066031b946818eeff9731dba4 GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^tUxTn!3HEs#ylDb50q$YKTtzQZ8Qcszea3Q$n8 z#5JNMI6tkVJh3R1p}f3YFEcN@I61K(RWH9NefB#WDWD=PPZ!4!iK)p`CQkf$-of>N yi|=6xAc)wsX_G`tOUsI+8@tQjOGvQqoz5s_&i0<^Jj+g?E(T9mKbLh*2~7YrkuMhj literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/progress-trough-vert.png b/vmcompact/sun-valley-theme/theme/dark/progress-trough-vert.png new file mode 100644 index 0000000000000000000000000000000000000000..22a8c1c640586e6d8af59d584ff97089b570fec8 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^tUxTn!3HEbP0l+XkK Dj5ILM literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/radio-disabled.png b/vmcompact/sun-valley-theme/theme/dark/radio-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..965136dc72ed7492600cd63e83e1a2b218717b3b GIT binary patch literal 553 zcmV+^0@nSBP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10k%m* zK~y-6rIp>TsxT0R7Y#p&Qxgm|K;kR#{tv=C&_Ey>(yA3w_k~-fVAOrix|`MEYi4Mt z-fp+MVkXb?Kt$l2BMd|Mz7GHx#}Svy1zKw;rEtA2K7}_2a?X(?34$P4Bu_OA1G=t* zQp)k!G!Q}{%d(F!00@ErS(ZTv@fs+EKpe*(L371%j3h}Ou@BtJoWrcOsHzH0(?Dwt z03afyX^K40!Pv97&1Qr1`3$Y~4LIEa0E{sx%W~15zVFfZJ*1QOtG#_Di)phN} zQ51pQ5A9v|AMlOlxxVka=kTxcJa6H#aU30E-qUwltyWGvjw6^c#xc`0{TevWHO7F= z`;g~3IOiW>oO9%P?s!^jFr^fRVR)E~F%(7d7RotCQ54Q?8HNE`>)W&;qQ!33T1Y8T z*Y(G%2LMvaClL7e;Q#>p{T^M{-737BZQJ5-IQ$n3_?pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10^&(T zK~y-6m6cCy3{f1%Kkv=XZfxz^k*cPhwrNt)y4Z3+Rdfjs{)DJFAt59#6~e&<3C9xB zIH*G#H&Gf+Qju*#8ZPXqZ9<6dpo;9Kt<^O<^BiUu{iF1IdNXO~yo*wc?9rUQ-Do2h6%NuaoV#^yhj{cMr! zx=QNBl#XVZ+r!E0VWXm zHE_qiGSJDt2R?}ycK|;Cb6E} zr~h&bc4lJMaP{Cq8cw%iHtr(hc+Os3KSeqbM+(hH#oiMD1T=y5r0q1fXjFX@sUDja8cnlvE(`!tB4?;w9@}Qi}f87TobKNCE!hGK~5rq!EpI zVQ7M(?)EvI&2&1>Q1?xA=~XQfZ9)dC>Hx2r*0Y}fh81Kz>%o@?7FDf4>Wh{DAO(zl zcr$O{_=h)$e1`N$2@<>~h1ZMomjF>%DWskL>;V;o%Bts$3zbz_g;BMf<=YRS1r}g`pCC8+4e8T~RM)X= z`$0CGy+NpEC6jsB$A=w^#&3JZr;M+?EtGCM1bBU^OMy=c3eDsKIagu3ihSA_dDw|{ zukF|PnlWG_(HNEcP7)}om@|dh(Imrnu8>ajPEGCXSAY+rK1L+kM6j}M+7&QJ`emF{ fq8H`lW_;);9`znQ3JgsY00000NkvXXu0mjf>yCx# literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/radio-pressed.png b/vmcompact/sun-valley-theme/theme/dark/radio-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..87bf8718e30763e2aabe9ba28f5ca3c5f735df48 GIT binary patch literal 786 zcmV+t1MU2YP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10-s4l zK~y-6os`Q@6Hye0zk8=sQ&0wZ(~=kh1hpkZSSXJKT)0rsjYM}wf<*lvj3NF5u3U%@ zSh+x>COljMiJ&p+#)9}D8bc}aXqZMUw4E6jKxL*>5`W1o?wNDG`JH>`9#K|SX5o-f zTxfwNG=C!=Uj=Th5P-P8L@YE*bZU~--~^VDbe1BVz}%W6vD))GJqH0=sgrNE;~ zvfT>VZUv7jaVsJn+Ij)a-w1#Uso-t9VoMN!N0o%%j`C@!pUBq_0OVEHP<^(OlKNKG z6DB)1-*@gR(U~_Whnm}a@{gaf0kc%ehex-0cmEb^OCd}niD@KRTMF^xthySHO;G6CQcED|9a{jtvlg(U)4M4Oq?Jh_}6)efi#h zf;Lv>nIG&;Im-y#^sSH^XhQQh;PF+VY6So!^krh9FX&T~tOh5+G}21{0G-nL`_GUO Q^#A|>07*qoM6N<$g44ri2LJ#7 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/radio-rest.png b/vmcompact/sun-valley-theme/theme/dark/radio-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..a86b523f78ed0497d3d081a5cc9bf9b5c2c41f78 GIT binary patch literal 830 zcmV-E1Ht@>P)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10?SE6 zK~y-6jg?Jo3}G0@fA2fHvt`+^gOZl6MOsqQP+JL!6YU~2y;eyaiVNZ*Q3r`2ZXA3x zPJ|v2k+jRfK^$x~p(<(hLra^sl9?iHbhf)Q4%?lbZfW}@Gnx0FXMXQ9PoDQbqOh>g zCMSf)ix#Oui&WxYUy7=&0U)6dGx4P*k?EoOSp_Gl$T1sl_Nhm(1 zrpX1>r}_P*4I>^ytSt)J+i$%lZ*|Cl*~SnpXAh!(`S{Pz)QZcfy7>a36*y4y$9LM! z>_uu7Q3ocbE1L@jpm%+s<=i3El!*{&&9`bTTBH)GMJk;{RY2#H#yMebXxG#G_+(ZK zmhVIQ!&|exlhD)LG%qX@-OZ2ji0pbvcpFj;<~xD}#`-=l7&zA3fph^?Z8Z|xHP^zq zEhvPLGX>j5CX7*MZP~Cqyk)__W#KJYu6j&k1UcUK$q|w^Y>d_}7`Q1~OVS0L=xs+D zt+DJ57L?S~qZOCU3)70rD5pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10kug) zK~y-6t(9G?;xG_EPrq!N#21SNq5uDnDF~YSU=yP;w)-IMu3neBUiUnOFgcllVJ2#t zX5fh^ijY#GlwvlUk)|mCAq2elSZguHFbrRwl0IK3rKqZk5CUD-aX1_ZA>4!0l%gn@ z&*v-_3);5D81q^fMG;k1A%tMJ+u@x1^1JsQ?>)!kk+LkQ>zbk{&{|J1@p!1JiagKR zY&I`t&p78;uh$esK~+_cLZuW!2)5fTecyj88|nL=?RJY&3Mu7XIF`EK@86P*+-^5^ zyB*8rk|>IZrIdsa{;ABr;he*JkCc*FDMi61qWD-Sgy3?y5L;_eN_{MpQev$o?z)aF%Me2RSXP!L zS(e>}0Bze+*ELC!ye&(Tgu1TLS~Cp8U1*HK7{h9{dP|xl39Ho#V+__>;E!pewdQ<2 z(=-ibS$-=k%aW#PaL&=T?R5XpFIsDybJTUs^?Jox%jtCDcDqd(2_cYDl4TiM>nXF5 q=+z1UrjeBA`NImhTrSfJc*QS>7}QeWq3D4C0000pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10q03X zK~y-6t<}A5;y@IJ;TO9AB-;g*BgUbhpX-vi*fF2muFFbwfLk37#QisJX6Wm&{=jEFFs&8X}8%jv%+2m;bH zr6>yWJm+*eeFT#vK`F&#GNEajzhdWfyIry@8%spcTJ!Sqay52NUDs%>5fQ8?iYUwS+t@i( zRS||Emhbz#zP{cJ)^*L@-5r+WIG1;JON=qNuG@C`f27mt0ALwoa2)4m&~Y5J)>xa( z2Bp-^pi+vrw>PY^ED6K#W>7?^stT(p3Ovsv2!d~8K@i}&ZVMidNAf&pJRZ~U_pio! zy&h?rGM!F291d-li=tq)TJiAkK(E)k3VVEfWVu{YRTTiX=XpN>o}Qi<3yf5{xmI0c(r_+5xMSLPT&JhuLg)sqBv+w8J)vBEm4l o_kBFi13+v2;R`q(k6$YP2{rQD5mPw%UH||907*qoM6N<$f;>wMqyPW_ literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/radio-unsel-pressed.png b/vmcompact/sun-valley-theme/theme/dark/radio-unsel-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..1534a969184e56e4f039e4fe143eb2897008bed7 GIT binary patch literal 616 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 RT<-t?002ovPDHLkV1jvZPDlU% literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/scale-thumb-rest.png b/vmcompact/sun-valley-theme/theme/dark/scale-thumb-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..f6571b9336e9fde5c8b92387bca71c4b0ede340b GIT binary patch literal 771 zcmV+e1N{7nP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10+2~W zK~y-6m6f}0)Ib!5zq$CfW*vvHh+>1p3s9w}gQwtC5aK0xfbmu4{7e=u+r9JUn+sp7@V-DWe^1-HUR717D2kp6A%@32!0Uq5r#ILanMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt-vZE{-7G896g;3H;Bs-V z3Rf``r|}i%@QEfR#lDRWik)3O%`1Mh+H6eHJZ7zopr08NrgdH?_b literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/scale-trough-vert.png b/vmcompact/sun-valley-theme/theme/dark/scale-trough-vert.png new file mode 100644 index 0000000000000000000000000000000000000000..205fed89725e9c6399776707dff139f02916abc3 GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt(B@E{-7HKKbo$Pw?#jYb+z^;UtvYqx^#{;HXxUHx3v IIVCg!0NgxI_W%F@ literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/scroll-down.png b/vmcompact/sun-valley-theme/theme/dark/scroll-down.png new file mode 100644 index 0000000000000000000000000000000000000000..4c0e24fa06c2478235e21ac90290d52cbe893c0a GIT binary patch literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^96-#*!3HG%vEKg;q&N#aB8wRq_zr_G1(%kFERZ*H}=vaekL7T zsTuPK4U5vV2y0-MR<@)j{#s;mWYtHOBA<(qDxmJDYlVy1)&gck!oWZK} zC|dC1;VA7r-;YTYuQU{#o7@xrzE=Ey`5S%)T|KpL{*DuX&SLO%^>bP0l+XkKH`8Hy literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/scroll-hor-trough.png b/vmcompact/sun-valley-theme/theme/dark/scroll-hor-trough.png new file mode 100644 index 0000000000000000000000000000000000000000..89d04035b472f791ab57dc0443a8b7f70b39d3e1 GIT binary patch literal 338 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W;!3HFgc;@~FQk(@Ik;M!Qe1}1p@p%4<6riAF ziEBhjaDG}zd16s2LwR|*US?i)adKios$PCk`s{Z$Qb0xbJzX3_G$yV+W9Y@~DAMro z|K6FZ8=@mlCfI9Lv+@fb^jcfYtFIK1uiRnTP%crxGlQF>*>{3S)9;+1j*iBZx*xaw zZ-^w%sd&HMB_%8ExWnoHYa7E8-p!FNIyawz>B9HFf(7Ym%cCdQ3r}oab*|`KzEJWU z6W`Apw7+rh4S0U%>pqEwnO`4U#I0K8_x)(yg6COj8^t*0WVrGqga}54u}sfO>)&c3 zICFJzp1?#`*7r+uZy%f*w9kpd|A1t{4((@q=P#WS#$3n-oCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt*MqE{-7_Gjsbk@*Xk}VSRs7 zFnfpNDFzRdH3uZ_HK;8;D%1C*jdw{vzN_rIIuoH)YEsP b2Ojgjc&2X4#`4$+=mG{$S3j3^P6$3n-oCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt%nyqq^H$w5`ut?h?T-$MEVZ9F z4@76D3tH}b6eqNF&gT<97Ot{2)}LCjl0|T7(5VYGyM!CekDXB}GGPc~xcmPdYv^6o V(3_U06oGa#c)I$ztaD0e0su$+QKSF> literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/scroll-up.png b/vmcompact/sun-valley-theme/theme/dark/scroll-up.png new file mode 100644 index 0000000000000000000000000000000000000000..7ddba7fff7796e7f279467b5fc1acbfbe765ad53 GIT binary patch literal 236 zcmeAS@N?(olHy`uVBq!ia0vp^96-#*!3HG%vEKg;q&N#aB8wRq_zr_GX%tdV$$gfy*IINX}`O{#?QQcXpFYCW`F+o~!wk zErDU{HN~YRlT6sf(#rDIK7DV{_t;M9+MhK==d2la{=Rf(ox`*H!IzGmd1E2S*w$eo f@nJ@X{CDw5#j>p3*0Usmj$rU~^>bP0l+XkKK4()N literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/scroll-vert-thumb.png b/vmcompact/sun-valley-theme/theme/dark/scroll-vert-thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..572f33d8df6df17dd658503f9e26acc2760b2d42 GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp^Ahrkx8<5=cZcP}F;wEaloG4buBjl9hU0$TW>Td&>S_rB+G1@j8y6VuNHddc2ZH1jRiJX#z+{X_J>NBmv4 zx7m70B>TuOD%P8_sQBHy=Z_CB&-}y?bV@8Ca+<;U&FBBH-o9@jy4KwA7|?+Xp00i_ I>zopr0OB2G#sB~S literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/scroll-vert-trough.png b/vmcompact/sun-valley-theme/theme/dark/scroll-vert-trough.png new file mode 100644 index 0000000000000000000000000000000000000000..c947ed1e9bc6585713c978ed6c50ba8c90921163 GIT binary patch literal 343 zcmV-d0jU0oP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10OUzT zK~yM_?aMJr13?sr@$bEvC9qpq$zVS!dj$^>!Ah-j4KE^CrxAiVfOi;h444ZDgG~q) ziu-J~5HV!8_Ybdm{63*yjB(<wDnH~4<7hvg}o9CQA00f|I+auu4%ue}ZBC=A| zS%SaJUP5?`J8cjRPp9Y(oh5 pz#DMT-zV@SBDYP`+@zE?0N+L>O0OTY#%}-s002ovPDHLkV1jbciuM2i literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/separator.png b/vmcompact/sun-valley-theme/theme/dark/separator.png new file mode 100644 index 0000000000000000000000000000000000000000..6e01f551a104e787194301b25e8d12128bb520f6 GIT binary patch literal 128 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}bl&H|6fVj#T-gc;Avs>lHuk|nMY zCBgY=CFO}lsSM@i<$9TU*~Q6;1*v-ZMd`EO*+>Bu@p`&AhH%VGzHt5ee|`q0)r`GU TeO=c8B^W$i{an^LB{Ts5>Ixx& literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/sizegrip.png b/vmcompact/sun-valley-theme/theme/dark/sizegrip.png new file mode 100644 index 0000000000000000000000000000000000000000..7080c04c67807e08452264809cbacf35b89a0503 GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4aTa()7BevL9R^{>lpinR(g8$%zH2dih1^v)|cB0TnIuba4!km|A<@H|v-IPs_vW zM}Hmco}=*Het~&k%Ix*smmD-!UOQ~OxM<$<_UXmtQQ0mm@%f4jp-ZPU%?$j{-Dk*f z;>`X<9Sc@5tl8SZVf0zEi{p49!-eYOcLPJe-Sgi#<&)K8#Wc0OpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10%}P_ zK~zYI#g<)fqCgaeA4ZHY4wVa>-=DddQ`#X-vvMiKRSeC_bIK(iFV`+b_-EK$IG*neZp68Thc{I;F2IhGlhGCGV zDNz*BG!1RrUKLOX!EiXlwrxDmW4GI}*=(q)>LAbf+(FlMab1@vipcZ)sz85|QVP%W zcz=IqyWRHR`wqIUi{m(~*K4%a-wFqiWf@gf@$m3~VHm`5{1Z@0$z(ENy0r?%Cf`=f?yW}0Z|n7gKFD0&(F_H zCX=Iu;y7lpSp0Ud|5Z{-JkMjbS|OyAXs!F72_a6x!G0W`o}Lgw+yt;F3bfWpDG^F3 zvMlR^^ZEQF+-JzyY<3esfHX}RkH?77XmoH?K@gl>WICPRf(?MOEU_#LVVWjQ)AWJv zLY$*ZaxazE8q+ipz}2_JHPkVQjz@T#|dK zq?FWkjmWYL$8q{V7>4~TeoAp16Ncf<0K3;k6h*;cFhEKPK-;z~7K@XR-9vqgZ36r5 znWjlm6nnEErR4tp{>!SH&1Oue)Bd(@w_8@L)y-BN>}M|s0^Z)<_N%UQGp_5Rl;ZXE z^}m<}0Mj&ie0(HHlHSquyDE-j(lo{QeUwt)4yTmD_x%Gn_{9$bj7B3o&qD}7nx>Rx zd2_?+I1X*wve|5?>-r$?3t%VPwi%Dd*tU&nnm4ihT5F1;AkXtJPP)?%6C*4`N&^#H P00000NkvXXu0mjf=LlB> literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/switch-off-hover.png b/vmcompact/sun-valley-theme/theme/dark/switch-off-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..5a136bd3f4c6fd280134f300e5cf50136e217b05 GIT binary patch literal 945 zcmV;i15W&jP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H113pPa zK~zYIy_QW&a$6XNuf023+x%!)<`lSP_n@SJa?RGpK4=$Gr zlgWf$ujl3ErB~^<)z{ZYr_-U)XizSf$>;M_tJR*h!biZ-(NR`bR_O2V=j!T;N~J=* zUg!DwSrfQ7>2x|Q77I?N6Q9pVyWJ+4Od`wj?*ZrL<_H7=93LNZb8~~L_H3@^5(I&X zi3x(iAZKT1TwY$j@BQ_*n4h0#YHEu8{e2Wg!D6ux4u|pk{fvx^03gdUnM{U6B0;@g z*9=fqRj#kEk!6|n^>sv14n1@7T4j2A8l6tp)1cXGvbVSQ{$FY-gTcVs+8XhAoLa3$pV@5wS*z6m2nK_c zN+pWLBB@l0Znw+8zyOjY(d~A*y}c!sO0m1UOR-qg9L{Jovazv2I-Mq)%>p0d*6i#o zi;Ih#oSaZ76#i)3a=YCuEiG|+diu-5`xIEMRx8WP%Se($KA)#tE>o}9>2x}pLh1E- zhK7c4I-Pht9$Kvy$z<}=*!l$cCcE9vj~_p9xm=jdX3ZmiyWRdJ^55Ov^{o9H?WJ3w Tsq6+i00000NkvXXu0mjfS6H?B literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/switch-off-pressed.png b/vmcompact/sun-valley-theme/theme/dark/switch-off-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..040e2ea30c96c8fcf103abdb749a706ec9b01975 GIT binary patch literal 963 zcmV;!13dhRP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H115ims zK~zYIy_QW&GHn=!562|6Mq7oJMv;@!rcWw2(MEI;En4&sY}JqGPecoULIlw&anT1A zMr5sGWOA}n3n9p68q2_W7cV`~lkdw@%5$y;=Hi%RxVgDbi_hmXX%N5PPcRsyzrP<* z6mdG8SS*%Cqu-8cniz(GuIpT1Uz5#dxx2e-IBWS`u&1YoNF+i>M+b_caCdjd^Yb&+ zY8BIL_%Gj%#bUwXa3G2zeSLjMlEll)3#n9!QmORcf|HYz%+AhoczB4SC@mBE6X9Sm zNH`qk;NXC>v$J3C+CCnpr>7YoA7^7@15ML#yWPZMF-Av6@pwG6x3_-*zrDS2e}B)# z#RbV^l1ioWBSF(Nk!6`usl@#JJc1x_dV2b=ywB$|2L=XMSXf|la}!Fu)up8+j*gBfm&=61VOCaFu-R%#UBgSYBe-XV{UGaOeTX62n49rYUJ~I+-^7Vc>Kq=)nc)*yu6Id z<@&K8fU2t0YBd6Z0K)L_Fp8o85R1jWb*zoza5#uYqfIdYuCA^Kg+d5kulLuHjE#*o z4Q>^uP$z6k^_Fl<(?rlTjgF2E z0LtZZOTew*bar;4>pDWIRKn-;0g%aLng#=$pPx6)@cDcc3I&AA%S$9l0w9@8Qms~- z0vm?G&dyHLf|4X5%Q8YPm&0bWF)%PdrBWf0Nc?yQo2E%3kwDY5rsM_(2eDeM)~!$|#LUbL`}_N!F6)=V>h*ewL?Vcyh@vRm z+}xn+I)-7iw6HpzPFyY*e!m|{l6Zc8CY4I@@bK_?_WvsX(9qDQ$}b2)O9bonI)-7O lX&U)_o@_Qtp-^Zz`wvZHY;hpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10}M$- zK~zYIz1Gi5Dr+3a@welhTr?v^t1Pq0q@<=*SWBZIqeZJATn7Ce=^xQbXjz-qB^cx` z`mqTMG0Y#CQjj3ygycxx#ktz);PH03&iSl{`96H-#RJbXU(4v|Xp;_cI-N{SP2qC6 zu-om3qR7X`N2jI#If5Wy7zUcAk$2i3I6%no6ZY zyJDwTc@^!a=&E-rF%azZMVqS@@Yxjm1?VqtoE znm{1H`T03lS6A)YU#*9Qg#~73XNg22=(_$#V68NpO_IqZg+hT~Fo+-sTwGjy0w*RW zn4h0#e}BJ?6Gf3gAb{WR$K`SXkk99d$Kyn!Q4GWAIaJqm4h|03-rnZr<%L`>hh=PR zthuwZLo^yClgR)uG&Dpg6hcvyj*T*z4B>E?a=F}dB!HqQtgWpPi9`@Q9uJzPwQ-^- zcE!Pu9pByEMHEF-fZ1%8YPE{n?MCo=y(AKeb}O zpzAu4B(-1u?w8XkkB^ULxB!r48C};AN~O}5LveO?_U$I|c-#cqkBpCxQ!Ew{lF1~h zs&0uh*$ot7NlT?(gq;dV1=(_HUD! VO;&6PK$8Ff002ovPDHLkV1k-`qrU(E literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/switch-on-disabled.png b/vmcompact/sun-valley-theme/theme/dark/switch-on-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..c0d67c567752d96e322b3f3dcea9cd95bbf8efec GIT binary patch literal 623 zcmV-#0+9WQP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10sKis zK~zYI&6cr}qCgZy4^0bI(;cV~5I9Cyg@2-d?4OWmFp&xE7|>HHC>vO^qEqh7j=i-v z;$2=9r=TD2dZW>(;YOb4p_D>vO%Mb~DG@^4w*5$_(}}vSIUEj@Wr?+xrny5w-WpnK z;y6aiyIW6{5P~2G2!a5uHC0t%jG-*cZr|m?^E~1>CP@yac0aUA1$-aTLx zMfCgqe-3u5e!ou?MQttN{8?SY`MytN}R$|;=h`w!vZe7t6}8NTng zo|F=$6hdq53=Sa6vWIXNMNveSWgSl`g$TpY6&nDP$>htuX_|KGFbombuhoUVGkk-= zpi@gJdG2~}AW_$~(+6y~+b{RNzrT0tx~>t2!{OOX9W9s3zwX`d_lVow_iW{Pjxpws zea0B_Jnwkc+B0BPRj&9r9*-;*i-(YxANA>UYQ3teu-4*@Mx#b+O_C(eAmN-|rqd~D znzqw=z3Q&v0M_gEZ$N-Jj{l3W0O!FfiUPPwGsc*2O`I!jx7*HfXoFwVG!#X_ZnqpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H111w2I zK~zYIwU$k66lEC4fA2dVrQ7agw-gIyT5W*1y=eJJ)FQE!EFLff1aFlCM!eO=)B^`2 z37m)^+5>4w2pSU-KGNXLqAew+=>=8~S`LcAPJvo*pl!BYXJ=jxv)jZiUmIutr^%cD zfAX6r&-=_HY};0pNN5Jh^_?U)yh*I-Ma*OavZ}h&_P-S5=K0s1BKy~M+{`d;W*Fsr zOMIdfux?YDrrkZ5^^K7NJx#g0lQ`#(^Uu{E9t|j@hP|hUmFcdE0BAy>OVEWti117) z$SZ~CD}sV=>e9DNoIj2Vd;s*~3n~RC5SSVSGxzv)pr6UHOUz9E0f1$%#eOACYS(^D ztDXfvpdsCbQi_Rl$HKgA+p2C;nl&FDsR&%PE^w|~Wb|k^UUu%0J|k93dv721>pRH$ zVJ&|@(TjWSN2JgU?032&hXbh6z`1gfk;Csl77oD6&M|UmAI?wTQKd-$n&15xp&Q8L z`cA4=*pb6&Lg3HbWAtcu*lbUeQjC7yO)z^GDZs36B-z%1Om5s7IUIm4VSJ$fiIppr zm!0MMz)1`l-l9ZXC$grwwK9N0;EWBHopZ(p(F=ez&$l9VYkAac07wC|xBe_UH+$;_ zqR|%Nq>$c&=}5tfQb2rFOWC=2V++MAm2>|_W^ay13RYBJ zDePCbm7TL+dy9M!B4%&?hIBK-QL_Qy`HIx8{TQ*@XU>>47Ogu!z$*aW|78T}W`@X3 zJCOqhfM(Ux-rEPy(u+dS{z)GqUPqw9<-yHdMk+s#bK%R#0Ra~LfYn=e@W!X7FkAn3UGJ6|C*_xGeGIOwfiGhZhJ3sNC@YmAqBb=i?b~# ze1I1y3T?-o!EbObe6_f4Em>HT8@AH4r>7$S=O-yQ?J#lf3*5}mf6kWxLUHBqAko%I ztT~05Y(QHUixkLT$QD-qaqee^aeuyy^7Bi44*@HzBP+<;3C;ij002ovPDHLkV1m(s Bw9^0p literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/switch-on-pressed.png b/vmcompact/sun-valley-theme/theme/dark/switch-on-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..00e87c68a1b37cde51142d964e4ac1374a69de4f GIT binary patch literal 936 zcmV;Z16TZsP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H112suR zK~zYIt(HG*6K5F4f8Td!J6Aio1W3V-qk?h^I*HjWdzO86QJ=?vgrD z3)sA|kHpSF!YymG0=-Y=XOGB_oMQUsrMCkLX%HXyh7bF8YkQ~=U74|JiwhVE?zey7LD<>#6SI< z&i=g^jVq{lKCN4JgHq(qpA23ynM|tYjeV@$vtJvWWlC~aGF(4#0Jk*v-g?uD(!K8x ziJl#lTpxh@!v}H3$B@D>N%ViM4K88|a#u2BkNvnTH~_aeOZMmxg=@bPF(m+PyS_u1 zA*7v36J8nD0w;vPd-0s>Ck}vGG92D5rMPx{Kih`*N#8$U2{$FKh3OSeiO9NV< ziVulRTkGnP*t8Y5x~&u+-bFeSSsiQuxW1yZe=nvL{a^QotQegGd#L!quy$@=MNZ$k zOnIuH1<+Rt*|>u4eTRaL_`gU9y1ze+h_;|q5FVU~EE3-%pE<1s5TNY&Bzks`9y+>g zCqq_@^w2Tlo3~T;0{3#~Pog{*qp7Lsr_$qpFdCvnKl)e;r0Xl}_6|C>eTfl{;1=g_ zOSAZHWwFL=_yD`TgZ10KqUVPrG_LDn-V4^=lhI$896JZp#I3}@Agz60Xn}+vT$zTz z5Tg3U-;7&If#(NtYhkoJ8U2+)=FDQ;S`t|8RGPM(-)h^Rm#gwrf!u|kamL5qIKKoC zs*%5|7rUz$t8D`zdlg2+(hB6w7pXXt6m$1*CbCSAXQAra>v{!PR4Lbkib03~0000< KMNUMnLSTZP*s$RM literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/switch-on-rest.png b/vmcompact/sun-valley-theme/theme/dark/switch-on-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..52a19ea658446caede4fb410192b05bdc78353ef GIT binary patch literal 859 zcmV-h1ElpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10_aIZ zK~zYIz1B@g6k#04@$d7@zUAtYPFj}YYA>1@NRowg=#*<2gjel_Adl4{2$aG@MMpc8 zc&qGK6qYU>f(XK;pce@(Enl$OXjYR}cGlgQ4(rRhnhH7nU>N4%cla=G&tK%_<(Z^J z*zBm4KGc0a+}>R{)Lax-T59c|5|2y~)xHt_(u)@GqXoJ#W7CUzA{DrysupiU6V9Cc zH3hAdNN|MVyVv;n^6}C@Ar%UaH?!sFng0q)&DYL$hHhWQG~xg#9*?I5z;@YR^sde9EMKc{Wb==?hzX71t4o{8QW^= zDXD8DsyLaRk#0WP$YkFuw4N?RzPHfabK@DVjRltB%+MI!=Z>I#e7j^vEiT8`+KEuN z%pvt3qr5(Q5UE!BEW?SJJGUGTKn)8c~bOSL~|A<&@MlqQ~dgLa&}8wVo~_ z!C^~)rU_BSiLbSDS>)`GT9*!HZ(t-if)?3h|7Xe{*!B{s45B2apG5)R_PP002ovPDHLkV1jPWmj3_% literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/tab-hover.png b/vmcompact/sun-valley-theme/theme/dark/tab-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..43a113b35c4019897390acd452cda5aab135512a GIT binary patch literal 265 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4j!ywFfJby(BP*AeO zHKHUqKdq!Zu_%?Hyu4g5GcUV1Ik6yBFTW^#_B$IXprUD>E{-7)t#7Y+3msPAVGc;# z;s37Q{Pe47lYDL&d7eBJb;zmzyup;*+byjdr#|JZU|BHNcbBz_Ko>H2y85}S Ib4q9e0C6#5TmS$7 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/tab-rest.png b/vmcompact/sun-valley-theme/theme/dark/tab-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..9753e067c6ba2e08b90d28da491836864a47eedb GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4j!ywFfJby(BP*AeO zHKHUqKdq!Zu_%?Hyu4g5GcUV1Ik6yBFTW^#_B$IXpdv$07srr@*0<*j85siF&&FxvXEnW$OKlEFe7>G-FC};|YBqbt`|hK~z4{J48!Zy<-k8&PDcU^mzkp!_ zBToVYv&4ah=M3w9NZ!n@Wq3XR=%navucin+t2}1nJDu^K?oyFBFaILBy_Of5fc|3e MboFyt=akR{0ByQ@3jhEB literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/dark/treeheading-hover.png b/vmcompact/sun-valley-theme/theme/dark/treeheading-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..beaaf1353fe62c3607118cbabce26b78ec5ceea0 GIT binary patch literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt)?TT^vI!df#5%$kl8h;`Xpu zHGG23uHXOGt2;GG>|ECD+v?Q5YH7DU%N#pDG3DC(>2(I*e--e(w_VlMQPcWlPUN&! z0j9KVhtFBw+NS#akJWv@(3iXV5+w|bwHV(2ReZB|SHuA}`JMlkUoG8xSgB~2#I{#L z5p%EEy=lw;(e|G${^NWN?J(8}LAzK)1)o*kdnoZ(^=g`1k6^_anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt-oKT^vI!df#4g>}xjQakwb| z#>4Ru$DRKzj7t+HM=lTxIUB+ha<*;%DK-6b#}>Z-eM5jw!N`qgXha3kZS z9%&gT3)7d?)r)to`FoM~{s-Rw(lOb#dz$OB_ZLe=Y@gH-(-u0la-R8)DNU;ut&-QT z(>m7C5#SXm&sb1ibZ*I%jN9KtYanMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt<;~T^vI!df!ex*wtbnz`8nF zL{WV2@BjPNJDQ~C-#lzkC^4h?v0n8?zs3otvYmFVeZA|5{DaSjs+~Bdq;}4nJ88+3 z4nw0pgcsqI&hao}L|^sv&cRlB#1*Rw@{LGIBe zotxkPZuu~`_WsIMuLNe_4EMb6srmGK;q+Yj9Y?qS5c@y-$JhS&hg+XpG?c~`zN@Nu zE^~U5%%jX%pN^TIJgYOmdY4UuN?YQBb+6aE3EQli_uTUPSDVi&PjA;X%g1a>RN*`` R;|9=Y44$rjF6*2UngA+#iNF8= literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light.tcl b/vmcompact/sun-valley-theme/theme/light.tcl new file mode 100644 index 0000000..ae548ea --- /dev/null +++ b/vmcompact/sun-valley-theme/theme/light.tcl @@ -0,0 +1,526 @@ +# Copyright © 2021 rdbende + +# A stunning light theme for ttk based on Microsoft's Sun Valley visual style + +package require Tk 8.6 + +namespace eval ttk::theme::sun-valley-light { + variable version 1.0 + package provide ttk::theme::sun-valley-light $version + + ttk::style theme create sun-valley-light -parent clam -settings { + proc load_images {imgdir} { + variable images + foreach file [glob -directory $imgdir *.png] { + set images([file tail [file rootname $file]]) \ + [image create photo -file $file -format png] + } + } + + load_images [file join [file dirname [info script]] light] + + array set colors { + -fg "#202020" + -bg "#fafafa" + -disabledfg "#a0a0a0" + -selectfg "#ffffff" + -selectbg "#2f60d8" + } + + ttk::style layout TButton { + Button.button -children { + Button.padding -children { + Button.label -side left -expand 1 + } + } + } + + ttk::style layout Toolbutton { + Toolbutton.button -children { + Toolbutton.padding -children { + Toolbutton.label -side left -expand 1 + } + } + } + + ttk::style layout TMenubutton { + Menubutton.button -children { + Menubutton.padding -children { + Menubutton.label -side left -expand 1 + Menubutton.indicator -side right -sticky nsew + } + } + } + + ttk::style layout TOptionMenu { + OptionMenu.button -children { + OptionMenu.padding -children { + OptionMenu.label -side left -expand 1 + OptionMenu.indicator -side right -sticky nsew + } + } + } + + ttk::style layout Accent.TButton { + AccentButton.button -children { + AccentButton.padding -children { + AccentButton.label -side left -expand 1 + } + } + } + + ttk::style layout Titlebar.TButton { + TitlebarButton.button -children { + TitlebarButton.padding -children { + TitlebarButton.label -side left -expand 1 + } + } + } + + ttk::style layout Close.Titlebar.TButton { + CloseButton.button -children { + CloseButton.padding -children { + CloseButton.label -side left -expand 1 + } + } + } + + ttk::style layout TCheckbutton { + Checkbutton.button -children { + Checkbutton.padding -children { + Checkbutton.indicator -side left + Checkbutton.label -side right -expand 1 + } + } + } + + ttk::style layout Switch.TCheckbutton { + Switch.button -children { + Switch.padding -children { + Switch.indicator -side left + Switch.label -side right -expand 1 + } + } + } + + ttk::style layout Toggle.TButton { + ToggleButton.button -children { + ToggleButton.padding -children { + ToggleButton.label -side left -expand 1 + } + } + } + + ttk::style layout TRadiobutton { + Radiobutton.button -children { + Radiobutton.padding -children { + Radiobutton.indicator -side left + Radiobutton.label -side right -expand 1 + } + } + } + + ttk::style layout Vertical.TScrollbar { + Vertical.Scrollbar.trough -sticky ns -children { + Vertical.Scrollbar.uparrow -side top + Vertical.Scrollbar.downarrow -side bottom + Vertical.Scrollbar.thumb -expand 1 + } + } + + ttk::style layout Horizontal.TScrollbar { + Horizontal.Scrollbar.trough -sticky ew -children { + Horizontal.Scrollbar.leftarrow -side left + Horizontal.Scrollbar.rightarrow -side right + Horizontal.Scrollbar.thumb -expand 1 + } + } + + ttk::style layout TSeparator { + TSeparator.separator -sticky nsew + } + + ttk::style layout TCombobox { + Combobox.field -sticky nsew -children { + Combobox.padding -expand 1 -sticky nsew -children { + Combobox.textarea -sticky nsew + } + } + null -side right -sticky ns -children { + Combobox.arrow -sticky nsew + } + } + + ttk::style layout TSpinbox { + Spinbox.field -sticky nsew -children { + Spinbox.padding -expand 1 -sticky nsew -children { + Spinbox.textarea -sticky nsew + } + + } + null -side right -sticky nsew -children { + Spinbox.uparrow -side left -sticky nsew + Spinbox.downarrow -side right -sticky nsew + } + } + + ttk::style layout Card.TFrame { + Card.field { + Card.padding -expand 1 + } + } + + ttk::style layout TLabelframe { + Labelframe.border { + Labelframe.padding -expand 1 -children { + Labelframe.label -side left + } + } + } + + ttk::style layout TNotebook { + Notebook.border -children { + TNotebook.Tab -expand 1 + Notebook.client -sticky nsew + } + } + + ttk::style layout Treeview.Item { + Treeitem.padding -sticky nsew -children { + Treeitem.image -side left -sticky {} + Treeitem.indicator -side left -sticky {} + Treeitem.text -side left -sticky {} + } + } + + # Button + ttk::style configure TButton -padding {8 4} -anchor center -foreground $colors(-fg) + + ttk::style map TButton -foreground \ + [list disabled #a2a2a2 \ + pressed #636363 \ + active #1a1a1a] + + ttk::style element create Button.button image \ + [list $images(button-rest) \ + {selected disabled} $images(button-disabled) \ + disabled $images(button-disabled) \ + selected $images(button-rest) \ + pressed $images(button-pressed) \ + active $images(button-hover) \ + ] -border 4 -sticky nsew + + # Toolbutton + ttk::style configure Toolbutton -padding {8 4} -anchor center + + ttk::style element create Toolbutton.button image \ + [list $images(empty) \ + {selected disabled} $images(button-disabled) \ + selected $images(button-rest) \ + pressed $images(button-pressed) \ + active $images(button-hover) \ + ] -border 4 -sticky nsew + + # Menubutton + ttk::style configure TMenubutton -padding {8 4 0 4} + + ttk::style element create Menubutton.button \ + image [list $images(button-rest) \ + disabled $images(button-disabled) \ + pressed $images(button-pressed) \ + active $images(button-hover) \ + ] -border 4 -sticky nsew + + ttk::style element create Menubutton.indicator image $images(arrow-down) -width 28 -sticky {} + + # OptionMenu + ttk::style configure TOptionMenu -padding {8 4 0 4} + + ttk::style element create OptionMenu.button \ + image [list $images(button-rest) \ + disabled $images(button-disabled) \ + pressed $images(button-pressed) \ + active $images(button-hover) \ + ] -border 4 -sticky nsew + + ttk::style element create OptionMenu.indicator image $images(arrow-down) -width 28 -sticky {} + + # Accent.TButton + ttk::style configure Accent.TButton -padding {8 4} -anchor center -foreground #ffffff + + ttk::style map Accent.TButton -foreground \ + [list disabled #ffffff \ + pressed #c1d8ee] + + ttk::style element create AccentButton.button image \ + [list $images(button-accent-rest) \ + {selected disabled} $images(button-accent-disabled) \ + disabled $images(button-accent-disabled) \ + selected $images(button-accent-rest) \ + pressed $images(button-accent-pressed) \ + active $images(button-accent-hover) \ + ] -border 4 -sticky nsew + + # Titlebar.TButton + ttk::style configure Titlebar.TButton -padding {8 4} -anchor center -foreground #1a1a1a + + ttk::style map Titlebar.TButton -foreground \ + [list disabled #a0a0a0 \ + pressed #606060 \ + active #191919] + + ttk::style element create TitlebarButton.button image \ + [list $images(empty) \ + disabled $images(empty) \ + pressed $images(button-titlebar-pressed) \ + active $images(button-titlebar-hover) \ + ] -border 4 -sticky nsew + + # Close.Titlebar.TButton + ttk::style configure Close.Titlebar.TButton -padding {8 4} -anchor center -foreground #1a1a1a + + ttk::style map Close.Titlebar.TButton -foreground \ + [list disabled #a0a0a0 \ + pressed #efc6c2 \ + active #ffffff] + + ttk::style element create CloseButton.button image \ + [list $images(empty) \ + disabled $images(empty) \ + pressed $images(button-close-pressed) \ + active $images(button-close-hover) \ + ] -border 4 -sticky nsew + + # Checkbutton + ttk::style configure TCheckbutton -padding 4 + + ttk::style element create Checkbutton.indicator image \ + [list $images(check-unsel-rest) \ + {alternate disabled} $images(check-tri-disabled) \ + {selected disabled} $images(check-disabled) \ + disabled $images(check-unsel-disabled) \ + {pressed alternate} $images(check-tri-hover) \ + {active alternate} $images(check-tri-hover) \ + alternate $images(check-tri-rest) \ + {pressed selected} $images(check-hover) \ + {active selected} $images(check-hover) \ + selected $images(check-rest) \ + {pressed !selected} $images(check-unsel-pressed) \ + active $images(check-unsel-hover) \ + ] -width 26 -sticky w + + # Switch.TCheckbutton + ttk::style element create Switch.indicator image \ + [list $images(switch-off-rest) \ + {selected disabled} $images(switch-on-disabled) \ + disabled $images(switch-off-disabled) \ + {pressed selected} $images(switch-on-pressed) \ + {active selected} $images(switch-on-hover) \ + selected $images(switch-on-rest) \ + {pressed !selected} $images(switch-off-pressed) \ + active $images(switch-off-hover) \ + ] -width 46 -sticky w + + # Toggle.TButton + ttk::style configure Toggle.TButton -padding {8 4 8 4} -anchor center -foreground $colors(-fg) + + ttk::style map Toggle.TButton -foreground \ + [list {selected disabled} #ffffff \ + {selected pressed} #636363 \ + selected #ffffff \ + pressed #c1d8ee \ + disabled #a2a2a2 \ + active #1a1a1a + ] + + ttk::style element create ToggleButton.button image \ + [list $images(button-rest) \ + {selected disabled} $images(button-accent-disabled) \ + disabled $images(button-disabled) \ + {pressed selected} $images(button-rest) \ + {active selected} $images(button-accent-hover) \ + selected $images(button-accent-rest) \ + {pressed !selected} $images(button-accent-rest) \ + active $images(button-hover) \ + ] -border 4 -sticky nsew + + # Radiobutton + ttk::style configure TRadiobutton -padding 4 + + ttk::style element create Radiobutton.indicator image \ + [list $images(radio-unsel-rest) \ + {selected disabled} $images(radio-disabled) \ + disabled $images(radio-unsel-disabled) \ + {pressed selected} $images(radio-pressed) \ + {active selected} $images(radio-hover) \ + selected $images(radio-rest) \ + {pressed !selected} $images(radio-unsel-pressed) \ + active $images(radio-unsel-hover) \ + ] -width 26 -sticky w + + # Scrollbar + ttk::style element create Horizontal.Scrollbar.trough image $images(scroll-hor-trough) -sticky ew -border 6 + ttk::style element create Horizontal.Scrollbar.thumb image $images(scroll-hor-thumb) -sticky ew -border 3 + + ttk::style element create Horizontal.Scrollbar.rightarrow image $images(scroll-right) -sticky {} -width 12 + ttk::style element create Horizontal.Scrollbar.leftarrow image $images(scroll-left) -sticky {} -width 12 + + ttk::style element create Vertical.Scrollbar.trough image $images(scroll-vert-trough) -sticky ns -border 6 + ttk::style element create Vertical.Scrollbar.thumb image $images(scroll-vert-thumb) -sticky ns -border 3 + + ttk::style element create Vertical.Scrollbar.uparrow image $images(scroll-up) -sticky {} -height 12 + ttk::style element create Vertical.Scrollbar.downarrow image $images(scroll-down) -sticky {} -height 12 + + # Scale + ttk::style element create Horizontal.Scale.trough image $images(scale-trough-hor) \ + -border 5 -padding 0 + + ttk::style element create Vertical.Scale.trough image $images(scale-trough-vert) \ + -border 5 -padding 0 + + ttk::style element create Scale.slider \ + image [list $images(scale-thumb-rest) \ + disabled $images(scale-thumb-disabled) \ + pressed $images(scale-thumb-pressed) \ + active $images(scale-thumb-hover) \ + ] -sticky {} + + # Progressbar + ttk::style element create Horizontal.Progressbar.trough image $images(progress-trough-hor) \ + -border 1 -sticky ew + + ttk::style element create Horizontal.Progressbar.pbar image $images(progress-pbar-hor) \ + -border 2 -sticky ew + + ttk::style element create Vertical.Progressbar.trough image $images(progress-trough-vert) \ + -border 1 -sticky ns + + ttk::style element create Vertical.Progressbar.pbar image $images(progress-pbar-vert) \ + -border 2 -sticky ns + + # Entry + ttk::style configure TEntry -foreground $colors(-fg) + + ttk::style map TEntry -foreground \ + [list disabled #0a0a0a \ + pressed #636363 \ + active #626262 + ] + + ttk::style element create Entry.field \ + image [list $images(entry-rest) \ + {focus hover !invalid} $images(entry-focus) \ + invalid $images(entry-invalid) \ + disabled $images(entry-disabled) \ + {focus !invalid} $images(entry-focus) \ + hover $images(entry-hover) \ + ] -border 5 -padding 8 -sticky nsew + + # Combobox + ttk::style configure TCombobox -foreground $colors(-fg) + + ttk::style configure ComboboxPopdownFrame -borderwidth 1 -relief solid + + ttk::style map TCombobox -foreground \ + [list disabled #0a0a0a \ + pressed #636363 \ + active #626262 + ] + + ttk::style map TCombobox -selectbackground [list \ + {readonly hover} $colors(-selectbg) \ + {readonly focus} $colors(-selectbg) \ + ] -selectforeground [list \ + {readonly hover} $colors(-selectfg) \ + {readonly focus} $colors(-selectfg) \ + ] + + ttk::style element create Combobox.field \ + image [list $images(entry-rest) \ + {readonly disabled} $images(button-disabled) \ + {readonly pressed} $images(button-pressed) \ + {readonly hover} $images(button-hover) \ + readonly $images(button-rest) \ + invalid $images(entry-invalid) \ + disabled $images(entry-disabled) \ + focus $images(entry-focus) \ + hover $images(entry-hover) \ + ] -border 5 -padding {8 8 28 8} + + ttk::style element create Combobox.arrow image $images(arrow-down) -width 35 -sticky {} + + # Spinbox + ttk::style configure TSpinbox -foreground $colors(-fg) + + ttk::style map TSpinbox -foreground \ + [list disabled #0a0a0a \ + pressed #636363 \ + active #626262 + ] + + ttk::style element create Spinbox.field \ + image [list $images(entry-rest) \ + invalid $images(entry-invalid) \ + disabled $images(entry-disabled) \ + focus $images(entry-focus) \ + hover $images(entry-hover) \ + ] -border 5 -padding {8 8 54 8} -sticky nsew + + ttk::style element create Spinbox.uparrow image $images(arrow-up) -width 35 -sticky {} + ttk::style element create Spinbox.downarrow image $images(arrow-down) -width 35 -sticky {} + + # Sizegrip + ttk::style element create Sizegrip.sizegrip image $images(sizegrip) \ + -sticky nsew + + # Separator + ttk::style element create TSeparator.separator image $images(separator) + + # Card + ttk::style element create Card.field image $images(card) \ + -border 10 -padding 4 -sticky nsew + + # Labelframe + ttk::style element create Labelframe.border image $images(card) \ + -border 5 -padding 4 -sticky nsew + + # Notebook + ttk::style configure TNotebook -padding 1 + + ttk::style element create Notebook.border \ + image $images(notebook-border) -border 5 -padding 5 + + ttk::style element create Notebook.client image $images(notebook) + + ttk::style element create Notebook.tab \ + image [list $images(tab-rest) \ + selected $images(tab-selected) \ + active $images(tab-hover) \ + ] -border 13 -padding {16 14 16 6} -height 32 + + # Treeview + ttk::style element create Treeview.field image $images(card) \ + -border 5 + + ttk::style element create Treeheading.cell \ + image [list $images(treeheading-rest) \ + pressed $images(treeheading-pressed) \ + active $images(treeheading-hover) + ] -border 5 -padding 15 -sticky nsew + + ttk::style element create Treeitem.indicator \ + image [list $images(arrow-right) \ + user2 $images(empty) \ + user1 $images(arrow-down) \ + ] -width 26 -sticky {} + + ttk::style configure Treeview -foregound #1a1a1a -background $colors(-bg) -rowheight [expr {[font metrics font -linespace] + 2}] + ttk::style map Treeview \ + -background [list selected #f0f0f0] \ + -foreground [list selected #191919] + + # Panedwindow + # Insane hack to remove clam's ugly sash + ttk::style configure Sash -gripcount 0 + } +} \ No newline at end of file diff --git a/vmcompact/sun-valley-theme/theme/light/arrow-down.png b/vmcompact/sun-valley-theme/theme/light/arrow-down.png new file mode 100644 index 0000000000000000000000000000000000000000..45fc33bd33a3d6408eefb367ff285967dec941dc GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^AT}!p8<4C?sm%aVoCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt+o^T^vI=X6E)9avgFIaQ*+r z!C}H3RhDXP?X@a%7o?c`>Lp~pWn{UT`*xCX1*4~z{{z-d9P7^Zg*qI$zwi5xC0qAt zE&X!;{#dF%Zo$S4(vDYsPIC;D1Hkdc)8n0iwm6_qf_s~F*$tJ$~3=j6+H}U-}b(4MN XIqN;$bHdI5oy*|q>gTe~DWM4f<}hm{ literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/arrow-right.png b/vmcompact/sun-valley-theme/theme/light/arrow-right.png new file mode 100644 index 0000000000000000000000000000000000000000..6461ffc94e88836ac40661d9ac943ce63592464e GIT binary patch literal 273 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1g!3HF2ETp?{#H&-P9X!wXP=*+-)~}Kvgh!TBPQ1m9ZGsT(>T4(;84osNt6Ca zNJ@6s|NZs!D37pB{l7oH$;ruXX=%@j)Yx|;L~N zjo*-Pkp0<}DanMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt-!OT^vI=X2$jzavgFIaQ%NK ztV!SlgPf9Y)O&%T$OsjkNzxTu-l{oGtt*8Dj+{Eh%)%7svP~d)_+WY2W|= literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/button-accent-disabled.png b/vmcompact/sun-valley-theme/theme/light/button-accent-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..c3845a54e8991cd4b466606b5c50396360cffc5a GIT binary patch literal 271 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|+Mu7sn8b-nUmb@-`cYxL)l3 z@4jf0`i483|LgE1?zDAsoU5*vmT)?7R3h-|=^3jg1tnSNEtt|Y^KU7mB1@20&*Kx^7S4|MmIhb< Q2D+2M)78&qol`;+0E^6Rj{pDw literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/button-accent-hover.png b/vmcompact/sun-valley-theme/theme/light/button-accent-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..054d56c0d2e22cc654f0dd1586e1dd8842f18df0 GIT binary patch literal 374 zcmV-+0g3*JP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10Ru@y zK~y-6?a!@C17QGw@#lSyefY5%78DUCR#6w$O^XJzMZsvX*aV~9DklF7!DbK^L`;It zg`u*AyK#4W-@P9OlVI>T<2`@C4<4bl_HV^(UPP=cS(>W^v{&mKb(%CARmAfk z^aqzud`1dw9M1bppcH~~NwQckb9J~uAh!0-9{OV@Q%g4LI}aG^QBzNt7-Y8>p>4L! z-_q7{{~97=WpOUIhjS1si_A~`tN;tJ0RIG5(TM+m@XQE}Y%K=_HqH;4l=eyqdAzgE z{Nw|Xj=-7hk~4^8$bxz2WOoyxwe~NA5$D&p+&%UfCn}Ryo2{_jTH|!T!&0Nh7iiII U9<_Fs3jhEB07*qoM6N<$f?4UA%K!iX literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/button-accent-pressed.png b/vmcompact/sun-valley-theme/theme/light/button-accent-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..9da8b53613ea07818317a7db21a0c144e0ed5e5b GIT binary patch literal 367 zcmV-#0g(QQP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10Q^Zr zK~y-6?bR_#13?sr@$b#yBq_a(-U>9-@8;d|{kKh%&KuRx?1852h3#-*& zA&R(JnQ>>wN>H$Hv+aHd`0;<$6KkzcUkr=oBdc^nZXH$Xv;xM%nAxPy!LCN`pWglX z)g8}SfpsO``%0jQphKY-x41k#BuGxqE^gO3rl_{;XGQ7xEK1%!3e+myVBPlEcgB@m zrx_}@j*3_QnfH(zhpJEgt^pgc0sjSdS^*+b9}?*505u-Q=&(K*g^Ht5f|^bG^tuu4 zNTIe^szhjqiv1nUd^$j^wf^DNuvo6SNi%X&@dfCB<59wVI$$r3_yWgoS4rv;lwtq? N002ovPDHLkV1nu-o45b~ literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/button-accent-rest.png b/vmcompact/sun-valley-theme/theme/light/button-accent-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..3b7959a323100057dddfa4edd26e18399d1c8c03 GIT binary patch literal 384 zcmV-`0e}99P)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10S!q+ zK~y-6?bN?Y!%!H8@h7K=fl@+21#u88>MH6W=;-1iI4F1p?rwrhCvo)(yavI|O^_}k zZVsX1(7}JjriPGna+1&4PNrG=T)>Za`98-OBi)aLi<>T;Fe28LGBtdct>q@Cdo5bC zb)4tkK=v;md5bjK3VBh=qo%-j6?4H9*C*@L;+4bp!|Ra52qNV$01?P?L1zWuu|ajh zh%_q?jh0&BJ{+K8Z7If?Hc}zNPij%sxBYDbPQVHHFR-pMlvDkdl>?2MMQtv4czIG8 z^lZ%bqK`T|Sf!c2})J? ee!R>4Ou#Qx(r!GF=i%T00000mmtT}V`<;yxP|;;i7sn8b-sC@DUtj+(&;QQI zX4Z|9AAWw}Y}+5d-(UjMjGdJdKhEe#rhGmvY4K#LgoORwUH|?^#TXo(e}2A)5r^!C z51$M(bmNX6koo&Q`|$SY>zYPAjg5^D@2{WFvp;TcN`g(^vXApa@*gpsv9aOtxdM@W zKV6^4C&ZYS%Z*pYwBU-vBA%3I&lb)~JY%zm$EPN3T8Qz4`wK7(8A5T-G@yGywoQ|A?yq literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/button-close-pressed.png b/vmcompact/sun-valley-theme/theme/light/button-close-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..d0bff3fa2976af5c9e1cf0f3d2ae3e4765d75d1f GIT binary patch literal 316 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|-v_G8x zT;$-#2=6T#Yu7qD-SzEmc7C8+!s{3v7uaOsCi3O@O0#}9`3_xE)`>4(R5PCckmV9$ zqpyBswrPln!g-@9o!pF;+Y+s~OV%iEd9p#jY+iGW>e2=J5mFLsYd-8eH@*MyJ|Q*+ zR>2o_%)x;HlE0T6(v7&8zW>x_ku_#-W0}nonE$aBDP|qsp?C1fjdi>xYQYAVBOAOI z8(n+#En%meiIUd5>&8j-yrOI;Hg6F*(#m&u-oYZmmtT}V`<;yxP|*QT7sn8b-nZuuX0;lKxL%yQ zxQxh>Y|Br@x#!%7FzYmmtT}V`<;yxP|bP0l+XkK&S7+& literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/button-pressed.png b/vmcompact/sun-valley-theme/theme/light/button-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..920bf70fb9f7aabc4a04b70935e97bc69246d1b9 GIT binary patch literal 289 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|-S17sn8b-nUl`^V$q}93G~t zGrB(dcRj@^q5X*LD!u(yCX1BcGt7T;RII$;knMTprD}Dh8J;d4nt|D_p%Y*4dSt;j zEp_3Prd588$vjcnGbC?sQ~bTp{oKsb*yRh(pXvF%@8Uh{rBmD`95h?+SxX6C&i*%T zm5`v#bi0S*H3!B2aBC>_7|J;dHg+t~RE^5+cPv+b-g7Ogu>4HUuc-e%X=yVgw}w5j hk8?QpQ(E{Tw^DiXl)8_0CxI?!@O1TaS?83{1OV`cZc_jN literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/button-rest.png b/vmcompact/sun-valley-theme/theme/light/button-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..1b211884bd062672de26718e641fb1b264a3c251 GIT binary patch literal 303 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|+Sw7sn8b-nZv>uWK>jX?fV` zIPvJx$A9MwGzKwD^L(>5LRL0+V`S97I=jrKRl8<7x&(MN?q0l1fN9n;M&srV0hc4& zbD52mk8voiVmiySic8S({`U-5mNPtQ>zdYeyx1!$7@)~&cx?WL{YNDNy%={^e?99j zD0oNq`_lg(nC%`g*D=qMJoCn^#FB;K_rCjV`ps>L2R7+=XevIB;e9%1V$h*o>m-f~ wI)?tW@jvsq=ds1A_rij^)*UwS&A2V5AJdy^Ep$ND0q73~Pgg&ebxsLQ0RK*M>i_@% literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/button-titlebar-hover.png b/vmcompact/sun-valley-theme/theme/light/button-titlebar-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..3f0586aa07cb787714ae4918823598b8471cb59c GIT binary patch literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP*Js~i(`mI@7pVee1{EqoCAZH zSnmGcvXO10^J87-;OZ~-2bynAX8Df#tZwu63_Xzp$jMtywkA zkYR@Q+TGJPMwTBgi!qhck^6svGyifTokD2}3EEPe)`zL2|mjCBg f<1BYiYf`bZ*l6VQx5V={&>0M#u6{1-oD!M<)8A80 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/button-titlebar-pressed.png b/vmcompact/sun-valley-theme/theme/light/button-titlebar-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..e0a5f10f20785a4740aba02d1f7963ba42cc63d3 GIT binary patch literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP*I+zi(`mI@7pUI`J4=SoG-rC z`1}9=+Nha~N{qt&(>KmDlC|tMeZD34S`@>LXI?6d6J~lSac!=ZT+Q^}?Mk8fwwu+$ z+n4H_Sly~^$i1b_Zu5Y#o+^!ce23#+!8|9;ZiHDjpgg)J+_iWA#$$6a|mg(0@mrh}F zV5``Fe}&ds)1q@7C*0+KNgF4h^L#%yO8fSaqGpmhCPv+*K25T{&V2r&8d+qwlaNSeYU9FNz2`c4;YRNp00i_>zopr09-Ml Au>b%7 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/check-disabled.png b/vmcompact/sun-valley-theme/theme/light/check-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..2c59e08fde6b9d9b35b23a844da6753026662ed5 GIT binary patch literal 381 zcmV-@0fPRCP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10SZY( zK~y-6t<}AXg)k6?;V+X2r!t73l~_u&^8W8b6g#~DAvPk3*=AkX1>N}bwgV5tG{e?) zb<46~7zWJq3~Mc}#5qS8hRCuEpU($OYwen*fidP1^fw^{%CZCv!|)gb0AmcsaRklt z{21HQT7$0M>?~_7=r!%TTObi3Ns@O!B7#y1aU4Gfi3mkez&VGm>-@nqO+oZ~v}24h zv~7!R+x)>OilCJGL4C19u-V6G7!@CjZ{56bo4hqBYHBd?k%CZbXoSxDvAq4U~2isr3IF8U--+BR3O5}Nt bAPDdUnj(YdxTMpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10clA@ zK~y-6t<*nA0$~`(@!!4Pc^;a7qChtdNy2n2a;U}zk+z5?E$PqTZXmSP-d35ov^O|4 zG(@>ao+|v%9(Z1cQmWiNOV}+`QLNPP*6u<}Hr|AY z-+^@0i?LAwO!=XvEbd>UF3Fmp-`NEgr>QVZjll9w`LU@B1Aw;N!&9At6e~5|*jJag zH4v>k`>RGv1~E+g>|Y?y5iCu+jRAR%Ah$M&h0ut8(99AX#Dh>2U?VT82Uli1uy8*| zW|rVE5d=#ZB(gVXcY5l<`H5lVlc8@^E!G#@%8O{yE>1SXa9KIkSYNQyRj{5DQI}*~ zY)^qOK>TPh)))Lhdq^IOI4iwkHCqCe2V(%hcv9zzs+TG={!(nb$uP_=upkk?!!U4m z+zFD7dSMq>-I&YDArtd~p_D53FB0|&Ra{l-XtcEb+(Q-?a{(tZF(2FxGu{ExU4WbI SxXB#=0000pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10bof) zK~y-6t<*hB!$2H>@h7>IhS<=8Ac!_Xbx?2-igvLG(#?dUC*a_Ve~h3PcAC4(_N!3Q4mfHUia7)k&D002ov JPDHLkV1f>4&!PYT literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/check-rest.png b/vmcompact/sun-valley-theme/theme/light/check-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..4f8d140379ca90dcee2d82e8b17da7be5018750e GIT binary patch literal 473 zcmV;~0Ve*5P)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10cJ@= zK~y-6t<<|OLtz+z@#lO!r7fjO7%HZcCXJ-UNTdVSlDbVSVjv8*T1+MBM1ntpCc9TmJ$|3h(S|LFQ=Dd5d&$Q>Urijzr648eUhRm>di}!|>D*Si5>mRfPd$^Ch0&b4b?t6SdMa%hh0( z5qe<&$xH#EoA%YeK$B50+waf^G#Ld4OJ4jvt<{6IvS4q)g9=RT#FPRZWu`)BmMdO|ouSqgh7yTsGanA-5e7 z3OKP@s^7A?-bi?&6G>4N_4YN*YUG~N_&do=W#3tYS!UR6Cp^)Kqp6lpn(BYD<0X+p P00000NkvXXu0mjfAj!+q literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/check-tri-disabled.png b/vmcompact/sun-valley-theme/theme/light/check-tri-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..5c796c07d129e7a97cea9575c7b2112f0ed4b78f GIT binary patch literal 299 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|*%g7sn8b-ltOyxegofxYp~a zrfl+8*z^2f`bow$(kHwP%-&woTbemrZOXKLUk^W4=DadB$nW$fg{3WXjH9w|FbN*4 z<`+C@(f8ua8F!QSD~L}2)^SbhPU1H1 zdW|Pr9b61}4&Plfg(-CJ?Amn?qngue{s+}Lc(}Bm?BF<8T|dL1g+W~@A#U%y>4|Aa rBre9rH>^5z=3W(}A`6iB-S(WZx>q;DiF-g_Gcb6%`njxgN@xNA=3R6R literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/check-tri-hover.png b/vmcompact/sun-valley-theme/theme/light/check-tri-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..a11cd661cdb79afbf83bb2415f2cac3f21a94f14 GIT binary patch literal 365 zcmV-z0h0cSP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10QyNp zK~y-6WBm2&*Z;e(zB9CMeZX-1&PRqXKmRh20(jV&8LU+J87h4g7?eag85plW`S?Fz z@+F2(-~W(g5IW%FWMSBtr^mqjSv|7h`m?VT8OFfC!0_|WKZci|elai|zw?n|!(ia( z?T-vhq=p$j@cG9d1}3VR1_dL~Ko(pQ#U2U_;{0q_#>dIRz+|PuPc;MW)C3rqDt#0f_&9NpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10QX5m zK~y-6WBm2&*Z+rae=tnl`%QImn0*)XQz_RDV+8OFfC!0_wOKZe(ze={(hdH9)P!(ia_ zgHH@hq=p$j@b%|k1}3VR1_dL~Ko(pQ?z*B3{G8aOKYstiu=Db3ta4mmtT}V`<;yxP|+Vx7sn8b-sC@DUtj+}TYsNn z$lAS!3mzO}Z#!@Q&tL*mg=K_s5(_SiCB5JaPMsi@lFq=u=I4|1S^qc>FdP^>UHx3v IIVCg!0K31G#Q*>R literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/check-unsel-disabled.png b/vmcompact/sun-valley-theme/theme/light/check-unsel-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..a0f31320c9ffa70bc3a3aef1bd4b890ba3a5023e GIT binary patch literal 324 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|-zC7sn8b-nUl`xmy$@j(t>D z&Gck%&JcLM?|*n^hTaC1m?;V(FPBC4Nw3R(`=7CH&-*VThQ~fz@cCSB5nw7hw?k;D z$ed!0r2(O$T<`x{_9@@m);dL~XQOvQkKj4WHLtt&y$|F$TyU+lcin3}$N7@U8{S)c za4-g)ik4t7@nwE*>v8Vqr`h+DdK91Y6h;4f!6^TMv7SkDX@}vxwji$sQ<@6SJ)EmmtT}V`<;yxP|(t_inA9gUj_onHRhG zu0;t5zB?k(EWqTYsp8p`aR2-2OsOfUoSLc@&$m0gx9u^U@m#VrRypJLH?PYgp`mx1 z?4;WmpI0hvx#r~clY_Zok;aB~+D=Nl{yvK@Jm=`bA@41}_W}352m2k4N$mOFulQVM zk%p5-OM~Gv!;BusX{j7jgJvw_d~9*Z^83})!v+bFVi{`%|M)rF|9)fJ+tr*WKFdU9 dA1UmS-!7NmmtT}V`<;yxP|mmtT}V`<;yxP|+<<7sn8b-nUm3`&tb|S|2hm zQsHH5)jIKrW1naEL9Imb1>Um~vKXD6nzD|X_DFp;N~(zX$6B*9d~Qd_y3aO-Jj~m2 znFSyE^%!y}E|}spEw$rY?fzZsoMW#~2x=;>v)9k7aiq{;hZ|pH_5s-7fSFPgN z6v4sx{7&)(%l1VY0@_Ox)*dzS{cx|obfzKOXB+42-WTOe#|n?^S{Lu@5IOBal(KK| a9|nQS#J#~6B87myWbkzLb6Mw<&;$VY3x65_ literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/empty.png b/vmcompact/sun-valley-theme/theme/light/empty.png new file mode 100644 index 0000000000000000000000000000000000000000..22183634d5e36298e12ed067750da6c7d2fcdea9 GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4aTa()7BevL9R^{>lpinR(g8$%zH2dih1^v)|cB0TuCix;TbNOifOZU~Lv=U|^iZ Vz$kX=awbrQ!PC{xWt~$(699LkAlU!_ literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/entry-disabled.png b/vmcompact/sun-valley-theme/theme/light/entry-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..920bf70fb9f7aabc4a04b70935e97bc69246d1b9 GIT binary patch literal 289 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|-S17sn8b-nUl`^V$q}93G~t zGrB(dcRj@^q5X*LD!u(yCX1BcGt7T;RII$;knMTprD}Dh8J;d4nt|D_p%Y*4dSt;j zEp_3Prd588$vjcnGbC?sQ~bTp{oKsb*yRh(pXvF%@8Uh{rBmD`95h?+SxX6C&i*%T zm5`v#bi0S*H3!B2aBC>_7|J;dHg+t~RE^5+cPv+b-g7Ogu>4HUuc-e%X=yVgw}w5j hk8?QpQ(E{Tw^DiXl)8_0CxI?!@O1TaS?83{1OV`cZc_jN literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/entry-focus.png b/vmcompact/sun-valley-theme/theme/light/entry-focus.png new file mode 100644 index 0000000000000000000000000000000000000000..56309029ffceb7d1799eecde1146f748356de8d3 GIT binary patch literal 331 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|*!f7sn8b-nZusy;u!JS|8e* zH}2_HKC$}kQQjLjcXC`$O3Z%hcc-OwF1NtO%^T{hoP89&M`T!6{YEksmMai-*DlZC6E%n_UzxnO2scB+hfTcX0$pn%YjQn4>HJ8E*h zH9g+Xo%4DBhWAhByxgn&&hGcK{7#N{=Zapc?`hKB(Nxdq%rWC;(up%1iVB8qS!=rw zMrmuRUi!ScxT^H{x-YH|%Jd8CE1fdd{ycp8#L=_D+xxBW-FtrU_v{llKQdl_?kmmtT}V`<;yxP|^y?ZlqORdubk%U1Oma=fei zJ*!?-X@~X0jbB!a*Bli8BVMuh;PTjdrw+qQ)%85z?s;kodTGv(O#5~S3j3^P6mmtT}V`<;yxP|-zC7sn8b-nZusy;vLtS|9FT z9ewN2%#`5X6i5AyoeMc0wfgdy-4vd&OFUx6!k3NfZg~hA7R)L6_ow#5Ars%cv?)Ou zYahNlquJunBN*!H;*oaDqHl$kWx7j>SVr2FD9N_Qb+0{^iiC)U&SkAtQ;NSG#C0i3 z`S~CHH`SKuQP~~4&+q#gt<Ia5%=TzXr(ZBb?Y@wd0N!~Od`?w@a4^8RJqyqj|0V(!EgvweN$)y5|D RjT`7W22WQ%mvv4FO#ouqfad@J literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/entry-rest.png b/vmcompact/sun-valley-theme/theme/light/entry-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..d347a65a9c36ef61e592f66bfa2e34660d47f5c6 GIT binary patch literal 308 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VXMsm#F#`kNVGw3Kp1&dmC@5Lt z8c`CQpH@mmtT}V`<;yxP|-n87sn8b-nZu+^I8me+#aT@ zyL28AwcufYZgD3eKxwhX=B&`r*eQvpZ~wlWZ@Bs4yDL#I_ZlC2;HBim(HO+F%B!Tj z@3F#jA1}_(y)3(|(~iCVnlvvxY36uU!p(}EU#@9Q(v z+y66s)hUVQ-m{LkFQ@vcs~sN98xS1}=NyQ8u4v5sj$8EY>_{mxjq`*PIc zYhIeID^|^ryuEGXd+XanMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&KtA z7E`k)|DN;QXuPp;Th-a-H)2{-obGehP1rT@^{zMj^0!a@IU3w+WQBu-Fp3qAz^LnJ!^~SJ$aQT#~2pZzmqm*UaVYq(qTQ%ms11? z{VtD^!^(n;p{BbYPh8csRAj>Y-6oz_q7>_mUEa$k_gp_Cur+ML5q7?EC;k=Xi+zD! OVDNPHb6Mw<&;$S}eSJOv literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/notebook.png b/vmcompact/sun-valley-theme/theme/light/notebook.png new file mode 100644 index 0000000000000000000000000000000000000000..255dee8e2309dba442cbcd78a38328d69de628ab GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU1|)m_?Z^dEoCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt*nzE{-7)t#8jQWNa`HVA#0r zxBs8EzJ?Bl!kG%yY4g4&KYx8-cGIc_S}V9#;imMCPGYgm%{I#bn#kbk>gTe~DWM4f DG!H=O literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/progress-pbar-hor.png b/vmcompact/sun-valley-theme/theme/light/progress-pbar-hor.png new file mode 100644 index 0000000000000000000000000000000000000000..9806e3d5fc81faf66368913c69487ab94563419c GIT binary patch literal 192 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W_!3HEylDb50q$YKTtzQZ8Qcszea3Q$n8 z#5JNMI6tkVJh3R1p}f3YFEcN@I61K(RWH9NefB#WDWD=>PZ!4!iK)qdzP`R*&!)vR z?bp|GiDhppk9>H2-oA?`DLFCeMDf)01d($$e*Qmwet$@ztUfz8b8y>a8D?p2;iGLE kHyRkGSe-O72(sp3JYgnw;To%SA<$q3Pgg&ebxsLQ00#v>bweIk=>!utY)$y{>b|Sh5TFw(>>EBq`cj5WBZ&n(&3X+8dbbk zNxo&bE6J&CW4=(w@L~7cABUyok8A9ixBo4}D;w2s^0Sm!AF$-lR6Lub$-fb3A%mx@ KpUXO@geCwXjZ9wv literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/progress-trough-hor.png b/vmcompact/sun-valley-theme/theme/light/progress-trough-hor.png new file mode 100644 index 0000000000000000000000000000000000000000..6999a37814de71d6b09fe3ffc3e924021ebd110d GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W_!3HEylDb50q$YKTtzQZ8Qcszea3Q$n8 z#5JNMI6tkVJh3R1p}f3YFEcN@I61K(RWH9NefB#WDWD>4PZ!4!iK)qdzP`R*&!)ws zmL+xU01#|SILOq-FK-uc)PRwZk?ok{`&0&X1)ifTTXS~lN zf9IQKU#pjx-O0#hSM!4*+2{c4#DgmodRbUmSROPnFi#R)5&3YZA5bTQr>mdKI;Vst E06Q)-zW@LL literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/radio-disabled.png b/vmcompact/sun-valley-theme/theme/light/radio-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..d44a9bf6ad73588f1421a14ba588c8ca861bdcc2 GIT binary patch literal 523 zcmV+m0`&cfP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10hmcd zK~y-6t(CEkt1u8n57rV(aSA{}geW9k3X1&ycch?6w-kUVTp0ZI}>(D2fQfko9^EK+`nT zbxl=O48yR1ZZ?~#u5H_nm&;{Qv(;)vnx-hFo_>`vhAhkIx^DKQl$_6Jgw}ci6GFU% z0Vt(N(-a}*iqW<$TI&h;s3?kF!XBYf6fHchHNqIPFvBqX5%yiIF$QrP+M8|-ct>_@ z-}m>i`Ck&Q>n@C@Y2Hq@V_nxp*bS)b`fZ>ctCT|6cd@D}>_$D4F@~}%7hVtq6HrPy zo5L`WW!X#UZLr7jzE`A_c%C;c2dy>N>vfUjI1bzG_UY9t%W?q&IGs*+ApHAs0NCwz z?Du=%VcR50LLA3`4U6M=hQTiv?D2TS^Sp)s1qeSs0YMN<^?LFI`~e-LKFh3 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/radio-hover.png b/vmcompact/sun-valley-theme/theme/light/radio-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..af45ede55aba74100cca821146c846c44f7f6dad GIT binary patch literal 837 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 LNkvXXu0mjfSkvT7 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/radio-unsel-hover.png b/vmcompact/sun-valley-theme/theme/light/radio-unsel-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..7abe53eba6e8608a5f2029f18ccf35e5e120e807 GIT binary patch literal 573 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 snoK4nNpf{GDWyHaK>z>% literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/scale-thumb-hover.png b/vmcompact/sun-valley-theme/theme/light/scale-thumb-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..34664b4365a089799f52819841eca8e0526e8528 GIT binary patch literal 749 zcmVpF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10(wbA zK~y-6wUxV08$lF?zuDWYy~ag=G!&6&f?_GW0Zm8~-he8hNqXLcK9N94#S0`|C=f4@ z6d=;%B0*)G!r8SwGrKz}Rvuqi5GcxD&Fy@1G?)Jft+k~_)>@1)7-J}k0&A;fLI`}{ zCk#WvFhmGZ7fw(IR7#3bHIC&vRO>)(qT%t+n*~eUc=h(P-QXoY!D5U@#caZnqsgn9g(_ zdX;MSk1sho>+z#I1Yq@HgJ(|`+1XfOsTBdxY&HQ%)6``ywAOYs8ey%a-EKSR$1h!W z56?+eQJZB;`s{75v9-SJ#`^s}LI~nG#v5N&k|ZTtaoRqi#eUd1VKPi6xA7zA3wmatKq%DKf99{&-1D?o?le| zL2p;xxAue(lx67#9xdJPb5t?0YnNq-5CYHleeyha6PumIdxM{MmR#EygYWxzVHl#6 zauYinE41Y89x<(jIACXE#r3t;gke~Lwbm3x^~9E15qsNf+~9^Y5(4(NAM+pyfy$H| zSO|fXk}S(yz}EUQZ(nv;h_AWoOs4N%b$Ib~@};vZa~3MJ)^=<{aU45C0qCWMgOdx6 zPJi>gI{;vHxyfdyGNEy%P&wRaG@3ObnAm2s*_?sjMRm6M|BZecK3$rmlsA?pt@YhX f)BFbiQcV8>eYs-Ep8zIn00000NkvXXu0mjf2U1Af literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/scale-thumb-pressed.png b/vmcompact/sun-valley-theme/theme/light/scale-thumb-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..b0de0d07965dc7eacaf15119b05001beacb29d7c GIT binary patch literal 675 zcmV;U0$lxxP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10x(HL zK~y-6t(Cz}+dvdWkH_P&ViOdWgsRJ;(l3Zq*z_~9qr3i2_m#TfFS@Cy1YbZA%Synm zL>R|-?3vd^h!wDtv{CPJeCNEe=lQ|Vy(p(gE0oJHA*P}y!X^~jkUJ%#Btmz@C+;> zR8@uY-lMf{8BWe`mqHuQS=*zv#(R$vk*4_$aBnH} z-tBEM9_@BQopVeklUZh1Yvu9r z5fNc~dwb=puhaegJxVF!IG%My9LG54D2ifZXi*e6=bE2Q!E7p|Y07ju-3UI9&BaXa z4Eit(Nz?TI1pOl1T1#1$e>IxoIG%OEs?qeaz^Y+7FSu-&{sENzIE*?h&~g9(002ov JPDHLkV1msrJEZ^s literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/scale-thumb-rest.png b/vmcompact/sun-valley-theme/theme/light/scale-thumb-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..46bd9ed0075b48ed4c008adb569292a5e01da686 GIT binary patch literal 701 zcmV;u0z&pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10!m3l zK~y-6t(CD-+dvS8Kb=k|TS5#eAs!welguzwA(i{&2|{Z3yhu`$)Z_{1p(7QO%rJR? z0HF+nkZhfFcPTtpe8x5&CfjLu_3i3T`){DNcFZy79Cck&*EQB!oExVFL4Xi~D2j-p zh#&~&y-qL-cFs{%6l&@~_{^)Sa(SM!v9aNu z>GhuxZ$F;%<1(My<<54-@xd<7pLJTFF^1dQTe2)e)OC$g%7a#oT?z&G{wwF*r*o>t zw!Sb7QA$zQ^*`{m9iCh+g-*l2oL+gp7Hq9WO6diU&TbxsF3OcsVy#6u=h~ltVn2W1 zuMEDp_P`hy-n}A zX&QtOh$xECT6@7kzsJsY_9%2`J7duAdA^A-wP0gR8;qsk_+WP_d@>+vYWj>ZXswY_ zjzwrR8sVH{eSO`p-dH}LUU77G)8788UdH>^n+*Cr4+?O1cZU#SJknZgHxZ#ur}HEc zg0aGlMx$0f1&p^snx>Rx$#6J)60|H!Pm|{geHezMY5ISJej2W|rmCuyR#P0uD5aLK jrr83^mg%J6qGkFQU&&dP858c)00000NkvXXu0mjf7>+yo literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/scale-trough-hor.png b/vmcompact/sun-valley-theme/theme/light/scale-trough-hor.png new file mode 100644 index 0000000000000000000000000000000000000000..7adbe2d02f6b77d3d5d9e278a0038d51227a3253 GIT binary patch literal 208 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt-{hE{-7G89K2hJm&Nt`HUVf%sN*7v$|4HsU%ahD=#xmAn(u%E4 zRqxZ+K5g1JHHgVPEObH%v*)6%Y$t`iEFQj>i!GCATX8f{4`>mCr>mdKI;Vst06@M+ AasU7T literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/scale-trough-vert.png b/vmcompact/sun-valley-theme/theme/light/scale-trough-vert.png new file mode 100644 index 0000000000000000000000000000000000000000..924dfa9c60ae6cf6fdbecda91b5d7db42401e4d6 GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt;)(E{-7HKKKxDVW&Su7;D zgTe~ HDWM4f5vffb literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/scroll-down.png b/vmcompact/sun-valley-theme/theme/light/scroll-down.png new file mode 100644 index 0000000000000000000000000000000000000000..f4dd741ad41fef3f49d476ac11c38f91bb2dcf58 GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^96-#*!3HG%vEKg;q&N#aB8wRq_zr_G@Mt{BJut(gJ>Hjh*KX-8{lZYe Yd~mL8f}kTaGthPhPgg&ebxsLQ0L7G89{>OV literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/scroll-hor-thumb.png b/vmcompact/sun-valley-theme/theme/light/scroll-hor-thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..989bc941ed811786635262e2fe62500b63b1da64 GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W;!3HFgc;@~FQk(@Ik;M!Qe1}1p@p%4<6riAF ziEBhjaDG}zd16s2LwR|*US?i)adKios$PCk`s{Z$Qb0xJo-U3d8WW#hQsg^qAi&~q z+t6U+l|Kpl6Mp{px5x|1oVn1EtM3SBhnA>$_?6lN8C%Queg9X|#yRbV{{f5VUz9dY zIPK9S+nB1Z>b(CFI4)#IzcDbb7BM!E2r#|6Z@Wu^e>ws_FM9Cc)S#+_V8-a> zQ>vyH->Z7RTlnJE;&qd^TuwCVdmPzQ$hzgvou?PC8*euEboN>~eGBssw&-sT|8fmy RT>|=y!PC{xWt~$(695mnf;0dC literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/scroll-left.png b/vmcompact/sun-valley-theme/theme/light/scroll-left.png new file mode 100644 index 0000000000000000000000000000000000000000..498d3caf57a8f0ed8c16c7b494eaf452ad955cce GIT binary patch literal 232 zcmeAS@N?(olHy`uVBq!ia0vp^Y(UJx0U~c5>$3n-oCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt-jVE{-7_Gh_QUayl7`xSs#Y zs#wjzr*MO1&Vk$*g&Rvwa&VdDCCp}(d3O7z>Ulpq%cr(7JCa=2etqz+y!=0h!gHCV z9&yj`1nvbvr_P<3cc3tq-ME^uTFvb92l2h%jX%t5-Fj`>luODjAEuTt@i=_GYj}(| aqON1M{CfGR=U)OHz~JfX=d#Wzp$Pzrj#Op< literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/scroll-right.png b/vmcompact/sun-valley-theme/theme/light/scroll-right.png new file mode 100644 index 0000000000000000000000000000000000000000..7f771bf82807b5456cdd6d4710c76e1f9062faa7 GIT binary patch literal 223 zcmeAS@N?(olHy`uVBq!ia0vp^Y(UJx0U~c5>$3n-oCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt(y8E{-7_Gn3!Ed1G?|2#y~) zG9@S|sAw7^m&EQ}yZ$-fte23KtlnSuH|qL@3m>>6nb`dP{{3w}tCLZ9hM}=>{xP+K z2Y{f#_tBO6`|E2bs{S)DGAgV4{q5|wO`AUPaWgX?u47|kb1Zqz#BfznRVv)A$qr~Q NgQu&X%Q~loCIBP>Q%(Q? literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/scroll-up.png b/vmcompact/sun-valley-theme/theme/light/scroll-up.png new file mode 100644 index 0000000000000000000000000000000000000000..09ef917ab4e4bcf12c3bca7a1333ce34842a4b6d GIT binary patch literal 237 zcmeAS@N?(olHy`uVBq!ia0vp^96-#*!3HG%vEKg;q&N#aB8wRq_zr_GI(6x;{(%$w+gIgXxyvssnDAon gd(j>KNBVDbzvxi%I2xj92y_L5r>mdKI;Vst09poCGXMYp literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/scroll-vert-thumb.png b/vmcompact/sun-valley-theme/theme/light/scroll-vert-thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..6f84abf0c516279f8b6b3bdd59a6b327ddffeb04 GIT binary patch literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eM!3HFEez+qDq&N#aB8wRq_zr_GE(z-`$&|{C-N%uEXj}r<|17d{jc5 zf#KXw#ie&R6}K9)?2Dk-b#dEHaVHM$1rKrsiq4tqJjgwEV13LX z)jzHYJ$nruG;3=`EuOQBwFsQw$KN09^_GF*-tUKtY>Sz;H5vVy?4_#*bRL7JtDnm{ Hr-UW|jkjX8 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/scroll-vert-trough.png b/vmcompact/sun-valley-theme/theme/light/scroll-vert-trough.png new file mode 100644 index 0000000000000000000000000000000000000000..175bb6e33c4983d9ee4db85da19dcd7ac3411eea GIT binary patch literal 324 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eM!3HFEez+qDq&N#aB8wRq_zr_GYVZd&>2p9~Aauj(x=VPjxAV9{s(*=9de#ews;t)JgowW=>BuI{($KetuC zRPOzrE^5e-J$NNaX5GW<`_{h{;1-^ob4K_~57979#$ zRlWmtu6w!-%O(X`0SΞO7!GNmze+qQp8U4&DZ-)Bg=N^G~Yn*{E#EctG6szXP9i T^s73c=NLR){an^LB{Ts5d3}P9 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/separator.png b/vmcompact/sun-valley-theme/theme/light/separator.png new file mode 100644 index 0000000000000000000000000000000000000000..1e7b972cdf57c1772f0f4a882617757da68229fe GIT binary patch literal 128 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}bl&H|6fVj#T-gc;Avs>lHuk|nMY zCBgY=CFO}lsSM@i<$9TU*~Q6;1*v-ZMd`EO*+>Bu@p`&AhH%VGuK4%oXFUU_GV|8= SxmoLh5)7WMelF{r5}E+?WFjg6 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/sizegrip.png b/vmcompact/sun-valley-theme/theme/light/sizegrip.png new file mode 100644 index 0000000000000000000000000000000000000000..bbcdc5f66a89a86fb391cc3f3d4f66b7f153f331 GIT binary patch literal 272 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4aTa()7BevL9R^{>lpinR(g8$%zH2dih1^v)|cB0Ts>lba4!km|ENKn0MGffLVR& zwM}~e{#(~h*s0BZ+qqFGbK(b^2NU``Jnp#&CG$jO*X(U(xHI?6k-IDBAGl{d>BhFV z_7=}s4xBMCHWD_jW_>pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10%J); zK~zYI&6eFt<4_bvSMw)on$t9hdSQ(a1;vNxqxT_%qEu`xsJ+O~i7CEo7^E?`j2K9P< zZg1^R!J;S_4u@#134#D21UoxBn5MZFxfxn(CX)$LO5!-iG)-Eq7W@1AKMRgVBc7k1 zIXyka_x-gB{f#tD84Ly-A0Kmgc=%oL<>iGqj=8wFz_#tJ%FR$pad&q|5Cj|@9RXkg zNGTbOMqFK8RdQNudc7X~ejh0%073}DFeHkiwZC!z+qOABKd0O6vbVQ~=Xum7lgaev z=7v_Qg%AROx3@PsoepW5&K>0YKJ9j!-QC@_O9JG1&R{U$`uZ9p%Q76tspPcQ3+3SR zd+BsKXstIQ=y@KF;~=HPNRosg2&!VQ*IOv}Rr3D+ej|baK@gB63C4Il#`CS%y`5 zS4Am>Wmy=m>yqbrRS3gy=^?B1u8Ncr*L5+P%_eaiSA{5wmO693?-NDQ#suRyrrB&_ z2q7rTvRV$)G-`1ts!PTg!< z8;wSF>NX`;mL=V8m$S38&r|omg@xPOTMiBmszmcGZaqCc5r*N`<5rR+JU%}D9JgkS z$76=WA@A?+TMew1WpQ$HvN*7Qr6>y0G~G(%_kADNb?5f}0&Rjs(ir0izyJUM07*qo IM6N<$g7=+K0ssI2 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/switch-off-hover.png b/vmcompact/sun-valley-theme/theme/light/switch-off-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..2af2b43301d63bbf75a61efe615bbe2e4ecb87b1 GIT binary patch literal 867 zcmV-p1DyPcP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10`N&h zK~zYIwU$pyGF=#luNe?K|NSa-j<$ zm0}dBR?Rq?;5>`S=*gZpU#8#so*x&7bDz1S*Vk8<5iw1ZySqCc9v-l5n|{BKEX$)t z$If6dz~}Q32m}a+!z?T;FgG_ha#s2qu+?gDetu4`*CQ5-5ekJ+RTZDl=Ly_<`u#qZ zWnr2owOS3o-;b{AXqxst;O*@#S65f8udfq{L_7uhuQVDBip3&pYiq2mtb7H$zP_eX zsj#!NgQ6%{mW5#$R4Nr7A0GjjnVBJxNTBOFs;YVp+39pRIXNMjOtQMV`T=-$;qsow2d8F@($I za^J!M^m;vVxg4cZ$#Xy<1e=?ioSvRC7z~hWwHiVQLZJ|rWs%S4aov%N{VA^Na&&Zr zZQGth27^I_5HuPM5=UG((ysfPmf(RH8tfm8}RnrD2jrtX&S9o3xGr-F?P}7;-c4Vz}qiZ(=_CGJWjn{ z2SC?#{C@wBON0<)GMQfitk>(r<8kC@G)lMI#WYP+RVACv{^(vwlEnW0K7l~MbGT-+ ziQ_m#B9XTx+1lFT^70bLaY&_792^`lF){INfe?bj!$X#rmpzAb9EXdG3%0knk!ATq z7H)2CD3{AaS+H$;q%0(pNivztubf<`)1go(u(Y%^G@4JkRVtMz7K^0QY3AqWJqP$# z-gPUTPJfb+FT&bxw=oQZZnsM`8YL78F*!N;E5iEn@`7oa)a!MG5a_zj?Ck8Pxi5h4 tX*Qcf<+m*BSCn5>)uHkSgTaxre*k`cUXudB&`SUS002ovPDHLkV1nONj%NS> literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/switch-off-pressed.png b/vmcompact/sun-valley-theme/theme/light/switch-off-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..d5fef562e0d53c0a274c50180817f4fd543f979c GIT binary patch literal 880 zcmV-$1CRWPP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10{uxu zK~zYIy_Qc)GF=>ouQR&f(0t#c()u_#(YtkNf+3y4^08Wic2GaGWnk zza1e29*+k_Q3!=X#N%-Sfxy?ZzY6NQ&gJDLmSqu%M9?%1MNyDt86m_}1Rcl0wrxz) z#4rpxoeqkku(Pv+rfI(ytkr5h(I?+uLkzZjRsm^Zrn+ zR;kr$92^{=C<>-&QZAQiwOTwsKQkN-KY{1w=J5G^tgWq)$z)Jfbs|9_1kq>|pU+3B zR00@Fis5kRbUGc*&d%81-)CWAfqK18p-{lK?LYpAEX(9_Ig-ibM3V2ZEQ^ba3l0wt z2?m2mj^j`)7TMa`8q1xWoP0|Tz_x9UkB@0I8m#pQpUtg(KtL*LVA%ys^&D3f& zs?{plY<650DwPV&W|Mxu|K$%{mSwzNFNs8gbUN*NloMv!4Xt^YrvIuKcEH{z&ClRdrnX{eJ(Kv;P9C;bZ9Vh#W!y0000pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H10=r2> zK~zYI#g;iw<4_bvk1ZpR2}^|>u!UHX0wDoX(!@Z8DCp?<0r^Mp1E`^b3M!j4wpbdF zuo59`CvwN;1cIeZfgC17*hYBflzvxNNALN)`w7ivvqcwt-=|zI<9Qwr4-Z69gdhmr zO2193)k2aaQmGWGsxm!2&FJW8*IMCE!CI|`VHh-5k zcXx;Dx?Emf(%ak1($W%&qP#D7dU}d&+bk|FGC4WQzyF`g#e`wV{{B8QGcznKEW8R{Ute>0c*y$tI1$>R4OGR2$0ESa2y9Q2!f6`$hPe-H?b@$2{+(n7lR-`48ySF)>f<4 zFE{zhPX8^bREjVR5d}e@)#^G-K1CG8AJ%#$b`oV-re3eN7v38=-AJd?KQ0y%pRA}T zO2<*<^Z73~`A+S3@qHgfQ4r(X5~J%ns;Yk4Kvh)=g+gM2j^mKYWDqANCTKJoxULI; zBuNyD#SbOphdQZg;&~p8MuYM3@t0BOx-JI?2X97QsZ_$UtoARUsw%l$jzXc3=&0M- z*r;JKIh)9dYaI>+S6=uIu7B4t;%nEH5uJGBVOp_eLqqhyVZp07*qoM6N<$f+tID@Bjb+ literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/switch-on-disabled.png b/vmcompact/sun-valley-theme/theme/light/switch-on-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..3d03bc91557b3933b80bf339a799720a246a76c1 GIT binary patch literal 590 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 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/tab-hover.png b/vmcompact/sun-valley-theme/theme/light/tab-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..0c6df3e27ff33d1fdb505b41866ad67fe2d25def GIT binary patch literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4j!ywFfJby(BP*AeO zHKHUqKdq!Zu_%?Hyu4g5GcUV1Ik6yBFTW^#_B$IXprS3FE{-7)t#7X#R>Vh4SF!oFPC={3jw7IVz?s~-}ksh^hpz|}CPR-scu*@Z>L@zbUL zvpi{Rp{=V91>U3{10U!a}WIZ36zwbBeHqfhM@ zJRWG)AaE%6X}auX#^Z)1$~&x2Us`v!}gA)@k!TV&l2pJ>trx}U+*)z4*}Q$iB}W%X{x literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/tab-rest.png b/vmcompact/sun-valley-theme/theme/light/tab-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..725beb9abf7018fe96dabd6fcb03fb0dd2aec914 GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4j!ywFfJby(BP*AeO zHKHUqKdq!Zu_%?Hyu4g5GcUV1Ik6yBFTW^#_B$IXpdv$07srr@*0<*j85sF_}IJxB(8DKVw7 z3BI+ekYIZ<=i$48@+WiZ#RUXs+{}AX-oc^BV&dB@p}cFI^ZoCeYd4E^a0GePADo^N z9^Vt<8 literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/treeheading-hover.png b/vmcompact/sun-valley-theme/theme/light/treeheading-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..47bf56f4a5e8cc6b7db6816c07230ecf7d668804 GIT binary patch literal 338 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt=aGT^vI!df#4k%s!$Z(DpD~ zSXHIs%>Vz5J6k*!X;|6jOkV2Ez4i8`({;-oKNPx1gnD`YX#SEOn5}xuLz8vlw#`$5 zN@9;2@MNsb&(>63xpmWf>uXUxh8jy}B?u}$_wnk?oOK~;F=J9sME1sOW{cC0KmRA8 ze1KPPX+lpXn|yN5!YM`Vu20#Z&00sP zMPOcA|KlB5ybtCi$A<6ue*H$arzY!r+uPe7&SAb+FVHZ@`1B?Lryc7)-_2Mnd3<8! iyqCZKDgU`$$vpLIzJK@D%w<5YGI+ZBxvXanMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt-oLT^vI!df#3>n{~v1$L(VF zPkzUH|9zV`_B_>FHo39U>9Rq|Gvo z7dcbo=y&J#y`K_v!cu(wbiPNDtFIp#+#ix-tidtrV{;XKe= N44$rjF6*2UngEe6hY$b& literal 0 HcmV?d00001 diff --git a/vmcompact/sun-valley-theme/theme/light/treeheading-rest.png b/vmcompact/sun-valley-theme/theme/light/treeheading-rest.png new file mode 100644 index 0000000000000000000000000000000000000000..d4aa09591d8d749f0a36640afa74788ea3e987c6 GIT binary patch literal 330 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4foCO|{#S9F5he4R}c>anMprB-l zYeY$Kep*R+Vo@qXd3m{BW?pu2a$-TMUVc&f>~}U&Kt<= zSI5X{74HQnR_h*{akeLO)`xqK=iD~mFKw)RtYg(B6JDhzh80@(elPEHS5o?28M^m6 zLy(unbH3*Fh36&){c0&bXFuzUsnVwX=PTc?Ruiu|DE=pY!_36Aoe)+>< zMTXqlMt#bPEZcIedGc<%aWvk3>vp~Lz;Ax04ePWI8*I=y{V-cl@YSwm@2gj>s%opZ Z&W|g~@xSWc@(Acf22WQ%mvv4FO#tQyiD3W$ literal 0 HcmV?d00001