├── .gitattributes ├── .github ├── FUNDING.yml ├── scripts │ ├── jpackage.bat │ └── jpackage.sh └── workflows │ ├── build.yml │ ├── delete-all-artifacts.yml │ ├── init.yml │ └── release.yml ├── .gitignore ├── LICENSE ├── README.md ├── assets ├── AppImage │ ├── AppRun │ └── Stream-Pi Server.desktop ├── launchers │ └── arm │ │ ├── run │ │ └── run_min ├── linux-icon.png ├── macos-icon.icns └── windows-icon.ico ├── i18n.md ├── logo.png ├── pom.xml ├── src └── main │ ├── java │ ├── com │ │ └── stream_pi │ │ │ └── server │ │ │ ├── Main.java │ │ │ ├── action │ │ │ └── ExternalPlugins.java │ │ │ ├── client │ │ │ ├── Client.java │ │ │ ├── ClientProfile.java │ │ │ └── ClientTheme.java │ │ │ ├── combobox │ │ │ ├── IPChooserComboBox.java │ │ │ └── LanguageChooserComboBox.java │ │ │ ├── config │ │ │ ├── Config.java │ │ │ └── record │ │ │ │ ├── ActionGridSettings.java │ │ │ │ ├── ConnectionSettings.java │ │ │ │ ├── GeneralSettings.java │ │ │ │ ├── LocationsSettings.java │ │ │ │ ├── OthersSettings.java │ │ │ │ └── SoundOnActionClickedSettings.java │ │ │ ├── connection │ │ │ ├── ClientConnection.java │ │ │ ├── ClientConnections.java │ │ │ └── MainServer.java │ │ │ ├── controller │ │ │ ├── ActionDataFormats.java │ │ │ ├── Controller.java │ │ │ ├── ServerExecutorService.java │ │ │ └── ServerListener.java │ │ │ ├── i18n │ │ │ └── I18N.java │ │ │ ├── info │ │ │ ├── ServerInfo.java │ │ │ └── StartupFlags.java │ │ │ ├── uipropertybox │ │ │ └── UIPropertyBox.java │ │ │ └── window │ │ │ ├── Base.java │ │ │ ├── ExceptionAndAlertHandler.java │ │ │ ├── GlobalExceptionAndAlertHandler.java │ │ │ ├── dashboard │ │ │ ├── ClientAndProfileSelectorPane.java │ │ │ ├── DashboardBase.java │ │ │ ├── DashboardInterface.java │ │ │ ├── PluginsPane.java │ │ │ ├── actiondetailspane │ │ │ │ ├── ActionDetailsPane.java │ │ │ │ ├── ActionDetailsPaneListener.java │ │ │ │ ├── CombineActionPropertiesPane.java │ │ │ │ ├── OnDeleteActionTask.java │ │ │ │ └── OnSaveActionTask.java │ │ │ └── actiongridpane │ │ │ │ ├── ActionBox.java │ │ │ │ ├── ActionGridPane.java │ │ │ │ └── ActionGridPaneListener.java │ │ │ ├── firsttimeuse │ │ │ ├── FinalConfigPane.java │ │ │ ├── FirstTimeUse.java │ │ │ ├── LicensePane.java │ │ │ ├── WelcomePane.java │ │ │ └── WindowName.java │ │ │ ├── helper │ │ │ ├── ControlNodePair.java │ │ │ └── Helper.java │ │ │ ├── settings │ │ │ ├── ClientsSettings.java │ │ │ ├── PluginsSettings.java │ │ │ ├── SettingsBase.java │ │ │ ├── ThemesSettings.java │ │ │ ├── about │ │ │ │ ├── About.java │ │ │ │ ├── ContactTab.java │ │ │ │ ├── ContributorsTab.java │ │ │ │ └── LicenseTab.java │ │ │ └── general │ │ │ │ ├── GeneralSettingsModel.java │ │ │ │ ├── GeneralSettingsPresenter.java │ │ │ │ ├── GeneralSettingsView.java │ │ │ │ └── GeneralSettingsViewListener.java │ │ │ └── windowmenubar │ │ │ ├── WindowMenuBar.java │ │ │ ├── filemenu │ │ │ ├── FileMenu.java │ │ │ └── SettingsMenu.java │ │ │ └── helpmenu │ │ │ └── HelpMenu.java │ └── module-info.java │ └── resources │ └── com │ └── stream_pi │ └── server │ ├── Default.zip │ ├── default_icons.css │ ├── i18n │ ├── i18n.properties │ ├── lang_de_DE.properties │ ├── lang_en.properties │ ├── lang_en_GB.properties │ ├── lang_en_IN.properties │ ├── lang_en_US.properties │ ├── lang_es_ES.properties │ ├── lang_fr.properties │ ├── lang_hi.properties │ └── lang_nl_NL.properties │ ├── icons │ ├── 16x16.png │ ├── 24x24.png │ ├── 256x256.png │ ├── 32x32.png │ └── 48x48.png │ ├── info │ ├── LICENSE │ └── build.properties │ └── style.css └── style_classes.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | *.bat text eol=crlf 4 | 5 | *.zip -text 6 | *.png -text -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: streampi 2 | -------------------------------------------------------------------------------- /.github/scripts/jpackage.bat: -------------------------------------------------------------------------------- 1 | :: 2 | :: Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macro Pad 3 | :: Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | :: 5 | :: This program is free software: you can redistribute it and/or modify 6 | :: it under the terms of the GNU General Public License as published by 7 | :: the Free Software Foundation, either version 3 of the License, or 8 | :: (at your option) any later version. 9 | :: This program is distributed in the hope that it will be useful, 10 | :: but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | :: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | :: GNU General Public License for more details. 13 | :: 14 | 15 | set /p REQ_MODULES=> $GITHUB_ENV 62 | - name: Set Build Number 63 | run: | 64 | RAW_BUILD_NUMBER=$(sed '4q;d' src/main/resources/com/stream_pi/server/info/build.properties) 65 | echo "BUILD_NUMBER=${RAW_BUILD_NUMBER#*=}" >> $GITHUB_ENV 66 | - name: Calculate required modules 67 | run: | 68 | JDEPS_MODULES=$(jdeps --module-path $JAVAFX_SDK/:target/lib/ --print-module-deps --ignore-missing-deps target/lib/server-$VERSION.jar) 69 | JAVAFX_MODULES=javafx.media, 70 | EXTRA_MODULES=java.base,java.logging,java.net.http,java.scripting,jdk.jsobject,jdk.unsupported,jdk.unsupported.desktop,jdk.xml.dom,java.xml,java.management,jdk.localedata,java.sql,jdk.crypto.ec 71 | echo "REQ_MODULES=$EXTRA_MODULES,$JDEPS_MODULES,$JAVAFX_MODULES" >> $GITHUB_ENV 72 | env: 73 | JAVAFX_SDK: /tmp/javafx-sdk-18/lib/ 74 | - name: Saving REQ_MODULES 75 | run: | 76 | echo $REQ_MODULES 77 | echo $REQ_MODULES > req_modules.txt 78 | - name: Uploading REQ_MODULES 79 | uses: actions/upload-artifact@v2 80 | with: 81 | name: req_modules 82 | path: req_modules.txt 83 | - name: Saving VERSION 84 | run: | 85 | echo $VERSION > version.txt 86 | - name: Uploading VERSION 87 | uses: actions/upload-artifact@v2 88 | with: 89 | name: version 90 | path: version.txt 91 | - name: Saving BUILD_NUMBER 92 | run: | 93 | echo $BUILD_NUMBER > build_number.txt 94 | - name: Uploading BUILD_NUMBER 95 | uses: actions/upload-artifact@v2 96 | with: 97 | name: build_number 98 | path: build_number.txt 99 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_run: 5 | workflows: ["Build"] 6 | types: 7 | - completed 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-20.04 12 | steps: 13 | - name: Download VERSION 14 | uses: dawidd6/action-download-artifact@v2 15 | with: 16 | workflow: init.yml 17 | name: version 18 | - name: Add VERSION to environment 19 | run: | 20 | echo "VERSION=$(> $GITHUB_ENV 21 | - name: Download BUILD_NUMBER 22 | uses: dawidd6/action-download-artifact@v2 23 | with: 24 | workflow: init.yml 25 | name: build_number 26 | - name: Add BUILD_NUMBER to environment 27 | run: | 28 | echo "BUILD_NUMBER=$(> $GITHUB_ENV 29 | - name: Download Windows x64 msi 30 | uses: dawidd6/action-download-artifact@v2 31 | with: 32 | workflow: build.yml 33 | name: windows-msi-x64 34 | path: target/install 35 | - name: Download Windows x86 msi 36 | uses: dawidd6/action-download-artifact@v2 37 | with: 38 | workflow: build.yml 39 | name: windows-msi-x86 40 | path: target/install 41 | - name: Download Linux x64 deb 42 | uses: dawidd6/action-download-artifact@v2 43 | with: 44 | workflow: build.yml 45 | name: linux-deb-x64 46 | path: target/install 47 | - name: Download Linux x64 rpm 48 | uses: dawidd6/action-download-artifact@v2 49 | with: 50 | workflow: build.yml 51 | name: linux-rpm-x64 52 | path: target/install 53 | - name: Download Linux x64 AppImage 54 | uses: dawidd6/action-download-artifact@v2 55 | with: 56 | workflow: build.yml 57 | name: linux-app-image-x64 58 | path: target/install 59 | - name: Download Linux x86 deb 60 | uses: dawidd6/action-download-artifact@v2 61 | with: 62 | workflow: build.yml 63 | name: linux-deb-x86 64 | path: target/install 65 | - name: Download Linux x86 rpm 66 | uses: dawidd6/action-download-artifact@v2 67 | with: 68 | workflow: build.yml 69 | name: linux-rpm-x86 70 | path: target/install 71 | - name: Download Linux x86 AppImage 72 | uses: dawidd6/action-download-artifact@v2 73 | with: 74 | workflow: build.yml 75 | name: linux-app-image-x86 76 | path: target/install 77 | - name: Download Linux aarch64 zip 78 | uses: dawidd6/action-download-artifact@v2 79 | with: 80 | workflow: build.yml 81 | name: linux-zip-aarch64 82 | path: target/install 83 | - name: Download Linux arm32 ZIP 84 | uses: dawidd6/action-download-artifact@v2 85 | with: 86 | workflow: build.yml 87 | name: linux-zip-arm32 88 | path: target/install 89 | - name: Download MacOS x64 pkg 90 | uses: dawidd6/action-download-artifact@v2 91 | with: 92 | workflow: build.yml 93 | name: macos-pkg-x64 94 | path: target/install 95 | - name: Delete old release if exists 96 | uses: dev-drprasad/delete-tag-and-release@v0.2.0 97 | continue-on-error: true 98 | with: 99 | delete_release: true 100 | tag_name: ${{ env.VERSION }} 101 | env: 102 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 103 | - name: Create release body 104 | run: | 105 | touch body.md 106 | 107 | echo Build Number : \`$BUILD_NUMBER\` >> body.md 108 | 109 | if [[ $VERSION == *"SNAPSHOT"* ]]; then 110 | echo "**These are snapshot builds. Untested and not recommended for daily use.**" >> body.md 111 | echo "PRE_RELEASE=true" >> $GITHUB_ENV 112 | else 113 | echo "PRE_RELEASE=false" >> $GITHUB_ENV 114 | fi 115 | - name: Release nightly build 116 | uses: ncipollo/release-action@v1.8.6 117 | with: 118 | allowUpdates: true 119 | name: ${{ env.VERSION }} 120 | artifacts: target/install/* 121 | token: ${{ secrets.GITHUB_TOKEN }} 122 | tag: ${{ env.VERSION }} 123 | bodyFile: "body.md" 124 | prerelease: ${{ env.PRE_RELEASE }} 125 | 126 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Maven 2 | target/ 3 | 4 | # IntelliJ IDEA 5 | .idea/ 6 | *.iml 7 | 8 | # Eclipse 9 | .settings/ 10 | .project 11 | .factorypath 12 | .classpath 13 | 14 | # Misc 15 | gen/ 16 | data/ 17 | 18 | #VS Code 19 | .vscode/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | logo 3 | 4 | # Stream-Pi Server 5 | 6 | *Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad* 7 | 8 | Server Software for the Stream-Pi Platform 9 | 10 | ![version](https://img.shields.io/badge/Version-2.0.0--SNAPSHOT-green) 11 | 12 | [![Discord](https://discordapp.com/api/guilds/582313435149238295/widget.png?style=shield)](https://discord.gg/BExqGmk) 13 | [![Matrix](https://img.shields.io/matrix/stream-pi-general:matrix.org?label=Matrix)](https://matrix.to/#/!hTwUYZonUXThjkMhCD:matrix.org?via=matrix.org) 14 | [![Become a patron](https://img.shields.io/badge/dynamic/json?color=%23e85b46&label=Donate&query=data.attributes.patron_count&suffix=%20patrons&url=https%3A%2F%2Fwww.patreon.com%2Fapi%2Fcampaigns%2F5789155)](https://www.patreon.com/streampi) 15 | ![Total Downloads](https://img.shields.io/github/downloads/stream-pi/server/total?label=Total%20Downloads) 16 | 17 | ### [Website](https://stream-pi.com) 18 | #### [Download latest release](https://github.com/stream-pi/server/releases/tag/1.0.0-EA%2B3) | [Download latest snapshot](https://github.com/stream-pi/server/releases/tag/2.0.0-SNAPSHOT) 19 | #### [Help us Translate!](https://github.com/stream-pi/server/blob/master/i18n.md) 20 |
21 | 22 | 23 | ## Compile and Run from source 24 | 25 | ### Prerequisites 26 | 27 | - Java >= 11 28 | - Maven >= 3.6.3 29 | 30 | ### Run 31 | 32 | Run `mvn clean javafx:run` 33 | 34 | 35 | ## Bugs and Support 36 | 37 | If you found a bug in the server, please report it by creating a [GitHub issue](https://github.com/stream-pi/server/issues). 38 | 39 | You may also reach us via any of the following platforms: 40 | * [E-mail](mailto:contact@stream-pi.com) 41 | * [Matrix](https://matrix.to/#/!hTwUYZonUXThjkMhCD:matrix.org?via=matrix.org) 42 | * [Discord](https://discord.gg/BExqGmk) 43 | * [Twitter](https://twitter.com/stream_pi) 44 | 45 | 46 | ## License 47 | 48 | This software is licensed to [GNU General Public License v3.0](https://github.com/stream-pi/server/blob/master/LICENSE). 49 | ``` 50 | Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 51 | Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 52 | 53 | This program is free software: you can redistribute it and/or modify 54 | it under the terms of the GNU General Public License as published by 55 | the Free Software Foundation, either version 3 of the License, or 56 | (at your option) any later version. 57 | This program is distributed in the hope that it will be useful, 58 | but WITHOUT ANY WARRANTY; without even the implied warranty of 59 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 60 | GNU General Public License for more details. 61 | 62 | 63 | Opensource Libraries/Technology used in Stream-Pi Server: 64 | 65 | 1. JavaFX - GNU General Public License with Classpath Exception 66 | https://openjdk.java.net/legal/gplv2+ce.html 67 | 68 | 2. Ikonli - Apache License 69 | https://github.com/kordamp/ikonli/blob/master/LICENSE 70 | 71 | 3. ControlsFX - BSD 3-Clause License 72 | https://github.com/controlsfx/controlsfx/blob/jfx-13/license.txt 73 | 74 | 4. Medusa - Apache License 2.0 75 | https://github.com/HanSolo/medusa/blob/master/LICENSE 76 | ``` -------------------------------------------------------------------------------- /assets/AppImage/AppRun: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macro Pad 4 | # Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | 16 | HERE="$(dirname "$(readlink -f "${0}")")" 17 | exec "$HERE/bin/Stream-Pi Server" "Stream-Pi.startupRunnerFileName=$APPIMAGE" "$@" 18 | -------------------------------------------------------------------------------- /assets/AppImage/Stream-Pi Server.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Stream-Pi Server 3 | Exec="Stream-Pi\ Server %F" 4 | Icon=Stream-Pi Server 5 | Type=Application 6 | Categories=Utility;Audio; 7 | MimeType=inode/directory;audio/flac; 8 | Name[en]=Stream-Pi Server 9 | Terminal=false 10 | StartupNotify=true 11 | NoDisplay=false 12 | -------------------------------------------------------------------------------- /assets/launchers/arm/run: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macro Pad 4 | # Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | 16 | cd "${0%/*}" 17 | 18 | DISPLAY=:0 jre/bin/java -Xmx700m --module-path . --add-modules ALL-MODULE-PATH -Djavafx.platform=gtk -Djavafx.verbose=true -Dprism.lcdtext=false -Dprism.verbose=true -Dcom.sun.javafx.isEmbedded=true -Dcom.sun.javafx.virtualKeyboard=javafx com.stream_pi.server.Main Stream-Pi.startupRunnerFileName=run_min Stream-Pi.appendPathBeforeRunnerFileToOvercomeJPackageLimitation=true 19 | -------------------------------------------------------------------------------- /assets/launchers/arm/run_min: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macro Pad 4 | # Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | 16 | cd "${0%/*}" 17 | 18 | DISPLAY=:0 jre/bin/java -Xmx700m --module-path . --add-modules ALL-MODULE-PATH -Djavafx.platform=gtk -Djavafx.verbose=true -Dprism.lcdtext=false -Dprism.verbose=true -Dcom.sun.javafx.isEmbedded=true -Dcom.sun.javafx.virtualKeyboard=javafx com.stream_pi.server.Main Stream-Pi.startMinimised=true Stream-Pi.startupRunnerFileName=run_min Stream-Pi.appendPathBeforeRunnerFileToOvercomeJPackageLimitation=true 19 | -------------------------------------------------------------------------------- /assets/linux-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stream-pi/server/a7c11776d67cc5efe6d43b184418253ee5f1f389/assets/linux-icon.png -------------------------------------------------------------------------------- /assets/macos-icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stream-pi/server/a7c11776d67cc5efe6d43b184418253ee5f1f389/assets/macos-icon.icns -------------------------------------------------------------------------------- /assets/windows-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stream-pi/server/a7c11776d67cc5efe6d43b184418253ee5f1f389/assets/windows-icon.ico -------------------------------------------------------------------------------- /i18n.md: -------------------------------------------------------------------------------- 1 | # Translation 2 | 3 | Clone this repository, create a new file `lang_.properties` in `src/main/resources/com/stream_pi/server/i18n/lang/`. 4 | 5 | Example file name: `lang_en_IN.properties` 6 | 7 | You can get the list of valid [ISO locales from here](https://docs.oracle.com/cd/E13214_01/wli/docs92/xref/xqisocodes.html). 8 | 9 | You can use the [English pack][fallback-locale] as a reference and begin translating all the strings on the right-hand side of the `=` sign. 10 | 11 | **Do not modify the comments and formatting strings (`%s`).** 12 | 13 | After that edit the file `i18n.properties` in `src/main/resources/com/stream_pi/server/i18n/` to add your new language pack in the following format: 14 | 15 | ` = ` 16 | 17 | Example: 18 | 19 | ``` 20 | hi = हिंदी 21 | ``` 22 | 23 | When you are done, send a pull request to get it accepted. 24 | 25 | You may also send a PR with appropriate details if you want to improve an existing translation. 26 | 27 | 28 | ### Supported Languages 29 | 30 | *Languages marked with `*` are community translations. Stream-Pi is not responsible for any malicious/incorrect translations in them. If you find any discrepancy, please report to the owners/core team immediately.* 31 | 32 | | Locale | Language | 33 | |-------------------------|-----------------------------------------------------| 34 | | [`en`][fallback-locale] | English (Fallback) | 35 | | [`de_DE`][de_DE] | 🇩🇪 German - Germany (Deutsch - Deutschland) * | 36 | | [`en_GB`][en_GB] | 🇬🇧 English - Great Britain | 37 | | [`en_IN`][en_IN] | 🇮🇳 English - India | 38 | | [`en_US`][en_US] | 🇺🇸 English - United States | 39 | | [`es_ES`][es_ES] | 🇪🇸 Spanish - Spain * | 40 | | [`fr`][fr] | 🇫🇷 French (Français) * | 41 | | [`hi`][hi] | 🇮🇳 Hindi (हिंदी) | 42 | | [`nl_NL`][nl_NL] | 🇳🇱 Dutch - Netherlands (Nederlands - Nederland) * | 43 | 44 | 45 | [fallback-locale]: https://github.com/stream-pi/server/blob/master/src/main/resources/com/stream_pi/server/i18n/lang_en.properties 46 | [de_DE]: https://github.com/stream-pi/server/blob/master/src/main/resources/com/stream_pi/server/i18n/lang_de_DE.properties 47 | [en_GB]: https://github.com/stream-pi/server/blob/master/src/main/resources/com/stream_pi/server/i18n/lang_en_GB.properties 48 | [en_IN]: https://github.com/stream-pi/server/blob/master/src/main/resources/com/stream_pi/server/i18n/lang_en_IN.properties 49 | [en_US]: https://github.com/stream-pi/server/blob/master/src/main/resources/com/stream_pi/server/i18n/lang_en_US.properties 50 | [es_ES]: https://github.com/stream-pi/server/blob/master/src/main/resources/com/stream_pi/server/i18n/lang_es_ES.properties 51 | [fr]: https://github.com/stream-pi/server/blob/master/src/main/resources/com/stream_pi/server/i18n/lang_fr.properties 52 | [hi]: https://github.com/stream-pi/server/blob/master/src/main/resources/com/stream_pi/server/i18n/lang_hi.properties 53 | [nl_NL]: https://github.com/stream-pi/client/blob/master/src/main/resources/com/stream_pi/client/i18n/lang_nl_NL.properties 54 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stream-pi/server/a7c11776d67cc5efe6d43b184418253ee5f1f389/logo.png -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/Main.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server; 16 | 17 | import com.stream_pi.server.controller.Controller; 18 | import com.stream_pi.server.info.ServerInfo; 19 | 20 | import com.stream_pi.server.info.StartupFlags; 21 | import com.stream_pi.util.exception.GlobalUncaughtExceptionHandler; 22 | import javafx.application.Application; 23 | import javafx.scene.Scene; 24 | import javafx.stage.Stage; 25 | 26 | import java.io.File; 27 | import java.net.URISyntaxException; 28 | 29 | public class Main extends Application 30 | { 31 | 32 | /** 33 | * First method to be called 34 | * This method first parses all the available command line arguments passed. 35 | * Then a new instance of controller is created, and then initialised. 36 | */ 37 | public void start(Stage stage) 38 | { 39 | StartupFlags.init(getParameters()); 40 | GlobalUncaughtExceptionHandler.init(); 41 | Controller d = new Controller(); 42 | Scene s = new Scene(d); 43 | stage.setScene(s); 44 | d.setHostServices(getHostServices()); 45 | d.init(); 46 | } 47 | 48 | /** 49 | * This is a fallback. Called in some JVMs. 50 | * This method just sends the command line arguments to JavaFX Application 51 | */ 52 | public static void main(String[] args) 53 | { 54 | launch(args); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/client/Client.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.client; 16 | 17 | import com.stream_pi.util.platform.Platform; 18 | import com.stream_pi.util.platform.ReleaseStatus; 19 | import com.stream_pi.util.version.Version; 20 | import javafx.geometry.Orientation; 21 | 22 | import java.net.SocketAddress; 23 | import java.util.ArrayList; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | 27 | public class Client 28 | { 29 | private String name; 30 | private final SocketAddress remoteSocketAddress; 31 | private final Platform platform; 32 | private final Version version; 33 | private final Version communicationProtocolVersion; 34 | private final Version themeAPIVersion; 35 | private final ReleaseStatus releaseStatus; 36 | 37 | private double displayHeight, displayWidth; 38 | 39 | private final HashMap profiles; 40 | 41 | private final HashMap themes; 42 | 43 | private String defaultProfileID; 44 | private String defaultThemeFullName; 45 | 46 | private Orientation orientation; 47 | 48 | public Client(Version version, ReleaseStatus releaseStatus, Version communicationProtocolVersion, 49 | Version themeAPIVersion, String name, Platform platform, SocketAddress remoteSocketAddress, 50 | Orientation orientation) 51 | { 52 | this.version = version; 53 | this.releaseStatus = releaseStatus; 54 | this.communicationProtocolVersion = communicationProtocolVersion; 55 | this.themeAPIVersion = themeAPIVersion; 56 | this.name = name; 57 | this.remoteSocketAddress = remoteSocketAddress; 58 | this.platform = platform; 59 | this.profiles = new HashMap<>(); 60 | this.themes = new HashMap<>(); 61 | this.orientation = orientation; 62 | } 63 | 64 | public ReleaseStatus getReleaseStatus() { 65 | return releaseStatus; 66 | } 67 | 68 | public void setDefaultThemeFullName(String defaultThemeFullName) { 69 | this.defaultThemeFullName = defaultThemeFullName; 70 | } 71 | 72 | public String getDefaultThemeFullName() { 73 | return defaultThemeFullName; 74 | } 75 | 76 | public void setDefaultProfileID(String ID) 77 | { 78 | defaultProfileID = ID; 79 | } 80 | 81 | public void addTheme(ClientTheme clientTheme) throws CloneNotSupportedException 82 | { 83 | themes.put(clientTheme.getFullName(), (ClientTheme) clientTheme.clone()); 84 | } 85 | 86 | public ArrayList getThemes() 87 | { 88 | ArrayList clientThemes = new ArrayList<>(); 89 | for(String clientTheme : themes.keySet()) 90 | { 91 | clientThemes.add(themes.get(clientTheme)); 92 | } 93 | return clientThemes; 94 | } 95 | 96 | public ClientTheme getThemeByFullName(String fullName) 97 | { 98 | return themes.getOrDefault(fullName, null); 99 | } 100 | 101 | public String getDefaultProfileID() 102 | { 103 | return defaultProfileID; 104 | } 105 | 106 | //client Profiles 107 | 108 | public void setName(String name) 109 | { 110 | this.name = name; 111 | } 112 | 113 | public List getAllClientProfiles() 114 | { 115 | ArrayList clientProfiles = new ArrayList<>(); 116 | for(String profile : profiles.keySet()) 117 | clientProfiles.add(profiles.get(profile)); 118 | return clientProfiles; 119 | } 120 | 121 | public void removeProfileFromID(String ID) 122 | { 123 | profiles.remove(ID); 124 | } 125 | 126 | public void addProfile(ClientProfile clientProfile) throws CloneNotSupportedException { 127 | profiles.put(clientProfile.getID(), (ClientProfile) clientProfile.clone()); 128 | } 129 | 130 | public synchronized ClientProfile getProfileByID(String ID) { 131 | return profiles.getOrDefault(ID, null); 132 | } 133 | 134 | public SocketAddress getRemoteSocketAddress() 135 | { 136 | return remoteSocketAddress; 137 | } 138 | 139 | public Platform getPlatform() 140 | { 141 | return platform; 142 | } 143 | 144 | public String getName() 145 | { 146 | return name; 147 | } 148 | 149 | public Version getVersion() 150 | { 151 | return version; 152 | } 153 | 154 | public Version getCommunicationProtocolVersion() 155 | { 156 | return communicationProtocolVersion; 157 | } 158 | 159 | public Version getThemeAPIVersion() 160 | { 161 | return themeAPIVersion; 162 | } 163 | 164 | public double getDisplayHeight() 165 | { 166 | return displayHeight; 167 | } 168 | 169 | public double getDisplayWidth() 170 | { 171 | return displayWidth; 172 | } 173 | 174 | public void setDisplayHeight(double height) 175 | { 176 | displayHeight = height; 177 | } 178 | 179 | public void setDisplayWidth(double width) 180 | { 181 | displayWidth = width; 182 | } 183 | 184 | private int getMaxRows(int eachActionSize) 185 | { 186 | return (int) (displayHeight / eachActionSize); 187 | } 188 | 189 | public int getMaxCols(int eachActionSize) 190 | { 191 | return (int) (displayWidth / eachActionSize); 192 | } 193 | 194 | public void setOrientation(Orientation orientation) 195 | { 196 | this.orientation = orientation; 197 | } 198 | 199 | public Orientation getOrientation() 200 | { 201 | return orientation; 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/client/ClientProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.client; 16 | 17 | import com.stream_pi.action_api.action.Action; 18 | 19 | import java.util.ArrayList; 20 | import java.util.HashMap; 21 | import java.util.Set; 22 | import java.util.UUID; 23 | 24 | public class ClientProfile implements Cloneable 25 | { 26 | 27 | private String name, ID; 28 | 29 | private int rows, cols; 30 | 31 | private double actionDefaultDisplayTextFontSize, actionSize, actionGap; 32 | 33 | private final HashMap actions; 34 | 35 | public ClientProfile(String name, String ID, int rows, int cols, double actionSize, double actionGap, double actionDefaultDisplayTextFontSize) 36 | { 37 | this.actions = new HashMap<>(); 38 | this.ID = ID; 39 | this.name = name; 40 | this.rows = rows; 41 | this.cols = cols; 42 | this.actionGap = actionGap; 43 | this.actionSize = actionSize; 44 | this.actionDefaultDisplayTextFontSize = actionDefaultDisplayTextFontSize; 45 | } 46 | 47 | public ArrayList getActions() 48 | { 49 | ArrayList p = new ArrayList<>(); 50 | for(String profile : actions.keySet()) 51 | p.add(actions.get(profile)); 52 | return p; 53 | } 54 | 55 | 56 | public ClientProfile(String name, int rows, int cols, double actionSize, double actionGap, double actionDefaultDisplayTextFontSize) 57 | { 58 | this(name, UUID.randomUUID().toString(), rows, cols, actionSize, actionGap, actionDefaultDisplayTextFontSize); 59 | } 60 | 61 | public Action getActionByID(String ID) 62 | { 63 | return actions.get(ID); 64 | } 65 | 66 | public void removeActionByID(String ID) 67 | { 68 | actions.remove(ID); 69 | } 70 | 71 | 72 | public Set getActionsKeySet() { 73 | return actions.keySet(); 74 | } 75 | 76 | public synchronized void addAction(Action action) throws CloneNotSupportedException { 77 | actions.put(action.getID(), action.clone()); 78 | } 79 | 80 | public String getID() 81 | { 82 | return ID; 83 | } 84 | 85 | public String getName() 86 | { 87 | return name; 88 | } 89 | 90 | public int getRows() 91 | { 92 | return rows; 93 | } 94 | 95 | public int getCols() 96 | { 97 | return cols; 98 | } 99 | 100 | public double getActionSize() 101 | { 102 | return actionSize; 103 | } 104 | 105 | public double getActionGap() 106 | { 107 | return actionGap; 108 | } 109 | 110 | public void setRows(int rows) 111 | { 112 | this.rows = rows; 113 | } 114 | 115 | public void setCols(int cols) 116 | { 117 | this.cols = cols; 118 | } 119 | 120 | public void setID(String ID) 121 | { 122 | this.ID = ID; 123 | } 124 | 125 | public void setActionSize(double actionSize) 126 | { 127 | this.actionSize = actionSize; 128 | } 129 | 130 | public void setActionGap(double actionGap) 131 | { 132 | this.actionGap = actionGap; 133 | } 134 | 135 | public void setName(String name) 136 | { 137 | this.name = name; 138 | } 139 | 140 | public double getActionDefaultDisplayTextFontSize() 141 | { 142 | return actionDefaultDisplayTextFontSize; 143 | } 144 | 145 | public void setActionDefaultDisplayTextFontSize(double actionDefaultDisplayTextFontSize) 146 | { 147 | this.actionDefaultDisplayTextFontSize = actionDefaultDisplayTextFontSize; 148 | } 149 | 150 | public Object clone() throws CloneNotSupportedException 151 | { 152 | return super.clone(); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/client/ClientTheme.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.client; 16 | 17 | import com.stream_pi.util.version.Version; 18 | 19 | public class ClientTheme implements Cloneable 20 | { 21 | public String fullName; 22 | public String shortName; 23 | public String author; 24 | public Version version; 25 | 26 | public ClientTheme(String fullName, String shortName, 27 | String author, Version version) 28 | { 29 | this.fullName = fullName; 30 | this.shortName = shortName; 31 | this.author = author; 32 | this.version = version; 33 | } 34 | 35 | public String getFullName() 36 | { 37 | return fullName; 38 | } 39 | 40 | public String getShortName() 41 | { 42 | return shortName; 43 | } 44 | 45 | public String getAuthor() 46 | { 47 | return author; 48 | } 49 | 50 | public Version getVersion() { 51 | return version; 52 | } 53 | 54 | public Object clone() throws CloneNotSupportedException 55 | { 56 | return super.clone(); 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/combobox/IPChooserComboBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.combobox; 16 | 17 | import com.stream_pi.server.i18n.I18N; 18 | import com.stream_pi.server.window.ExceptionAndAlertHandler; 19 | import com.stream_pi.server.window.GlobalExceptionAndAlertHandler; 20 | import com.stream_pi.util.exception.SevereException; 21 | import javafx.scene.control.ComboBox; 22 | import javafx.scene.control.ListCell; 23 | import javafx.scene.control.ListView; 24 | import javafx.util.Callback; 25 | 26 | import java.net.Inet4Address; 27 | import java.net.InetAddress; 28 | import java.net.NetworkInterface; 29 | import java.net.SocketException; 30 | import java.util.Enumeration; 31 | 32 | public class IPChooserComboBox extends ComboBox 33 | { 34 | private final GlobalExceptionAndAlertHandler exceptionAndAlertHandler = GlobalExceptionAndAlertHandler.getInstance(); 35 | 36 | public IPChooserComboBox() 37 | { 38 | Callback, ListCell> callbackFactory = new Callback<>() { 39 | @Override 40 | public ListCell call(ListView str) { 41 | return new ListCell<>() { 42 | @Override 43 | protected void updateItem(String str, boolean b) 44 | { 45 | super.updateItem(str, b); 46 | 47 | if (str != null) 48 | { 49 | setText(str); 50 | } 51 | } 52 | }; 53 | } 54 | }; 55 | 56 | setCellFactory(callbackFactory); 57 | setButtonCell(callbackFactory.call(null)); 58 | } 59 | 60 | public void configureOptions() 61 | { 62 | configureOptions(null); 63 | } 64 | 65 | public void configureOptions(String ip) 66 | { 67 | try 68 | { 69 | int si = 0, ci = 0; 70 | 71 | getItems().clear(); 72 | getItems().add(I18N.getString("combobox.IPChooserComboBox.allAddresses")); 73 | Enumeration e = NetworkInterface.getNetworkInterfaces(); 74 | while(e.hasMoreElements()) 75 | { 76 | NetworkInterface n = e.nextElement(); 77 | Enumeration ee = n.getInetAddresses(); 78 | while (ee.hasMoreElements()) 79 | { 80 | InetAddress i = ee.nextElement(); 81 | if(i instanceof Inet4Address) 82 | { 83 | ci+=1; 84 | getItems().add(i.getHostAddress()); 85 | 86 | if (ip!=null && i.getHostAddress().equals(ip)) 87 | { 88 | si = ci; 89 | } 90 | } 91 | } 92 | } 93 | 94 | getSelectionModel().select(si); 95 | } 96 | catch (SocketException e) 97 | { 98 | exceptionAndAlertHandler.handleSevereException(new SevereException(I18N.getString("combobox.IPChooserComboBox.unableToRetrieveNetworkInterfaces"))); 99 | } 100 | } 101 | 102 | public String getSelectedIP() 103 | { 104 | if (getSelectionModel().getSelectedIndex() == 0) 105 | { 106 | return ""; 107 | } 108 | else 109 | { 110 | return getSelectionModel().getSelectedItem(); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/combobox/LanguageChooserComboBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.combobox; 16 | 17 | import com.stream_pi.server.i18n.I18N; 18 | import com.stream_pi.util.i18n.language.Language; 19 | import javafx.collections.FXCollections; 20 | import javafx.scene.control.ComboBox; 21 | import javafx.scene.control.ListCell; 22 | import javafx.scene.control.ListView; 23 | import javafx.util.Callback; 24 | 25 | import java.util.Locale; 26 | 27 | public class LanguageChooserComboBox extends ComboBox 28 | { 29 | public LanguageChooserComboBox() 30 | { 31 | Callback, ListCell> callbackFactory = new Callback<>() { 32 | @Override 33 | public ListCell call(ListView locale) { 34 | return new ListCell<>() { 35 | @Override 36 | protected void updateItem(Language language, boolean b) 37 | { 38 | super.updateItem(language, b); 39 | 40 | if (language != null) 41 | { 42 | setText(language.getDisplayName()); 43 | } 44 | } 45 | }; 46 | } 47 | }; 48 | 49 | setCellFactory(callbackFactory); 50 | setButtonCell(callbackFactory.call(null)); 51 | 52 | setItems(FXCollections.observableArrayList(I18N.getLanguages())); 53 | } 54 | 55 | public Locale getSelectedLocale() 56 | { 57 | return getSelectionModel().getSelectedItem().getLocale(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/config/record/ActionGridSettings.java: -------------------------------------------------------------------------------- 1 | package com.stream_pi.server.config.record; 2 | 3 | public record ActionGridSettings(double actionGridActionSize, boolean actionGridUseSameActionSizeAsProfile, double actionGridActionGap, boolean actionGridUseSameActionGapAsProfile, double actionGridActionDisplayTextFontSize, boolean actionGridUseSameActionDisplayTextFontSizeAsProfile) 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/config/record/ConnectionSettings.java: -------------------------------------------------------------------------------- 1 | package com.stream_pi.server.config.record; 2 | 3 | public record ConnectionSettings(String serverName, int port, String IP) { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/config/record/GeneralSettings.java: -------------------------------------------------------------------------------- 1 | package com.stream_pi.server.config.record; 2 | 3 | // TODO: This should be moved to Config and not only just GeneralSettings 4 | /*public record GeneralSettings(String serverName, int port, double actionGridActionDisplayTextFontSize, 5 | String pluginsPath, String themesPath, 6 | double actionGridActionSize, 7 | boolean actionGridUseSameActionSizeAsProfile, boolean actionGridUseSameActionGapAsProfile, 8 | boolean actionGridUseSameActionDisplayTextFontSizeAsProfile, 9 | double actionGridActionGap, 10 | boolean minimiseToSystemTrayOnClose, boolean showAlertsPopup, boolean startOnBoot, 11 | boolean soundOnActionClickedStatus, String soundOnActionClickedFilePath, 12 | String IP, Locale currentLanguageLocale) 13 | { 14 | 15 | }*/ 16 | 17 | public record GeneralSettings(ConnectionSettings connection, ActionGridSettings actionGrid, LocationsSettings locations, SoundOnActionClickedSettings soundOnActionClicked, OthersSettings others) 18 | { 19 | 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/config/record/LocationsSettings.java: -------------------------------------------------------------------------------- 1 | package com.stream_pi.server.config.record; 2 | 3 | public record LocationsSettings(String pluginsPath, String themesPath) { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/config/record/OthersSettings.java: -------------------------------------------------------------------------------- 1 | package com.stream_pi.server.config.record; 2 | 3 | import java.util.Locale; 4 | 5 | public record OthersSettings(Locale currentLanguageLocale, boolean minimiseToSystemTrayOnClose, boolean startOnBoot, boolean showAlertsPopup) { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/config/record/SoundOnActionClickedSettings.java: -------------------------------------------------------------------------------- 1 | package com.stream_pi.server.config.record; 2 | 3 | public record SoundOnActionClickedSettings(String soundOnActionClickedFilePath, boolean soundOnActionClickedStatus) { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/connection/ClientConnections.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.connection; 16 | 17 | 18 | import javafx.beans.property.IntegerProperty; 19 | import javafx.beans.property.SimpleIntegerProperty; 20 | 21 | import java.net.SocketAddress; 22 | import java.util.ArrayList; 23 | 24 | public class ClientConnections 25 | { 26 | private ArrayList connections; 27 | 28 | private static ClientConnections instance = null; 29 | 30 | private IntegerProperty sizeProperty; 31 | 32 | 33 | private ClientConnections() 34 | { 35 | connections = new ArrayList<>(); 36 | sizeProperty = new SimpleIntegerProperty(0); 37 | } 38 | 39 | public static synchronized ClientConnections getInstance() 40 | { 41 | if(instance == null) 42 | { 43 | instance = new ClientConnections(); 44 | } 45 | 46 | return instance; 47 | } 48 | 49 | public ArrayList getConnections() 50 | { 51 | return connections; 52 | } 53 | 54 | public void addConnection(ClientConnection connection) 55 | { 56 | sizeProperty.set(sizeProperty.get()+1); 57 | connections.add(connection); 58 | } 59 | 60 | public void removeConnection(ClientConnection clientConnection) 61 | { 62 | sizeProperty.set(sizeProperty.get()-1); 63 | connections.remove(clientConnection); 64 | } 65 | 66 | public void disconnectAll() 67 | { 68 | for(ClientConnection clientConnection : connections) 69 | { 70 | clientConnection.exit(false); 71 | } 72 | 73 | sizeProperty.set(0); 74 | connections.clear(); 75 | } 76 | 77 | public ClientConnection getClientConnectionBySocketAddress(SocketAddress socketAddress) 78 | { 79 | for(ClientConnection clientConnection : connections) 80 | { 81 | if(clientConnection.getClient().getRemoteSocketAddress().equals(socketAddress)) 82 | return clientConnection; 83 | } 84 | 85 | return null; 86 | } 87 | 88 | public IntegerProperty getSizeProperty() 89 | { 90 | return sizeProperty; 91 | } 92 | } -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/connection/MainServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.connection; 16 | 17 | import com.stream_pi.server.controller.ServerListener; 18 | import com.stream_pi.server.i18n.I18N; 19 | import com.stream_pi.server.window.ExceptionAndAlertHandler; 20 | import com.stream_pi.util.exception.MinorException; 21 | import com.stream_pi.util.exception.SevereException; 22 | import javafx.application.Platform; 23 | import javafx.beans.property.BooleanProperty; 24 | import javafx.beans.property.SimpleBooleanProperty; 25 | 26 | import java.io.IOException; 27 | import java.net.*; 28 | import java.util.Enumeration; 29 | import java.util.SimpleTimeZone; 30 | import java.util.concurrent.atomic.AtomicBoolean; 31 | import java.util.logging.Logger; 32 | 33 | public class MainServer extends Thread 34 | { 35 | private ServerListener serverListener; 36 | 37 | private Logger logger = Logger.getLogger(MainServer.class.getName()); 38 | private int port; 39 | private String ip = null; 40 | private ServerSocket serverSocket = null; 41 | 42 | private AtomicBoolean stop = new AtomicBoolean(false); 43 | 44 | private ExceptionAndAlertHandler exceptionAndAlertHandler; 45 | public MainServer(ServerListener serverListener, ExceptionAndAlertHandler exceptionAndAlertHandler) 46 | { 47 | this.exceptionAndAlertHandler = exceptionAndAlertHandler; 48 | this.serverListener = serverListener; 49 | } 50 | 51 | 52 | public void setPort(int port) 53 | { 54 | this.port = port; 55 | } 56 | 57 | public void setIP(String ip) 58 | { 59 | this.ip = ip; 60 | } 61 | 62 | @Override 63 | public synchronized void start() { 64 | stop.set(false); 65 | super.start(); 66 | } 67 | 68 | public void stopListeningForConnections() 69 | { 70 | try 71 | { 72 | logger.info("Stopping listening for connections ..."); 73 | if(serverSocket!=null) 74 | { 75 | if(!serverSocket.isClosed()) 76 | { 77 | stop.set(true); 78 | serverSocket.close(); 79 | } 80 | } 81 | } 82 | catch (IOException e) 83 | { 84 | e.printStackTrace(); 85 | } 86 | finally { 87 | logger.info("... Done!"); 88 | } 89 | } 90 | 91 | @Override 92 | public void run() 93 | { 94 | try 95 | { 96 | logger.info("Starting server on port "+port+" ..."); 97 | 98 | if (ip.isBlank()) 99 | { 100 | logger.info("No preferred IP to bind to! Binding on all IPs ..."); 101 | serverSocket = new ServerSocket(port); 102 | } 103 | else 104 | { 105 | InetAddress address = InetAddress.getByName(ip); 106 | logger.info("Binding to '"+ip+"' ..."); 107 | serverSocket = new ServerSocket(port, 0, address); 108 | } 109 | 110 | isFailedToStart.set(false); 111 | while(!stop.get()) 112 | { 113 | Socket s = serverSocket.accept(); 114 | ClientConnections.getInstance().addConnection(new ClientConnection(s, serverListener, exceptionAndAlertHandler)); 115 | 116 | logger.info("New client connected ("+s.getRemoteSocketAddress()+") !"); 117 | } 118 | } 119 | catch (SocketException e) 120 | { 121 | e.printStackTrace(); 122 | if(!e.getMessage().contains("Socket closed") && !e.getMessage().contains("Interrupted function call: accept failed")) 123 | { 124 | logger.warning("Main Server stopped accepting calls ..."); 125 | isFailedToStart.set(true); 126 | serverListener.showUserChooseIPAndPortDialog(); 127 | } 128 | } 129 | catch (IOException e) 130 | { 131 | e.printStackTrace(); 132 | exceptionAndAlertHandler.handleSevereException(new SevereException(I18N.getString("connection.MainServer.IOExceptionOccurred", e.getMessage()))); 133 | } 134 | } 135 | 136 | private BooleanProperty isFailedToStart = new SimpleBooleanProperty(false); 137 | 138 | public BooleanProperty isFailedToStart() 139 | { 140 | return isFailedToStart; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/controller/ActionDataFormats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.controller; 16 | 17 | import javafx.scene.input.DataFormat; 18 | 19 | public class ActionDataFormats 20 | { 21 | public static final DataFormat IS_NEW = new DataFormat("Is New"); 22 | public static final DataFormat ACTION_TYPE = new DataFormat("Action Type"); 23 | public static final DataFormat UNIQUE_ID = new DataFormat("Unique ID"); 24 | public static final DataFormat CLIENT_PROPERTIES = new DataFormat("Client Properties"); 25 | public static final DataFormat ICONS = new DataFormat("Icons"); 26 | public static final DataFormat CURRENT_ICON_STATE = new DataFormat("Current Icon State"); 27 | public static final DataFormat BACKGROUND_COLOUR = new DataFormat("Background Colour"); 28 | public static final DataFormat DISPLAY_TEXT_FONT_COLOUR = new DataFormat("Display Text Font Colour"); 29 | public static final DataFormat DISPLAY_TEXT = new DataFormat("Display Text"); 30 | public static final DataFormat DISPLAY_TEXT_ALIGNMENT = new DataFormat("Display Text Alignment"); 31 | public static final DataFormat DISPLAY_TEXT_SHOW = new DataFormat("Display Text Show"); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/controller/ServerExecutorService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.controller; 16 | 17 | import java.util.concurrent.ExecutorService; 18 | import java.util.concurrent.Executors; 19 | 20 | public class ServerExecutorService 21 | { 22 | private static ExecutorService executorService = null; 23 | 24 | public static ExecutorService getExecutorService() 25 | { 26 | if (executorService == null) 27 | { 28 | executorService = Executors.newCachedThreadPool(); 29 | } 30 | 31 | return executorService; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/controller/ServerListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.controller; 16 | 17 | import com.stream_pi.action_api.externalplugin.NormalAction; 18 | import com.stream_pi.action_api.externalplugin.ToggleAction; 19 | import com.stream_pi.action_api.externalplugin.inputevent.StreamPiInputEvent; 20 | import com.stream_pi.server.client.Client; 21 | import com.stream_pi.server.window.dashboard.ClientAndProfileSelectorPane; 22 | import com.stream_pi.server.window.dashboard.DashboardBase; 23 | import com.stream_pi.server.window.settings.SettingsBase; 24 | import com.stream_pi.util.exception.SevereException; 25 | import javafx.event.EventType; 26 | import javafx.scene.input.MouseEvent; 27 | import javafx.scene.input.TouchEvent; 28 | import javafx.stage.Stage; 29 | 30 | import java.net.SocketAddress; 31 | 32 | public interface ServerListener 33 | { 34 | void onInputEventInAction(Client client, String profileID, String actionID, StreamPiInputEvent streamPiInputEvent); 35 | 36 | void onSetToggleStatus(Client client, String profileID, String actionID, boolean toggleStatus); 37 | 38 | void clearTemp(); 39 | 40 | void init(); 41 | 42 | void restart(); 43 | 44 | Stage getStage(); 45 | 46 | DashboardBase getDashboardBase(); 47 | SettingsBase getSettingsBase(); 48 | 49 | void initLogger() throws SevereException; 50 | 51 | void factoryReset(); 52 | 53 | void initSoundOnActionClicked(); 54 | 55 | void showUserChooseIPAndPortDialog(); 56 | 57 | void fullExit(); 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/i18n/I18N.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.i18n; 16 | 17 | import com.stream_pi.util.exception.SevereException; 18 | import com.stream_pi.util.i18n.language.Language; 19 | 20 | import java.io.BufferedReader; 21 | import java.io.InputStreamReader; 22 | import java.nio.charset.StandardCharsets; 23 | import java.util.*; 24 | 25 | public class I18N 26 | { 27 | public static Locale BASE_LOCALE = new Locale("en"); 28 | private static ResourceBundle RESOURCE_BUNDLE; 29 | private static ResourceBundle BASE_RESOURCE_BUNDLE; 30 | 31 | public static void init(Locale locale) 32 | { 33 | RESOURCE_BUNDLE = ResourceBundle.getBundle(I18N.class.getPackageName()+".lang", locale); 34 | } 35 | 36 | public static String getString(String key, Object... args) 37 | { 38 | String result; 39 | 40 | if (RESOURCE_BUNDLE.containsKey(key)) 41 | { 42 | result = RESOURCE_BUNDLE.getString(key); 43 | } 44 | else 45 | { 46 | if (BASE_RESOURCE_BUNDLE == null) 47 | { 48 | BASE_RESOURCE_BUNDLE = ResourceBundle.getBundle(I18N.class.getPackageName()+".lang", new Locale("en")); 49 | } 50 | 51 | result = BASE_RESOURCE_BUNDLE.getString(key); 52 | } 53 | 54 | if (args.length == 0) 55 | { 56 | return result; 57 | } 58 | else 59 | { 60 | return String.format(result, args); 61 | } 62 | } 63 | 64 | private static List languages; 65 | 66 | public static void initAvailableLanguages() throws SevereException 67 | { 68 | try 69 | { 70 | languages = new ArrayList<>(); 71 | 72 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader( 73 | Objects.requireNonNull(I18N.class.getResourceAsStream("i18n.properties")), 74 | StandardCharsets.UTF_8 75 | )); 76 | 77 | while(true) 78 | { 79 | String line = bufferedReader.readLine(); 80 | 81 | if(line == null) 82 | { 83 | break; 84 | } 85 | else if (line.startsWith("#") || line.startsWith("!") || !line.contains("=")) 86 | { 87 | continue; 88 | } 89 | 90 | 91 | String[] lineParts = line.split("="); 92 | 93 | String localeStr = lineParts[0].strip(); 94 | String displayName = lineParts[1].strip(); 95 | 96 | String[] localeArr = localeStr.split("_"); 97 | 98 | Locale locale; 99 | 100 | if(localeArr.length == 1) 101 | { 102 | locale = new Locale(localeArr[0]); 103 | } 104 | else if(localeArr.length == 2) 105 | { 106 | locale = new Locale(localeArr[0], localeArr[1]); 107 | } 108 | else 109 | { 110 | locale = new Locale(localeArr[0], localeArr[1], localeArr[2]); 111 | } 112 | 113 | 114 | languages.add(new Language(locale, displayName)); 115 | } 116 | } 117 | catch (Exception e) 118 | { 119 | e.printStackTrace(); 120 | throw new SevereException("Unable to parse initialise i18n.\n"+e.getMessage()); 121 | } 122 | } 123 | 124 | public static boolean isLanguageAvailable(Locale locale) 125 | { 126 | return getLanguage(locale) != null; 127 | } 128 | 129 | public static Language getLanguage(Locale locale) 130 | { 131 | for (Language eachLanguage : languages) 132 | { 133 | if(eachLanguage.getLocale().equals(locale)) 134 | { 135 | return eachLanguage; 136 | } 137 | } 138 | 139 | return null; 140 | } 141 | 142 | public static List getLanguages() 143 | { 144 | return languages; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/info/ServerInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | /* 16 | ServerInfo.java 17 | 18 | Stores basic information about the server - name, platform type 19 | 20 | Contributors: Debayan Sutradhar (@dubbadhar) 21 | */ 22 | 23 | package com.stream_pi.server.info; 24 | 25 | import com.stream_pi.server.Main; 26 | import com.stream_pi.server.i18n.I18N; 27 | import com.stream_pi.util.platform.Platform; 28 | import com.stream_pi.util.platform.ReleaseStatus; 29 | import com.stream_pi.util.version.Version; 30 | import javafx.scene.control.Label; 31 | 32 | import java.io.*; 33 | import java.nio.charset.StandardCharsets; 34 | import java.util.Objects; 35 | import java.util.Properties; 36 | import java.util.logging.Level; 37 | import java.util.logging.Logger; 38 | 39 | public class ServerInfo 40 | { 41 | private final Version version; 42 | private final ReleaseStatus releaseStatus; 43 | private final Platform platform; 44 | private final String prePath; 45 | private final Version communicationProtocolVersion; 46 | private String buildNumber; 47 | private String license; 48 | 49 | private static ServerInfo instance = null; 50 | 51 | 52 | private ServerInfo() 53 | { 54 | version = new Version(2,0,0); 55 | communicationProtocolVersion = new Version(2,0,0); 56 | 57 | releaseStatus = ReleaseStatus.EA; 58 | prePath = System.getProperty("user.home") + File.separator + "Stream-Pi" + File.separator + "Server" + File.separator; 59 | 60 | String osName = System.getProperty("os.name").toLowerCase(); 61 | 62 | if(osName.contains("windows")) 63 | { 64 | platform = Platform.WINDOWS; 65 | } 66 | else if (osName.contains("linux")) 67 | { 68 | platform = Platform.LINUX; 69 | } 70 | else if (osName.contains("mac")) 71 | { 72 | platform = Platform.MAC; 73 | } 74 | else 75 | { 76 | platform = Platform.UNKNOWN; 77 | } 78 | 79 | try 80 | { 81 | InputStream inputStream = ServerInfo.class.getResourceAsStream("build.properties"); 82 | if (inputStream != null) 83 | { 84 | Properties properties = new Properties(); 85 | properties.load(inputStream); 86 | inputStream.close(); 87 | 88 | buildNumber = properties.getProperty("build.number"); 89 | } 90 | } 91 | catch (IOException e) 92 | { 93 | e.printStackTrace(); 94 | Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Unable to fetch build.properties!", e); 95 | } 96 | 97 | try 98 | { 99 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader( 100 | Objects.requireNonNull(ServerInfo.class.getResourceAsStream("LICENSE")), 101 | StandardCharsets.UTF_8 102 | )); 103 | 104 | StringBuilder licenseTxt = new StringBuilder(); 105 | while(true) 106 | { 107 | String line = bufferedReader.readLine(); 108 | 109 | if(line == null) 110 | { 111 | break; 112 | } 113 | 114 | licenseTxt.append(line).append("\n"); 115 | } 116 | 117 | license = licenseTxt.toString(); 118 | } 119 | catch (IOException e) 120 | { 121 | e.printStackTrace(); 122 | Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Unable to fetch LICENSE!", e); 123 | } 124 | 125 | } 126 | 127 | 128 | public String getPrePath() 129 | { 130 | return prePath; 131 | } 132 | 133 | public static synchronized ServerInfo getInstance() 134 | { 135 | if(instance == null) 136 | { 137 | instance = new ServerInfo(); 138 | } 139 | 140 | return instance; 141 | } 142 | 143 | 144 | public Platform getPlatform() 145 | { 146 | return platform; 147 | } 148 | 149 | public Version getVersion() { 150 | return version; 151 | } 152 | 153 | public ReleaseStatus getReleaseStatus() 154 | { 155 | return releaseStatus; 156 | } 157 | 158 | public Version getCommunicationProtocolVersion() 159 | { 160 | return communicationProtocolVersion; 161 | } 162 | 163 | public String getBuildNumber() 164 | { 165 | return buildNumber; 166 | } 167 | 168 | public String getLicense() 169 | { 170 | return license; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/info/StartupFlags.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.info; 16 | 17 | import javafx.application.Application; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | public class StartupFlags 23 | { 24 | public static String RUNNER_FILE_NAME = null; 25 | public static boolean START_MINIMISED = false; 26 | public static boolean APPEND_PATH_BEFORE_RUNNER_FILE_TO_OVERCOME_JPACKAGE_LIMITATION = false; 27 | public static boolean ALLOW_ROOT = false; 28 | 29 | public static final String RUNNER_FILE_NAME_ARG = "Stream-Pi.startupRunnerFileName"; 30 | public static final String START_MINIMISED_ARG = "Stream-Pi.startMinimised"; 31 | public static final String APPEND_PATH_BEFORE_RUNNER_FILE_TO_OVERCOME_JPACKAGE_LIMITATION_ARG = "Stream-Pi.appendPathBeforeRunnerFileToOvercomeJPackageLimitation"; 32 | public static final String ALLOW_ROOT_ARG = "Stream-Pi.allowRoot"; 33 | 34 | public static void init(Application.Parameters parameters) 35 | { 36 | for (String arg : parameters.getRaw()) 37 | { 38 | String[] arr = arg.split("="); 39 | 40 | if (arr.length == 2) 41 | { 42 | String val = arr[1].strip(); 43 | switch(arr[0]) 44 | { 45 | case RUNNER_FILE_NAME_ARG: RUNNER_FILE_NAME = val; break; 46 | case START_MINIMISED_ARG: START_MINIMISED = val.equals("true"); break; 47 | case APPEND_PATH_BEFORE_RUNNER_FILE_TO_OVERCOME_JPACKAGE_LIMITATION_ARG: APPEND_PATH_BEFORE_RUNNER_FILE_TO_OVERCOME_JPACKAGE_LIMITATION = val.equals("true"); break; 48 | case ALLOW_ROOT_ARG: ALLOW_ROOT = val.equals("true"); break; 49 | } 50 | } 51 | } 52 | } 53 | 54 | public static String[] generateRuntimeArgumentsForStartOnBoot() 55 | { 56 | List arrayList = new ArrayList<>(); 57 | 58 | if (RUNNER_FILE_NAME!=null) 59 | { 60 | arrayList.add(RUNNER_FILE_NAME_ARG+"='"+RUNNER_FILE_NAME+"'"); 61 | } 62 | 63 | arrayList.add(START_MINIMISED_ARG+"=true"); 64 | arrayList.add(APPEND_PATH_BEFORE_RUNNER_FILE_TO_OVERCOME_JPACKAGE_LIMITATION_ARG+"="+APPEND_PATH_BEFORE_RUNNER_FILE_TO_OVERCOME_JPACKAGE_LIMITATION); 65 | arrayList.add(ALLOW_ROOT_ARG+"="+ALLOW_ROOT); 66 | 67 | return arrayList.toArray(new String[0]); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/ExceptionAndAlertHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window; 16 | 17 | import com.stream_pi.util.alert.StreamPiAlert; 18 | import com.stream_pi.util.exception.MinorException; 19 | import com.stream_pi.util.exception.SevereException; 20 | 21 | //TODO: Deprecated. To be replaced with GlobalExceptionAndAlertHandler 22 | 23 | public interface ExceptionAndAlertHandler 24 | { 25 | StreamPiAlert handleMinorException(MinorException e); 26 | StreamPiAlert handleMinorException(String message, MinorException e); 27 | StreamPiAlert handleSevereException(SevereException e); 28 | StreamPiAlert handleSevereException(String message, SevereException e); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/GlobalExceptionAndAlertHandler.java: -------------------------------------------------------------------------------- 1 | package com.stream_pi.server.window; 2 | 3 | import com.stream_pi.server.controller.ServerListener; 4 | import com.stream_pi.server.i18n.I18N; 5 | import com.stream_pi.server.config.Config; 6 | import com.stream_pi.util.alert.StreamPiAlert; 7 | import com.stream_pi.util.alert.StreamPiAlertButton; 8 | import com.stream_pi.util.alert.StreamPiAlertListener; 9 | import com.stream_pi.util.alert.StreamPiAlertType; 10 | import com.stream_pi.util.exception.MinorException; 11 | import com.stream_pi.util.exception.SevereException; 12 | 13 | import java.util.logging.Level; 14 | import java.util.logging.Logger; 15 | 16 | public class GlobalExceptionAndAlertHandler 17 | { 18 | private static GlobalExceptionAndAlertHandler instance = null; 19 | 20 | public static GlobalExceptionAndAlertHandler getInstance() { 21 | return instance; 22 | } 23 | 24 | private final ServerListener serverListener; 25 | public GlobalExceptionAndAlertHandler(ServerListener serverListener) 26 | { 27 | this.serverListener = serverListener; 28 | } 29 | 30 | public static void nullify() 31 | { 32 | instance = null; 33 | } 34 | 35 | public static void initialise(ServerListener serverListener) throws SevereException 36 | { 37 | if(instance != null) 38 | { 39 | Logger.getLogger(Config.class.getName()).warning("ExceptionAndAlertHandler was already loaded! Re-loading ..."); 40 | } 41 | 42 | instance = new GlobalExceptionAndAlertHandler(serverListener); 43 | } 44 | 45 | public StreamPiAlert handleMinorException(MinorException e) 46 | { 47 | return handleMinorException(e.getMessage(), e); 48 | } 49 | 50 | public StreamPiAlert handleMinorException(String message, MinorException e) 51 | { 52 | Logger.getLogger(GlobalExceptionAndAlertHandler.class.getName()).log(Level.SEVERE, message, e); 53 | e.printStackTrace(); 54 | StreamPiAlert alert = new StreamPiAlert(e.getTitle(), message, StreamPiAlertType.WARNING); 55 | alert.show(); 56 | return alert; 57 | } 58 | 59 | public StreamPiAlert handleSevereException(SevereException e) 60 | { 61 | return handleSevereException(e.getMessage(), e); 62 | } 63 | 64 | public StreamPiAlert handleSevereException(String message, SevereException e) 65 | { 66 | Logger.getLogger(GlobalExceptionAndAlertHandler.class.getName()).log(Level.SEVERE, message, e); 67 | e.printStackTrace(); 68 | 69 | StreamPiAlert alert = new StreamPiAlert(e.getTitle(), message +"\n" + I18N.getString("controller.Controller.willNowExit"), StreamPiAlertType.ERROR); 70 | 71 | alert.setOnClicked(new StreamPiAlertListener() 72 | { 73 | @Override 74 | public void onClick(StreamPiAlertButton s) 75 | { 76 | serverListener.fullExit(); 77 | } 78 | }); 79 | 80 | alert.show(); 81 | 82 | return alert; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/dashboard/ClientAndProfileSelectorPane.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.dashboard; 16 | 17 | import com.stream_pi.server.client.Client; 18 | import com.stream_pi.server.client.ClientProfile; 19 | import com.stream_pi.server.connection.ClientConnection; 20 | import com.stream_pi.server.connection.ClientConnections; 21 | import com.stream_pi.server.i18n.I18N; 22 | import javafx.collections.FXCollections; 23 | import javafx.geometry.Insets; 24 | import javafx.scene.CacheHint; 25 | import javafx.scene.control.*; 26 | import javafx.scene.layout.HBox; 27 | import javafx.scene.layout.Priority; 28 | import javafx.scene.layout.VBox; 29 | import javafx.util.Callback; 30 | 31 | public class ClientAndProfileSelectorPane extends HBox { 32 | 33 | private DashboardInterface dashboard; 34 | 35 | public ClientAndProfileSelectorPane(DashboardInterface dashboard) 36 | { 37 | this.dashboard = dashboard; 38 | 39 | VBox.setVgrow(this, Priority.NEVER); 40 | getStyleClass().add("client_and_profile_selector_pane"); 41 | setPadding(new Insets(10)); 42 | setMinHeight(90); 43 | setMaxHeight(90); 44 | 45 | initUI(); 46 | loadData(); 47 | 48 | setCache(true); 49 | setCacheHint(CacheHint.SPEED); 50 | } 51 | 52 | private ComboBox clientsComboBox; 53 | private Label noClientsConnectedLabel; 54 | private ComboBox clientProfilesComboBox; 55 | 56 | 57 | private ClientProfile currentSelectedClientProfile = null; 58 | 59 | public ClientProfile getCurrentSelectedClientProfile() 60 | { 61 | return currentSelectedClientProfile; 62 | } 63 | 64 | private ClientConnection currentSelectedClientConnection = null; 65 | 66 | public ClientConnection getCurrentSelectedClientConnection() 67 | { 68 | return currentSelectedClientConnection; 69 | } 70 | 71 | public void initUI() 72 | { 73 | noClientsConnectedLabel = new Label(I18N.getString("noClientsConnected")); 74 | noClientsConnectedLabel.getStyleClass().add("client_and_profile_selector_pane_no_clients_connected_label"); 75 | noClientsConnectedLabel.managedProperty().bind(noClientsConnectedLabel.visibleProperty()); 76 | 77 | clientsComboBox = new ComboBox<>(); 78 | clientsComboBox.getStyleClass().add("client_and_profile_selector_pane_client_selector_combo_box"); 79 | clientsComboBox.setPromptText(I18N.getString("window.dashboard.ClientAndProfileSelectorPane.chooseClient")); 80 | 81 | clientsComboBox.valueProperty().addListener((observableValue, oldVal, newVal) -> { 82 | if(oldVal!=newVal && newVal!=null) 83 | { 84 | currentSelectedClientConnection = newVal; 85 | dashboard.newSelectedClientConnection(newVal); 86 | clientProfilesComboBox.setItems(FXCollections.observableArrayList(newVal.getClient().getAllClientProfiles())); 87 | clientProfilesComboBox.setVisible(true); 88 | } 89 | }); 90 | 91 | clientsComboBox.managedProperty().bind(clientsComboBox.visibleProperty()); 92 | 93 | 94 | Callback, ListCell> clientsComboBoxFactory = new Callback<>() { 95 | @Override 96 | public ListCell call(ListView clientConnectionListView) { 97 | 98 | return new ListCell<>() { 99 | @Override 100 | protected void updateItem(ClientConnection clientConnection, boolean b) { 101 | super.updateItem(clientConnection, b); 102 | 103 | if(clientConnection == null) 104 | { 105 | setText(I18N.getString("window.dashboard.ClientAndProfileSelectorPane.chooseClient")); 106 | } 107 | else 108 | { 109 | Client client = clientConnection.getClient(); 110 | setText(client.getName()); 111 | } 112 | } 113 | }; 114 | } 115 | }; 116 | clientsComboBox.setCellFactory(clientsComboBoxFactory); 117 | clientsComboBox.setButtonCell(clientsComboBoxFactory.call(null)); 118 | 119 | 120 | 121 | clientProfilesComboBox = new ComboBox<>(); 122 | clientProfilesComboBox.getStyleClass().add("client_and_profile_selector_pane_profile_selector_combo_box"); 123 | clientProfilesComboBox.setPromptText(I18N.getString("window.dashboard.ClientAndProfileSelectorPane.chooseProfile")); 124 | clientProfilesComboBox.valueProperty().addListener((observableValue, oldVal, newVal) -> { 125 | if(oldVal!=newVal && newVal!=null) 126 | { 127 | currentSelectedClientProfile = newVal; 128 | dashboard.newSelectedClientProfile(newVal); 129 | } 130 | }); 131 | 132 | 133 | clientProfilesComboBox.managedProperty().bind(clientProfilesComboBox.visibleProperty()); 134 | Callback, ListCell> clientProfilesComboBoxFactory = new Callback<>() { 135 | @Override 136 | public ListCell call(ListView clientProfileListView) { 137 | return new ListCell<>() 138 | { 139 | @Override 140 | protected void updateItem(ClientProfile profile, boolean b) { 141 | super.updateItem(profile, b); 142 | 143 | if(profile == null) 144 | { 145 | setText(I18N.getString("window.dashboard.ClientAndProfileSelectorPane.chooseProfile")); 146 | } 147 | else 148 | { 149 | setText(profile.getName()); 150 | } 151 | } 152 | }; 153 | } 154 | }; 155 | clientProfilesComboBox.setCellFactory(clientProfilesComboBoxFactory); 156 | clientProfilesComboBox.setButtonCell(clientProfilesComboBoxFactory.call(null)); 157 | 158 | VBox stack = new VBox(noClientsConnectedLabel, clientsComboBox, clientProfilesComboBox); 159 | stack.getStyleClass().add("client_and_profile_selector_pane_stack"); 160 | 161 | getChildren().addAll(stack); 162 | 163 | } 164 | 165 | 166 | private void loadData() 167 | { 168 | clientsComboBox.getSelectionModel().clearSelection(); 169 | clientProfilesComboBox.getSelectionModel().clearSelection(); 170 | 171 | if(ClientConnections.getInstance().getConnections().size() == 0) 172 | { 173 | noClientsConnectedLabel.setVisible(true); 174 | 175 | clientsComboBox.setVisible(false); 176 | 177 | clientProfilesComboBox.setVisible(false); 178 | 179 | 180 | dashboard.newSelectedClientConnection(null); 181 | 182 | } 183 | else 184 | { 185 | noClientsConnectedLabel.setVisible(false); 186 | 187 | clientsComboBox.setVisible(true); 188 | clientProfilesComboBox.setVisible(false); 189 | 190 | clientsComboBox.setItems(FXCollections.observableArrayList(ClientConnections.getInstance().getConnections())); 191 | } 192 | } 193 | 194 | public void refresh() 195 | { 196 | loadData(); 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/dashboard/DashboardBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.dashboard; 16 | 17 | import java.util.logging.Logger; 18 | 19 | import com.stream_pi.server.client.ClientProfile; 20 | import com.stream_pi.server.connection.ClientConnection; 21 | import com.stream_pi.server.window.windowmenubar.WindowMenuBar; 22 | import com.stream_pi.server.window.dashboard.actiongridpane.ActionGridPane; 23 | import com.stream_pi.server.window.dashboard.actiondetailspane.ActionDetailsPane; 24 | import com.stream_pi.server.window.ExceptionAndAlertHandler; 25 | import com.stream_pi.util.exception.SevereException; 26 | import javafx.application.HostServices; 27 | import javafx.geometry.Orientation; 28 | import javafx.scene.control.SplitPane; 29 | import javafx.scene.layout.Priority; 30 | import javafx.scene.layout.VBox; 31 | 32 | public class DashboardBase extends VBox implements DashboardInterface 33 | { 34 | 35 | private final SplitPane leftSplitPane; 36 | 37 | private Logger logger; 38 | 39 | public ClientProfile currentClientProfile; 40 | 41 | private ExceptionAndAlertHandler exceptionAndAlertHandler; 42 | 43 | private SplitPane splitPane; 44 | private WindowMenuBar windowMenuBar; 45 | 46 | public DashboardBase(ExceptionAndAlertHandler exceptionAndAlertHandler, HostServices hostServices) 47 | { 48 | this.exceptionAndAlertHandler = exceptionAndAlertHandler; 49 | logger = Logger.getLogger(DashboardBase.class.getName()); 50 | 51 | getStyleClass().add("dashboard_base"); 52 | 53 | windowMenuBar = new WindowMenuBar(); 54 | 55 | splitPane = new SplitPane(); 56 | 57 | leftSplitPane = new SplitPane(); 58 | leftSplitPane.getStyleClass().add("dashboard_left_split_pane"); 59 | leftSplitPane.setOrientation(Orientation.VERTICAL); 60 | 61 | splitPane.getStyleClass().add("dashboard_right_split_pane"); 62 | VBox.setVgrow(splitPane, Priority.ALWAYS); 63 | 64 | splitPane.getItems().add(leftSplitPane); 65 | 66 | setPluginsPane(new PluginsPane(hostServices)); 67 | 68 | setClientDetailsPane(new ClientAndProfileSelectorPane(this)); 69 | 70 | setActionGridPane(new ActionGridPane(exceptionAndAlertHandler)); 71 | 72 | setActionDetailsPane(new ActionDetailsPane(exceptionAndAlertHandler, hostServices, getActionGridPane())); 73 | 74 | getActionGridPane().setActionDetailsPaneListener(getActionDetailsPane()); 75 | 76 | getChildren().addAll( 77 | windowMenuBar, 78 | splitPane 79 | ); 80 | } 81 | 82 | public SplitPane getSplitPane() 83 | { 84 | return splitPane; 85 | } 86 | 87 | public WindowMenuBar getWindowMenuBar() 88 | { 89 | return windowMenuBar; 90 | } 91 | 92 | private PluginsPane pluginsPane; 93 | private void setPluginsPane(PluginsPane pluginsPane) 94 | { 95 | this.pluginsPane = pluginsPane; 96 | splitPane.getItems().add(this.pluginsPane); 97 | } 98 | public PluginsPane getPluginsPane() 99 | { 100 | return pluginsPane; 101 | } 102 | 103 | private ClientAndProfileSelectorPane clientAndProfileSelectorPane; 104 | private void setClientDetailsPane(ClientAndProfileSelectorPane clientAndProfileSelectorPane) 105 | { 106 | this.clientAndProfileSelectorPane = clientAndProfileSelectorPane; 107 | leftSplitPane.getItems().add(this.clientAndProfileSelectorPane); 108 | } 109 | 110 | public ClientAndProfileSelectorPane getClientAndProfileSelectorPane() 111 | { 112 | return clientAndProfileSelectorPane; 113 | } 114 | 115 | private ActionGridPane actionGridPane; 116 | private void setActionGridPane(ActionGridPane actionGridPane) 117 | { 118 | this.actionGridPane = actionGridPane; 119 | leftSplitPane.getItems().add(this.actionGridPane); 120 | } 121 | public ActionGridPane getActionGridPane() 122 | { 123 | return actionGridPane; 124 | } 125 | 126 | private ActionDetailsPane actionDetailsPane; 127 | private void setActionDetailsPane(ActionDetailsPane actionDetailsPane) 128 | { 129 | this.actionDetailsPane = actionDetailsPane; 130 | leftSplitPane.getItems().add(this.actionDetailsPane); 131 | } 132 | public ActionDetailsPane getActionDetailsPane() 133 | { 134 | return actionDetailsPane; 135 | } 136 | 137 | public void newSelectedClientConnection(ClientConnection clientConnection) 138 | { 139 | if(clientConnection == null) 140 | { 141 | logger.info("Remove action grid"); 142 | } 143 | else 144 | { 145 | getActionDetailsPane().setClientConnection(clientConnection); 146 | getActionGridPane().setClientConnection(clientConnection); 147 | } 148 | } 149 | 150 | public void newSelectedClientProfile(ClientProfile clientProfile) 151 | { 152 | this.currentClientProfile = clientProfile; 153 | 154 | getActionDetailsPane().setClientProfile(clientProfile); 155 | 156 | drawProfile(this.currentClientProfile); 157 | } 158 | 159 | public void reDrawProfile() 160 | { 161 | drawProfile(getActionGridPane().getCurrentProfile()); 162 | } 163 | 164 | public void drawProfile(ClientProfile clientProfile) 165 | { 166 | logger.info("Drawing ..."); 167 | 168 | getActionGridPane().setClientProfile(clientProfile); 169 | 170 | try 171 | { 172 | getActionGridPane().setFreshRender(true); 173 | getActionGridPane().renderGrid(); 174 | getActionGridPane().renderActions(); 175 | } 176 | catch (SevereException e) 177 | { 178 | exceptionAndAlertHandler.handleSevereException(e); 179 | } 180 | } 181 | 182 | public SplitPane getLeftSplitPane() 183 | { 184 | return leftSplitPane; 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/dashboard/DashboardInterface.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.dashboard; 16 | 17 | import com.stream_pi.server.client.ClientProfile; 18 | import com.stream_pi.server.connection.ClientConnection; 19 | 20 | public interface DashboardInterface 21 | { 22 | void newSelectedClientConnection(ClientConnection clientConnection); 23 | void newSelectedClientProfile(ClientProfile clientProfile); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/dashboard/PluginsPane.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.dashboard; 16 | import com.stream_pi.action_api.action.ActionType; 17 | import com.stream_pi.action_api.externalplugin.ExternalPlugin; 18 | import com.stream_pi.action_api.otheractions.CombineAction; 19 | import com.stream_pi.action_api.otheractions.FolderAction; 20 | import com.stream_pi.server.action.ExternalPlugins; 21 | 22 | import com.stream_pi.server.controller.ActionDataFormats; 23 | import com.stream_pi.server.i18n.I18N; 24 | import com.stream_pi.util.uihelper.SpaceFiller; 25 | import javafx.application.HostServices; 26 | import javafx.geometry.Insets; 27 | import javafx.geometry.Pos; 28 | import javafx.scene.CacheHint; 29 | import javafx.scene.Node; 30 | import javafx.scene.control.*; 31 | import javafx.scene.image.ImageView; 32 | import javafx.scene.input.ClipboardContent; 33 | import javafx.scene.input.Dragboard; 34 | import javafx.scene.input.TransferMode; 35 | import javafx.scene.layout.*; 36 | import org.kordamp.ikonli.javafx.FontIcon; 37 | 38 | import java.util.ArrayList; 39 | import java.util.HashMap; 40 | 41 | public class PluginsPane extends VBox 42 | { 43 | 44 | public PluginsPane(HostServices hostServices) 45 | { 46 | setMinWidth(250); 47 | setMaxWidth(350); 48 | getStyleClass().add("plugins_pane"); 49 | 50 | this.hostServices = hostServices; 51 | 52 | initUI(); 53 | } 54 | 55 | private Accordion pluginsAccordion; 56 | 57 | public void initUI() 58 | { 59 | pluginsAccordion = new Accordion(); 60 | pluginsAccordion.getStyleClass().add("plugins_pane_accordion"); 61 | pluginsAccordion.setCache(true); 62 | pluginsAccordion.setCacheHint(CacheHint.SPEED); 63 | 64 | Label pluginsLabel = new Label(I18N.getString("window.dashboard.PluginsPane.plugins")); 65 | pluginsLabel.getStyleClass().add("plugins_pane_top_label"); 66 | 67 | ScrollPane scrollPane = new ScrollPane(pluginsAccordion); 68 | scrollPane.getStyleClass().add("plugins_pane_accordion_scroll_pane"); 69 | scrollPane.setFitToWidth(true); 70 | 71 | VBox.setVgrow(scrollPane, Priority.ALWAYS); 72 | 73 | getChildren().addAll(pluginsLabel, scrollPane); 74 | } 75 | 76 | public void clearData() 77 | { 78 | pluginsAccordion.getPanes().clear(); 79 | } 80 | 81 | public void loadData() 82 | { 83 | HashMap> sortedPlugins = ExternalPlugins.getInstance().getSortedPlugins(); 84 | 85 | for(String eachCategory : sortedPlugins.keySet()) 86 | { 87 | VBox vBox = new VBox(); 88 | vBox.getStyleClass().add("plugins_pane_each_plugin_box_parent"); 89 | 90 | TitledPane pane = new TitledPane(eachCategory, vBox); 91 | pane.getStyleClass().add("plugins_pane_each_plugin_category_titled_pane"); 92 | for(ExternalPlugin eachAction : sortedPlugins.get(eachCategory)) 93 | { 94 | if(!eachAction.isVisibleInPluginsPane()) 95 | continue; 96 | 97 | Button eachNormalActionPluginButton = new Button(); 98 | eachNormalActionPluginButton.getStyleClass().add("plugins_pane_each_plugin_button"); 99 | HBox.setHgrow(eachNormalActionPluginButton, Priority.ALWAYS); 100 | eachNormalActionPluginButton.setMaxWidth(Double.MAX_VALUE); 101 | eachNormalActionPluginButton.setAlignment(Pos.CENTER_LEFT); 102 | 103 | Node graphic = eachAction.getServerButtonGraphic(); 104 | 105 | if(graphic == null) 106 | { 107 | if(eachAction.getActionType() == ActionType.TOGGLE) 108 | { 109 | FontIcon toggleIcon = new FontIcon("fas-toggle-on"); 110 | toggleIcon.getStyleClass().add("plugins_pane_each_plugin_button_icon_toggle"); 111 | eachNormalActionPluginButton.setGraphic(toggleIcon); 112 | } 113 | else if(eachAction.getActionType() == ActionType.GAUGE) 114 | { 115 | FontIcon dynamicIcon = new FontIcon("fas-magic"); 116 | dynamicIcon.getStyleClass().add("plugins_pane_each_plugin_button_icon_dynamic"); 117 | eachNormalActionPluginButton.setGraphic(dynamicIcon); 118 | } 119 | else if(eachAction.getActionType() == ActionType.NORMAL) 120 | { 121 | FontIcon normalIcon = new FontIcon("fas-cogs"); 122 | normalIcon.getStyleClass().add("plugins_pane_each_plugin_button_icon_normal"); 123 | eachNormalActionPluginButton.setGraphic(normalIcon); 124 | } 125 | } 126 | else 127 | { 128 | if(graphic instanceof FontIcon) 129 | { 130 | FontIcon fi = (FontIcon) graphic; 131 | fi.getStyleClass().add("plugins_pane_each_plugin_button_icon"); 132 | eachNormalActionPluginButton.setGraphic(fi); 133 | } 134 | else if(graphic instanceof ImageView) 135 | { 136 | ImageView iv = (ImageView) graphic; 137 | iv.getStyleClass().add("plugins_pane_each_plugin_button_imageview"); 138 | iv.setPreserveRatio(false); 139 | eachNormalActionPluginButton.setGraphic(iv); 140 | } 141 | } 142 | eachNormalActionPluginButton.setText(eachAction.getName()); 143 | 144 | 145 | eachNormalActionPluginButton.setOnDragDetected(mouseEvent -> { 146 | Dragboard db = eachNormalActionPluginButton.startDragAndDrop(TransferMode.ANY); 147 | 148 | ClipboardContent content = new ClipboardContent(); 149 | 150 | content.put(ActionDataFormats.ACTION_TYPE, eachAction.getActionType()); 151 | content.put(ActionDataFormats.UNIQUE_ID, eachAction.getUniqueID()); 152 | content.put(ActionDataFormats.IS_NEW, true); 153 | 154 | db.setContent(content); 155 | 156 | mouseEvent.consume(); 157 | }); 158 | 159 | 160 | 161 | HBox hBox = new HBox(eachNormalActionPluginButton); 162 | hBox.getStyleClass().add("plugins_pane_each_plugin_box"); 163 | hBox.setAlignment(Pos.TOP_LEFT); 164 | 165 | HBox.setHgrow(eachNormalActionPluginButton, Priority.ALWAYS); 166 | 167 | if(eachAction.getHelpLink() != null) { 168 | Button helpButton = new Button(); 169 | helpButton.getStyleClass().add("plugins_pane_each_plugin_button_help_icon"); 170 | FontIcon questionIcon = new FontIcon("fas-question"); 171 | questionIcon.getStyleClass().add("plugins_pane_each_plugin_button_help_button_icon"); 172 | helpButton.setGraphic(questionIcon); 173 | helpButton.setOnAction(event -> hostServices.showDocument(eachAction.getHelpLink())); 174 | 175 | hBox.getChildren().add(helpButton); 176 | } 177 | 178 | 179 | vBox.getChildren().add(hBox); 180 | } 181 | 182 | if(vBox.getChildren().size() > 0) 183 | pluginsAccordion.getPanes().add(pane); 184 | } 185 | } 186 | 187 | 188 | private HostServices hostServices; 189 | 190 | public void loadOtherActions() 191 | { 192 | VBox vBox = new VBox(); 193 | vBox.getStyleClass().add("plugins_pane_each_plugin_box_parent"); 194 | 195 | Button folderActionButton = new Button(FolderAction.getUIName()); 196 | folderActionButton.getStyleClass().add("plugins_pane_each_plugin_button"); 197 | folderActionButton.setMaxWidth(Double.MAX_VALUE); 198 | folderActionButton.setAlignment(Pos.CENTER_LEFT); 199 | FontIcon folder = new FontIcon("fas-folder"); 200 | folderActionButton.setGraphic(folder); 201 | 202 | folderActionButton.setOnDragDetected(mouseEvent -> { 203 | Dragboard db = folderActionButton.startDragAndDrop(TransferMode.ANY); 204 | 205 | ClipboardContent content = new ClipboardContent(); 206 | 207 | content.put(ActionDataFormats.ACTION_TYPE, ActionType.FOLDER); 208 | 209 | db.setContent(content); 210 | 211 | mouseEvent.consume(); 212 | }); 213 | 214 | 215 | 216 | 217 | Button combineActionButton = new Button(CombineAction.getUIName()); 218 | combineActionButton.getStyleClass().add("plugins_pane_each_plugin_button"); 219 | combineActionButton.setMaxWidth(Double.MAX_VALUE); 220 | combineActionButton.setAlignment(Pos.CENTER_LEFT); 221 | FontIcon list = new FontIcon("fas-list"); 222 | combineActionButton.setGraphic(list); 223 | 224 | combineActionButton.setOnDragDetected(mouseEvent -> { 225 | Dragboard db = combineActionButton.startDragAndDrop(TransferMode.ANY); 226 | 227 | ClipboardContent content = new ClipboardContent(); 228 | 229 | content.put(ActionDataFormats.ACTION_TYPE, ActionType.COMBINE); 230 | 231 | db.setContent(content); 232 | 233 | mouseEvent.consume(); 234 | }); 235 | 236 | HBox.setHgrow(folderActionButton, Priority.ALWAYS); 237 | HBox h1 = new HBox(folderActionButton); 238 | h1.getStyleClass().add("plugins_pane_each_plugin_box"); 239 | 240 | HBox.setHgrow(combineActionButton, Priority.ALWAYS); 241 | HBox h2 = new HBox(combineActionButton); 242 | h2.getStyleClass().add("plugins_pane_each_plugin_box"); 243 | 244 | vBox.getChildren().addAll(h1, h2); 245 | 246 | TitledPane pane = new TitledPane(I18N.getString("window.dashboard.PluginsPane.othersHeading"), vBox); 247 | pane.getStyleClass().add("plugins_pane_each_plugin_category_titled_pane"); 248 | 249 | pluginsAccordion.getPanes().add(pane); 250 | } 251 | 252 | } 253 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/dashboard/actiondetailspane/ActionDetailsPaneListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.dashboard.actiondetailspane; 16 | 17 | import com.stream_pi.action_api.action.Action; 18 | import com.stream_pi.server.window.dashboard.actiongridpane.ActionBox; 19 | import com.stream_pi.util.exception.MinorException; 20 | import javafx.stage.Window; 21 | 22 | public interface ActionDetailsPaneListener 23 | { 24 | void onActionClicked(Action action, ActionBox actionBox) throws MinorException; 25 | 26 | void saveAction(boolean runAsync, boolean runOnActionSavedFromServer); 27 | 28 | void saveAction(Action action, boolean runAsync, boolean runOnActionSavedFromServer); 29 | 30 | void clear(); 31 | 32 | void setSendIcon(boolean sendIcon); 33 | 34 | void setAction(Action action); 35 | 36 | void onOpenFolderButtonClicked(); 37 | 38 | Window getCurrentWindow(); 39 | 40 | void refresh(); 41 | 42 | void onDeleteButtonClicked(); 43 | 44 | void renderAction(Action action) throws MinorException; 45 | 46 | void clearActionBox(int col, int row, int colSpan, int rowSpan); 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/dashboard/actiondetailspane/CombineActionPropertiesPane.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.dashboard.actiondetailspane; 16 | 17 | import com.stream_pi.action_api.action.Action; 18 | import com.stream_pi.action_api.actionproperty.property.Property; 19 | import com.stream_pi.action_api.otheractions.CombineAction; 20 | import com.stream_pi.server.client.ClientProfile; 21 | import com.stream_pi.util.exception.MinorException; 22 | import javafx.event.ActionEvent; 23 | import javafx.geometry.Insets; 24 | import javafx.scene.Node; 25 | import javafx.scene.control.Button; 26 | import javafx.scene.control.Label; 27 | import javafx.scene.layout.HBox; 28 | import javafx.scene.layout.Priority; 29 | import javafx.scene.layout.Region; 30 | import javafx.scene.layout.VBox; 31 | import org.kordamp.ikonli.javafx.FontIcon; 32 | 33 | public class CombineActionPropertiesPane extends VBox { 34 | private CombineAction combineAction; 35 | private ClientProfile clientProfile; 36 | private ActionDetailsPane actionDetailsPane; 37 | 38 | public CombineAction getCombineAction() { 39 | return combineAction; 40 | } 41 | 42 | public CombineActionPropertiesPane(CombineAction combineAction, ClientProfile clientProfile, ActionDetailsPane actionDetailsPane) throws MinorException { 43 | this.combineAction = combineAction; 44 | this.clientProfile = clientProfile; 45 | this.actionDetailsPane = actionDetailsPane; 46 | 47 | setSpacing(10.0); 48 | 49 | setPadding(new Insets(0,0,10,0)); 50 | 51 | renderProps(); 52 | } 53 | 54 | 55 | public void renderProps() throws MinorException 56 | { 57 | getChildren().clear(); 58 | 59 | int i = 0; 60 | 61 | for(String actionID : combineAction.getChildrenIDSequential()) 62 | { 63 | Action action = clientProfile.getActionByID(actionID); 64 | 65 | Button settingsButton = new Button(); 66 | 67 | FontIcon settingsFontIcon = new FontIcon("fas-cog"); 68 | settingsButton.setGraphic(settingsFontIcon); 69 | 70 | 71 | settingsButton.setOnAction(event -> onSettingsButtonClicked(action)); 72 | 73 | Button upButton = new Button(); 74 | FontIcon upButtonFontIcon = new FontIcon("fas-chevron-up"); 75 | upButton.setGraphic(upButtonFontIcon); 76 | 77 | 78 | Button downButton = new Button(); 79 | FontIcon downButtonFontIcon = new FontIcon("fas-chevron-down"); 80 | downButton.setGraphic(downButtonFontIcon); 81 | 82 | Label displayTextLabel = new Label(action.getDisplayText()); 83 | displayTextLabel.setId(action.getID()); 84 | 85 | Region r = new Region(); 86 | HBox.setHgrow(r, Priority.ALWAYS); 87 | 88 | HBox actionHBox = new HBox(displayTextLabel, r, settingsButton, upButton, downButton); 89 | actionHBox.setSpacing(5.0); 90 | 91 | upButton.setUserData(i); 92 | downButton.setUserData(i); 93 | 94 | 95 | upButton.setOnAction(this::onUpButtonClicked); 96 | 97 | downButton.setOnAction(this::onDownButtonClicked); 98 | getChildren().add(actionHBox); 99 | i++; 100 | } 101 | } 102 | 103 | public void onSettingsButtonClicked(Action action) 104 | { 105 | actionDetailsPane.clear(false); 106 | actionDetailsPane.setAction(action); 107 | try 108 | { 109 | actionDetailsPane.renderActionProperties(); 110 | } 111 | catch (MinorException e) 112 | { 113 | e.printStackTrace(); 114 | } 115 | } 116 | 117 | public void onUpButtonClicked(ActionEvent event) 118 | { 119 | try { 120 | Node node = (Node) event.getSource(); 121 | 122 | int currentIndex = (int) node.getUserData(); 123 | 124 | if(currentIndex > 0) 125 | { 126 | Property current = combineAction.getClientProperties().getSingleProperty(currentIndex+""); 127 | Property aboveOne = combineAction.getClientProperties().getSingleProperty((currentIndex-1)+""); 128 | 129 | combineAction.addChild(current.getRawValue(), currentIndex-1); 130 | combineAction.addChild(aboveOne.getRawValue(), currentIndex); 131 | 132 | actionDetailsPane.setAction(combineAction); 133 | actionDetailsPane.saveAction(true, true); 134 | renderProps(); 135 | } 136 | 137 | } 138 | catch (MinorException e) 139 | { 140 | e.printStackTrace(); 141 | } 142 | } 143 | 144 | 145 | public void onDownButtonClicked(ActionEvent event) 146 | { 147 | try { 148 | Node node = (Node) event.getSource(); 149 | 150 | int currentIndex = (int) node.getUserData(); 151 | 152 | if(currentIndex < getChildren().size() - 1) 153 | { 154 | Property current = combineAction.getClientProperties().getSingleProperty(currentIndex+""); 155 | Property belowOne = combineAction.getClientProperties().getSingleProperty((currentIndex+1)+""); 156 | 157 | combineAction.addChild(current.getRawValue(), currentIndex+1); 158 | combineAction.addChild(belowOne.getRawValue(), currentIndex); 159 | 160 | actionDetailsPane.setAction(combineAction); 161 | actionDetailsPane.saveAction(true, true); 162 | renderProps(); 163 | } 164 | } 165 | catch (MinorException e) 166 | { 167 | e.printStackTrace(); 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/dashboard/actiondetailspane/OnDeleteActionTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.dashboard.actiondetailspane; 16 | 17 | import java.util.logging.Logger; 18 | 19 | import com.stream_pi.action_api.action.Action; 20 | import com.stream_pi.action_api.externalplugin.ExternalPlugin; 21 | import com.stream_pi.server.client.ClientProfile; 22 | import com.stream_pi.server.connection.ClientConnection; 23 | import com.stream_pi.server.window.ExceptionAndAlertHandler; 24 | import com.stream_pi.server.window.dashboard.actiongridpane.ActionBox; 25 | 26 | import com.stream_pi.util.exception.MinorException; 27 | import com.stream_pi.util.exception.SevereException; 28 | import javafx.application.Platform; 29 | import javafx.concurrent.Task; 30 | 31 | public class OnDeleteActionTask extends Task 32 | { 33 | private Logger logger; 34 | 35 | public OnDeleteActionTask(ClientConnection connection, Action action, boolean isCombineChild, 36 | CombineActionPropertiesPane combineActionPropertiesPane, ClientProfile clientProfile, ActionBox actionBox, 37 | ActionDetailsPane actionDetailsPane, 38 | ExceptionAndAlertHandler exceptionAndAlertHandler, boolean runAsync) 39 | { 40 | this.connection = connection; 41 | this.action = action; 42 | this.isCombineChild = isCombineChild; 43 | this.combineActionPropertiesPane = combineActionPropertiesPane; 44 | this.clientProfile = clientProfile; 45 | this.actionBox = actionBox; 46 | this.actionDetailsPane = actionDetailsPane; 47 | this.exceptionAndAlertHandler = exceptionAndAlertHandler; 48 | 49 | logger = Logger.getLogger(getClass().getName()); 50 | 51 | if(runAsync) 52 | new Thread(this).start(); 53 | else 54 | runTask(); 55 | } 56 | 57 | private ClientConnection connection; 58 | private Action action; 59 | private ActionBox actionBox; 60 | private ActionDetailsPaneListener actionDetailsPane; 61 | private boolean isCombineChild; 62 | private ClientProfile clientProfile; 63 | private CombineActionPropertiesPane combineActionPropertiesPane; 64 | private ExceptionAndAlertHandler exceptionAndAlertHandler; 65 | 66 | 67 | private void runTask() 68 | { 69 | try 70 | { 71 | 72 | if(action instanceof ExternalPlugin) 73 | { 74 | try 75 | { 76 | ((ExternalPlugin) action).onActionDeleted(); 77 | } 78 | catch (MinorException e) 79 | { 80 | e.setTitle("Unable to run onActionDeleted for "+action.getUniqueID()); 81 | exceptionAndAlertHandler.handleMinorException("Display Text: "+action.getDisplayText()+"\nDetailed message : \n\n"+e.getMessage(), e); 82 | } 83 | 84 | } 85 | 86 | 87 | connection.deleteAction(clientProfile.getID(), action.getID()); 88 | clientProfile.removeActionByID(action.getID()); 89 | 90 | if(isCombineChild) 91 | { 92 | combineActionPropertiesPane.getCombineAction().removeChild(action.getID()); 93 | 94 | combineActionPropertiesPane.renderProps(); 95 | 96 | try 97 | { 98 | connection.saveActionDetails(clientProfile.getID(), combineActionPropertiesPane.getCombineAction()); 99 | 100 | actionDetailsPane.onActionClicked( 101 | combineActionPropertiesPane.getCombineAction(), 102 | actionBox 103 | ); 104 | } 105 | catch (MinorException e) 106 | { 107 | e.printStackTrace(); 108 | } 109 | } 110 | else 111 | { 112 | Platform.runLater(()->{ 113 | actionDetailsPane.clearActionBox(action.getLocation().getCol(), action.getLocation().getRow(), 114 | action.getLocation().getColSpan(), action.getLocation().getRowSpan()); 115 | actionDetailsPane.clear(); 116 | }); 117 | } 118 | } 119 | catch (SevereException e) 120 | { 121 | e.printStackTrace(); 122 | exceptionAndAlertHandler.handleSevereException(e); 123 | } 124 | catch (MinorException e) 125 | { 126 | e.printStackTrace(); 127 | exceptionAndAlertHandler.handleMinorException(e); 128 | } 129 | } 130 | 131 | 132 | @Override 133 | protected Void call() throws Exception 134 | { 135 | runTask(); 136 | return null; 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/dashboard/actiongridpane/ActionGridPaneListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.dashboard.actiongridpane; 16 | 17 | import com.stream_pi.action_api.action.Action; 18 | import com.stream_pi.action_api.action.ActionType; 19 | import com.stream_pi.action_api.externalplugin.ExternalPlugin; 20 | import com.stream_pi.action_api.otheractions.FolderAction; 21 | import com.stream_pi.server.client.ClientProfile; 22 | import com.stream_pi.server.connection.ClientConnection; 23 | import com.stream_pi.util.exception.MinorException; 24 | import com.stream_pi.util.exception.SevereException; 25 | 26 | public interface ActionGridPaneListener 27 | { 28 | void addActionToCurrentClientProfile(Action newAction); 29 | 30 | ActionBox getActionBoxByProfileAndID(String profileID, String actionID); 31 | 32 | void renderFolder(FolderAction action); 33 | void renderAction(Action action) throws MinorException; 34 | 35 | String getCurrentParent(); 36 | 37 | ClientProfile getCurrentProfile(); 38 | 39 | void setCurrentParent(String currentParent); 40 | 41 | ClientConnection getClientConnection(); 42 | 43 | ActionBox getActionBox(int col, int row); 44 | 45 | ExternalPlugin createNewActionFromExternalPlugin(String module) throws CloneNotSupportedException; 46 | Action createNewOtherAction(ActionType actionType) throws Exception; 47 | void clearActionBox(int col, int row, int colSpan, int rowSpan); 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/firsttimeuse/FinalConfigPane.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.firsttimeuse; 16 | 17 | import com.stream_pi.server.controller.ServerListener; 18 | import com.stream_pi.server.i18n.I18N; 19 | import com.stream_pi.server.info.ServerInfo; 20 | import com.stream_pi.server.config.Config; 21 | import com.stream_pi.server.window.ExceptionAndAlertHandler; 22 | import com.stream_pi.server.combobox.IPChooserComboBox; 23 | import com.stream_pi.util.alert.StreamPiAlert; 24 | import com.stream_pi.util.alert.StreamPiAlertType; 25 | import com.stream_pi.util.exception.SevereException; 26 | import com.stream_pi.util.rootchecker.RootChecker; 27 | import com.stream_pi.util.uihelper.HBoxInputBox; 28 | 29 | import com.stream_pi.util.uihelper.HBoxWithSpaceBetween; 30 | import javafx.application.Platform; 31 | import javafx.concurrent.Task; 32 | import javafx.scene.control.Button; 33 | import javafx.scene.control.Label; 34 | import javafx.scene.control.TextField; 35 | import javafx.scene.layout.VBox; 36 | 37 | import java.net.InetAddress; 38 | import java.net.UnknownHostException; 39 | import java.util.logging.Logger; 40 | 41 | public class FinalConfigPane extends VBox 42 | { 43 | private TextField serverNameTextField; 44 | private TextField serverPortTextField; 45 | private IPChooserComboBox ipChooserComboBox; 46 | private Button nextButton; 47 | 48 | private ExceptionAndAlertHandler exceptionAndAlertHandler; 49 | private ServerListener serverListener; 50 | 51 | public FinalConfigPane(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener, 52 | Button nextButton) 53 | { 54 | this.exceptionAndAlertHandler = exceptionAndAlertHandler; 55 | this.serverListener = serverListener; 56 | this.nextButton = nextButton; 57 | 58 | getStyleClass().add("first_time_use_pane_final_config"); 59 | 60 | Label label = new Label(I18N.getString("window.firsttimeuse.FinalConfigPane.subHeading")); 61 | label.setWrapText(true); 62 | label.getStyleClass().add("first_time_use_pane_final_config_label"); 63 | 64 | serverNameTextField = new TextField(); 65 | serverPortTextField = new TextField(Config.getDefaultPort()+""); 66 | ipChooserComboBox = new IPChooserComboBox(); 67 | ipChooserComboBox.configureOptions(); 68 | 69 | HBoxInputBox serverNickNameInputBox = new HBoxInputBox(I18N.getString("serverName"), serverNameTextField, 200); 70 | HBoxInputBox serverPortInputBox = new HBoxInputBox(I18N.getString("serverPort"), serverPortTextField); 71 | HBoxWithSpaceBetween ipChooserHBox = new HBoxWithSpaceBetween(I18N.getString("serverIPBinding"), ipChooserComboBox); 72 | 73 | Label securityWarningLabel = new Label(I18N.getString("window.firsttimeuse.FinalConfigPane.securityWarning")); 74 | securityWarningLabel.setWrapText(true); 75 | securityWarningLabel.prefWidthProperty().bind(widthProperty()); 76 | securityWarningLabel.getStyleClass().add("first_time_use_pane_final_config_security_warning_label"); 77 | 78 | getChildren().addAll(label, serverNickNameInputBox, serverPortInputBox, ipChooserHBox, securityWarningLabel); 79 | 80 | setSpacing(10.0); 81 | 82 | setVisible(false); 83 | 84 | try 85 | { 86 | serverNameTextField.setText(InetAddress.getLocalHost().getHostName()); 87 | } 88 | catch (UnknownHostException e) 89 | { 90 | Logger.getLogger(getClass().getName()).warning("Hostname lookup failed! Not setting any placeholder for serverNameTextField."); 91 | } 92 | } 93 | 94 | public void makeChangesToNextButton() 95 | { 96 | nextButton.setText(I18N.getString("window.firsttimeuse.FinalConfigPane.confirm")); 97 | nextButton.setOnAction(actionEvent -> new Thread(new Task() { 98 | @Override 99 | protected Void call() 100 | { 101 | onConfirmButtonClicked(); 102 | return null; 103 | } 104 | }).start()); 105 | } 106 | 107 | private void onConfirmButtonClicked() 108 | { 109 | Platform.runLater(()->nextButton.setDisable(true)); 110 | 111 | StringBuilder errors = new StringBuilder(); 112 | 113 | String serverNameStr = serverNameTextField.getText(); 114 | String serverPortStr = serverPortTextField.getText(); 115 | 116 | if(serverNameStr.isBlank()) 117 | { 118 | errors.append("* ").append(I18N.getString("serverNameCannotBeBlank")).append("\n"); 119 | } 120 | 121 | int serverPort=-1; 122 | try { 123 | serverPort = Integer.parseInt(serverPortStr); 124 | 125 | if (serverPort < 1024 && !RootChecker.isRoot(ServerInfo.getInstance().getPlatform())) 126 | { 127 | errors.append("* ").append(I18N.getString("serverPortMustBeGreaterThan1024")).append("\n"); 128 | } 129 | else if(serverPort > 65535) 130 | { 131 | errors.append("* ").append(I18N.getString("serverPortMustBeLesserThan65535")).append("\n"); 132 | } 133 | } 134 | catch (NumberFormatException e) 135 | { 136 | errors.append("* ").append(I18N.getString("serverPortMustBeInteger")).append("\n"); 137 | } 138 | 139 | if(errors.toString().isEmpty()) 140 | { 141 | try 142 | { 143 | Config.getInstance().setServerName(serverNameStr); 144 | Config.getInstance().setPort(serverPort); 145 | Config.getInstance().setIP(ipChooserComboBox.getSelectedIP()); 146 | Config.getInstance().setFirstTimeUse(false); 147 | Config.getInstance().save(); 148 | 149 | Platform.runLater(()->serverListener.restart()); 150 | } 151 | catch(SevereException e) 152 | { 153 | exceptionAndAlertHandler.handleSevereException(e); 154 | } 155 | } 156 | else 157 | { 158 | Platform.runLater(()->nextButton.setDisable(false)); 159 | new StreamPiAlert(I18N.getString("validationError", errors), StreamPiAlertType.ERROR).show(); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/firsttimeuse/FirstTimeUse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.firsttimeuse; 16 | 17 | import com.stream_pi.server.Main; 18 | import com.stream_pi.server.controller.ServerListener; 19 | import com.stream_pi.server.i18n.I18N; 20 | import com.stream_pi.server.window.ExceptionAndAlertHandler; 21 | import com.stream_pi.util.uihelper.SpaceFiller; 22 | 23 | import javafx.geometry.Insets; 24 | import javafx.scene.control.Button; 25 | import javafx.scene.control.Label; 26 | import javafx.scene.layout.HBox; 27 | import javafx.scene.layout.Priority; 28 | import javafx.scene.layout.StackPane; 29 | import javafx.scene.layout.VBox; 30 | import javafx.scene.text.Font; 31 | 32 | import java.util.Objects; 33 | 34 | public class FirstTimeUse extends VBox{ 35 | 36 | 37 | public FirstTimeUse(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener) 38 | { 39 | getStyleClass().add("first_time_use_pane"); 40 | 41 | headingLabel = new Label(); 42 | headingLabel.getStyleClass().add("first_time_use_pane_heading_label"); 43 | 44 | StackPane stackPane = new StackPane(); 45 | stackPane.getStyleClass().add("first_time_use_pane_stackpane"); 46 | 47 | VBox.setVgrow(stackPane, Priority.ALWAYS); 48 | 49 | nextButton = new Button(I18N.getString("window.firsttimeuse.FirstTimeUse.next")); 50 | nextButton.setOnAction(event-> onNextButtonClicked()); 51 | 52 | previousButton = new Button(I18N.getString("window.firsttimeuse.FirstTimeUse.previous")); 53 | previousButton.setOnAction(event-> onPreviousButtonClicked()); 54 | 55 | 56 | HBox buttonBar = new HBox(previousButton, SpaceFiller.horizontal(), nextButton); 57 | buttonBar.setSpacing(10.0); 58 | 59 | welcomePane = new WelcomePane(exceptionAndAlertHandler, serverListener); 60 | licensePane = new LicensePane(); 61 | finalConfigPane = new FinalConfigPane(exceptionAndAlertHandler, serverListener, nextButton); 62 | 63 | stackPane.getChildren().addAll( 64 | welcomePane, 65 | licensePane, 66 | finalConfigPane 67 | ); 68 | 69 | getChildren().addAll(headingLabel, stackPane, buttonBar); 70 | 71 | setWindow(WindowName.WELCOME); 72 | } 73 | 74 | private Label headingLabel; 75 | private Button nextButton; 76 | private Button previousButton; 77 | private WelcomePane welcomePane; 78 | private LicensePane licensePane; 79 | private FinalConfigPane finalConfigPane; 80 | 81 | private WindowName windowName; 82 | 83 | private void onNextButtonClicked() 84 | { 85 | if(windowName == WindowName.WELCOME) 86 | { 87 | setWindow(WindowName.LICENSE); 88 | } 89 | else if(windowName == WindowName.LICENSE) 90 | { 91 | setWindow(WindowName.FINAL); 92 | } 93 | } 94 | 95 | private void onPreviousButtonClicked() 96 | { 97 | if(windowName == WindowName.FINAL) 98 | { 99 | setWindow(WindowName.LICENSE); 100 | } 101 | else if(windowName == WindowName.LICENSE) 102 | { 103 | setWindow(WindowName.WELCOME); 104 | } 105 | } 106 | 107 | private void setWindow(WindowName windowName) 108 | { 109 | if (windowName == WindowName.WELCOME) 110 | { 111 | this.windowName = WindowName.WELCOME; 112 | welcomePane.toFront(); 113 | welcomePane.setVisible(true); 114 | licensePane.setVisible(false); 115 | finalConfigPane.setVisible(false); 116 | 117 | headingLabel.setText(""); 118 | 119 | nextButton.setText(I18N.getString("window.firsttimeuse.FirstTimeUse.next")); 120 | nextButton.setOnAction(event-> onNextButtonClicked()); 121 | previousButton.setVisible(false); 122 | } 123 | else if (windowName == WindowName.LICENSE) 124 | { 125 | this.windowName = WindowName.LICENSE; 126 | licensePane.toFront(); 127 | welcomePane.setVisible(false); 128 | licensePane.setVisible(true); 129 | finalConfigPane.setVisible(false); 130 | 131 | headingLabel.setText(I18N.getString("window.firsttimeuse.FirstTimeUse.licenseAgreement")); 132 | 133 | nextButton.setText(I18N.getString("window.firsttimeuse.FirstTimeUse.agreeAndContinue")); 134 | nextButton.setOnAction(event-> onNextButtonClicked()); 135 | previousButton.setVisible(true); 136 | } 137 | else if (windowName == WindowName.FINAL) 138 | { 139 | this.windowName = WindowName.FINAL; 140 | finalConfigPane.toFront(); 141 | welcomePane.setVisible(false); 142 | licensePane.setVisible(false); 143 | finalConfigPane.setVisible(true); 144 | 145 | headingLabel.setText(I18N.getString("window.firsttimeuse.FirstTimeUse.finishingUp")); 146 | 147 | finalConfigPane.makeChangesToNextButton(); 148 | previousButton.setVisible(true); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/firsttimeuse/LicensePane.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.firsttimeuse; 16 | 17 | 18 | import com.stream_pi.server.info.ServerInfo; 19 | import javafx.scene.control.Button; 20 | import javafx.scene.control.Label; 21 | import javafx.scene.control.TextArea; 22 | import javafx.scene.layout.Priority; 23 | import javafx.scene.layout.VBox; 24 | 25 | public class LicensePane extends VBox 26 | { 27 | public LicensePane() 28 | { 29 | getStyleClass().add("first_time_use_pane_license"); 30 | 31 | TextArea licenseTextArea = new TextArea(ServerInfo.getInstance().getLicense()); 32 | licenseTextArea.setWrapText(false); 33 | licenseTextArea.setEditable(false); 34 | 35 | licenseTextArea.prefWidthProperty().bind(widthProperty()); 36 | VBox.setVgrow(licenseTextArea, Priority.ALWAYS); 37 | 38 | getChildren().addAll(licenseTextArea); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/firsttimeuse/WelcomePane.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.firsttimeuse; 16 | 17 | import com.stream_pi.server.Main; 18 | import com.stream_pi.server.combobox.LanguageChooserComboBox; 19 | import com.stream_pi.server.controller.ServerListener; 20 | import com.stream_pi.server.i18n.I18N; 21 | import com.stream_pi.server.config.Config; 22 | import com.stream_pi.server.window.ExceptionAndAlertHandler; 23 | import com.stream_pi.util.exception.SevereException; 24 | import javafx.geometry.Insets; 25 | import javafx.geometry.Pos; 26 | import javafx.scene.control.Label; 27 | import javafx.scene.image.Image; 28 | import javafx.scene.image.ImageView; 29 | import javafx.scene.layout.VBox; 30 | 31 | import java.util.Objects; 32 | 33 | public class WelcomePane extends VBox 34 | { 35 | public WelcomePane(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener) 36 | { 37 | getStyleClass().add("first_time_use_welcome_pane"); 38 | 39 | Image appIcon = new Image(Objects.requireNonNull(Main.class.getResourceAsStream("icons/256x256.png"))); 40 | ImageView appIconImageView = new ImageView(appIcon); 41 | VBox.setMargin(appIconImageView, new Insets(10, 0, 10, 0)); 42 | appIconImageView.setFitHeight(128); 43 | appIconImageView.setFitWidth(128); 44 | 45 | 46 | Label welcomeLabel = new Label(I18N.getString("window.firsttimeuse.WelcomePane.welcome")); 47 | welcomeLabel.setWrapText(true); 48 | welcomeLabel.setAlignment(Pos.CENTER); 49 | welcomeLabel.getStyleClass().add("first_time_use_welcome_pane_welcome_label"); 50 | 51 | LanguageChooserComboBox languageChooserComboBox = new LanguageChooserComboBox(); 52 | languageChooserComboBox.getStyleClass().add("first_time_use_welcome_pane_language_chooser_combo_box"); 53 | 54 | languageChooserComboBox.getSelectionModel().select(I18N.getLanguage(Config.getInstance().getCurrentLanguageLocale())); 55 | 56 | 57 | languageChooserComboBox.valueProperty().addListener((observableValue, oldVal, newVal) -> 58 | { 59 | try 60 | { 61 | if(oldVal!=newVal && newVal!=null) 62 | { 63 | Config.getInstance().setCurrentLanguageLocale(newVal.getLocale()); 64 | Config.getInstance().save(); 65 | serverListener.restart(); 66 | } 67 | } 68 | catch (SevereException e) 69 | { 70 | exceptionAndAlertHandler.handleSevereException(e); 71 | } 72 | }); 73 | 74 | 75 | getChildren().addAll(appIconImageView, welcomeLabel, languageChooserComboBox); 76 | 77 | setVisible(false); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/firsttimeuse/WindowName.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.firsttimeuse; 16 | 17 | public enum WindowName 18 | { 19 | WELCOME, LICENSE, FINAL 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/helper/ControlNodePair.java: -------------------------------------------------------------------------------- 1 | package com.stream_pi.server.window.helper; 2 | 3 | import javafx.beans.value.ChangeListener; 4 | import javafx.scene.Node; 5 | 6 | public class ControlNodePair 7 | { 8 | private Node controlNode = null; 9 | private Node UINode = null; 10 | 11 | private boolean changed = false; 12 | 13 | public void setUINode(Node UINode) { 14 | this.UINode = UINode; 15 | } 16 | public Node getUINode() 17 | { 18 | return UINode; 19 | } 20 | 21 | public void setControlNode(Node controlNode) { 22 | this.controlNode = controlNode; 23 | } 24 | 25 | public Node getControlNode() 26 | { 27 | return controlNode; 28 | } 29 | 30 | public boolean isChanged() { 31 | return changed; 32 | } 33 | 34 | public void setChanged(boolean changed) { 35 | this.changed = changed; 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/helper/Helper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.helper; 16 | 17 | public class Helper 18 | { 19 | // Remove this 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/settings/SettingsBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.settings; 16 | 17 | import com.stream_pi.server.controller.ServerListener; 18 | import com.stream_pi.server.i18n.I18N; 19 | import com.stream_pi.server.window.ExceptionAndAlertHandler; 20 | import com.stream_pi.server.window.settings.about.About; 21 | import com.stream_pi.server.window.settings.general.GeneralSettingsPresenter; 22 | import javafx.application.HostServices; 23 | import javafx.event.Event; 24 | import javafx.geometry.Insets; 25 | import javafx.scene.CacheHint; 26 | import javafx.scene.control.*; 27 | import javafx.scene.input.SwipeEvent; 28 | import javafx.scene.layout.Priority; 29 | import javafx.scene.layout.VBox; 30 | 31 | public class SettingsBase extends VBox 32 | { 33 | 34 | private TabPane tabPane; 35 | 36 | private Tab generalSettingsTab, pluginsSettingsTab, themesSettingsTab, clientsSettingsTab, aboutTab; 37 | 38 | private GeneralSettingsPresenter generalSettings; 39 | private PluginsSettings pluginsSettings; 40 | private ThemesSettings themesSettings; 41 | private ClientsSettings clientsSettings; 42 | 43 | private Button closeButton; 44 | 45 | private HostServices hostServices; 46 | private ExceptionAndAlertHandler exceptionAndAlertHandler; 47 | 48 | public SettingsBase(HostServices hostServices, ExceptionAndAlertHandler exceptionAndAlertHandler, 49 | ServerListener serverListener) 50 | { 51 | this.exceptionAndAlertHandler = exceptionAndAlertHandler; 52 | this.hostServices = hostServices; 53 | 54 | tabPane = new TabPane(); 55 | tabPane.addEventFilter(SwipeEvent.ANY, Event::consume); 56 | tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE); 57 | VBox.setVgrow(tabPane, Priority.ALWAYS); 58 | 59 | generalSettingsTab = new Tab(I18N.getString("general")); 60 | generalSettings = new GeneralSettingsPresenter(exceptionAndAlertHandler, serverListener, hostServices); 61 | generalSettingsTab.setContent(generalSettings.getView()); 62 | 63 | pluginsSettingsTab = new Tab(I18N.getString("plugins")); 64 | pluginsSettings = new PluginsSettings(exceptionAndAlertHandler, hostServices); 65 | pluginsSettingsTab.setContent(pluginsSettings); 66 | 67 | themesSettingsTab = new Tab(I18N.getString("themes")); 68 | themesSettings = new ThemesSettings(hostServices); 69 | themesSettingsTab.setContent(themesSettings); 70 | 71 | clientsSettingsTab = new Tab(I18N.getString("clients")); 72 | clientsSettings = new ClientsSettings(exceptionAndAlertHandler, serverListener); 73 | clientsSettingsTab.setContent(clientsSettings); 74 | 75 | aboutTab = new Tab(I18N.getString("about")); 76 | aboutTab.setContent(new About(hostServices)); 77 | 78 | tabPane.getTabs().addAll(generalSettingsTab, pluginsSettingsTab, themesSettingsTab, clientsSettingsTab, aboutTab); 79 | 80 | 81 | closeButton = new Button(I18N.getString("window.settings.SettingsBase.close")); 82 | closeButton.getStyleClass().add("settings_close_button"); 83 | VBox.setMargin(closeButton, new Insets(0,10, 10, 0)); 84 | 85 | getChildren().addAll(tabPane, closeButton); 86 | 87 | setCache(true); 88 | setCacheHint(CacheHint.SCALE); 89 | 90 | getStyleClass().add("settings_base"); 91 | } 92 | 93 | public TabPane getTabPane() 94 | { 95 | return tabPane; 96 | } 97 | 98 | public void setDefaultTabToGeneral() 99 | { 100 | tabPane.getSelectionModel().selectFirst(); 101 | } 102 | 103 | public Button getCloseButton() 104 | { 105 | return closeButton; 106 | } 107 | 108 | public GeneralSettingsPresenter getGeneralSettings() 109 | { 110 | return generalSettings; 111 | } 112 | 113 | public PluginsSettings getPluginsSettings() 114 | { 115 | return pluginsSettings; 116 | } 117 | 118 | public ThemesSettings getThemesSettings() 119 | { 120 | return themesSettings; 121 | } 122 | 123 | public ClientsSettings getClientsSettings() 124 | { 125 | return clientsSettings; 126 | } 127 | 128 | public Tab getGeneralSettingsTab() 129 | { 130 | return generalSettingsTab; 131 | } 132 | 133 | public Tab getThemesSettingsTab() 134 | { 135 | return themesSettingsTab; 136 | } 137 | 138 | public Tab getClientsSettingsTab() 139 | { 140 | return clientsSettingsTab; 141 | } 142 | 143 | public Tab getPluginsSettingsTab() 144 | { 145 | return pluginsSettingsTab; 146 | } 147 | 148 | public Tab getAboutTab() 149 | { 150 | return aboutTab; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/settings/ThemesSettings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.settings; 16 | 17 | import com.stream_pi.server.controller.Controller; 18 | import com.stream_pi.server.i18n.I18N; 19 | import com.stream_pi.server.config.Config; 20 | import com.stream_pi.theme_api.Theme; 21 | import com.stream_pi.theme_api.Themes; 22 | import com.stream_pi.util.exception.SevereException; 23 | import com.stream_pi.util.uihelper.SpaceFiller; 24 | import javafx.application.HostServices; 25 | import javafx.application.Platform; 26 | import javafx.geometry.Pos; 27 | import javafx.scene.control.*; 28 | import javafx.scene.layout.HBox; 29 | import javafx.scene.layout.Priority; 30 | import javafx.scene.layout.VBox; 31 | import org.controlsfx.control.ToggleSwitch; 32 | import org.kordamp.ikonli.javafx.FontIcon; 33 | 34 | import java.util.ArrayList; 35 | import java.util.logging.Logger; 36 | 37 | public class ThemesSettings extends VBox 38 | { 39 | private VBox themesSettingsVBox; 40 | 41 | private Controller controller; 42 | 43 | private Logger logger; 44 | private HostServices hostServices; 45 | 46 | public ThemesSettings(HostServices hostServices) 47 | { 48 | this.hostServices = hostServices; 49 | getStyleClass().add("themes_settings"); 50 | logger = Logger.getLogger(ThemesSettings.class.getName()); 51 | 52 | themesSettingsVBox = new VBox(); 53 | themesSettingsVBox.getStyleClass().add("themes_settings_vbox"); 54 | themesSettingsVBox.setAlignment(Pos.TOP_CENTER); 55 | 56 | ScrollPane scrollPane = new ScrollPane(); 57 | scrollPane.getStyleClass().add("themes_settings_scroll_pane"); 58 | scrollPane.setFitToWidth(true); 59 | scrollPane.maxWidthProperty().bind(widthProperty().multiply(0.8)); 60 | 61 | scrollPane.setContent(themesSettingsVBox); 62 | 63 | VBox.setVgrow(scrollPane, Priority.ALWAYS); 64 | 65 | setAlignment(Pos.TOP_CENTER); 66 | 67 | getChildren().addAll(scrollPane); 68 | 69 | toggleSwitches = new ArrayList<>(); 70 | 71 | } 72 | 73 | public void setController(Controller controller) 74 | { 75 | this.controller = controller; 76 | } 77 | 78 | private Themes themes; 79 | private String currentThemeFullName; 80 | 81 | public void setThemes(Themes themes) 82 | { 83 | this.themes = themes; 84 | } 85 | 86 | public void setCurrentThemeFullName(String currentThemeFullName) 87 | { 88 | this.currentThemeFullName = currentThemeFullName; 89 | } 90 | 91 | private ArrayList toggleSwitches; 92 | 93 | public void loadThemes() 94 | { 95 | toggleSwitches.clear(); 96 | 97 | Platform.runLater(()-> themesSettingsVBox.getChildren().clear()); 98 | 99 | 100 | for(int i = 0; i hostServices.showDocument(theme.getWebsite())); 127 | 128 | topRowHBox.getChildren().addAll(SpaceFiller.horizontal(), helpButton); 129 | } 130 | 131 | ToggleSwitch toggleSwitch = new ToggleSwitch(); 132 | toggleSwitch.getStyleClass().add("themes_settings_each_theme_toggle_switch"); 133 | 134 | toggleSwitch.setSelected(theme.getFullName().equals(currentThemeFullName)); 135 | toggleSwitch.setId(theme.getFullName()); 136 | 137 | 138 | if(theme.getFullName().equals(currentThemeFullName)) 139 | { 140 | toggleSwitch.setSelected(true); 141 | toggleSwitch.setDisable(true); 142 | } 143 | 144 | 145 | toggleSwitch.setOnMouseClicked(event -> { 146 | ToggleSwitch toggleSwitch1 = (ToggleSwitch) event.getSource(); 147 | 148 | try 149 | { 150 | Config.getInstance().setCurrentThemeFullName(toggleSwitch1.getId()); 151 | Config.getInstance().save(); 152 | 153 | for(ToggleSwitch toggleSwitch2 : toggleSwitches) 154 | { 155 | if(toggleSwitch2.getId().equals(Config.getInstance().getCurrentThemeFullName())) 156 | { 157 | toggleSwitch2.setDisable(true); 158 | toggleSwitch2.setSelected(true); 159 | } 160 | else 161 | { 162 | toggleSwitch2.setDisable(false); 163 | toggleSwitch2.setSelected(false); 164 | } 165 | } 166 | 167 | controller.initThemes(); 168 | } 169 | catch (SevereException e) 170 | { 171 | controller.handleSevereException(e); 172 | } 173 | }); 174 | 175 | HBox hBox = new HBox(toggleSwitch); 176 | hBox.getStyleClass().add("themes_settings_each_theme_toggle_button_parent"); 177 | 178 | hBox.setAlignment(Pos.TOP_RIGHT); 179 | 180 | VBox vBox = new VBox(topRowHBox, authorLabel, fullNameLabel, versionLabel, hBox); 181 | 182 | 183 | vBox.getStyleClass().add("theme_settings_each_theme_box"); 184 | 185 | Platform.runLater(()->themesSettingsVBox.getChildren().add(vBox)); 186 | 187 | 188 | toggleSwitches.add(toggleSwitch); 189 | } 190 | 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/settings/about/About.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.settings.about; 16 | 17 | import com.stream_pi.action_api.ActionAPI; 18 | import com.stream_pi.theme_api.ThemeAPI; 19 | import com.stream_pi.util.Util; 20 | import com.stream_pi.server.i18n.I18N; 21 | import com.stream_pi.server.info.ServerInfo; 22 | import com.stream_pi.server.Main; 23 | import com.stream_pi.util.links.Links; 24 | import javafx.application.HostServices; 25 | import javafx.event.Event; 26 | import javafx.geometry.Insets; 27 | import javafx.geometry.Pos; 28 | import javafx.scene.control.*; 29 | import javafx.scene.image.Image; 30 | import javafx.scene.image.ImageView; 31 | import javafx.scene.input.SwipeEvent; 32 | import javafx.scene.layout.HBox; 33 | import javafx.scene.layout.Priority; 34 | import javafx.scene.layout.VBox; 35 | 36 | import java.io.IOException; 37 | import java.io.InputStream; 38 | import java.lang.management.ManagementFactory; 39 | import java.util.Objects; 40 | import java.util.Properties; 41 | import java.util.logging.Logger; 42 | 43 | public class About extends VBox 44 | { 45 | 46 | private final HostServices hostServices; 47 | 48 | public About(HostServices hostServices) 49 | { 50 | getStyleClass().add("about"); 51 | this.hostServices = hostServices; 52 | 53 | setAlignment(Pos.TOP_CENTER); 54 | 55 | Image appIcon = new Image(Objects.requireNonNull(Main.class.getResourceAsStream("icons/256x256.png"))); 56 | ImageView appIconImageView = new ImageView(appIcon); 57 | VBox.setMargin(appIconImageView, new Insets(10, 0, 10, 0)); 58 | appIconImageView.setFitHeight(128); 59 | appIconImageView.setFitWidth(128); 60 | 61 | TabPane tabPane = new TabPane(); 62 | tabPane.addEventFilter(SwipeEvent.ANY, Event::consume); 63 | tabPane.getStyleClass().add("settings_about_tab_internal"); 64 | tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE); 65 | tabPane.setMaxWidth(600); 66 | VBox.setVgrow(tabPane, Priority.ALWAYS); 67 | 68 | Tab licenseTab = new Tab(I18N.getString("window.settings.about.About.licenseTabHeading")); 69 | licenseTab.setContent(new LicenseTab()); 70 | 71 | 72 | Tab contributorsTab = new Tab(I18N.getString("window.settings.about.About.contributorsTabHeading")); 73 | contributorsTab.setContent(new ContributorsTab(hostServices)); 74 | 75 | Tab contactTab = new Tab(I18N.getString("window.settings.about.About.contactTabHeading")); 76 | contactTab.setContent(new ContactTab(hostServices)); 77 | 78 | tabPane.getTabs().addAll(licenseTab, contributorsTab, contactTab); 79 | 80 | 81 | Hyperlink donateButton = new Hyperlink(I18N.getString("donate")); 82 | donateButton.setOnAction(event -> openWebpage(Links.getDonateLink())); 83 | donateButton.getStyleClass().add("about_donate_hyperlink"); 84 | 85 | ServerInfo serverInfo = ServerInfo.getInstance(); 86 | 87 | Label versionLabel = new Label(serverInfo.getVersion().getText() + " - "+ serverInfo.getPlatform().getUIName() + " - "+ serverInfo.getReleaseStatus().getUIName()); 88 | versionLabel.getStyleClass().add("about_version_label"); 89 | 90 | HBox hBox1 = new HBox(versionLabel); 91 | 92 | hBox1.setAlignment(Pos.CENTER); 93 | hBox1.setSpacing(10); 94 | 95 | if (serverInfo.getBuildNumber() != null) 96 | { 97 | Label buildNumberLabel = new Label(I18N.getString("window.settings.about.About.buildNumber", serverInfo.getBuildNumber())); 98 | buildNumberLabel.getStyleClass().add("about_build_number_label"); 99 | hBox1.getChildren().addAll(getSep(), buildNumberLabel); 100 | } 101 | 102 | Label commStandardLabel = new Label(I18N.getString("window.settings.about.About.serverCommunicationProtocolVersion", serverInfo.getCommunicationProtocolVersion().getText())); 103 | commStandardLabel.getStyleClass().add("about_comm_standard_label"); 104 | 105 | Label currentActionAPILabel = new Label("Action API " + ActionAPI.VERSION.getText()); 106 | currentActionAPILabel.getStyleClass().add("about_current_action_api_label"); 107 | 108 | Label currentUtilLabel = new Label("Util " + Util.VERSION.getText()); 109 | currentUtilLabel.getStyleClass().add("about_current_util_label"); 110 | 111 | HBox hBox2 = new HBox(commStandardLabel, getSep(), 112 | currentActionAPILabel, getSep(), 113 | currentUtilLabel); 114 | 115 | hBox2.setAlignment(Pos.CENTER); 116 | hBox2.setSpacing(10); 117 | 118 | Label javaVersionLabel = new Label("Java " + System.getProperty("java.version") + ", " + System.getProperty("java.vm.name")); 119 | javaVersionLabel.getStyleClass().add("about_java_version"); 120 | 121 | Label javafxVersionLabel = new Label("JavaFX " + System.getProperty("javafx.version")); 122 | javafxVersionLabel.getStyleClass().add("about_javafx_version"); 123 | 124 | Label javaGCLabel = new Label("GC: " + ManagementFactory.getGarbageCollectorMXBeans().get(0).getName()); 125 | javaGCLabel.getStyleClass().add("about_java_gc"); 126 | 127 | HBox hBox3 = new HBox(javaVersionLabel, getSep(), 128 | javafxVersionLabel, getSep(), 129 | javaGCLabel); 130 | 131 | hBox3.setAlignment(Pos.CENTER); 132 | hBox3.setSpacing(10); 133 | 134 | 135 | getChildren().addAll(appIconImageView, tabPane, donateButton, hBox1, hBox2, hBox3); 136 | } 137 | 138 | public void openWebpage(String url) 139 | { 140 | hostServices.showDocument(url); 141 | } 142 | 143 | private Label getSep() 144 | { 145 | Label label = new Label("|"); 146 | label.getStyleClass().add("separator_ui_label"); 147 | return label; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/settings/about/ContactTab.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.settings.about; 16 | 17 | import com.stream_pi.server.i18n.I18N; 18 | import com.stream_pi.util.links.Links; 19 | import javafx.application.HostServices; 20 | import javafx.scene.control.Hyperlink; 21 | import javafx.scene.control.ScrollPane; 22 | import javafx.scene.layout.VBox; 23 | 24 | 25 | public class ContactTab extends ScrollPane 26 | { 27 | private final HostServices hostServices; 28 | 29 | 30 | public ContactTab(HostServices hostServices) 31 | { 32 | this.hostServices = hostServices; 33 | 34 | getStyleClass().add("about_contact_tab_scroll_pane"); 35 | 36 | Hyperlink github = new Hyperlink("GitHub"); 37 | github.setOnAction(event -> openWebpage(Links.getGitHub())); 38 | 39 | Hyperlink discord = new Hyperlink("Discord"); 40 | discord.setOnAction(event -> openWebpage(Links.getDiscord())); 41 | 42 | Hyperlink website = new Hyperlink(I18N.getString("website")); 43 | website.setOnAction(event -> openWebpage(Links.getWebsite())); 44 | 45 | Hyperlink twitter = new Hyperlink("Twitter"); 46 | twitter.setOnAction(event -> openWebpage(Links.getTwitter())); 47 | 48 | Hyperlink matrix = new Hyperlink("Matrix"); 49 | matrix.setOnAction(event -> openWebpage(Links.getMatrix())); 50 | 51 | VBox vBox = new VBox(github, discord, website, twitter, matrix); 52 | vBox.setSpacing(10.0); 53 | 54 | setContent(vBox); 55 | } 56 | 57 | 58 | public void openWebpage(String url) 59 | { 60 | hostServices.showDocument(url); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/settings/about/ContributorsTab.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.settings.about; 16 | 17 | import com.stream_pi.server.i18n.I18N; 18 | import com.stream_pi.util.links.Links; 19 | import javafx.application.HostServices; 20 | import javafx.scene.control.*; 21 | import javafx.scene.layout.VBox; 22 | 23 | public class ContributorsTab extends ScrollPane 24 | { 25 | private final HostServices hostServices; 26 | public ContributorsTab(HostServices hostServices) 27 | { 28 | this.hostServices = hostServices; 29 | 30 | getStyleClass().add("about_contributors_tab_scroll_pane"); 31 | 32 | Hyperlink team = new Hyperlink(I18N.getString("window.settings.about.ContributorsTab.team")); 33 | team.setOnAction(event -> openWebpage(Links.getWebsiteAbout())); 34 | 35 | Hyperlink server = new Hyperlink(I18N.getString("window.settings.about.ContributorsTab.server")); 36 | server.setOnAction(event -> openWebpage(Links.getServerContributors())); 37 | 38 | Hyperlink client = new Hyperlink(I18N.getString("window.settings.about.ContributorsTab.client")); 39 | client.setOnAction(event -> openWebpage(Links.getClientContributors())); 40 | 41 | Hyperlink action_api = new Hyperlink("Action API"); 42 | action_api.setOnAction(event -> openWebpage(Links.getActionAPIContributors())); 43 | 44 | Hyperlink theme_api = new Hyperlink("Theme API"); 45 | theme_api.setOnAction(event -> openWebpage(Links.getThemeAPIContributors())); 46 | 47 | Hyperlink util = new Hyperlink("Util"); 48 | util.setOnAction(event -> openWebpage(Links.getUtilContributors())); 49 | 50 | VBox vBox = new VBox(team, server, client, action_api, theme_api, util); 51 | vBox.setSpacing(10.0); 52 | 53 | setContent(vBox); 54 | } 55 | 56 | 57 | public void openWebpage(String url) 58 | { 59 | hostServices.showDocument(url); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/settings/about/LicenseTab.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.settings.about; 16 | 17 | 18 | import com.stream_pi.server.info.ServerInfo; 19 | import javafx.scene.control.TextArea; 20 | 21 | public class LicenseTab extends TextArea 22 | { 23 | public LicenseTab() 24 | { 25 | setText(ServerInfo.getInstance().getLicense()); 26 | getStyleClass().add("about_license_text_area"); 27 | setWrapText(false); 28 | setEditable(false); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/settings/general/GeneralSettingsModel.java: -------------------------------------------------------------------------------- 1 | package com.stream_pi.server.window.settings.general; 2 | 3 | import com.stream_pi.server.Main; 4 | import com.stream_pi.server.controller.ServerListener; 5 | import com.stream_pi.server.i18n.I18N; 6 | import com.stream_pi.server.info.ServerInfo; 7 | import com.stream_pi.server.info.StartupFlags; 8 | import com.stream_pi.server.config.Config; 9 | import com.stream_pi.server.window.GlobalExceptionAndAlertHandler; 10 | import com.stream_pi.server.config.record.*; 11 | import com.stream_pi.util.alert.StreamPiAlert; 12 | import com.stream_pi.util.alert.StreamPiAlertType; 13 | import com.stream_pi.util.exception.MinorException; 14 | import com.stream_pi.util.exception.SevereException; 15 | import com.stream_pi.util.platform.PlatformType; 16 | import com.stream_pi.util.startonboot.StartOnBoot; 17 | 18 | public class GeneralSettingsModel 19 | { 20 | private GeneralSettings currentSettings; 21 | private final GlobalExceptionAndAlertHandler exceptionAndAlertHandler = GlobalExceptionAndAlertHandler.getInstance(); 22 | 23 | private ServerListener serverListener; 24 | public GeneralSettingsModel(ServerListener serverListener) 25 | { 26 | this.serverListener = serverListener; 27 | } 28 | public void loadSettings() 29 | { 30 | Config config = Config.getInstance(); 31 | 32 | /*currentSettings = new GeneralSettings(config.getServerName(), config.getPort(), config.getActionGridActionDisplayTextFontSize(), 33 | config.getPluginsPath(), config.getThemesPath(), 34 | config.getActionGridActionSize(), 35 | config.getActionGridUseSameActionSizeAsProfile(), config.getActionGridUseSameActionGapAsProfile(), 36 | config.getActionGridUseSameActionDisplayTextFontSizeAsProfile(), 37 | config.getActionGridActionGap(), 38 | config.getMinimiseToSystemTrayOnClose(), config.isShowAlertsPopup(), config.isStartOnBoot(), 39 | config.getSoundOnActionClickedStatus(), config.getSoundOnActionClickedFilePath(), 40 | config.getIP(), config.getCurrentLanguageLocale());*/ 41 | 42 | currentSettings = new GeneralSettings( 43 | new ConnectionSettings(config.getServerName(), config.getPort(), config.getIP()), 44 | new ActionGridSettings( 45 | config.getActionGridActionSize(), config.getActionGridUseSameActionSizeAsProfile(), 46 | config.getActionGridActionGap(), config.getActionGridUseSameActionGapAsProfile(), 47 | config.getActionGridActionDisplayTextFontSize(),config.getActionGridUseSameActionDisplayTextFontSizeAsProfile() 48 | ), 49 | new LocationsSettings(config.getPluginsPath(), config.getThemesPath()), 50 | new SoundOnActionClickedSettings(config.getSoundOnActionClickedFilePath(), config.getSoundOnActionClickedStatus()), 51 | new OthersSettings(config.getCurrentLanguageLocale(), config.getMinimiseToSystemTrayOnClose(), config.isStartOnBoot(), config.isShowAlertsPopup()) 52 | ); 53 | } 54 | 55 | public GeneralSettings getCurrentSettings() 56 | { 57 | return currentSettings; 58 | } 59 | 60 | public void saveSettings(GeneralSettings newSettings) throws SevereException 61 | { 62 | Config config = Config.getInstance(); 63 | 64 | ConnectionSettings connectionSettings = newSettings.connection(); 65 | config.setServerName(connectionSettings.serverName()); 66 | config.setPort(connectionSettings.port()); 67 | config.setIP(connectionSettings.IP()); 68 | 69 | ActionGridSettings actionGridSettings = newSettings.actionGrid(); 70 | config.setActionGridActionSize(actionGridSettings.actionGridActionSize()); 71 | config.setActionGridUseSameActionSizeAsProfile(actionGridSettings.actionGridUseSameActionSizeAsProfile()); 72 | config.setActionGridActionGap(actionGridSettings.actionGridActionGap()); 73 | config.setActionGridUseSameActionGapAsProfile(actionGridSettings.actionGridUseSameActionGapAsProfile()); 74 | config.setActionGridActionDisplayTextFontSize(actionGridSettings.actionGridActionDisplayTextFontSize()); 75 | config.setActionGridUseSameActionDisplayTextFontSizeAsProfile(actionGridSettings.actionGridUseSameActionDisplayTextFontSizeAsProfile()); 76 | 77 | LocationsSettings locationsSettings = newSettings.locations(); 78 | config.setPluginsPath(locationsSettings.pluginsPath()); 79 | config.setThemesPath(locationsSettings.themesPath()); 80 | 81 | SoundOnActionClickedSettings soundOnActionClickedSettings = newSettings.soundOnActionClicked(); 82 | config.setSoundOnActionClickedFilePath(soundOnActionClickedSettings.soundOnActionClickedFilePath()); 83 | boolean soundOnActionClicked = soundOnActionClickedSettings.soundOnActionClickedStatus(); 84 | config.setSoundOnActionClickedStatus(soundOnActionClicked); 85 | if(soundOnActionClicked) 86 | { 87 | serverListener.initSoundOnActionClicked(); 88 | } 89 | 90 | 91 | OthersSettings othersSettings = newSettings.others(); 92 | config.setCurrentLanguageLocale(othersSettings.currentLanguageLocale()); 93 | config.setMinimiseToSystemTrayOnClose(othersSettings.minimiseToSystemTrayOnClose()); 94 | 95 | boolean startOnBoot = othersSettings.startOnBoot(); 96 | if(config.isStartOnBoot() != startOnBoot) 97 | { 98 | StartOnBoot startAtBoot = new StartOnBoot(PlatformType.SERVER, ServerInfo.getInstance().getPlatform(), 99 | Main.class.getProtectionDomain().getCodeSource().getLocation(), 100 | StartupFlags.APPEND_PATH_BEFORE_RUNNER_FILE_TO_OVERCOME_JPACKAGE_LIMITATION); 101 | 102 | if(startOnBoot) 103 | { 104 | try 105 | { 106 | startAtBoot.create(StartupFlags.RUNNER_FILE_NAME, StartupFlags.generateRuntimeArgumentsForStartOnBoot()); 107 | } 108 | catch (MinorException e) 109 | { 110 | exceptionAndAlertHandler.handleMinorException(e); 111 | startOnBoot = false; 112 | } 113 | } 114 | else 115 | { 116 | try 117 | { 118 | boolean result = startAtBoot.delete(); 119 | if(!result) 120 | new StreamPiAlert(I18N.getString("window.settings.GeneralSettings.unableToDeleteStarterFile"), StreamPiAlertType.ERROR).show(); 121 | } 122 | catch (MinorException e) 123 | { 124 | exceptionAndAlertHandler.handleMinorException(e); 125 | } 126 | } 127 | } 128 | config.setStartupOnBoot(startOnBoot); 129 | 130 | boolean showAlertsPopup = othersSettings.showAlertsPopup(); 131 | StreamPiAlert.setIsShowPopup(showAlertsPopup); 132 | config.setShowAlertsPopup(showAlertsPopup); 133 | 134 | config.save(); 135 | 136 | loadSettings(); 137 | } 138 | 139 | public boolean shouldServerBeReloaded(GeneralSettings newSettings) 140 | { 141 | boolean reload = false; 142 | 143 | ConnectionSettings currentConnectionSettings = currentSettings.connection(); 144 | ConnectionSettings newConnectionSettings = newSettings.connection(); 145 | 146 | if(!currentConnectionSettings.serverName().equals(newConnectionSettings.serverName())) 147 | { 148 | reload = true; 149 | } 150 | 151 | if(currentConnectionSettings.port()!=newConnectionSettings.port()) 152 | { 153 | reload = true; 154 | } 155 | 156 | if (!currentConnectionSettings.IP().equals(newConnectionSettings.IP())) 157 | { 158 | reload = true; 159 | } 160 | 161 | LocationsSettings currentLocationsSettings = currentSettings.locations(); 162 | LocationsSettings newLocationsSettings = newSettings.locations(); 163 | 164 | if(!currentLocationsSettings.pluginsPath().equals(newLocationsSettings.pluginsPath())) 165 | { 166 | reload = true; 167 | } 168 | 169 | if(!currentLocationsSettings.themesPath().equals(newLocationsSettings.themesPath())) 170 | { 171 | reload = true; 172 | } 173 | 174 | if (!currentSettings.others().currentLanguageLocale().equals(newSettings.others().currentLanguageLocale())) 175 | { 176 | reload = true; 177 | } 178 | 179 | return reload; 180 | } 181 | 182 | public boolean shouldServerDashboardBeReloaded(GeneralSettings newSettings) 183 | { 184 | boolean reload = false; 185 | 186 | ActionGridSettings currentActionGridSettings = currentSettings.actionGrid(); 187 | ActionGridSettings newActionGridSettings = newSettings.actionGrid(); 188 | 189 | if(currentActionGridSettings.actionGridActionSize() != newActionGridSettings.actionGridActionSize()) 190 | { 191 | reload = true; 192 | } 193 | 194 | if(currentActionGridSettings.actionGridUseSameActionSizeAsProfile() != newActionGridSettings.actionGridUseSameActionSizeAsProfile()) 195 | { 196 | reload = true; 197 | } 198 | 199 | if(currentActionGridSettings.actionGridActionGap() != newActionGridSettings.actionGridActionGap()) 200 | { 201 | reload = true; 202 | } 203 | 204 | if(currentActionGridSettings.actionGridUseSameActionGapAsProfile() != newActionGridSettings.actionGridUseSameActionGapAsProfile()) 205 | { 206 | reload = true; 207 | } 208 | 209 | if (currentActionGridSettings.actionGridUseSameActionDisplayTextFontSizeAsProfile() != newActionGridSettings.actionGridUseSameActionDisplayTextFontSizeAsProfile()) 210 | { 211 | reload = true; 212 | } 213 | 214 | 215 | return reload; 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/settings/general/GeneralSettingsPresenter.java: -------------------------------------------------------------------------------- 1 | package com.stream_pi.server.window.settings.general; 2 | 3 | import com.stream_pi.server.connection.ClientConnections; 4 | import com.stream_pi.server.controller.ServerListener; 5 | import com.stream_pi.server.i18n.I18N; 6 | import com.stream_pi.server.info.ServerInfo; 7 | import com.stream_pi.server.window.ExceptionAndAlertHandler; 8 | import com.stream_pi.server.config.record.GeneralSettings; 9 | import com.stream_pi.util.alert.StreamPiAlert; 10 | import com.stream_pi.util.alert.StreamPiAlertButton; 11 | import com.stream_pi.util.alert.StreamPiAlertListener; 12 | import com.stream_pi.util.alert.StreamPiAlertType; 13 | import com.stream_pi.util.checkforupdates.CheckForUpdates; 14 | import com.stream_pi.util.checkforupdates.UpdateHyperlinkOnClick; 15 | import com.stream_pi.util.exception.SevereException; 16 | import com.stream_pi.util.platform.PlatformType; 17 | import javafx.application.HostServices; 18 | import javafx.beans.property.SimpleBooleanProperty; 19 | import javafx.beans.value.ObservableBooleanValue; 20 | import javafx.concurrent.Task; 21 | import javafx.event.ActionEvent; 22 | import javafx.scene.control.Button; 23 | 24 | public class GeneralSettingsPresenter implements GeneralSettingsViewListener 25 | { 26 | final GeneralSettingsModel model; 27 | final GeneralSettingsView view; 28 | 29 | private final ExceptionAndAlertHandler exceptionAndAlertHandler; 30 | 31 | private ServerListener serverListener; 32 | 33 | private HostServices hostServices; 34 | 35 | public GeneralSettingsPresenter(ExceptionAndAlertHandler exceptionAndAlertHandler, ServerListener serverListener, HostServices hostServices) 36 | { 37 | this.exceptionAndAlertHandler=exceptionAndAlertHandler; 38 | this.serverListener = serverListener; 39 | this.hostServices = hostServices; 40 | 41 | model = new GeneralSettingsModel(serverListener); 42 | view = new GeneralSettingsView(this); 43 | } 44 | 45 | public GeneralSettingsView getView() 46 | { 47 | return view; 48 | } 49 | 50 | public void load() 51 | { 52 | model.loadSettings(); 53 | view.updateFields(model.getCurrentSettings()); 54 | } 55 | 56 | @Override 57 | public ExceptionAndAlertHandler getExceptionAndAlertHandler() { 58 | return exceptionAndAlertHandler; 59 | } 60 | 61 | @Override 62 | public void onCheckForUpdatesButtonClicked(Button checkForUpdatesButton) 63 | { 64 | new CheckForUpdates(checkForUpdatesButton, 65 | PlatformType.SERVER, ServerInfo.getInstance().getVersion(), new UpdateHyperlinkOnClick() { 66 | @Override 67 | public void handle(ActionEvent actionEvent) { 68 | hostServices.showDocument(getURL()); 69 | } 70 | }); 71 | } 72 | 73 | @Override 74 | public void onRestartButtonClicked() 75 | { 76 | if (ClientConnections.getInstance().getConnections().size() > 0) 77 | { 78 | showRestartPrompt(I18N.getString("window.settings.GeneralSettings.restartPromptWarning")); 79 | } 80 | else 81 | { 82 | serverListener.restart(); 83 | } 84 | } 85 | 86 | private void showRestartPrompt(String promptText) 87 | { 88 | StreamPiAlert restartPrompt = new StreamPiAlert(promptText, 89 | StreamPiAlertType.WARNING, StreamPiAlertButton.YES, StreamPiAlertButton.NO 90 | ); 91 | 92 | restartPrompt.setOnClicked(new StreamPiAlertListener() { 93 | @Override 94 | public void onClick(StreamPiAlertButton s) { 95 | if(s.equals(StreamPiAlertButton.YES)) 96 | { 97 | serverListener.restart(); 98 | } 99 | } 100 | }); 101 | 102 | restartPrompt.show(); 103 | } 104 | 105 | @Override 106 | public void onFactoryResetButtonClicked() 107 | { 108 | StreamPiAlert confirmation = new StreamPiAlert( I18N.getString("window.settings.GeneralSettings.resetAreYouSure"), 109 | StreamPiAlertType.WARNING, StreamPiAlertButton.YES, StreamPiAlertButton.NO 110 | ); 111 | 112 | confirmation.setOnClicked(new StreamPiAlertListener() { 113 | @Override 114 | public void onClick(StreamPiAlertButton s) { 115 | if (s.equals(StreamPiAlertButton.YES)) { 116 | serverListener.factoryReset(); 117 | } 118 | } 119 | }); 120 | 121 | confirmation.show(); 122 | } 123 | 124 | @Override 125 | public void onSaveButtonClicked(Button saveButton, GeneralSettings newSettingsRecord) 126 | { 127 | new Thread(new Task() { 128 | @Override 129 | protected Void call() 130 | { 131 | try 132 | { 133 | settingsBeingSaved.set(true); 134 | 135 | boolean shouldServerBeReloaded = model.shouldServerBeReloaded(newSettingsRecord); 136 | boolean shouldServerDashboardBeReloaded = model.shouldServerDashboardBeReloaded(newSettingsRecord); 137 | 138 | model.saveSettings(newSettingsRecord); 139 | view.updateFields(model.getCurrentSettings()); 140 | 141 | if(shouldServerBeReloaded) 142 | { 143 | showRestartPrompt(I18N.getString("window.settings.GeneralSettings.needsToBeRestartedToApplySettings") + "\n" + I18N.getString("window.settings.GeneralSettings.restartPromptWarning")); 144 | } 145 | 146 | if(shouldServerDashboardBeReloaded) 147 | { 148 | serverListener.clearTemp(); 149 | } 150 | } 151 | catch (SevereException e) 152 | { 153 | exceptionAndAlertHandler.handleSevereException(e); 154 | } 155 | finally 156 | { 157 | settingsBeingSaved.set(false); 158 | } 159 | return null; 160 | } 161 | }).start(); 162 | } 163 | 164 | private final SimpleBooleanProperty settingsBeingSaved = new SimpleBooleanProperty(false); 165 | @Override 166 | public ObservableBooleanValue isSettingsBeingSaved() { 167 | return settingsBeingSaved; 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/settings/general/GeneralSettingsViewListener.java: -------------------------------------------------------------------------------- 1 | package com.stream_pi.server.window.settings.general; 2 | 3 | import com.stream_pi.server.window.ExceptionAndAlertHandler; 4 | import com.stream_pi.server.config.record.GeneralSettings; 5 | import javafx.beans.value.ObservableBooleanValue; 6 | import javafx.scene.control.Button; 7 | 8 | public interface GeneralSettingsViewListener 9 | { 10 | ExceptionAndAlertHandler getExceptionAndAlertHandler(); 11 | void onCheckForUpdatesButtonClicked(Button checkForUpdatesButton); 12 | void onFactoryResetButtonClicked(); 13 | 14 | void onRestartButtonClicked(); 15 | 16 | void onSaveButtonClicked(Button saveButton, GeneralSettings newSettingsRecord); 17 | 18 | ObservableBooleanValue isSettingsBeingSaved(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/windowmenubar/WindowMenuBar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.windowmenubar; 16 | 17 | 18 | import com.stream_pi.server.i18n.I18N; 19 | import com.stream_pi.server.window.windowmenubar.filemenu.FileMenu; 20 | import com.stream_pi.server.window.windowmenubar.helpmenu.HelpMenu; 21 | import javafx.scene.control.*; 22 | 23 | public class WindowMenuBar extends MenuBar 24 | { 25 | private final FileMenu fileMenu; 26 | private final HelpMenu helpMenu; 27 | private final Label showIPPortConfigurationMenuLabel; 28 | 29 | public WindowMenuBar() 30 | { 31 | getStyleClass().add("menu_bar"); 32 | 33 | fileMenu = new FileMenu(); 34 | helpMenu = new HelpMenu(); 35 | 36 | Menu showIPPortConfigurationMenu = new Menu(); 37 | showIPPortConfigurationMenu.getStyleClass().add("menu_bar_show_ip_port_configuration_menu"); 38 | showIPPortConfigurationMenuLabel = new Label(I18N.getString("window.windowmenubar.WindowMenuBar.showIPPortConfiguration")); 39 | showIPPortConfigurationMenuLabel.getStyleClass().add("menu_bar_show_ip_port_configuration_menu_label"); 40 | showIPPortConfigurationMenu.setGraphic(showIPPortConfigurationMenuLabel); 41 | 42 | getMenus().addAll(fileMenu, helpMenu, showIPPortConfigurationMenu); 43 | } 44 | 45 | 46 | public FileMenu getFileMenu() 47 | { 48 | return fileMenu; 49 | } 50 | 51 | public HelpMenu getHelpMenu() 52 | { 53 | return helpMenu; 54 | } 55 | 56 | public Label getShowIPPortConfigurationMenuLabel() 57 | { 58 | return showIPPortConfigurationMenuLabel; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/windowmenubar/filemenu/FileMenu.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.windowmenubar.filemenu; 16 | 17 | import com.stream_pi.server.i18n.I18N; 18 | import javafx.scene.control.Menu; 19 | import javafx.scene.control.MenuItem; 20 | 21 | public class FileMenu extends Menu 22 | { 23 | private SettingsMenu settingsMenu; 24 | private MenuItem exitMenuItem; 25 | private MenuItem disconnectFromAllClients; 26 | 27 | public FileMenu() 28 | { 29 | setText(I18N.getString("window.windowmenubar.filemenu.FileMenu.file")); 30 | getStyleClass().add("menu_bar_file_menu"); 31 | 32 | settingsMenu = new SettingsMenu(); 33 | 34 | disconnectFromAllClients = new MenuItem(I18N.getString("window.windowmenubar.filemenu.FileMenu.disconnectFromAllClients")); 35 | exitMenuItem = new MenuItem(I18N.getString("exit")); 36 | 37 | getItems().addAll(settingsMenu, disconnectFromAllClients, exitMenuItem); 38 | } 39 | 40 | public SettingsMenu getSettingsMenu() 41 | { 42 | return settingsMenu; 43 | } 44 | 45 | public MenuItem getDisconnectFromAllClients() 46 | { 47 | return disconnectFromAllClients; 48 | } 49 | 50 | public MenuItem getExitMenuItem() 51 | { 52 | return exitMenuItem; 53 | } 54 | } -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/windowmenubar/filemenu/SettingsMenu.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.windowmenubar.filemenu; 16 | 17 | import com.stream_pi.server.i18n.I18N; 18 | import javafx.scene.control.Menu; 19 | import javafx.scene.control.MenuItem; 20 | 21 | public class SettingsMenu extends Menu 22 | { 23 | private MenuItem generalSettingsMenuItem, pluginsSettingsMenuItem, themesSettingsMenuItem, clientSettingsMenuItem; 24 | 25 | public SettingsMenu() 26 | { 27 | setText(I18N.getString("window.windowmenubar.filemenu.SettingsMenu.settings")); 28 | 29 | generalSettingsMenuItem = new MenuItem(I18N.getString("general")); 30 | pluginsSettingsMenuItem = new MenuItem(I18N.getString("plugins")); 31 | themesSettingsMenuItem = new MenuItem(I18N.getString("themes")); 32 | clientSettingsMenuItem = new MenuItem(I18N.getString("clients")); 33 | 34 | getItems().addAll(generalSettingsMenuItem, pluginsSettingsMenuItem, themesSettingsMenuItem, clientSettingsMenuItem); 35 | } 36 | 37 | public MenuItem getGeneralSettingsMenuItem() 38 | { 39 | return generalSettingsMenuItem; 40 | } 41 | 42 | public MenuItem getPluginsSettingsMenuItem() 43 | { 44 | return pluginsSettingsMenuItem; 45 | } 46 | 47 | public MenuItem getThemesSettingsMenuItem() 48 | { 49 | return themesSettingsMenuItem; 50 | } 51 | 52 | public MenuItem getClientSettingsMenuItem() 53 | { 54 | return clientSettingsMenuItem; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/stream_pi/server/window/windowmenubar/helpmenu/HelpMenu.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | package com.stream_pi.server.window.windowmenubar.helpmenu; 16 | 17 | import com.stream_pi.server.i18n.I18N; 18 | import javafx.scene.control.Menu; 19 | import javafx.scene.control.MenuItem; 20 | import javafx.scene.control.SeparatorMenuItem; 21 | 22 | public class HelpMenu extends Menu 23 | { 24 | private MenuItem websiteMenuItem, donateMenuItem, aboutMenuItem; 25 | 26 | public HelpMenu() 27 | { 28 | setText(I18N.getString("window.windowmenubar.helpmenu.HelpMenu.help")); 29 | getStyleClass().add("menu_bar_help_menu"); 30 | 31 | websiteMenuItem = new MenuItem(I18N.getString("website")); 32 | donateMenuItem = new MenuItem(I18N.getString("donate")); 33 | aboutMenuItem = new MenuItem(I18N.getString("about")); 34 | 35 | getItems().addAll(websiteMenuItem, new SeparatorMenuItem(), donateMenuItem, aboutMenuItem); 36 | } 37 | 38 | public MenuItem getWebsiteMenuItem() 39 | { 40 | return websiteMenuItem; 41 | } 42 | 43 | public MenuItem getDonateMenuItem() 44 | { 45 | return donateMenuItem; 46 | } 47 | 48 | public MenuItem getAboutMenuItem() 49 | { 50 | return aboutMenuItem; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | module com.stream_pi.server 16 | { 17 | 18 | uses com.stream_pi.action_api.action.Action; 19 | uses com.stream_pi.action_api.externalplugin.NormalAction; 20 | uses com.stream_pi.action_api.externalplugin.ExternalPlugin; 21 | 22 | requires com.stream_pi.action_api; 23 | requires com.stream_pi.util; 24 | requires com.stream_pi.theme_api; 25 | 26 | requires org.kordamp.ikonli.javafx; 27 | 28 | requires java.xml; 29 | 30 | requires javafx.base; 31 | requires javafx.graphics; 32 | requires javafx.controls; 33 | requires javafx.media; 34 | 35 | requires eu.hansolo.medusa; 36 | 37 | requires java.management; 38 | requires java.desktop; 39 | 40 | requires java.sql; 41 | 42 | opens com.stream_pi.server.window.settings; 43 | 44 | requires org.controlsfx.controls; 45 | 46 | exports com.stream_pi.server; 47 | opens com.stream_pi.server.window.settings.about; 48 | opens com.stream_pi.server.combobox; 49 | } -------------------------------------------------------------------------------- /src/main/resources/com/stream_pi/server/Default.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stream-pi/server/a7c11776d67cc5efe6d43b184418253ee5f1f389/src/main/resources/com/stream_pi/server/Default.zip -------------------------------------------------------------------------------- /src/main/resources/com/stream_pi/server/default_icons.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | .alert_error_icon 16 | { 17 | -fx-icon-color: RED; 18 | } 19 | 20 | .alert_information_icon 21 | { 22 | -fx-icon-color: BLUE; 23 | } 24 | 25 | .alert_warning_icon 26 | { 27 | -fx-icon-color: #ffcc00; 28 | } 29 | 30 | .action_details_pane_delete_button_icon, .action_box_delete_menu_item_icon 31 | { 32 | -fx-icon-color:red; 33 | } 34 | 35 | .action_box_toggle_on 36 | { 37 | -fx-icon-code: fas-toggle-on; 38 | } 39 | 40 | .action_box_toggle_off 41 | { 42 | -fx-icon-code: fas-toggle-off; 43 | } 44 | 45 | .action_details_pane_reset_button_icon 46 | { 47 | -fx-icon-color:orange; 48 | } -------------------------------------------------------------------------------- /src/main/resources/com/stream_pi/server/i18n/i18n.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | # Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | 15 | # Available Languages 16 | 17 | en = English 18 | de_DE = Deutsch (Deutschland) 19 | en_GB = English (Great Britain) 20 | en_IN = English (India) 21 | en_US = English (United States) 22 | es_ES = Español (Spain) 23 | fr = Français 24 | hi = हिन्दी 25 | nl_NL = Nederlands (Nederland) 26 | -------------------------------------------------------------------------------- /src/main/resources/com/stream_pi/server/icons/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stream-pi/server/a7c11776d67cc5efe6d43b184418253ee5f1f389/src/main/resources/com/stream_pi/server/icons/16x16.png -------------------------------------------------------------------------------- /src/main/resources/com/stream_pi/server/icons/24x24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stream-pi/server/a7c11776d67cc5efe6d43b184418253ee5f1f389/src/main/resources/com/stream_pi/server/icons/24x24.png -------------------------------------------------------------------------------- /src/main/resources/com/stream_pi/server/icons/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stream-pi/server/a7c11776d67cc5efe6d43b184418253ee5f1f389/src/main/resources/com/stream_pi/server/icons/256x256.png -------------------------------------------------------------------------------- /src/main/resources/com/stream_pi/server/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stream-pi/server/a7c11776d67cc5efe6d43b184418253ee5f1f389/src/main/resources/com/stream_pi/server/icons/32x32.png -------------------------------------------------------------------------------- /src/main/resources/com/stream_pi/server/icons/48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stream-pi/server/a7c11776d67cc5efe6d43b184418253ee5f1f389/src/main/resources/com/stream_pi/server/icons/48x48.png -------------------------------------------------------------------------------- /src/main/resources/com/stream_pi/server/info/LICENSE: -------------------------------------------------------------------------------- 1 | Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 2 | Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | 14 | Opensource Libraries/Technology used in Stream-Pi Server: 15 | 16 | 1. JavaFX - GNU General Public License with Classpath Exception 17 | https://openjdk.java.net/legal/gplv2+ce.html 18 | 19 | 2. Ikonli - Apache License 20 | https://github.com/kordamp/ikonli/blob/master/LICENSE 21 | 22 | 3. ControlsFX - BSD 3-Clause License 23 | https://github.com/controlsfx/controlsfx/blob/jfx-13/license.txt 24 | 25 | 4. Medusa - Apache License 2.0 26 | https://github.com/HanSolo/medusa/blob/master/LICENSE -------------------------------------------------------------------------------- /src/main/resources/com/stream_pi/server/info/build.properties: -------------------------------------------------------------------------------- 1 | #maven.buildNumber.plugin properties file 2 | #Tue Dec 27 13:53:44 IST 2022 3 | build.number=${buildNumber} 4 | buildNumber=400 5 | -------------------------------------------------------------------------------- /src/main/resources/com/stream_pi/server/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Stream-Pi - Free, Open-Source, Modular, Cross-Platform and Programmable Macro Pad 3 | * Copyright (C) 2019-2022 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones) 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | 16 | 17 | .about_donate_hyperlink 18 | { 19 | -fx-padding : 10 0 0 0; 20 | -fx-font-size : 2em; 21 | -fx-border-color: transparent; 22 | } 23 | 24 | .plugins_settings_each_plugin_button_bar 25 | { 26 | -fx-alignment:CENTER_RIGHT; 27 | } 28 | 29 | .theme_settings_each_theme_box, .plugins_settings_each_plugin_box, .clients_settings_each_client_box 30 | { 31 | -fx-border-width : 0 0 1 0; 32 | -fx-border-color : grey; 33 | } 34 | 35 | .plugins_settings_each_plugin_heading_label, .themes_settings_each_theme_heading, .client_settings_each_client_nick_name_label 36 | { 37 | -fx-font-size : 1.5em; 38 | } 39 | 40 | .plugins_settings 41 | { 42 | -fx-alignment: TOP_CENTER; 43 | } 44 | 45 | .action_box 46 | { 47 | -fx-border-width: 1px; 48 | -fx-border-color : grey; 49 | } 50 | 51 | .action_box_display_text_label 52 | { 53 | 54 | } 55 | 56 | .action_box_icon_present 57 | { 58 | 59 | } 60 | 61 | .action_box_valid 62 | { 63 | -fx-border-color: grey; 64 | } 65 | 66 | .action_box_invalid 67 | { 68 | -fx-border-color: red; 69 | } 70 | 71 | .action_details_pane_heading_label 72 | { 73 | -fx-font-size : 1.5em; 74 | } 75 | 76 | .alert_header 77 | { 78 | -fx-padding: 10; 79 | } 80 | 81 | .alert_pane 82 | { 83 | -fx-border-width : 5; 84 | -fx-border-radius : 5; 85 | -fx-background-radius : 5; 86 | -fx-max-width : 400; 87 | -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0.0 , 0 ); 88 | } 89 | 90 | .alert_header_icon 91 | { 92 | -fx-icon-size : 30; 93 | } 94 | 95 | .alert_content_pane 96 | { 97 | -fx-padding: 5; 98 | } 99 | 100 | .alert_pane_popup_node_parent 101 | { 102 | -fx-background-color : rgba(0,0,0,0.5); 103 | -fx-padding: 10; 104 | } 105 | 106 | .alert_pane_header_text 107 | { 108 | -fx-font-size: 1.5em; 109 | } 110 | 111 | .alert_button_bar 112 | { 113 | -fx-alignment: CENTER_RIGHT; 114 | -fx-spacing: 5; 115 | -fx-padding: 5; 116 | } 117 | 118 | .alert_scroll_pane { 119 | -fx-max-height : 300; 120 | } 121 | 122 | .plugins_pane 123 | { 124 | -fx-spacing: 5; 125 | -fx-padding: 10; 126 | } 127 | 128 | .plugins_pane_each_plugin_button_imageview 129 | { 130 | -fx-width:20; 131 | -fx-height:20; 132 | } 133 | 134 | 135 | .first_time_use_pane 136 | { 137 | -fx-spacing: 10; 138 | -fx-padding : 10; 139 | } 140 | 141 | .first_time_use_pane_heading_label 142 | { 143 | -fx-font-size: 2em; 144 | } 145 | 146 | .first_time_use_pane_stackpane 147 | { 148 | 149 | } 150 | 151 | .first_time_use_pane_license 152 | { 153 | -fx-spacing : 10; 154 | } 155 | 156 | .first_time_use_pane_final_config 157 | { 158 | } 159 | 160 | .first_time_use_pane_final_config_label 161 | { 162 | -fx-padding: 0 0 15 0; 163 | } 164 | 165 | .first_time_use_pane_final_config_security_warning_label 166 | { 167 | -fx-padding: 15 20 0 20; 168 | -fx-alignment: center; 169 | -fx-text-alignment: center; 170 | -fx-font-weight: bold; 171 | } 172 | 173 | .first_time_use_welcome_pane 174 | { 175 | -fx-spacing: 10.0; 176 | -fx-alignment: CENTER; 177 | } 178 | 179 | .first_time_use_welcome_pane_welcome_label 180 | { 181 | -fx-font-size: 2.5em; 182 | } 183 | 184 | .first_time_use_welcome_pane_next_to_continue_label 185 | { 186 | -fx-padding: 0 0 15 0; 187 | } 188 | 189 | .plugins_settings_scroll_pane, .themes_settings_scroll_pane, .clients_settings_scroll_pane 190 | { 191 | -fx-padding: 10 0 0 0; 192 | } 193 | 194 | .plugins_settings_each_plugin_box, .theme_settings_each_theme_box, .clients_settings_each_client_box 195 | { 196 | -fx-spacing : 5; 197 | -fx-padding : 10 0 10 0; 198 | } 199 | 200 | .plugins_pane_each_plugin_box_parent, .plugins_pane_each_plugin_box 201 | { 202 | -fx-spacing : 5; 203 | } 204 | 205 | .about 206 | { 207 | -fx-spacing : 5; 208 | } 209 | 210 | .about_links_box 211 | { 212 | -fx-spacing : 15; 213 | } 214 | 215 | 216 | .action_details_pane_delete_button 217 | { 218 | -fx-text-fill : red; 219 | } 220 | 221 | .action_box_delete_menu_item .label 222 | { 223 | -fx-text-fill: red; 224 | } 225 | 226 | .action_details_pane_reset_button 227 | { 228 | -fx-text-fill : orange; 229 | } 230 | 231 | .client_and_profile_selector_pane_stack 232 | { 233 | -fx-spacing: 5; 234 | } 235 | 236 | .plugins_settings, .themes_settings, .clients_settings, .general_settings 237 | { 238 | -fx-padding: 0 0 5 0; 239 | } 240 | 241 | /*Alert Classes added to default stylesheet to show init error, if occurs */ 242 | 243 | .alert_pane 244 | { 245 | -fx-background-color : white; 246 | -fx-border-color : white; 247 | } 248 | 249 | .alert_content_pane 250 | { 251 | -fx-background-color: white; 252 | -fx-padding: 5; 253 | } 254 | 255 | .alert_scroll_pane 256 | { 257 | -fx-background: white; 258 | -fx-border-color:white; 259 | } 260 | 261 | .plugins_pane_accordion_scroll_pane 262 | { 263 | -fx-background-color: transparent; 264 | } 265 | 266 | .plugins_pane_accordion_scroll_pane .viewport 267 | { 268 | -fx-background-color: transparent; 269 | } 270 | 271 | .alert_button_bar 272 | { 273 | -fx-background-color:white; 274 | } 275 | 276 | .split-pane-divider { 277 | -fx-padding: 2; 278 | } 279 | 280 | .separator_ui_label 281 | { 282 | -fx-text-fill: grey; 283 | } 284 | 285 | .about_license_contributors_disclaimer_label 286 | { 287 | -fx-min-height : 50; 288 | } 289 | 290 | .action_box_selected 291 | { 292 | -fx-border-width: 2px; 293 | -fx-border-insets: -2px; 294 | -fx-border-color: orange; 295 | } 296 | 297 | .general_settings_sub_heading 298 | { 299 | -fx-font-size: 1.5em; 300 | -fx-padding: 10 0 5 0; 301 | } 302 | 303 | .general_settings_buttons_vbox 304 | { 305 | -fx-spacing: 5; 306 | -fx-alignment: CENTER_RIGHT; 307 | } 308 | 309 | .general_settings_grid_pane 310 | { 311 | -fx-vgap:10; 312 | -fx-hgap:10; 313 | -fx-padding: 0 10 0 10; 314 | } 315 | 316 | .themes_settings_vbox, .plugins_settings_vbox, .clients_settings_vbox 317 | { 318 | -fx-padding: 0 5 0 0; 319 | } 320 | 321 | .plugins_settings_unsaved_changes_label 322 | { 323 | -fx-padding: 10 0 10 0; 324 | -fx-font-size: 1.5em; 325 | -fx-text-fill: red; 326 | } 327 | 328 | .general_settings 329 | { 330 | -fx-spacing: 5; 331 | -fx-alignment: CENTER; 332 | } 333 | 334 | .settings_base 335 | { 336 | -fx-alignment: TOP_RIGHT; 337 | } 338 | 339 | .scroll-pane:focused 340 | { 341 | -fx-background-color: transparent, transparent, transparent; 342 | -fx-background-insets: 0, 1, 2; 343 | -fx-background-radius: 5, 4, 3; 344 | } 345 | 346 | .invalid_ip_prompt_label 347 | { 348 | -fx-padding: 0 0 15 0; 349 | } 350 | 351 | .user_choose_ip_and_port_dialog 352 | { 353 | -fx-spacing: 10; 354 | } 355 | 356 | .settings_about_tab_app_icon 357 | { 358 | -fx-padding: 50 50 50 50; 359 | } 360 | 361 | .action_grid_pane 362 | { 363 | -fx-background-color: transparent; 364 | } 365 | 366 | .menu-item 367 | { 368 | -fx-padding: 3 5 3 5; 369 | } 370 | 371 | .menu 372 | { 373 | -fx-padding: 3 5 3 5; 374 | } 375 | 376 | .menu_bar_show_ip_port_configuration_menu_label:hover 377 | { 378 | -fx-text-fill: white; 379 | } 380 | 381 | .menu_bar_show_ip_port_configuration_menu_label 382 | { 383 | -fx-background-insets: -5; 384 | -fx-background-color: transparent; 385 | } 386 | 387 | .validated_text_field_error_prompt_label 388 | { 389 | -fx-text-fill: red; 390 | } -------------------------------------------------------------------------------- /style_classes.txt: -------------------------------------------------------------------------------- 1 | This list is outdated. Some classes are missing/no longer work. This will be updated soon 2 | 3 | dashboard 4 | Action Details Pane - action_details_pane 5 | Heading HBox - action_details_pane_heading_box 6 | Heading Label - action_details_pane_heading_label 7 | Scroll Pane - action_details_pane_scroll_pane 8 | VBox (Content Pane) - action_details_pane_vbox 9 | Bottom Button Bar - action_details_pane_button_bar 10 | Delete Button - action_details_pane_delete_button 11 | Icon - action_details_pane_delete_button_icon 12 | 13 | Action Grid Pane (Scroll Pane) - action_grid_pane_parent 14 | Main Grid Pane - action_grid_pane 15 | 16 | Action Box - action_box 17 | if folder back button : 18 | Icon : folder_action_back_button_icon 19 | 20 | Is Icon Present ? 21 | yes : action_box_icon_present 22 | no : action_box_icon_not_present 23 | Is Action Valid (is plugin by module name found) ? 24 | yes : action_box_valid 25 | no : action_box_invalid 26 | 27 | Display Text Label - action_box_display_text_label 28 | 29 | Client & Profile Selector Pane - client_and_profile_selector_pane 30 | Stack VBox - client_and_profile_selector_pane_stack 31 | "No Clients Connected" Label - client_and_profile_selector_pane_no_clients_connected_label 32 | Client Combo Box - client_and_profile_selector_pane_client_selector_combo_box 33 | Profile Combo Box - client_and_profile_selector_pane_profile_selector_combo_box 34 | 35 | Plugins Pane - plugins_pane 36 | "Plugins" Label - plugins_pane_top_label 37 | 38 | Accordion - plugins_pane_accordion 39 | Category - plugins_pane_each_plugin_category_titled_pane 40 | VBox - plugins_pane_each_plugin_box_parent 41 | HBox - plugins_pane_each_plugin_box 42 | Each Plugin Button - plugins_pane_each_plugin_button 43 | Icon - plugins_pane_each_plugin_button_icon 44 | OR 45 | ImageView (NOT RECOMMENDED FOR USE) - plugins_pane_each_plugin_button_imageview] 46 | 47 | Help Button - plugins_pane_each_plugin_button_help_icon 48 | Icon - plugins_pane_each_plugin_button_help_button_icon 49 | 50 | HBox - plugins_pane_settings_button 51 | Settings Button - plugins_pane_settings_button 52 | 53 | settings 54 | General - general_settings 55 | 56 | Plugins - plugins_settings 57 | Scroll Pane (CENTER) - plugins_settings_scroll_pane 58 | VBox - plugins_settings_vbox 59 | "No Plugins Present Label" - plugins_pane_no_plugins_installed_label 60 | 61 | Each Plugin Box - plugins_settings_each_plugin_box 62 | Header HBox - plugins_settings_each_plugin_header 63 | Heading Label - plugins_settings_each_plugin_heading_label 64 | Help Button - plugins_settings_each_plugin_help_button 65 | Help Icon - plugins_settings_each_plugin_help_icon 66 | 67 | Author Label - plugins_settings_each_plugin_author_label 68 | Module Label - plugins_settings_each_plugin_module_label 69 | Version Label - plugins_settings_each_plugin_version_label 70 | 71 | Server Properties Box - plugins_settings_each_plugin_server_properties_box 72 | 73 | buttonBarHBox - plugins_settings_each_plugin_button_bar 74 | 75 | Themes - themes_settings 76 | Scroll Pane (CENTER) - themes_settings_scroll_pane 77 | VBox - themes_settings_vbox 78 | Each Theme Box - theme_settings_each_theme_box 79 | Heading HBox - themes_settings_each_theme_header 80 | Heading Label - themes_settings_each_theme_heading 81 | Help Button - themes_settings_each_theme_help_button 82 | Help Icon - themes_settings_each_theme_help_icon 83 | 84 | Author Label - themes_settings_each_theme_author_label 85 | Full Name Label - themes_settings_each_theme_full_name_label 86 | Version Label - themes_settings_each_theme_version_label 87 | 88 | Toggle Button HBox - themes_settings_each_theme_toggle_button_parent 89 | Toggle Button - themes_settings_each_theme_toggle_button 90 | 91 | 92 | 93 | Client - clients_settings 94 | Scroll Pane (CENTER) - clients_settings_scroll_pane 95 | VBox - clients_settings_vbox 96 | Each Client Box - clients_settings_each_client_box 97 | Nick Name Label - client_settings_each_client_nick_name_label 98 | Socket Connection Label - client_settings_each_client_socket_connection_label 99 | Platform Label - client_settings_each_client_platform_label 100 | Version Label - client_settings_each_client_version_label 101 | 102 | Profiles Accordion - client_settings_each_client_profiles_accordion 103 | Each Titled Pane - client_settings_each_client_accordion_each_titled_pane 104 | Content VBox - client_settings_each_client_accordion_each_profile_box 105 | About - about 106 | 107 | Tab Pane - settings_about_tab_internal 108 | License Tab (Text Area) - about_license_text_area 109 | Contributors Tab (VBox) - about_license_contributors_vbox 110 | Table View - about_license_contributors_table_view 111 | Disclaimer Label - about_license_contributors_disclaimer_label 112 | Contact Tab (Scroll Pane) - about_contact_tab_scroll_pane 113 | 114 | DONATE Hyperlink - about_donate_hyperlink 115 | 116 | Version Label - about_version_label 117 | Comm Standard Label - about_comm_standard_label 118 | Min Theme API Label - about_min_theme_api_label 119 | Min Action API Label - about_min_action_api_label 120 | Current Action API Label - about_current_action_api_label 121 | 122 | 123 | --------------------------------------------------------------------------------