Merge branch 'feature/check-for-updates' into 'develop'

Allow to check for updates

See merge request cc-ru/ocelot/ocelot-desktop!73
This commit is contained in:
Dmitry Zhidenkov 2023-10-14 16:52:01 +00:00
commit d92f150be2
35 changed files with 709 additions and 384 deletions

@ -1 +1 @@
Subproject commit 6fc005d04d785d76fd3330ac304cc717eb99e752
Subproject commit ece53729967381bc1278479242a147539f33c60a

BIN
sprites/Loading.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
sprites/Logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
sprites/icons/Book.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

BIN
sprites/icons/Help.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

BIN
sprites/icons/Ocelot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

BIN
sprites/loading.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
sprites/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,3 +1,12 @@
Accent = #bd353e
AboutLogo = #ffffffee
AboutForeground = #eeeeee
AboutForegroundSubtle = #eeeeeeee
AboutButtonForeground = #222222
AboutButtonBorder = #444444
AboutButtonBackground = #777777
PortDown = #8382d8
PortUp = #75bdc1
PortNorth = #c8ca5f
@ -23,7 +32,7 @@ ConnectionDel = #7f3333
Connection = #909090
NodeSelectorRing = #4c7f66
NodeSelectorBackground = #000000BB
NodeSelectorBackground = #000000bb
ContextMenuBackground = #222222ee
ContextMenuBorder = #444444

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 140 KiB

View File

