From cda10c54039d4784387c7f9229a74865a19e634b Mon Sep 17 00:00:00 2001 From: tobias <thinkdifferent055@gmail.com> Date: Sat, 20 Nov 2021 18:01:22 +0100 Subject: [PATCH] #174 - Add settings section for remote playwall instances --- .../de/tobias/playpad/view/PseudoClasses.java | 2 - .../playpad/settings/GlobalSettings.java | 14 +- .../api/settings/WebApiRemoteSettings.java | 48 +++++++ .../settings/WebApiSettings.java | 15 +- .../plugin/webapi/lang/base_de.properties | 16 ++- .../plugin/webapi/view/WebApiSettings.fxml | 63 +++++++-- .../playpad/plugin/api/WebApiPlugin.scala | 6 +- .../WebApiSettingsViewController.scala | 130 ++++++++++++++++++ .../WebApiSettingsViewController.scala | 81 ----------- 9 files changed, 262 insertions(+), 113 deletions(-) create mode 100644 PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/settings/WebApiRemoteSettings.java rename PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/{websocket => }/settings/WebApiSettings.java (55%) create mode 100644 PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/settings/WebApiSettingsViewController.scala delete mode 100644 PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettingsViewController.scala diff --git a/PlayWall/src/main/java/de/tobias/playpad/view/PseudoClasses.java b/PlayWall/src/main/java/de/tobias/playpad/view/PseudoClasses.java index 3af53dd3..1a62b1c1 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/view/PseudoClasses.java +++ b/PlayWall/src/main/java/de/tobias/playpad/view/PseudoClasses.java @@ -15,6 +15,4 @@ public class PseudoClasses { public static final PseudoClass DRAG_CLASS = PseudoClass.getPseudoClass("drag"); public static final PseudoClass DEACTIVATED_CLASS = PseudoClass.getPseudoClass("deactivated"); - - } diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/settings/GlobalSettings.java b/PlayWallCore/src/main/java/de/tobias/playpad/settings/GlobalSettings.java index 38d09edc..3ca3f35b 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/settings/GlobalSettings.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/settings/GlobalSettings.java @@ -34,7 +34,7 @@ public class GlobalSettings { private Path savePath; // Key Binding - private KeyCollection keyCollection = new KeyCollection(); + private final KeyCollection keyCollection = new KeyCollection(); // Update private boolean autoUpdate = true; @@ -114,13 +114,11 @@ public class GlobalSettings { return openLastDocument; } - public boolean isEnableAutosave() - { + public boolean isEnableAutosave() { return enableAutosave; } - public int getAutosaveIntervalInMinutes() - { + public int getAutosaveIntervalInMinutes() { return autosaveIntervalInMinutes; } @@ -169,13 +167,11 @@ public class GlobalSettings { this.openLastDocument = openLastDocument; } - public void setEnableAutosave(boolean enableAutosave) - { + public void setEnableAutosave(boolean enableAutosave) { this.enableAutosave = enableAutosave; } - public void setAutosaveIntervalInMinutes(int autosaveIntervalInMinutes) - { + public void setAutosaveIntervalInMinutes(int autosaveIntervalInMinutes) { this.autosaveIntervalInMinutes = autosaveIntervalInMinutes; } diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/settings/WebApiRemoteSettings.java b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/settings/WebApiRemoteSettings.java new file mode 100644 index 00000000..40c5d72a --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/settings/WebApiRemoteSettings.java @@ -0,0 +1,48 @@ +package de.tobias.playpad.plugin.api.settings; + +import de.thecodelabs.storage.settings.annotation.Key; +import de.tobias.playpad.Displayable; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; + +public class WebApiRemoteSettings implements Displayable { + @Key + private String name; + @Key + private String serverAddress; + @Key + private int port; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + displayProperty.set(name); + } + + public String getServerAddress() { + return serverAddress; + } + + public void setServerAddress(String serverAddress) { + this.serverAddress = serverAddress; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + private final StringProperty displayProperty = new SimpleStringProperty(); + + @Override + public StringProperty displayProperty() { + displayProperty.set(name); + return displayProperty; + } +} diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettings.java b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/settings/WebApiSettings.java similarity index 55% rename from PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettings.java rename to PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/settings/WebApiSettings.java index c5b35f5f..0d34d964 100644 --- a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettings.java +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/settings/WebApiSettings.java @@ -1,14 +1,19 @@ -package de.tobias.playpad.plugin.api.websocket.settings; +package de.tobias.playpad.plugin.api.settings; import de.thecodelabs.storage.settings.annotation.FilePath; import de.thecodelabs.storage.settings.annotation.Key; +import java.util.ArrayList; +import java.util.List; + @FilePath("webapi.json") public class WebApiSettings { @Key private boolean enabled = false; @Key private int port = 9876; + @Key + private List<WebApiRemoteSettings> remoteSettings = new ArrayList<>(); public boolean isEnabled() { return enabled; @@ -25,4 +30,12 @@ public class WebApiSettings { public void setPort(int port) { this.port = port; } + + public List<WebApiRemoteSettings> getRemoteSettings() { + return remoteSettings; + } + + public void setRemoteSettings(List<WebApiRemoteSettings> remoteSettings) { + this.remoteSettings = remoteSettings; + } } diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base_de.properties b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base_de.properties index 0b7b9cf8..7a95dbf9 100644 --- a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base_de.properties +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base_de.properties @@ -1,5 +1,13 @@ webapi.settings=WebAPI -webapi.settings.enable=WebAPI -webapi.settings.enabled=Aktiv -webapi.settings.port=Port -webapi.settings.restart=\u00C4nderungen an den Einstellungen werden erst mit einem Neustart von PlayWall wirksam. \ No newline at end of file +webapi-settings.server=Fernsteuerung +webapi.settings.server.enable=WebAPI +webapi.settings.server.enabled=Aktiv +webapi.settings.server.port=Port +webapi.settings.server.restart=\u00C4nderungen an den Einstellungen werden erst mit einem Neustart von PlayWall wirksam. + +webapi-settings.remote=PlayWall Instanzen fernsteuern +webapi-settings.remote.name=Name +webapi-settings.remote.address=IP-Address/Host +webapi-settings.remote.port=Port +webapi-settings.remote.add=Hinzuf\u00FCgen +webapi-settings.remote.remove=L\u00F6schen diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml index 473dba8d..affd019e 100644 --- a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml @@ -2,32 +2,69 @@ <?import de.thecodelabs.utils.ui.scene.input.NumberTextField?> <?import javafx.geometry.Insets?> -<?import javafx.scene.control.CheckBox?> -<?import javafx.scene.control.Label?> -<?import javafx.scene.layout.HBox?> -<?import javafx.scene.layout.VBox?> -<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" spacing="14.0" - xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"> +<?import javafx.scene.control.*?> +<?import javafx.scene.layout.*?> +<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" spacing="14.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1"> <children> + <Label text="%webapi-settings.server" underline="true" /> <HBox alignment="CENTER_LEFT" spacing="14.0"> <children> - <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%webapi.settings.enable"/> - <CheckBox fx:id="activeCheckbox" mnemonicParsing="false" text="%webapi.settings.enabled"/> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%webapi.settings.server.enable" /> + <CheckBox fx:id="activeCheckbox" mnemonicParsing="false" text="%webapi.settings.server.enabled" /> </children> </HBox> <HBox alignment="CENTER_LEFT" spacing="14.0"> <children> - <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%webapi.settings.port"/> - <NumberTextField fx:id="portTextField"/> + <Label alignment="CENTER_RIGHT" prefWidth="150.0" text="%webapi.settings.server.port" /> + <NumberTextField fx:id="portTextField" /> </children> </HBox> - <Label text="%webapi.settings.restart"> + <Label text="%webapi.settings.server.restart"> <padding> - <Insets left="164.0"/> + <Insets left="164.0" /> </padding> </Label> + <Separator prefWidth="200.0" /> + <Label text="%webapi-settings.remote" underline="true" /> + <HBox spacing="14.0" VBox.vgrow="ALWAYS"> + <children> + <VBox spacing="14.0"> + <children> + <ListView fx:id="remoteListView" VBox.vgrow="ALWAYS" /> + <HBox spacing="14.0"> + <children> + <Button fx:id="remoteAddButton" onAction="#onRemoteAddButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="%webapi-settings.remote.add" HBox.hgrow="ALWAYS" /> + <Button fx:id="remoteDeleteButton" onAction="#onRemoteDeleteButton" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="%webapi-settings.remote.remove" HBox.hgrow="ALWAYS" /> + </children> + </HBox> + </children> + </VBox> + <VBox spacing="14.0"> + <children> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="100.0" text="%webapi-settings.remote.name" /> + <TextField fx:id="remoteNameTextField" /> + </children> + </HBox> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="100.0" text="%webapi-settings.remote.address" /> + <TextField fx:id="remoteAddressTextField" /> + </children> + </HBox> + <HBox alignment="CENTER_LEFT" spacing="14.0"> + <children> + <Label alignment="CENTER_RIGHT" prefWidth="100.0" text="%webapi-settings.remote.port" /> + <NumberTextField fx:id="remotePortTextField" /> + </children> + </HBox> + </children> + </VBox> + </children> + </HBox> </children> <padding> - <Insets bottom="14.0" left="14.0" right="14.0" top="14.0"/> + <Insets bottom="14.0" left="14.0" right="14.0" top="14.0" /> </padding> </VBox> diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/WebApiPlugin.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/WebApiPlugin.scala index 0d4d7321..986fd6bb 100644 --- a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/WebApiPlugin.scala +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/WebApiPlugin.scala @@ -1,7 +1,5 @@ package de.tobias.playpad.plugin.api -import java.nio.file.{Files, Path} - import de.thecodelabs.logger.Logger import de.thecodelabs.plugins.PluginDescriptor import de.thecodelabs.plugins.versionizer.PluginArtifact @@ -10,12 +8,14 @@ import de.thecodelabs.utils.application.ApplicationUtils import de.thecodelabs.utils.application.container.PathType import de.thecodelabs.utils.util.Localization import de.tobias.playpad.PlayPadPlugin +import de.tobias.playpad.plugin.api.settings.{WebApiSettings, WebApiSettingsViewController} import de.tobias.playpad.plugin.api.websocket.WebSocketHandler import de.tobias.playpad.plugin.api.websocket.listener.{PadStatusListener, ProjectListener} -import de.tobias.playpad.plugin.api.websocket.settings.{WebApiSettings, WebApiSettingsViewController} import de.tobias.playpad.plugin.{Module, PlayPadPluginStub} import spark.{Request, Response, Spark} +import java.nio.file.{Files, Path} + class WebApiPlugin extends PlayPadPluginStub with PluginArtifact { private var module: Module = _ diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/settings/WebApiSettingsViewController.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/settings/WebApiSettingsViewController.scala new file mode 100644 index 00000000..2cf3262c --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/settings/WebApiSettingsViewController.scala @@ -0,0 +1,130 @@ +package de.tobias.playpad.plugin.api.settings + +import de.thecodelabs.logger.Logger +import de.thecodelabs.storage.settings.{Storage, StorageTypes} +import de.thecodelabs.utils.ui.scene.input.NumberTextField +import de.thecodelabs.utils.util.Localization +import de.tobias.playpad.plugin.api.WebApiPlugin +import de.tobias.playpad.settings.GlobalSettings +import de.tobias.playpad.viewcontroller.option.GlobalSettingsTabViewController +import javafx.event.ActionEvent +import javafx.fxml.FXML +import javafx.scene.control._ + +import java.nio.file.Files + +class WebApiSettingsViewController(val webApiSettings: WebApiSettings) extends GlobalSettingsTabViewController { + + load("plugin/webapi/view", "WebApiSettings", Localization.getBundle) + + @FXML + var activeCheckbox: CheckBox = _ + + @FXML + var portTextField: NumberTextField = _ + + @FXML var remoteListView: ListView[WebApiRemoteSettings] = _ + @FXML var remoteAddButton: Button = _ + @FXML var remoteDeleteButton: Button = _ + @FXML var remoteNameTextField: TextField = _ + @FXML var remoteAddressTextField: TextField = _ + @FXML var remotePortTextField: NumberTextField = _ + + override def init(): Unit = { + remoteListView.getItems.setAll(webApiSettings.getRemoteSettings) + remoteDeleteButton.disableProperty().bind(remoteListView.getSelectionModel.selectedItemProperty().isNull) + + remoteListView.setCellFactory((_: ListView[WebApiRemoteSettings]) => new ListCell[WebApiRemoteSettings] { + override def updateItem(item: WebApiRemoteSettings, empty: Boolean): Unit = { + super.updateItem(item, empty) + if (!empty) { + textProperty().bind(item.displayProperty()) + } else { + textProperty().unbind() + setText("") + } + } + }) + remoteListView.getSelectionModel.selectedItemProperty().addListener((_, oldValue, newValue) => { + if (oldValue != null) { + saveSettingsToRemoteList(oldValue) + } + if (newValue != null) { + showRemoteConfiguration(newValue) + } else { + clearTextFields() + } + }) + } + + private def saveSettingsToRemoteList(remote: WebApiRemoteSettings): Unit = { + remote.setName(remoteNameTextField.getText) + remote.setServerAddress(remoteAddressTextField.getText) + remote.setPort(remotePortTextField.getText.toInt) + } + + + private def showRemoteConfiguration(remote: WebApiRemoteSettings): Unit = { + remoteNameTextField.setText(remote.getName) + remoteAddressTextField.setText(remote.getServerAddress) + remotePortTextField.setText(remote.getPort.toString) + } + + private def clearTextFields(): Unit = { + remoteNameTextField.setText("") + remoteAddressTextField.setText("") + remotePortTextField.setText("") + } + + @FXML def onRemoteAddButton(event: ActionEvent): Unit = { + val remoteSettings = new WebApiRemoteSettings() + remoteSettings.setName("Default") + webApiSettings.getRemoteSettings.add(remoteSettings) + + remoteListView.getItems.add(remoteSettings) + } + + @FXML def onRemoteDeleteButton(event: ActionEvent): Unit = { + val selectedItem = remoteListView.getSelectionModel.getSelectedItem + if (selectedItem != null) { + remoteListView.getItems.remove(selectedItem) + webApiSettings.getRemoteSettings.remove(selectedItem) + } + } + + override def loadSettings(settings: GlobalSettings): Unit = { + activeCheckbox.setSelected(webApiSettings.isEnabled) + portTextField.setText(webApiSettings.getPort.toString) + } + + override def saveSettings(settings: GlobalSettings): Unit = { + webApiSettings.setEnabled(activeCheckbox.isSelected) + webApiSettings.setPort(portTextField.getText.toInt) + + val selectedItem = remoteListView.getSelectionModel.getSelectedItem + if (selectedItem != null) { + saveSettingsToRemoteList(selectedItem) + } + + saveToFile() + } + + override def needReload(): Boolean = { + false + } + + override def validSettings(): Boolean = { + true + } + + override def name(): String = Localization.getString("webapi.settings") + + private def saveToFile(): Unit = { + val settingsPath = WebApiPlugin.getWebApiSettingsPath + if (Files.notExists(settingsPath)) { + Files.createDirectories(settingsPath.getParent) + } + Storage.save(StorageTypes.JSON, webApiSettings) + Logger.info(f"Save WebAPI settings to $settingsPath") + } +} diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettingsViewController.scala b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettingsViewController.scala deleted file mode 100644 index 4f86d86d..00000000 --- a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettingsViewController.scala +++ /dev/null @@ -1,81 +0,0 @@ -package de.tobias.playpad.plugin.api.websocket.settings - -import java.nio.file.Files - -import de.thecodelabs.logger.Logger -import de.thecodelabs.storage.settings.{Storage, StorageTypes} -import de.thecodelabs.utils.ui.scene.input.NumberTextField -import de.thecodelabs.utils.util.Localization -import de.tobias.playpad.plugin.api.WebApiPlugin -import de.tobias.playpad.settings.GlobalSettings -import de.tobias.playpad.viewcontroller.option.GlobalSettingsTabViewController -import javafx.fxml.FXML -import javafx.scene.control.CheckBox - -class WebApiSettingsViewController(val webApiSettings: WebApiSettings) extends GlobalSettingsTabViewController { - - load("plugin/webapi/view", "WebApiSettings", Localization.getBundle) - - @FXML - var activeCheckbox: CheckBox = _ - - @FXML - var portTextField: NumberTextField = _ - - /** - * Lädt alle Einstellungen vom Model in die GUI. - * - * @param settings Aktuelles GlobalSettings - */ - override def loadSettings(settings: GlobalSettings): Unit = { - activeCheckbox.setSelected(webApiSettings.isEnabled) - portTextField.setText(webApiSettings.getPort.toString) - } - - /** - * Speichert alle Änderungen in das Model. - * - * @param settings Aktuelles GlobalSettings - */ - override def saveSettings(settings: GlobalSettings): Unit = { - webApiSettings.setEnabled(activeCheckbox.isSelected) - webApiSettings.setPort(portTextField.getText.toInt) - - saveToFile() - } - - /** - * Gibt <code>true</code> zurück, wenn im Hauptprogramm etwas neu geladen werden muss. - * - * @return <code>true</code> Benötigt Reload - */ - override def needReload(): Boolean = { - false - } - - /** - * Prüft ob die eingetragen Einstellungen erlaubt sind. Bei falschen Eingaben können die Einstellungen nicht - * geschlossen werden. - * - * @return <code>true</code> Einstellungen erlaubt. <code>false</code> Einstellungen fehlerhaft. - */ - override def validSettings(): Boolean = { - true - } - - /** - * Gibt den Namen für den Tab zurück. - * - * @return Display Name des Tabs. - */ - override def name(): String = Localization.getString("webapi.settings") - - private def saveToFile(): Unit = { - val settingsPath = WebApiPlugin.getWebApiSettingsPath - if (Files.notExists(settingsPath)) { - Files.createDirectories(settingsPath.getParent) - } - Storage.save(StorageTypes.JSON, webApiSettings) - Logger.info(f"Save WebAPI settings to $settingsPath") - } -} -- GitLab