From d5b5caf0d01fa0580aab03bfa278348cb0ade4f6 Mon Sep 17 00:00:00 2001 From: tobias <thinkdifferent055@gmail.com> Date: Sun, 21 Nov 2021 16:54:42 +0100 Subject: [PATCH] #174 - Add remote playwall connection icon to toolbar --- .../DesktopMenuToolbarViewController.java | 3 +- .../main/listener/LockedListener.java | 5 +- .../WebApiRemoteConnectionStateListener.java | 69 +++++++++++++++++++ .../plugin/webapi/lang/base_de.properties | 1 + .../playpad/plugin/api/WebApiPlugin.scala | 6 +- .../WebApiSettingsViewController.scala | 7 +- 6 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/client/WebApiRemoteConnectionStateListener.java diff --git a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMenuToolbarViewController.java b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMenuToolbarViewController.java index 3e5ef927..2f3410e6 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMenuToolbarViewController.java +++ b/PlayWall/src/main/java/de/tobias/playpad/layout/desktop/DesktopMenuToolbarViewController.java @@ -21,7 +21,6 @@ import de.tobias.playpad.profile.Profile; import de.tobias.playpad.profile.ProfileNotFoundException; import de.tobias.playpad.profile.ProfileSettings; import de.tobias.playpad.profile.ref.ProfileReference; -import de.tobias.playpad.profile.ref.ProfileReferenceManager; import de.tobias.playpad.project.Project; import de.tobias.playpad.project.ProjectNotFoundException; import de.tobias.playpad.project.ProjectReader.ProjectReaderDelegate.ProfileAbortException; @@ -148,7 +147,7 @@ public class DesktopMenuToolbarViewController extends BasicMenuToolbarViewContro private ToggleButton colorButton; private Button addPageButton; - private IMainViewController mainViewController; + private final IMainViewController mainViewController; private transient ProjectSettingsViewController projectSettingsViewController; private transient ProfileSettingsViewController profileSettingsViewController; diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/listener/LockedListener.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/listener/LockedListener.java index 00748a4a..43127d5e 100644 --- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/listener/LockedListener.java +++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/main/listener/LockedListener.java @@ -10,9 +10,8 @@ import javafx.scene.control.Label; public class LockedListener implements ChangeListener<Boolean> { - private IMainViewController mainViewController; - - private Label lockedLabel; + private final IMainViewController mainViewController; + private final Label lockedLabel; public LockedListener(IMainViewController mainViewController) { this.mainViewController = mainViewController; diff --git a/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/client/WebApiRemoteConnectionStateListener.java b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/client/WebApiRemoteConnectionStateListener.java new file mode 100644 index 00000000..1f1dc56f --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginWebAPI/src/main/java/de/tobias/playpad/plugin/api/client/WebApiRemoteConnectionStateListener.java @@ -0,0 +1,69 @@ +package de.tobias.playpad.plugin.api.client; + +import com.neovisionaries.ws.client.WebSocketState; +import de.thecodelabs.utils.ui.icon.FontAwesomeType; +import de.thecodelabs.utils.ui.icon.FontIcon; +import de.thecodelabs.utils.util.Localization; +import de.tobias.playpad.api.PlayPadClient; +import de.tobias.playpad.plugin.MainWindowListener; +import de.tobias.playpad.plugin.api.WebApiPlugin$; +import de.tobias.playpad.viewcontroller.main.IMainViewController; +import javafx.beans.InvalidationListener; +import javafx.beans.binding.Bindings; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.scene.control.Tooltip; + +import java.util.stream.Collectors; + +public class WebApiRemoteConnectionStateListener implements MainWindowListener { + + private final FontIcon connectionStateIcon; + private final IntegerProperty connectedProperty; + + public WebApiRemoteConnectionStateListener() { + connectionStateIcon = new FontIcon(FontAwesomeType.CLOUD); + connectionStateIcon.setSize(20); + + connectedProperty = new SimpleIntegerProperty(0); + connectedProperty.addListener((observable, oldValue, newValue) -> { + boolean allConnected = newValue.intValue() == 0; + + connectionStateIcon.setIcons(allConnected ? FontAwesomeType.CLOUD : FontAwesomeType.EXCLAMATION_CIRCLE); + if (!allConnected) { + final String disconnectedServers = WebApiPlugin$.MODULE$.connections().entrySet().stream() + .filter(entry -> entry.getValue().getPlayPadConnectionState() != WebSocketState.OPEN) + .map(entry -> entry.getKey().getName()).collect(Collectors.joining(", ")); + connectionStateIcon.setTooltip(new Tooltip(Localization.getString("webapi-settings.remote.state.tooltip", disconnectedServers))); + connectionStateIcon.setStyle("-fx-text-fill: red;"); + } else { + connectionStateIcon.setTooltip(null); + connectionStateIcon.setStyle(""); + } + }); + + WebApiPlugin$.MODULE$.connections().addListener((InvalidationListener) observable -> createConnectionStateBinding()); + createConnectionStateBinding(); + } + + private void createConnectionStateBinding() { + connectedProperty.bind(Bindings.createIntegerBinding(() -> (int) WebApiPlugin$.MODULE$.connections().values().stream() + .filter(client -> client.getPlayPadConnectionState() != WebSocketState.OPEN) + .count(), + WebApiPlugin$.MODULE$.connections().values().stream() + .map(PlayPadClient::playPadConnectionState) + .toArray(ObjectProperty[]::new)) + ); + } + + @Override + public void onInit(IMainViewController mainViewController) { + mainViewController.performLayoutDependedAction((oldToolbar, newToolbar) -> { + if (oldToolbar != null) { + oldToolbar.removeToolbarItem(connectionStateIcon); + } + newToolbar.addToolbarItem(connectionStateIcon); + }); + } +} 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 9c330604..7e270638 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 @@ -6,6 +6,7 @@ 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.state.tooltip=Keine Verbindung zu: {} webapi-settings.remote.name=Name webapi-settings.remote.address=IP-Address/Host webapi-settings.remote.port=Port 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 e0fb6496..7d05ca35 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 @@ -10,10 +10,12 @@ import de.thecodelabs.utils.threading.Worker import de.thecodelabs.utils.util.Localization import de.tobias.playpad.PlayPadPlugin import de.tobias.playpad.api.{PlayPadClient, PlayPadClientImpl} +import de.tobias.playpad.plugin.api.client.WebApiRemoteConnectionStateListener import de.tobias.playpad.plugin.api.settings.{WebApiRemoteSettings, 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.{Module, PlayPadPluginStub} +import javafx.collections.{FXCollections, ObservableMap} import spark.{Request, Response, Spark} import java.nio.file.{Files, Path} @@ -66,6 +68,7 @@ class WebApiPlugin extends PlayPadPluginStub with PluginArtifact { }) PlayPadPlugin.getInstance().addGlobalSettingsTab(() => new WebApiSettingsViewController(webApiSettings)) + PlayPadPlugin.getInstance().addMainViewListener(new WebApiRemoteConnectionStateListener) } override def shutdown(): Unit = { @@ -80,7 +83,8 @@ class WebApiPlugin extends PlayPadPluginStub with PluginArtifact { object WebApiPlugin { def getWebApiSettingsPath: Path = ApplicationUtils.getApplication.getPath(PathType.CONFIGURATION, "webapi.json") - var connections: util.Map[WebApiRemoteSettings, PlayPadClient] = new util.HashMap() + var connections: ObservableMap[WebApiRemoteSettings, PlayPadClient] = FXCollections.observableMap( + new util.HashMap[WebApiRemoteSettings, PlayPadClient]()) def getConnection(id: UUID): Optional[PlayPadClient] = { connections.entrySet().stream().filter(entry => entry.getKey.getId == id).findFirst().map(_.getValue) 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 index 2cf3262c..30de1703 100644 --- 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 @@ -17,11 +17,8 @@ class WebApiSettingsViewController(val webApiSettings: WebApiSettings) extends G load("plugin/webapi/view", "WebApiSettings", Localization.getBundle) - @FXML - var activeCheckbox: CheckBox = _ - - @FXML - var portTextField: NumberTextField = _ + @FXML var activeCheckbox: CheckBox = _ + @FXML var portTextField: NumberTextField = _ @FXML var remoteListView: ListView[WebApiRemoteSettings] = _ @FXML var remoteAddButton: Button = _ -- GitLab