@ -1,295 +1,300 @@
BackgroundPattern 0 0 304 304
BarSegment 29 499 16 4
Empty 278 351 16 16
EmptySlot 256 376 18 18
Knob 692 0 50 50
KnobCenter 743 0 50 50
KnobLimits 794 0 50 50
ShadowBorder 0 538 1 24
ShadowCorner 153 351 24 24
TabArrow 0 484 8 14
blocks/Generic 295 351 16 16
blocks/HologramEffect 8 547 4 4
blocks/HologramProjector1Top 312 351 16 16
blocks/HologramProjector2Top 329 351 16 16
blocks/HologramProjectorSide 346 351 16 16
buttons/BottomDrawerClose 275 376 18 18
buttons/BottomDrawerOpen 294 376 18 18
buttons/OpenFMRadioCloseOff 48 510 7 8
buttons/OpenFMRadioCloseOn 56 510 7 8
buttons/OpenFMRadioRedstoneOff 3 510 8 8
buttons/OpenFMRadioRedstoneOn 12 510 8 8
buttons/OpenFMRadioStartOff 178 351 24 24
buttons/OpenFMRadioStartOn 203 351 24 24
buttons/OpenFMRadioStopOff 228 351 24 24
buttons/OpenFMRadioStopOn 253 351 24 24
buttons/OpenFMRadioVolumeDownOff 9 484 10 10
buttons/OpenFMRadioVolumeDownOn 20 484 10 10
buttons/OpenFMRadioVolumeUpOff 31 484 10 10
buttons/OpenFMRadioVolumeUpOn 42 484 10 10
buttons/PowerOff 313 376 18 18
buttons/PowerOn 332 376 18 18
buttons/RackRelayOff 153 332 65 18
buttons/RackRelayOn 219 332 65 18
icons/Antenna 363 351 16 16
icons/ArrowRight 380 351 16 16
icons/AspectRatio 397 351 16 16
icons/ButtonCheck 153 409 17 17
icons/ButtonClipboard 171 409 17 17
icons/ButtonRandomize 189 409 17 17
icons/CPU 414 351 16 16
icons/Card 431 351 16 16
icons/Close 0 451 15 14
icons/Code 448 351 16 16
icons/ComponentBus 465 351 16 16
icons/Copy 482 351 16 16
icons/Cross 499 351 16 16
icons/Delete 516 351 16 16
icons/DragLMB 351 376 21 14
icons/DragRMB 373 376 21 14
icons/EEPROM 533 351 16 16
icons/Edit 550 351 16 16
icons/Eject 567 351 16 16
icons/File 584 351 16 16
icons/Floppy 601 351 16 16
icons/Folder 618 351 16 16
icons/FolderSlash 635 351 16 16
icons/Grid 187 376 22 22
icons/GridOff 210 376 22 22
icons/HDD 652 351 16 16
icons/Home 233 376 22 22
icons/LMB 84 466 11 14
icons/Label 669 351 16 16
icons/LinesHorizontal 686 351 16 16
icons/Link 703 351 16 16
icons/LinkSlash 720 351 16 16
icons/Memory 737 351 16 16
icons/Microchip 754 351 16 16
icons/NA 771 351 16 16
icons/NotificationError 108 466 11 11
icons/NotificationInfo 120 466 11 11
icons/NotificationWarning 132 466 11 11
icons/Pin 39 466 14 14
icons/Plus 788 351 16 16
icons/Power 805 351 16 16
icons/RMB 96 466 11 14
icons/Restart 822 351 16 16
icons/Save 839 351 16 16
icons/SaveAs 856 351 16 16
icons/Server 873 351 16 16
icons/SettingsSound 0 466 12 17
icons/SettingsSystem 13 466 12 17
icons/SettingsUI 26 466 12 17
icons/Tier0 890 351 16 16
icons/Tier1 907 351 16 16
icons/Tier2 924 351 16 16
icons/Tiers 941 351 16 16
icons/Unpin 54 466 14 14
icons/WaveLFSR 580 434 24 10
icons/WaveNoise 605 434 24 10
icons/WaveSawtooth 630 434 24 10
icons/WaveSine 655 434 24 10
icons/WaveSquare 680 434 24 10
icons/WaveTriangle 705 434 24 10
icons/Window 958 351 16 16
icons/WireArrowLeft 2 538 4 8
icons/WireArrowRight 7 538 4 8
items/APU0 85 332 16 96
items/APU1 102 332 16 96
items/APU2 119 332 16 96
items/CPU0 975 351 16 16
items/CPU1 992 351 16 16
items/CPU2 285 332 16 16
items/CardBase 302 332 16 16
items/CircuitBoard 319 332 16 16
items/ComponentBus0 336 332 16 16
items/ComponentBus1 353 332 16 16
items/ComponentBus2 370 332 16 16
items/ComponentBus3 387 332 16 16
items/DataCard0 0 305 16 128
items/DataCard1 17 305 16 128
items/DataCard2 34 305 16 128
items/DebugCard 404 332 16 16
items/DiskDriveMountable 421 332 16 16
items/EEPROM 438 332 16 16
items/FloppyDisk_dyeBlack 455 332 16 16
items/FloppyDisk_dyeBlue 472 332 16 16
items/FloppyDisk_dyeBrown 489 332 16 16
items/FloppyDisk_dyeCyan 506 332 16 16
items/FloppyDisk_dyeGray 523 332 16 16
items/FloppyDisk_dyeGreen 540 332 16 16
items/FloppyDisk_dyeLightBlue 557 332 16 16
items/FloppyDisk_dyeLightGray 574 332 16 16
items/FloppyDisk_dyeLime 591 332 16 16
items/FloppyDisk_dyeMagenta 608 332 16 16
items/FloppyDisk_dyeOrange 625 332 16 16
items/FloppyDisk_dyePink 642 332 16 16
items/FloppyDisk_dyePurple 659 332 16 16
items/FloppyDisk_dyeRed 676 332 16 16
items/FloppyDisk_dyeWhite 693 332 16 16
items/FloppyDisk_dyeYellow 710 332 16 16
items/GraphicsCard0 727 332 16 16
items/GraphicsCard1 744 332 16 16
items/GraphicsCard2 761 332 16 16
items/HardDiskDrive0 778 332 16 16
items/HardDiskDrive1 795 332 16 16
items/HardDiskDrive2 812 332 16 16
items/InternetCard 153 376 16 32
items/LinkedCard 136 332 16 96
items/Memory0 829 332 16 16
items/Memory1 846 332 16 16
items/Memory2 863 332 16 16
items/Memory3 880 332 16 16
items/Memory4 897 332 16 16
items/Memory5 914 332 16 16
items/Memory6 931 332 16 16
items/NetworkCard 948 332 16 16
items/OcelotCard 51 305 16 128
items/RedstoneCard0 965 332 16 16
items/RedstoneCard1 982 332 16 16
items/SelfDestructingCard 170 376 16 32
items/Server0 999 332 16 16
items/Server1 152 305 16 16
items/Server2 169 305 16 16
items/Server3 186 305 16 16
items/SoundCard 68 305 16 128
items/WirelessNetworkCard0 203 305 16 16
items/WirelessNetworkCard1 220 305 16 16
light-panel/BookmarkLeft 561 434 18 14
light-panel/BookmarkRight 207 409 20 14
light-panel/BorderB 13 547 4 4
light-panel/BorderL 103 547 4 2
light-panel/BorderR 18 547 4 4
light-panel/BorderT 23 547 4 4
light-panel/CornerBL 28 547 4 4
light-panel/CornerBR 33 547 4 4
light-panel/CornerTL 38 547 4 4
light-panel/CornerTR 43 547 4 4
light-panel/Fill 6 558 2 2
light-panel/Vent 0 499 2 38
nodes/Cable 21 510 8 8
nodes/Camera 237 305 16 16
nodes/Chest 69 466 14 14
nodes/HologramProjector0 254 305 16 16
nodes/HologramProjector1 271 305 16 16
nodes/IronNoteBlock 288 305 16 16
nodes/Lamp 305 305 16 16
nodes/LampFrame 322 305 16 16
nodes/LampGlow 305 106 128 128
nodes/NewNode 339 305 16 16
nodes/NoteBlock 356 305 16 16
nodes/OpenFMRadio 373 305 16 16
nodes/Relay 390 305 16 16
nodes/computer/Default 407 305 16 16
nodes/computer/DiskActivity 424 305 16 16
nodes/computer/Error 441 305 16 16
nodes/computer/On 458 305 16 16
nodes/disk-drive/Default 475 305 16 16
nodes/disk-drive/DiskActivity 492 305 16 16
nodes/disk-drive/Floppy 509 305 16 16
nodes/microcontroller/Default 526 305 16 16
nodes/microcontroller/Error 543 305 16 16
nodes/microcontroller/On 560 305 16 16
nodes/rack/Default 577 305 16 16
nodes/rack/Empty 594 305 16 16
nodes/rack/drive/0/Default 611 305 16 16
nodes/rack/drive/0/DiskActivity 628 305 16 16
nodes/rack/drive/0/Floppy 645 305 16 16
nodes/rack/drive/1/Default 662 305 16 16
nodes/rack/drive/1/DiskActivity 679 305 16 16
nodes/rack/drive/1/Floppy 696 305 16 16
nodes/rack/drive/2/Default 713 305 16 16
nodes/rack/drive/2/DiskActivity 730 305 16 16
nodes/rack/drive/2/Floppy 747 305 16 16
nodes/rack/drive/3/Default 764 305 16 16
nodes/rack/drive/3/DiskActivity 781 305 16 16
nodes/rack/drive/3/Floppy 798 305 16 16
nodes/rack/drive/Floppy 815 305 16 16
nodes/rack/server/0/Default 832 305 16 16
nodes/rack/server/0/DiskActivity 849 305 16 16
nodes/rack/server/0/Error 866 305 16 16
nodes/rack/server/0/NetworkActivity 883 305 16 16
nodes/rack/server/0/On 900 305 16 16
nodes/rack/server/1/Default 917 305 16 16
nodes/rack/server/1/DiskActivity 934 305 16 16
nodes/rack/server/1/Error 951 305 16 16
nodes/rack/server/1/NetworkActivity 968 305 16 16
nodes/rack/server/1/On 985 305 16 16
nodes/rack/server/2/Default 1002 305 16 16
nodes/rack/server/2/DiskActivity 0 434 16 16
nodes/rack/server/2/Error 17 434 16 16
nodes/rack/server/2/NetworkActivity 34 434 16 16
nodes/rack/server/2/On 51 434 16 16
nodes/rack/server/3/Default 68 434 16 16
nodes/rack/server/3/DiskActivity 85 434 16 16
nodes/rack/server/3/Error 102 434 16 16
nodes/rack/server/3/NetworkActivity 119 434 16 16
nodes/rack/server/3/On 136 434 16 16
nodes/raid/0/DiskActivity 153 434 16 16
nodes/raid/0/Error 170 434 16 16
nodes/raid/1/DiskActivity 187 434 16 16
nodes/raid/1/Error 204 434 16 16
nodes/raid/2/DiskActivity 221 434 16 16
nodes/raid/2/Error 238 434 16 16
nodes/raid/Default 255 434 16 16
nodes/screen/BottomLeft 272 434 16 16
nodes/screen/BottomMiddle 289 434 16 16
nodes/screen/BottomRight 306 434 16 16
nodes/screen/ColumnBottom 323 434 16 16
nodes/screen/ColumnMiddle 340 434 16 16
nodes/screen/ColumnTop 357 434 16 16
nodes/screen/Middle 374 434 16 16
nodes/screen/MiddleLeft 391 434 16 16
nodes/screen/MiddleRight 408 434 16 16
nodes/screen/PowerOnOverlay 425 434 16 16
nodes/screen/RowLeft 442 434 16 16
nodes/screen/RowMiddle 459 434 16 16
nodes/screen/RowRight 476 434 16 16
nodes/screen/Standalone 493 434 16 16
nodes/screen/TopLeft 510 434 16 16
nodes/screen/TopMiddle 527 434 16 16
nodes/screen/TopRight 544 434 16 16
panel/BorderB 48 547 4 4
panel/BorderL 108 547 4 2
panel/BorderR 53 547 4 4
panel/BorderT 58 547 4 4
panel/CornerBL 63 547 4 4
panel/CornerBR 68 547 4 4
panel/CornerTL 73 547 4 4
panel/CornerTR 78 547 4 4
panel/Fill 9 558 2 2
particles/Note 21 499 7 10
screen/BorderB 5 547 2 8
screen/BorderT 2 547 2 10
screen/CornerBL 30 510 8 8
screen/CornerBR 39 510 8 8
screen/CornerTL 3 499 8 10
screen/CornerTR 12 499 8 10
window/BorderDark 2 558 1 4
window/BorderLight 4 558 1 4
window/CornerBL 83 547 4 4
window/CornerBR 88 547 4 4
window/CornerTL 93 547 4 4
window/CornerTR 98 547 4 4
window/OpenFMRadio 305 0 232 105
window/case/Motherboard 612 0 79 70
window/rack/Lines 538 0 73 91
window/rack/Motherboard 434 106 100 78
window/rack/NetworkBack 20 552 1 2
window/rack/NetworkBottom 22 552 1 2
window/rack/NetworkConnector 24 552 1 2
window/rack/NetworkLeft 26 552 1 2
window/rack/NetworkRight 28 552 1 2
window/rack/NetworkTop 30 552 1 2
window/rack/NodeBack 113 547 5 1
window/rack/NodeBottom 119 547 5 1
window/rack/NodeLeft 125 547 5 1
window/rack/NodeRight 131 547 5 1
window/rack/NodeTop 137 547 5 1
window/rack/SideBack 8 552 1 3
window/rack/SideBottom 10 552 1 3
window/rack/SideConnector 12 552 1 3
window/rack/SideLeft 14 552 1 3
window/rack/SideRight 16 552 1 3
window/rack/SideTop 18 552 1 3
window/raid/Slots 85 305 66 26
BarSegment 385 434 16 4
Empty 327 572 16 16
EmptySlot 305 597 18 18
Knob 203 434 50 50
KnobCenter 254 434 50 50
KnobLimits 305 434 50 50
Loading 0 305 48 448
Logo 305 0 168 200
ShadowBorder 49 720 1 24
ShadowCorner 202 572 24 24
TabArrow 49 705 8 14
blocks/Generic 344 572 16 16
blocks/HologramEffect 57 729 4 4
blocks/HologramProjector1Top 361 572 16 16
blocks/HologramProjector2Top 378 572 16 16
blocks/HologramProjectorSide 395 572 16 16
buttons/BottomDrawerClose 324 597 18 18
buttons/BottomDrawerOpen 343 597 18 18
buttons/OpenFMRadioCloseOff 404 445 7 8
buttons/OpenFMRadioCloseOn 412 445 7 8
buttons/OpenFMRadioRedstoneOff 359 445 8 8
buttons/OpenFMRadioRedstoneOn 368 445 8 8
buttons/OpenFMRadioStartOff 227 572 24 24
buttons/OpenFMRadioStartOn 252 572 24 24
buttons/OpenFMRadioStopOff 277 572 24 24
buttons/OpenFMRadioStopOn 302 572 24 24
buttons/OpenFMRadioVolumeDownOff 58 705 10 10
buttons/OpenFMRadioVolumeDownOn 69 705 10 10
buttons/OpenFMRadioVolumeUpOff 80 705 10 10
buttons/OpenFMRadioVolumeUpOn 91 705 10 10
buttons/PowerOff 362 597 18 18
buttons/PowerOn 381 597 18 18
buttons/RackRelayOff 202 553 65 18
buttons/RackRelayOn 268 553 65 18
icons/Antenna 412 572 16 16
icons/ArrowRight 429 572 16 16
icons/AspectRatio 446 572 16 16
icons/Book 463 572 16 16
icons/ButtonCheck 202 630 17 17
icons/ButtonClipboard 220 630 17 17
icons/ButtonRandomize 238 630 17 17
icons/CPU 480 572 16 16
icons/Card 497 572 16 16
icons/Close 49 672 15 14
icons/Code 514 572 16 16
icons/ComponentBus 531 572 16 16
icons/Copy 548 572 16 16
icons/Cross 565 572 16 16
icons/Delete 582 572 16 16
icons/DragLMB 400 597 21 14
icons/DragRMB 422 597 21 14
icons/EEPROM 599 572 16 16
icons/Edit 616 572 16 16
icons/Eject 633 572 16 16
icons/File 650 572 16 16
icons/Floppy 667 572 16 16
icons/Folder 684 572 16 16
icons/FolderSlash 701 572 16 16
icons/Grid 236 597 22 22
icons/GridOff 259 597 22 22
icons/HDD 718 572 16 16
icons/Help 735 572 16 16
icons/Home 282 597 22 22
icons/LMB 133 687 11 14
icons/Label 752 572 16 16
icons/LinesHorizontal 769 572 16 16
icons/Link 786 572 16 16
icons/LinkSlash 803 572 16 16
icons/Memory 820 572 16 16
icons/Microchip 837 572 16 16
icons/NA 854 572 16 16
icons/NotificationError 157 687 11 11
icons/NotificationInfo 169 687 11 11
icons/NotificationWarning 181 687 11 11
icons/Ocelot 871 572 16 16
icons/Pin 88 687 14 14
icons/Plus 888 572 16 16
icons/Power 905 572 16 16
icons/RMB 145 687 11 14
icons/Restart 922 572 16 16
icons/Save 939 572 16 16
icons/SaveAs 956 572 16 16
icons/Server 973 572 16 16
icons/SettingsSound 49 687 12 17
icons/SettingsSystem 62 687 12 17
icons/SettingsUI 75 687 12 17
icons/Tier0 990 572 16 16
icons/Tier1 1007 572 16 16
icons/Tier2 334 553 16 16
icons/Tiers 351 553 16 16
icons/Unpin 103 687 14 14
icons/WaveLFSR 816 655 24 10
icons/WaveNoise 841 655 24 10
icons/WaveSawtooth 866 655 24 10
icons/WaveSine 891 655 24 10
icons/WaveSquare 916 655 24 10
icons/WaveTriangle 941 655 24 10
icons/Window 368 553 16 16
icons/WireArrowLeft 51 720 4 8
icons/WireArrowRight 56 720 4 8
items/APU0 134 553 16 96
items/APU1 151 553 16 96
items/APU2 168 553 16 96
items/CPU0 385 553 16 16
items/CPU1 402 553 16 16
items/CPU2 419 553 16 16
items/CardBase 436 553 16 16
items/CircuitBoard 453 553 16 16
items/ComponentBus0 470 553 16 16
items/ComponentBus1 487 553 16 16
items/ComponentBus2 504 553 16 16
items/ComponentBus3 521 553 16 16
items/DataCard0 49 526 16 128
items/DataCard1 66 526 16 128
items/DataCard2 83 526 16 128
items/DebugCard 538 553 16 16
items/DiskDriveMountable 555 553 16 16
items/EEPROM 572 553 16 16
items/FloppyDisk_dyeBlack 589 553 16 16
items/FloppyDisk_dyeBlue 606 553 16 16
items/FloppyDisk_dyeBrown 623 553 16 16
items/FloppyDisk_dyeCyan 640 553 16 16
items/FloppyDisk_dyeGray 657 553 16 16
items/FloppyDisk_dyeGreen 674 553 16 16
items/FloppyDisk_dyeLightBlue 691 553 16 16
items/FloppyDisk_dyeLightGray 708 553 16 16
items/FloppyDisk_dyeLime 725 553 16 16
items/FloppyDisk_dyeMagenta 742 553 16 16
items/FloppyDisk_dyeOrange 759 553 16 16
items/FloppyDisk_dyePink 776 553 16 16
items/FloppyDisk_dyePurple 793 553 16 16
items/FloppyDisk_dyeRed 810 553 16 16
items/FloppyDisk_dyeWhite 827 553 16 16
items/FloppyDisk_dyeYellow 844 553 16 16
items/GraphicsCard0 861 553 16 16
items/GraphicsCard1 878 553 16 16
items/GraphicsCard2 895 553 16 16
items/HardDiskDrive0 912 553 16 16
items/HardDiskDrive1 929 553 16 16
items/HardDiskDrive2 946 553 16 16
items/InternetCard 202 597 16 32
items/LinkedCard 185 553 16 96
items/Memory0 963 553 16 16
items/Memory1 980 553 16 16
items/Memory2 997 553 16 16
items/Memory3 201 526 16 16
items/Memory4 218 526 16 16
items/Memory5 235 526 16 16
items/Memory6 252 526 16 16
items/NetworkCard 269 526 16 16
items/OcelotCard 100 526 16 128
items/RedstoneCard0 286 526 16 16
items/RedstoneCard1 303 526 16 16
items/SelfDestructingCard 219 597 16 32
items/Server0 320 526 16 16
items/Server1 337 526 16 16
items/Server2 354 526 16 16
items/Server3 371 526 16 16
items/SoundCard 117 526 16 128
items/WirelessNetworkCard0 388 526 16 16
items/WirelessNetworkCard1 405 526 16 16
light-panel/BookmarkLeft 797 655 18 14
light-panel/BookmarkRight 256 630 20 14
light-panel/BorderB 62 729 4 4
light-panel/BorderL 152 729 4 2
light-panel/BorderR 67 729 4 4
light-panel/BorderT 72 729 4 4
light-panel/CornerBL 77 729 4 4
light-panel/CornerBR 82 729 4 4
light-panel/CornerTL 87 729 4 4
light-panel/CornerTR 92 729 4 4
light-panel/Fill 55 740 2 2
light-panel/Vent 356 434 2 38
nodes/Cable 377 445 8 8
nodes/Camera 422 526 16 16
nodes/Chest 118 687 14 14
nodes/HologramProjector0 439 526 16 16
nodes/HologramProjector1 456 526 16 16
nodes/IronNoteBlock 473 526 16 16
nodes/Lamp 490 526 16 16
nodes/LampFrame 507 526 16 16
nodes/LampGlow 49 305 128 128
nodes/NewNode 524 526 16 16
nodes/NoteBlock 541 526 16 16
nodes/OpenFMRadio 558 526 16 16
nodes/Relay 575 526 16 16
nodes/computer/Default 592 526 16 16
nodes/computer/DiskActivity 609 526 16 16
nodes/computer/Error 626 526 16 16
nodes/computer/On 643 526 16 16
nodes/disk-drive/Default 660 526 16 16
nodes/disk-drive/DiskActivity 677 526 16 16
nodes/disk-drive/Floppy 694 526 16 16
nodes/microcontroller/Default 711 526 16 16
nodes/microcontroller/Error 728 526 16 16
nodes/microcontroller/On 745 526 16 16
nodes/rack/Default 762 526 16 16
nodes/rack/Empty 779 526 16 16
nodes/rack/drive/0/Default 796 526 16 16
nodes/rack/drive/0/DiskActivity 813 526 16 16
nodes/rack/drive/0/Floppy 830 526 16 16
nodes/rack/drive/1/Default 847 526 16 16
nodes/rack/drive/1/DiskActivity 864 526 16 16
nodes/rack/drive/1/Floppy 881 526 16 16
nodes/rack/drive/2/Default 898 526 16 16
nodes/rack/drive/2/DiskActivity 915 526 16 16
nodes/rack/drive/2/Floppy 932 526 16 16
nodes/rack/drive/3/Default 949 526 16 16
nodes/rack/drive/3/DiskActivity 966 526 16 16
nodes/rack/drive/3/Floppy 983 526 16 16
nodes/rack/drive/Floppy 1000 526 16 16
nodes/rack/server/0/Default 49 655 16 16
nodes/rack/server/0/DiskActivity 66 655 16 16
nodes/rack/server/0/Error 83 655 16 16
nodes/rack/server/0/NetworkActivity 100 655 16 16
nodes/rack/server/0/On 117 655 16 16
nodes/rack/server/1/Default 134 655 16 16
nodes/rack/server/1/DiskActivity 151 655 16 16
nodes/rack/server/1/Error 168 655 16 16
nodes/rack/server/1/NetworkActivity 185 655 16 16
nodes/rack/server/1/On 202 655 16 16
nodes/rack/server/2/Default 219 655 16 16
nodes/rack/server/2/DiskActivity 236 655 16 16
nodes/rack/server/2/Error 253 655 16 16
nodes/rack/server/2/NetworkActivity 270 655 16 16
nodes/rack/server/2/On 287 655 16 16
nodes/rack/server/3/Default 304 655 16 16
nodes/rack/server/3/DiskActivity 321 655 16 16
nodes/rack/server/3/Error 338 655 16 16
nodes/rack/server/3/NetworkActivity 355 655 16 16
nodes/rack/server/3/On 372 655 16 16
nodes/raid/0/DiskActivity 389 655 16 16
nodes/raid/0/Error 406 655 16 16
nodes/raid/1/DiskActivity 423 655 16 16
nodes/raid/1/Error 440 655 16 16
nodes/raid/2/DiskActivity 457 655 16 16
nodes/raid/2/Error 474 655 16 16
nodes/raid/Default 491 655 16 16
nodes/screen/BottomLeft 508 655 16 16
nodes/screen/BottomMiddle 525 655 16 16
nodes/screen/BottomRight 542 655 16 16
nodes/screen/ColumnBottom 559 655 16 16
nodes/screen/ColumnMiddle 576 655 16 16
nodes/screen/ColumnTop 593 655 16 16
nodes/screen/Middle 610 655 16 16
nodes/screen/MiddleLeft 627 655 16 16
nodes/screen/MiddleRight 644 655 16 16
nodes/screen/PowerOnOverlay 661 655 16 16
nodes/screen/RowLeft 678 655 16 16
nodes/screen/RowMiddle 695 655 16 16
nodes/screen/RowRight 712 655 16 16
nodes/screen/Standalone 729 655 16 16
nodes/screen/TopLeft 746 655 16 16
nodes/screen/TopMiddle 763 655 16 16
nodes/screen/TopRight 780 655 16 16
panel/BorderB 97 729 4 4
panel/BorderL 157 729 4 2
panel/BorderR 102 729 4 4
panel/BorderT 107 729 4 4
panel/CornerBL 112 729 4 4
panel/CornerBR 117 729 4 4
panel/CornerTL 122 729 4 4
panel/CornerTR 127 729 4 4
panel/Fill 58 740 2 2
particles/Note 377 434 7 10
screen/BorderB 54 729 2 8
screen/BorderT 51 729 2 10
screen/CornerBL 386 445 8 8
screen/CornerBR 395 445 8 8
screen/CornerTL 359 434 8 10
screen/CornerTR 368 434 8 10
window/BorderDark 51 740 1 4
window/BorderLight 53 740 1 4
window/CornerBL 132 729 4 4
window/CornerBR 137 729 4 4
window/CornerTL 142 729 4 4
window/CornerTR 147 729 4 4
window/OpenFMRadio 474 0 232 105
window/case/Motherboard 123 434 79 70
window/rack/Lines 49 434 73 91
window/rack/Motherboard 178 305 100 78
window/rack/NetworkBack 69 734 1 2
window/rack/NetworkBottom 71 734 1 2
window/rack/NetworkConnector 73 734 1 2
window/rack/NetworkLeft 75 734 1 2
window/rack/NetworkRight 77 734 1 2
window/rack/NetworkTop 79 734 1 2
window/rack/NodeBack 162 729 5 1
window/rack/NodeBottom 168 729 5 1
window/rack/NodeLeft 174 729 5 1
window/rack/NodeRight 180 729 5 1
window/rack/NodeTop 186 729 5 1
window/rack/SideBack 57 734 1 3
window/rack/SideBottom 59 734 1 3
window/rack/SideConnector 61 734 1 3
window/rack/SideLeft 63 734 1 3
window/rack/SideRight 65 734 1 3
window/rack/SideTop 67 734 1 3
window/raid/Slots 134 526 66 26

