From 11303a181124aead260a1405a9072d52d7636bef Mon Sep 17 00:00:00 2001 From: tobias <thinkdifferent055@gmail.com> Date: Tue, 17 Nov 2020 14:29:10 +0100 Subject: [PATCH] Fixed #161 - Add WebAPI port settings --- .../java/de/tobias/playpad/PlayPadImpl.java | 37 +++++++-- .../global/GlobalSettingsViewController.java | 12 ++- .../ProfileSettingsViewController.java | 15 +++- .../main/java/de/tobias/playpad/PlayPad.java | 14 ++++ .../websocket/settings/WebApiSettings.java | 28 +++++++ .../plugin/webapi/lang/base.properties | 0 .../plugin/webapi/lang/base_de.properties | 5 ++ .../plugin/webapi/view/WebApiSettings.fxml | 33 ++++++++ .../playpad/plugin/api/WebApiPlugin.scala | 39 +++++++-- .../WebApiSettingsViewController.scala | 81 +++++++++++++++++++ 10 files changed, 245 insertions(+), 19 deletions(-) create mode 100644 PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettings.java create mode 100644 PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base.properties create mode 100644 PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base_de.properties create mode 100644 PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml create 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/PlayPadImpl.java b/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java index f3f434f5..a8590e8e 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java +++ b/PlayWall/src/main/java/de/tobias/playpad/PlayPadImpl.java @@ -26,6 +26,8 @@ import de.tobias.playpad.viewcontroller.dialog.project.ProjectLoadDialog; import de.tobias.playpad.viewcontroller.dialog.project.ProjectReaderDelegateImpl; import de.tobias.playpad.viewcontroller.main.IMainViewController; import de.tobias.playpad.viewcontroller.main.MainViewController; +import de.tobias.playpad.viewcontroller.option.GlobalSettingsTabViewController; +import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController; import javafx.application.Application; import javafx.application.Platform; import javafx.scene.image.Image; @@ -37,21 +39,24 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; +import java.util.function.Supplier; public class PlayPadImpl implements PlayPad { - private Application.Parameters parameters; + private final Application.Parameters parameters; - private List<MainWindowListener> mainViewListeners = new ArrayList<>(); - private List<SettingsListener> settingsListeners = new ArrayList<>(); - private List<PadListener> padListeners = new ArrayList<>(); - private List<GlobalListener> globalListeners = new ArrayList<>(); + private final List<MainWindowListener> mainViewListeners = new ArrayList<>(); + private final List<SettingsListener> settingsListeners = new ArrayList<>(); + private final List<PadListener> padListeners = new ArrayList<>(); + private final List<GlobalListener> globalListeners = new ArrayList<>(); + private final List<Supplier<ProfileSettingsTabViewController>> additionalProfileSettingsTabs = new ArrayList<>(); + private final List<Supplier<GlobalSettingsTabViewController>> additionalGlobalSettingsTabs = new ArrayList<>(); private MainViewController mainViewController; private Image stageIcon; private Project currentProject; - private Module module; + private final Module module; private UpdateService updateService; protected GlobalSettings globalSettings; @@ -242,6 +247,26 @@ public class PlayPadImpl implements PlayPad { return updateService; } + @Override + public void addAdditionalProfileSettingsTab(Supplier<ProfileSettingsTabViewController> tab) { + additionalProfileSettingsTabs.add(tab); + } + + @Override + public List<Supplier<ProfileSettingsTabViewController>> getAdditionalProfileSettingsTabs() { + return additionalProfileSettingsTabs; + } + + @Override + public void addGlobalSettingsTab(Supplier<GlobalSettingsTabViewController> tab) { + additionalGlobalSettingsTabs.add(tab); + } + + @Override + public List<Supplier<GlobalSettingsTabViewController>> getGlobalSettingsTabs() { + return additionalGlobalSettingsTabs; + } + /* Getter / Setter */ diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/GlobalSettingsViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/GlobalSettingsViewController.java index 068ecda3..e29db503 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/GlobalSettingsViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/global/GlobalSettingsViewController.java @@ -36,9 +36,8 @@ public class GlobalSettingsViewController extends NVC implements IGlobalSettings @FXML private Button finishButton; - private List<GlobalSettingsTabViewController> tabs = new ArrayList<>(); - - private Runnable onFinish; + private final List<GlobalSettingsTabViewController> tabs = new ArrayList<>(); + private final Runnable onFinish; public GlobalSettingsViewController(Window owner, Runnable onFinish) { load("view/option/global", "GlobalSettingsView", Localization.getBundle()); @@ -53,6 +52,13 @@ public class GlobalSettingsViewController extends NVC implements IGlobalSettings addTab(new KeysTabViewController()); addTab(new UpdateTabViewController()); + PlayPadPlugin.getInstance().getGlobalSettingsTabs().forEach(supplier -> { + final GlobalSettingsTabViewController globalSettingsTabViewController = supplier.get(); + if (globalSettingsTabViewController != null) { + addTab(globalSettingsTabViewController); + } + }); + // Show Current Settings loadTabs(); } diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/ProfileSettingsViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/ProfileSettingsViewController.java index 1c4b3641..4f0ab953 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/ProfileSettingsViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/ProfileSettingsViewController.java @@ -40,15 +40,15 @@ public class ProfileSettingsViewController extends NVC implements IProfileSettin @FXML private Button finishButton; - private List<ProfileSettingsTabViewController> tabs = new ArrayList<>(); + private final List<ProfileSettingsTabViewController> tabs = new ArrayList<>(); - private Runnable onFinish; + private final Runnable onFinish; public ProfileSettingsViewController(Window owner, Project project, Runnable onFinish) { load("view/option/profile", "SettingsView", Localization.getBundle()); this.onFinish = onFinish; - boolean activePlayer = project.hasActivePlayers(); + boolean hasActivePlayers = project.hasActivePlayers(); addTab(new MappingTabViewController()); addTab(new DesignTabViewController()); @@ -58,12 +58,19 @@ public class ProfileSettingsViewController extends NVC implements IProfileSettin PadContentRegistry padContents = PlayPadPlugin.getRegistries().getPadContents(); for (String type : padContents.getTypes()) { PadContentFactory component = padContents.getFactory(type); - ProfileSettingsTabViewController controller = component.getSettingsTabViewController(activePlayer); + ProfileSettingsTabViewController controller = component.getSettingsTabViewController(hasActivePlayers); if (controller != null) { addTab(controller); } } + PlayPadPlugin.getInstance().getAdditionalProfileSettingsTabs().forEach(supplier -> { + ProfileSettingsTabViewController controller = supplier.get(); + if (controller != null) { + addTab(controller); + } + }); + NVCStage nvcStage = applyViewControllerToStage(); nvcStage.initOwner(owner); nvcStage.addCloseHook(this::onFinish); diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java b/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java index 14d50ffa..c480828c 100644 --- a/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java +++ b/PlayWallCore/src/main/java/de/tobias/playpad/PlayPad.java @@ -14,12 +14,15 @@ import de.tobias.playpad.project.ProjectReader.ProjectReaderDelegate.ProfileAbor import de.tobias.playpad.project.ref.ProjectReference; import de.tobias.playpad.settings.GlobalSettings; import de.tobias.playpad.viewcontroller.main.IMainViewController; +import de.tobias.playpad.viewcontroller.option.GlobalSettingsTabViewController; +import de.tobias.playpad.viewcontroller.option.ProfileSettingsTabViewController; import javafx.scene.image.Image; import org.dom4j.DocumentException; import java.io.IOException; import java.util.List; import java.util.function.Consumer; +import java.util.function.Supplier; /** * Hauptfunktionen für Listener und zur Programmsteuerung für Plugins. @@ -138,4 +141,15 @@ public interface PlayPad { UpdateService getUpdateService(); + /* + Settings Views + */ + + void addAdditionalProfileSettingsTab(Supplier<ProfileSettingsTabViewController> tab); + + List<Supplier<ProfileSettingsTabViewController>> getAdditionalProfileSettingsTabs(); + + void addGlobalSettingsTab(Supplier<GlobalSettingsTabViewController> tab); + + List<Supplier<GlobalSettingsTabViewController>> getGlobalSettingsTabs(); } 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/websocket/settings/WebApiSettings.java new file mode 100644 index 00000000..c5b35f5f --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettings.java @@ -0,0 +1,28 @@ +package de.tobias.playpad.plugin.api.websocket.settings; + +import de.thecodelabs.storage.settings.annotation.FilePath; +import de.thecodelabs.storage.settings.annotation.Key; + +@FilePath("webapi.json") +public class WebApiSettings { + @Key + private boolean enabled = false; + @Key + private int port = 9876; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } +} diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base.properties b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base.properties new file mode 100644 index 00000000..e69de29b 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 new file mode 100644 index 00000000..e38784c8 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/lang/base_de.properties @@ -0,0 +1,5 @@ +webapi.settings=WebAPI +webapi.settings.enable=WebAPI aktiv +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 diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml new file mode 100644 index 00000000..473dba8d --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/resources/plugin/webapi/view/WebApiSettings.fxml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?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"> + <children> + <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"/> + </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"/> + </children> + </HBox> + <Label text="%webapi.settings.restart"> + <padding> + <Insets left="164.0"/> + </padding> + </Label> + </children> + <padding> + <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 b48693f9..0d4d7321 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,18 +1,27 @@ 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 +import de.thecodelabs.storage.settings.{Storage, StorageTypes} +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.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.Spark +import spark.{Request, Response, Spark} class WebApiPlugin extends PlayPadPluginStub with PluginArtifact { private var module: Module = _ + private var webApiSettings: WebApiSettings = _ + override def startup(descriptor: PluginDescriptor): Unit = { module = new Module(descriptor.getName, descriptor.getArtifactId) @@ -21,16 +30,34 @@ class WebApiPlugin extends PlayPadPluginStub with PluginArtifact { Logger.debug("Enable Web API Plugin") - Spark.port(9876) - Spark.webSocket("/api", WebSocketHandler.instance) - Spark.get("/", (_, _) => "PlayWall API") + val settingsPath = WebApiPlugin.getWebApiSettingsPath + if (Files.exists(settingsPath)) { + webApiSettings = Storage.load(StorageTypes.JSON, classOf[WebApiSettings]) + } + if (webApiSettings == null) { + webApiSettings = new WebApiSettings + } + + if (webApiSettings.isEnabled) { + Spark.port(webApiSettings.getPort) + Spark.webSocket("/api", WebSocketHandler.instance) + Spark.get("/", (_: Request, _: Response) => "PlayWall API") + Logger.info(f"Start WebAPI on port ${webApiSettings.getPort}") + } + + PlayPadPlugin.getInstance().addGlobalSettingsTab(() => new WebApiSettingsViewController(webApiSettings)) + Localization.addResourceBundle("plugin/webapi/lang/base", getClass.getClassLoader) } override def shutdown(): Unit = { - Logger.debug("Disable Web API Plugin") - Spark.stop() + Logger.debug("Disable Web API Plugin") } override def getModule: Module = module + } + +object WebApiPlugin { + def getWebApiSettingsPath: Path = ApplicationUtils.getApplication.getPath(PathType.CONFIGURATION, "webapi.json") +} \ No newline at end of file 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 new file mode 100644 index 00000000..4f86d86d --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/scala/de/tobias/playpad/plugin/api/websocket/settings/WebApiSettingsViewController.scala @@ -0,0 +1,81 @@ +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