View File

@ -6,11 +6,13 @@ import ocelot.desktop.util.Logging
import scala.collection.mutable
import scala.io.Source
object ColorScheme extends Logging {
class ColorScheme extends Logging {
private val entries = new mutable.HashMap[String, RGBAColorNorm]()
def apply(key: String): RGBAColorNorm = entries(key)
def add(key: String, color: RGBAColorNorm): Unit = entries.addOne((key, color))
def load(source: Source): Unit = {
logger.info(s"Loading color scheme")
@ -36,3 +38,11 @@ object ColorScheme extends Logging {
logger.info(s"Loaded ${entries.size - oldSize} colors")
}
}
object ColorScheme {
val General = new ColorScheme
def load(source: Source): Unit = General.load(source)
def apply(key: String): RGBAColorNorm = General(key)
}

View File

@ -6,7 +6,6 @@ import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.swing.SplashScreen
import ocelot.desktop.ui.widget._
import ocelot.desktop.ui.widget.modal.notification.{NotificationDialog, NotificationType}
import ocelot.desktop.ui.widget.settings.SettingsDialog
import ocelot.desktop.util.CommandLine.Argument
import ocelot.desktop.util.FileUtils.getOcelotConfigDirectory
import ocelot.desktop.util._
@ -372,8 +371,6 @@ object OcelotDesktop extends Logging {
}
}
def showSettings(): Unit = new SettingsDialog().show()
def exit(): Unit = showCloseConfirmationDialog() {
UiHandler.exit()
}

View File

@ -1,7 +1,7 @@
package ocelot.desktop.audio
import ocelot.desktop.Settings
import ocelot.desktop.util.{Logging, OpenAlException}
import ocelot.desktop.util.Logging
import org.lwjgl.openal.AL10
import java.nio.{ByteBuffer, IntBuffer}

View File

@ -1,7 +1,7 @@
package ocelot.desktop.audio
import ocelot.desktop.Settings
import ocelot.desktop.util.{Logging, OpenAlException, Transaction}
import ocelot.desktop.util.{Logging, Transaction}
import org.lwjgl.LWJGLException
import org.lwjgl.openal.{AL, AL10, ALC10}

View File

@ -1,4 +1,4 @@
package ocelot.desktop.util
package ocelot.desktop.audio
import scala.util.control
import scala.util.control.Exception.Catch

View File

@ -1,6 +1,6 @@
package ocelot.desktop.audio
import ocelot.desktop.util.{FileUtils, Logging, OpenAlException, Resource}
import ocelot.desktop.util.{FileUtils, Logging, Resource}
import org.lwjgl.openal.AL10
class SoundBuffer(val file: String) extends Resource with Logging {

View File

@ -1,6 +1,6 @@
package ocelot.desktop.audio
import ocelot.desktop.util.{Logging, OpenAlException}
import ocelot.desktop.util.Logging
import org.lwjgl.openal.AL10
import java.nio.ByteBuffer

View File

@ -2,6 +2,7 @@ package ocelot.desktop.graphics
import ocelot.desktop.color.{Color, RGBAColorNorm}
import ocelot.desktop.geometry.{Rect2D, Size2D, Transform2D, Vector2D}
import ocelot.desktop.graphics.IconSource.Animation
import ocelot.desktop.graphics.mesh.{Mesh2D, MeshInstance2D, MeshVertex2D}
import ocelot.desktop.graphics.render.InstanceRenderer
import ocelot.desktop.ui.UiHandler
@ -279,9 +280,14 @@ class Graphics(private var scalingFactor: Float) extends Logging with Resource {
sprite(name, pos.x, pos.y, size.width, size.height)
}
def sprite(name: String, x: Float, y: Float): Unit = {
val size = Spritesheet.spriteSize(name)
sprite(name, x, y, size.width, size.height)
}
def sprite(name: String, x: Float, y: Float, width: Float, height: Float,
color: Color = RGBAColorNorm(1f, 1f, 1f),
animation: Option[IconSource.Animation] = None): Unit =
animation: Option[Animation] = None): Unit =
{
sprite = name
foreground = color
@ -308,23 +314,27 @@ class Graphics(private var scalingFactor: Float) extends Logging with Resource {
private def _rect(x: Float, y: Float, width: Float, height: Float,
fixUV: Boolean = true,
animation: Option[Array[(Int, Float)]] = None): Unit = {
animation: Option[Animation] = None): Unit = {
val spriteRect = animation match {
case None => this.spriteRect
case Some(frames) =>
val duration = frames.map(_._2).sum
case Some(animation) =>
val duration = animation.frames.map(_._2).sum
var timeOffset = 0f
var curFrame = 0
breakable {
for ((idx, dur) <- frames) {
for ((idx, dur) <- animation.frames) {
timeOffset += dur
curFrame = idx
if (timeOffset >= time % duration) break
}
}
this.spriteRect.copy(y = this.spriteRect.y + curFrame * this.spriteRect.w, h = this.spriteRect.w)
val size = animation.frameSize match {
case Some(size) => Size2D(this.spriteRect.w, this.spriteRect.w * size.height / size.width)
case None => Size2D(this.spriteRect.w, this.spriteRect.w)
}
this.spriteRect.copy(y = this.spriteRect.y + curFrame * size.height, h = size.height)
}
val uvTransform = Transform2D.translate(spriteRect.x, spriteRect.y) >>

View File

@ -1,5 +1,6 @@
package ocelot.desktop.graphics
import ocelot.desktop.geometry.Size2D
import ocelot.desktop.ui.widget.modal.notification.NotificationType.NotificationType
import totoro.ocelot.brain.util.DyeColor
import totoro.ocelot.brain.util.ExtendedTier.ExtendedTier
@ -11,8 +12,6 @@ case class IconSource(
)
object IconSource {
type Animation = Array[(Int, Float)]
val CardIcon: IconSource = IconSource("icons/Card")
val CpuIcon: IconSource = IconSource("icons/CPU")
val HddIcon: IconSource = IconSource("icons/HDD")
@ -88,24 +87,36 @@ object IconSource {
//noinspection ScalaWeakerAccess
object Animations {
val Apu: Animation = Array(
val Apu: Animation = Animation(
(0, 3f), (1, 3f), (2, 3f), (3, 3f), (4, 3f), (5, 3f),
(4, 3f), (3, 3f), (2, 3f), (1, 3f), (0, 3f))
val LinkedCard: Animation =
Array((0, 3f), (1, 3f), (2, 3f), (3, 3f), (4, 3f), (5, 3f))
Animation((0, 3f), (1, 3f), (2, 3f), (3, 3f), (4, 3f), (5, 3f))
val InternetCard: Animation = Array(
val InternetCard: Animation = Animation(
(0, 2f), (1, 7f), (0, 5f), (1, 4f), (0, 7f), (1, 2f), (0, 8f),
(1, 9f), (0, 6f), (1, 4f))
val DataCard: Animation = Array(
val DataCard: Animation = Animation(
(0, 4f), (1, 4f), (2, 4f), (3, 4f), (4, 4f), (5, 4f), (6, 4f), (7, 4f))
val SelfDestructingCard: Animation = Array((0, 4f), (1, 4f))
val SelfDestructingCard: Animation = Animation((0, 4f), (1, 4f))
val OcelotCard: Animation = Array(
val OcelotCard: Animation = Animation(
(0, 12f), (1, 4f), (2, 4f), (3, 4f), (4, 5f), (5, 6f), (0, 9f), (6, 4f), (7, 3f))
val Loading: Animation = Animation(Size2D(48, 32),
(0, 0.7f), (1, 0.7f), (2, 0.7f), (3, 0.7f), (4, 0.7f), (5, 0.7f), (6, 0.7f),
(7, 0.7f), (8, 0.7f), (9, 0.7f), (10, 0.7f), (11, 0.7f), (12, 0.7f), (13, 0.7f)
)
}
case class Animation(frames: Array[(Int, Float)], frameSize: Option[Size2D])
object Animation {
def apply(frames: (Int, Float)*) = new Animation(frames.toArray, None)
def apply(size: Size2D, frames: (Int, Float)*) = new Animation(frames.toArray, Some(size))
def apply(size: Option[Size2D] = None, frames: Array[(Int, Float)]) = new Animation(frames, size)
}
// ----------------------- Ocelot interface icons -----------------------
@ -115,6 +126,8 @@ object IconSource {
IconSource(s"icons/Notification$notificationType")
}
val Loading: IconSource = IconSource("Loading", animation = Some(Animations.Loading))
val SettingsSystem: IconSource = IconSource("icons/SettingsSystem")
val SettingsSound: IconSource = IconSource("icons/SettingsSound")
val SettingsUI: IconSource = IconSource("icons/SettingsUI")
@ -142,4 +155,7 @@ object IconSource {
val Tiers: IconSource = IconSource("icons/Tiers")
val LinesHorizontal: IconSource = IconSource("icons/LinesHorizontal")
val ArrowRight: IconSource = IconSource("icons/ArrowRight")
val Book: IconSource = IconSource("icons/Book")
val Help: IconSource = IconSource("icons/Help")
val Ocelot: IconSource = IconSource("icons/Ocelot")
}

View File

@ -5,11 +5,14 @@ import ocelot.desktop.audio.SoundSource
import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Size2D
import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.event.handlers.ClickHandler
import ocelot.desktop.ui.event.{ClickEvent, MouseEvent}
import ocelot.desktop.ui.event.handlers.{ClickHandler, HoverHandler}
import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent}
import ocelot.desktop.ui.widget.tooltip.Tooltip
import ocelot.desktop.util.DrawUtils
class Button extends Widget with ClickHandler with ClickSoundSource {
class Button(tooltip: Tooltip = null) extends Widget with ClickHandler with HoverHandler with ClickSoundSource {
protected def colorScheme: ColorScheme = ColorScheme.General
def text: String = ""
def onClick(): Unit = {}
@ -19,23 +22,37 @@ class Button extends Widget with ClickHandler with ClickSoundSource {
eventHandlers += {
case ClickEvent(MouseEvent.Button.Left, _) if enabled =>
onClick()
clickSoundSource.play()
}
if (tooltip != null) {
eventHandlers += {
case HoverEvent(HoverEvent.State.Enter) => onHoverEnter()
case HoverEvent(HoverEvent.State.Leave) => onHoverLeave()
}
}
private def onHoverEnter(): Unit = {
root.get.tooltipPool.addTooltip(tooltip)
}
private def onHoverLeave(): Unit = {
root.get.tooltipPool.closeTooltip(tooltip)
}
override def minimumSize: Size2D = Size2D(24 + text.length * 8, 24)
override def maximumSize: Size2D = minimumSize
override def draw(g: Graphics): Unit = {
val (background, border, foreground) = if (enabled) (
ColorScheme("ButtonBackground"),
ColorScheme("ButtonBorder"),
ColorScheme("ButtonForeground")
colorScheme("ButtonBackground"),
colorScheme("ButtonBorder"),
colorScheme("ButtonForeground")
) else (
ColorScheme("ButtonBackgroundDisabled"),
ColorScheme("ButtonBorderDisabled"),
ColorScheme("ButtonForegroundDisabled")
colorScheme("ButtonBackgroundDisabled"),
colorScheme("ButtonBorderDisabled"),
colorScheme("ButtonForegroundDisabled")
)
g.rect(bounds, background)

View File

@ -24,9 +24,7 @@ class ChangeSimulationSpeedDialog() extends ModalDialog {
children :+= new PaddingBox(new Widget {
override val layout = new LinearLayout(this, orientation = Orientation.Vertical)
children :+= new PaddingBox(new Label {
override def text = "Change simulation speed"
}, Padding2D(bottom = 16))
children :+= new PaddingBox(new Label("Change simulation speed"), Padding2D(bottom = 16))
private var inputTPS: TextInput = _
private var inputMSPT: TextInput = _
@ -73,13 +71,9 @@ class ChangeSimulationSpeedDialog() extends ModalDialog {
override def onConfirm(): Unit = confirm()
}
children :+= new Label {
override def text = "Milliseconds per tick:"
}
children :+= new Label("Milliseconds per tick:")
children :+= new PaddingBox(inputMSPT, Padding2D(bottom = 8))
children :+= new Label {
override def text = "Ticks per second:"
}
children :+= new Label("Ticks per second:")
children :+= new PaddingBox(inputTPS, Padding2D(bottom = 8))
children :+= new Widget {

View File

@ -65,9 +65,7 @@ class DiskEditWindow(item: DiskItem) extends PanelWindow {
override val layout = new LinearLayout(this,
orientation = Orientation.Horizontal, alignItems = AlignItems.Center)
children :+= new Label {
override def text: String = "Label"
}
children :+= new Label("Label")
children :+= new TextInput(item.label.getOrElse("")) {
override def onConfirm(): Unit = {

View File

@ -5,7 +5,7 @@ import ocelot.desktop.geometry.Size2D
import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.util.Spritesheet
class Icon(icon: IconSource) extends Widget {
class Icon(icon: IconSource, size: Size2D = null, private val color: Color = Color.White) extends Widget {
def this(name: String) {
this(IconSource(name))
}
@ -14,18 +14,14 @@ class Icon(icon: IconSource) extends Widget {
this(IconSource(name, animation = Some(animation)))
}
def iconColor: Color = Color.White
def iconSize: Size2D = Spritesheet.spriteSize(icon.path)
override def minimumSize: Size2D = {
val size = iconSize
icon.animation match {
case None => size
case Some(_) => size.copy(height = size.width)
}
}
def iconColor: Color = color
def iconSize: Size2D =
if (size != null) size
else if (icon.animation.isDefined && icon.animation.get.frameSize.isDefined)
icon.animation.get.frameSize.get
else Spritesheet.spriteSize(icon.path)
override def minimumSize: Size2D = iconSize
override def maximumSize: Size2D = minimumSize
override def draw(g: Graphics): Unit = {

View File

@ -5,11 +5,9 @@ import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Size2D
import ocelot.desktop.graphics.Graphics
class Label extends Widget {
def text: String = ""
def isSmall: Boolean = false
class Label(private val value: String = "", private val small: Boolean = false) extends Widget {
def text: String = value
def isSmall: Boolean = small
def color: Color = ColorScheme("Label")
private var textWidth = text.length * 8

View File

@ -5,6 +5,8 @@ import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.ui.event.KeyEvent
import ocelot.desktop.ui.widget.contextmenu.{ContextMenuEntry, ContextMenuSubmenu}
import ocelot.desktop.ui.widget.help.{AboutDialog, UpdateCheckerDialog}
import ocelot.desktop.ui.widget.settings.SettingsDialog
import ocelot.desktop.{ColorScheme, OcelotDesktop}
import org.lwjgl.input.Keyboard
@ -43,7 +45,16 @@ class MenuBar extends Widget {
})
}))
addEntry(new MenuBarButton("Settings", () => OcelotDesktop.showSettings()))
addEntry(new MenuBarButton("Settings", () => new SettingsDialog().show()))
addEntry(new MenuBarSubmenu("Help", menu => {
menu.addEntry(ContextMenuEntry("Check for Updates", IconSource.Help) {
new UpdateCheckerDialog().show()
})
menu.addSeparator()
menu.addEntry(ContextMenuEntry("Manual", IconSource.Book) {}.setEnabled(false))
menu.addEntry(ContextMenuEntry("About", IconSource.Ocelot) { new AboutDialog().show() })
}))
addEntry(new Widget {
override def maximumSize: Size2D = Size2D(Float.PositiveInfinity, 1)

View File

@ -12,12 +12,7 @@ class ScreenAspectRatioDialog(screenNode: ScreenNode) extends ModalDialog {
new Widget {
override val layout = new LinearLayout(this, orientation = Orientation.Vertical)
children :+= new PaddingBox(
new Label {
override def text = "Set aspect ratio"
},
Padding2D(bottom = 16)
)
children :+= new PaddingBox(new Label("Set aspect ratio"), Padding2D(bottom = 16))
private var typedWidth: Option[Int] = Some(screenNode.screen.aspectRatio._1.toInt)
private var typedHeight: Option[Int] = Some(screenNode.screen.aspectRatio._2.toInt)
@ -61,9 +56,7 @@ class ScreenAspectRatioDialog(screenNode: ScreenNode) extends ModalDialog {
)
}
children :+= new Label {
override def text = "Width:"
}
children :+= new Label("Width:")
addInput(
8,
@ -71,9 +64,7 @@ class ScreenAspectRatioDialog(screenNode: ScreenNode) extends ModalDialog {
value => typedWidth = value
)
children :+= new Label {
override def text = "Height:"
}
children :+= new Label("Height:")
addInput(
6,

View File

@ -32,9 +32,7 @@ class TunnelDialog(
new Widget {
override val layout = new LinearLayout(this, orientation = Orientation.Vertical, gap = 8)
children :+= new PaddingBox(new Label {
override def text: String = "Set channel name/code"
}, Padding2D(bottom = 8))
children :+= new PaddingBox(new Label("Set channel name/code"), Padding2D(bottom = 8))
children :+= new Widget {
children :+= input

View File

@ -0,0 +1,118 @@
package ocelot.desktop.ui.widget.help
import buildinfo.BuildInfo
import ocelot.desktop.ColorScheme
import ocelot.desktop.color.Color
import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.{Button, Filler, Label, PaddingBox, Widget}
import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.ui.widget.tooltip.{LabelTooltip, Tooltip}
import ocelot.desktop.util.{DrawUtils, Orientation, Spritesheet}
import java.awt.Desktop
import java.net.URI
import java.time.Year
class AboutDialog extends ModalDialog {
val WebsiteURL: String = "https://ocelot.fomalhaut.me/desktop"
val IrcURL: String = "https://webchat.esper.net/?join=cc.ru"
val DiscordURL: String = "https://discord.gg/ygxUkxg9pt"
children :+= new Widget {
private val logo: Widget = new Widget {
override def minimumSize: Size2D = Spritesheet.spriteSize("Logo") + 40
override def draw(g: Graphics): Unit = {
g.sprite("Logo", bounds.x + 20, bounds.y + 80, ColorScheme("AboutLogo"))
drawChildren(g)
}
}
children :+= logo
children :+= new PaddingBox(new Widget {
override val layout = new LinearLayout(this, orientation = Orientation.Vertical, gap = 8)
children :++= Seq(
new PaddingBox(AboutLabel("OCELOT DESKTOP"), Padding2D(top = 32)),
new PaddingBox(AboutLabel(" OpenComputers Emulator", isSmall = true), Padding2D(bottom = 16)),
AboutLabel(s"Version: ${BuildInfo.version}"),
new PaddingBox(AboutLabel(s" (${BuildInfo.commit.take(7)})", isSmall = true), Padding2D(bottom = 16)),
AboutLabel(s"MIT License (c) ${Year.now.getValue} Ocelot Dev Team"),
AboutLabel(" OpenComputers (C) 2013-2015, MIT, Florian \"Sangar\" Nücke", isSmall = true),
AboutLabel(" MineOS (C) 2022, Dungeon MIT License, ECS", isSmall = true),
AboutLabel(" Advanced Loader (C) 2018, MIT, Luca_S", isSmall = true),
AboutLabel(" LuaJ (C) 2007, MIT, Luaj.org", isSmall = true),
AboutLabel(" Unifont (C) 2007, SIL OFL 1.1, Roman Czyborra", isSmall = true),
AboutLabel(" Unscii (Public Domain) by viznut", isSmall = true),
AboutLabel(" wcwidth (C) 2005-2020, MIT, Rich Felker, et al.", isSmall = true),
AboutLabel(" JNLua (C) 2008-2012, MIT, Andre Naef", isSmall = true),
AboutLabel(" LuaJ (C) 2007, MIT, Luaj.org", isSmall = true),
AboutLabel(" Typesafe Config (C) 2011-2012, Apache License 2.0, Typesafe Inc.", isSmall = true),
)
children :+= new Filler
children :+= new Widget {
children :+= new Filler {
override def maximumSize: Size2D = Size2D(Float.PositiveInfinity, 1)
}
if (Desktop.isDesktopSupported) {
children :+= new PaddingBox(new AboutButton("Website", WebsiteURL), Padding2D(right = 8))
children :+= new PaddingBox(new AboutButton("IRC", IrcURL), Padding2D(right = 8))
children :+= new PaddingBox(new AboutButton("Discord", DiscordURL), Padding2D(right = 20))
}
children :+= new Button {
override def text: String = "Ok"
override def onClick(): Unit = close()
override protected def colorScheme: ColorScheme = customButtonColorScheme
}
}
}, Padding2D.equal(18))
override def draw(g: Graphics): Unit = {
g.rect(bounds.x, bounds.y, logo.bounds.w, bounds.h, ColorScheme("Accent"))
super.draw(g)
}
}
protected override def drawInner(g: Graphics): Unit = {
DrawUtils.shadow(g, bounds.x - 8, bounds.y - 8, bounds.w + 16, bounds.h + 20, 0.5f)
g.rect(bounds, ColorScheme("ContextMenuBackground"))
DrawUtils.ring(g, bounds.x, bounds.y, bounds.w, bounds.h, 1, ColorScheme("ContextMenuBorder"))
drawChildren(g)
}
private def customButtonColorScheme = {
val scheme = new ColorScheme()
scheme.add("ButtonBackground", ColorScheme("AboutButtonBackground"))
scheme.add("ButtonBorder", ColorScheme("AboutButtonBorder"))
scheme.add("ButtonForeground", ColorScheme("AboutButtonForeground"))
scheme.add("ButtonBackgroundDisabled", ColorScheme("ButtonBackgroundDisabled"))
scheme.add("ButtonBorderDisabled", ColorScheme("ButtonBorderDisabled"))
scheme.add("ButtonForegroundDisabled", ColorScheme("ButtonForegroundDisabled"))
scheme
}
private class AboutButton(val label: String, val url: String) extends Button(new LabelTooltip(url)) {
override def text: String = label
override def onClick(): Unit = Desktop.getDesktop.browse(new URI(url))
override protected def colorScheme: ColorScheme = customButtonColorScheme
}
private class AboutLabel(private val _text: String, private val _isSmall: Boolean = false) extends Label {
override def text: String = _text
override def isSmall: Boolean = _isSmall
override def color: Color = if (isSmall) ColorScheme("AboutForegroundSubtle") else ColorScheme("AboutForeground")
}
private object AboutLabel {
def apply(text: String, isSmall: Boolean = false): AboutLabel = new AboutLabel(text, isSmall)
}
}

View File

@ -0,0 +1,113 @@
package ocelot.desktop.ui.widget.help
import buildinfo.BuildInfo
import ocelot.desktop.ColorScheme
import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.IconSource
import ocelot.desktop.ui.layout.{Layout, LinearLayout}
import ocelot.desktop.ui.widget.{Button, Filler, Icon, Label, PaddingBox, Widget}
import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.util.Orientation.Vertical
import ocelot.desktop.util.{Logging, OcelotOnlineAPI}
import java.awt.Desktop
import java.net.URI
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import scala.collection.immutable.ArraySeq
import scala.util.{Failure, Success}
class UpdateCheckerDialog extends ModalDialog with Logging {
private val dateFormat = DateTimeFormatter.ofPattern("dd MMM YYYY (HH:mm:ss Z)")
private val container = new Widget {
override protected val layout: Layout = new LinearLayout(this, orientation = Vertical)
}
children :+= new PaddingBox(new Widget {
override protected val layout: Layout = new LinearLayout(this, orientation = Vertical, gap = 16)
children :+= container
children :+= new Widget {
children :+= new Filler {
override def maximumSize: Size2D = Size2D(Float.PositiveInfinity, 1)
}
children :+= new Button {
override def text: String = "Ok"
override def onClick(): Unit = close()
}
}
}, Padding2D.equal(16))
// loading screen
container.children :+= new Label("Checking development news...")
container.children :+= new PaddingBox(new Icon(IconSource.Loading, color = ColorScheme("Label")), Padding2D(16, 0, 0, 90))
// check the API
OcelotOnlineAPI.checkRemoteVersion {
case Success(version) =>
setContainerChildren(ArraySeq.empty)
if (version.releaseVersion.isDefined) {
val newReleaseVersion = version.releaseVersion.get.drop(1)
container.children :+= new Label(s"Release: ${BuildInfo.version} ${newReleaseVersion}")
if (newReleaseVersion == BuildInfo.version) {
container.children :+= new PaddingBox(new Label("Up to date!", small = true), Padding2D(6))
} else {
container.children :+= new PaddingBox(new Label("New release version is available:", small = true), Padding2D(6))
if (Desktop.isDesktopSupported) {
container.children :+= new PaddingBox(new Button {
override def text: String = "Download"
override def onClick(): Unit = Desktop.getDesktop.browse(new URI("https://ocelot.fomalhaut.me/desktop"))
}, Padding2D(6))
} else {
container.children :+= new PaddingBox(new Label("https://ocelot.fomalhaut.me/desktop", small = true), Padding2D(6))
}
}
} else {
container.children :+= new Label("Release: N\\A")
}
container.children :+= new Filler {
override def minimumSize: Size2D = Size2D(8, 16)
}
if (version.devId.isDefined && version.devDate.isDefined) {
val newDevVersion = version.devId.get.take(7)
container.children :+= new Label(s"Dev build: ${BuildInfo.commit.take(7)} ${newDevVersion}")
if (BuildInfo.commit.take(7) == newDevVersion) {
container.children :+= new PaddingBox(new Label("Up to date!", small = true), Padding2D(6))
} else {
container.children :+= new PaddingBox(
new Label(s"New dev build from ${version.devDate.get.withZoneSameInstant(ZoneId.systemDefault()).format(dateFormat)}:", small = true)
, Padding2D(4))
if (Desktop.isDesktopSupported) {
container.children :+= new PaddingBox(new Button {
override def text: String = "Download"
override def onClick(): Unit = Desktop.getDesktop.browse(new URI("https://ocelot.fomalhaut.me/desktop"))
}, Padding2D(6))
} else {
container.children :+= new PaddingBox(new Label("https://ocelot.fomalhaut.me/desktop", small = true), Padding2D(6))
}
}
} else {
container.children :+= new Label("Dev build: N\\A")
}
case Failure(exception) =>
logger.error("Cannot download information about new Ocelot version!", exception)
val message = "Ocelot website is unavailable...\n" +
s"($exception)\n" +
"Check the log file for a full stacktrace."
setContainerChildren(ArraySeq.unsafeWrapArray(message.split('\n').map(line => new Label {
override def text: String = line
})))
}
private def setContainerChildren(children: ArraySeq[Widget]): Unit = {
container.children.foreach(it => { it.parent = None; it.root = None })
container.children = children
}
}

View File

@ -9,7 +9,6 @@ import ocelot.desktop.util.animation.UnitAnimation
import org.lwjgl.input.Keyboard
abstract class ModalDialog(val autoClose: Boolean = true) extends Widget {
protected def dialogPool: ModalDialogPool = parent.get.asInstanceOf[ModalDialogPool]
protected val openCloseAnimation: UnitAnimation = UnitAnimation.easeInOutQuad(0.13f)
if (autoClose) {

View File

@ -2,7 +2,7 @@ package ocelot.desktop.ui.widget.modal.notification
import ocelot.desktop.ColorScheme
import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Padding2D
import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget._
@ -11,7 +11,7 @@ import ocelot.desktop.ui.widget.modal.notification.NotificationType.Notification
import ocelot.desktop.util.{DrawUtils, Orientation}
class NotificationDialog(message: String, notificationType: NotificationType = NotificationType.Warning) extends ModalDialog {
protected val buttonsLayout: Widget = new Widget {
private val buttonsLayout: Widget = new Widget {
override val layout: LinearLayout = new LinearLayout(this, gap = 15)
children :+= new Filler
@ -30,7 +30,7 @@ class NotificationDialog(message: String, notificationType: NotificationType = N
// Icon
children :+= new PaddingBox(
new Icon(IconSource.Notification(notificationType)),
new Icon(IconSource.Notification(notificationType), Size2D(22, 22)),
Padding2D.equal(10)
)

View File

@ -15,9 +15,7 @@ class SystemSettingsTab extends SettingsTab {
override val icon: IconSource = IconSource.SettingsSystem
override val label: String = "System"
children :+= new PaddingBox(new Label {
override def text = "OpenComputers configuration file path"
}, Padding2D(bottom = 8))
children :+= new PaddingBox(new Label("OpenComputers configuration file path"), Padding2D(bottom = 8))
children :+= new PaddingBox(new Widget {
override val layout = new LinearLayout(this, orientation = Orientation.Horizontal)

View File

@ -22,9 +22,7 @@ class VerticalMenuButton(icon: IconSource, label: String, handler: VerticalMenuB
override val layout = new LinearLayout(this, orientation = Orientation.Horizontal)
children :+= new PaddingBox(
new Icon(icon) {
override def iconColor: Color = ColorScheme("VerticalMenuEntryIcon")
},
new Icon(icon, color = ColorScheme("VerticalMenuEntryIcon")),
Padding2D(right = 8)
)

View File

@ -0,0 +1,49 @@
package ocelot.desktop.util
import java.net.{HttpURLConnection, URL}
import java.time.ZonedDateTime
import scala.util.{Success, Try, Using}
object OcelotOnlineAPI {
private val UrlInfo: String = "https://ocelot.fomalhaut.me/desktop/info"
private val RegexDevId = "\"dev\":\\s?\\{.*?\"id\":\\s?\"(.*?)\"".r
private val RegexDevDate = "\"dev\":\\s?\\{.*?\"date\":\\s?\"(.*?)\"".r
private val RegexReleaseVersion = "\"release\":\\s?\\{.*?\"version\":\\s?\"(.*?)\"".r
private val RegexReleaseDate = "\"release\":\\s?\\{.*?\"date\":\\s?\"(.*?)\"".r
def checkRemoteVersion(callback: Try[Version] => Unit): Unit =
new Thread(() => callback(getVersion)).start()
private def getVersion: Try[Version] = Try {
val source = scala.io.Source.fromURL(UrlInfo)
val response = source.mkString
val devId = RegexDevId.findFirstMatchIn(response).map(_.group(1))
val devDate = RegexDevDate.findFirstMatchIn(response).map(_.group(1))
val releaseVersion = RegexReleaseVersion.findFirstMatchIn(response).map(_.group(1))
val releaseDate = RegexReleaseDate.findFirstMatchIn(response).map(_.group(1))
val version = Version(
devId, devDate.map(it => ZonedDateTime.parse(it)),
releaseVersion, releaseDate.map(it => ZonedDateTime.parse(it))
)
source.close()
version
}
@throws(classOf[java.io.IOException])
@throws(classOf[java.net.SocketTimeoutException])
def get(url: String, connectTimeout: Int = 5000, readTimeout: Int = 5000, requestMethod: String = "GET"): String = {
val connection = new URL(url).openConnection.asInstanceOf[HttpURLConnection]
connection.setConnectTimeout(connectTimeout)
connection.setReadTimeout(readTimeout)
connection.setRequestMethod(requestMethod)
Using.resource(connection.getInputStream) { inputStream =>
val content = io.Source.fromInputStream(inputStream).mkString
content
}
}
case class Version(devId: Option[String], devDate: Option[ZonedDateTime], releaseVersion: Option[String], releaseDate: Option[ZonedDateTime])
}