diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
new file mode 100644
index 000000000..2b63946d5
--- /dev/null
+++ b/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/org/cryptomator/ui/controls/CustomDialog.java b/src/main/java/org/cryptomator/ui/controls/CustomDialog.java
new file mode 100644
index 000000000..3bf0a62f6
--- /dev/null
+++ b/src/main/java/org/cryptomator/ui/controls/CustomDialog.java
@@ -0,0 +1,124 @@
+package org.cryptomator.ui.controls;
+
+import org.cryptomator.ui.common.FxmlFile;
+import org.cryptomator.ui.common.FxmlLoaderFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Parent;
+import javafx.scene.Scene;
+import javafx.stage.Modality;
+import javafx.stage.Stage;
+import java.util.ResourceBundle;
+import java.util.function.Consumer;
+
+public class CustomDialog {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CustomDialog.class);
+
+ private final Stage dialogStage;
+
+ CustomDialog(Builder builder){
+ dialogStage = new Stage();
+ dialogStage.initOwner(builder.owner);
+ dialogStage.initModality(Modality.WINDOW_MODAL);
+ dialogStage.setTitle(resolveText(builder.resourceBundle, builder.titleKey, builder.titleArgs));
+
+ try{
+ FxmlLoaderFactory loaderFactory = FxmlLoaderFactory.forController(new CustomDialogController(), Scene::new, builder.resourceBundle);
+ FXMLLoader loader = loaderFactory.load(FxmlFile.CUSTOM_DIALOG.getRessourcePathString());
+ Parent root = loader.getRoot();
+ CustomDialogController controller = loader.getController();
+
+ controller.setMessage(resolveText(builder.resourceBundle, builder.messageKey, null));
+ controller.setDescription(resolveText(builder.resourceBundle, builder.descriptionKey, null));
+ controller.setIcon(builder.icon);
+ controller.setOkButtonText(resolveText(builder.resourceBundle, builder.okButtonKey, null));
+ controller.setCancelButtonText(resolveText(builder.resourceBundle, builder.cancelButtonKey, null));
+
+ controller.setOkAction(() -> builder.okAction.accept(dialogStage));
+ controller.setCancelAction(() -> builder.cancelAction.accept(dialogStage));
+
+ dialogStage.setScene(new Scene(root));
+ dialogStage.showAndWait();
+ } catch (Exception e) {
+ LOG.error("Failed to build and show dialog stage.", e);
+ }
+
+ }
+
+ private String resolveText(ResourceBundle resourceBundle, String key, String[] args) {
+ String text = resourceBundle.getString(key);
+ return args != null && args.length > 0 ? String.format(text, (Object[]) args) : text;
+ }
+
+ public static class Builder {
+ private Stage owner;
+ private ResourceBundle resourceBundle;
+ private String titleKey;
+ private String[] titleArgs;
+ private String messageKey;
+ private String descriptionKey;
+ private String okButtonKey;
+ private String cancelButtonKey;
+
+ private FontAwesome5Icon icon;
+ private Consumer okAction = Stage::close;
+ private Consumer cancelAction = Stage::close;
+
+ public Builder setOwner(Stage owner) {
+ this.owner = owner;
+ return this;
+ }
+ public Builder resourceBundle(ResourceBundle resourceBundle) {
+ this.resourceBundle = resourceBundle;
+ return this;
+ }
+
+ public Builder titleKey(String titleKey, String... args) {
+ this.titleKey = titleKey;
+ this.titleArgs = args;
+ return this;
+ }
+
+ public Builder messageKey(String messageKey) {
+ this.messageKey = messageKey;
+ return this;
+ }
+
+ public Builder descriptionKey(String descriptionKey) {
+ this.descriptionKey = descriptionKey;
+ return this;
+ }
+
+ public Builder icon(FontAwesome5Icon icon) {
+ this.icon = icon;
+ return this;
+ }
+
+ public Builder okButtonKey(String okButtonKey) {
+ this.okButtonKey = okButtonKey;
+ return this;
+ }
+
+ public Builder cancelButtonKey(String cancelButtonKey) {
+ this.cancelButtonKey = cancelButtonKey;
+ return this;
+ }
+
+ public Builder okAction(Consumer okAction) {
+ this.okAction = okAction;
+ return this;
+ }
+
+ public Builder cancelAction(Consumer cancelAction) {
+ this.cancelAction = cancelAction;
+ return this;
+ }
+
+ public CustomDialog build(){
+ return new CustomDialog(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/cryptomator/ui/controls/CustomDialogBuilder.java b/src/main/java/org/cryptomator/ui/controls/CustomDialogBuilder.java
deleted file mode 100644
index 180dfee1d..000000000
--- a/src/main/java/org/cryptomator/ui/controls/CustomDialogBuilder.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package org.cryptomator.ui.controls;
-
-import org.cryptomator.ui.common.FxmlFile;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javafx.fxml.FXMLLoader;
-import javafx.scene.Scene;
-import javafx.scene.layout.Pane;
-import javafx.stage.Modality;
-import javafx.stage.Stage;
-import java.util.function.Consumer;
-
-public class CustomDialogBuilder {
-
- private static final Logger LOG = LoggerFactory.getLogger(CustomDialogBuilder.class);
-
- private String title;
- private String message;
- private String description;
- private FontAwesome5Icon icon;
- private String okButtonText = "OK";
- private String cancelButtonText = "Cancel";
- private Consumer okAction;
- private Consumer cancelAction;
-
- public CustomDialogBuilder setTitle(String title) {
- this.title = title;
- return this;
- }
-
- public CustomDialogBuilder setMessage(String message) {
- this.message = message;
- return this;
- }
-
- public CustomDialogBuilder setDescription(String description) {
- this.description = description;
- return this;
- }
-
- public CustomDialogBuilder setIcon(FontAwesome5Icon icon) {
- this.icon = icon;
- return this;
- }
-
- public CustomDialogBuilder setOkButtonText(String okButtonText) {
- this.okButtonText = okButtonText;
- return this;
- }
-
- public CustomDialogBuilder setCancelButtonText(String cancelButtonText) {
- this.cancelButtonText = cancelButtonText;
- return this;
- }
-
- public CustomDialogBuilder setOkAction(Consumer okAction) {
- this.okAction = okAction;
- return this;
- }
-
- public CustomDialogBuilder setCancelAction(Consumer cancelAction) {
- this.cancelAction = cancelAction;
- return this;
- }
-
-
- public void buildAndShow(Stage owner) {
- try {
- FXMLLoader loader = new FXMLLoader(getClass().getResource(FxmlFile.CUSTOM_DIALOG.getRessourcePathString()));
- Pane pane = loader.load();
-
- CustomDialogController controller = loader.getController();
- controller.setMessage(message);
- controller.setDescription(description);
- controller.setIcon(icon);
- controller.setOkButtonText(okButtonText);
- controller.setCancelButtonText(cancelButtonText);
-
- Stage dialogStage = new Stage();
- dialogStage.setTitle(title);
- dialogStage.initModality(Modality.WINDOW_MODAL);
- dialogStage.initOwner(owner);
- dialogStage.setScene(new Scene(pane));
-
- controller.setOkAction(() -> okAction.accept(dialogStage));
- controller.setCancelAction(() -> cancelAction.accept(dialogStage));
- dialogStage.showAndWait();
- } catch (Exception e) {
- LOG.error("Failed to build and show dialog stage.", e);
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/cryptomator/ui/controls/CustomDialogController.java b/src/main/java/org/cryptomator/ui/controls/CustomDialogController.java
index 7308bb0b3..299173526 100644
--- a/src/main/java/org/cryptomator/ui/controls/CustomDialogController.java
+++ b/src/main/java/org/cryptomator/ui/controls/CustomDialogController.java
@@ -1,10 +1,12 @@
package org.cryptomator.ui.controls;
+import org.cryptomator.ui.common.FxController;
+
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
-public class CustomDialogController {
+public class CustomDialogController implements FxController {
@FXML
private Label messageLabel;
diff --git a/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java b/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java
index 394474f80..032b3e49e 100644
--- a/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java
+++ b/src/main/java/org/cryptomator/ui/fxapp/FxApplicationWindows.java
@@ -5,7 +5,7 @@ import dagger.Lazy;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.integrations.tray.TrayIntegrationProvider;
-import org.cryptomator.ui.controls.CustomDialogBuilder;
+import org.cryptomator.ui.controls.CustomDialog;
import org.cryptomator.ui.controls.FontAwesome5Icon;
import org.cryptomator.ui.dokanysupportend.DokanySupportEndComponent;
import org.cryptomator.ui.error.ErrorComponent;
@@ -155,19 +155,21 @@ public class FxApplicationWindows {
public void showDokanySupportEndWindow() {
CompletableFuture.runAsync(() -> {
- new CustomDialogBuilder() //
- .setTitle(resourceBundle.getString("dokanySupportEnd.title")) //
- .setMessage(resourceBundle.getString("dokanySupportEnd.message")) //
- .setDescription(resourceBundle.getString("dokanySupportEnd.description")) //
- .setIcon(FontAwesome5Icon.EXCLAMATION) //
- .setOkButtonText(resourceBundle.getString("generic.button.close")) //
- .setCancelButtonText(resourceBundle.getString("dokanySupportEnd.preferencesBtn")) //
- .setOkAction(Stage::close) //
- .setCancelAction(v -> {
+ new CustomDialog.Builder()
+ .setOwner(mainWindow.get().window())
+ .resourceBundle(resourceBundle)
+ .titleKey("dokanySupportEnd.title")
+ .messageKey("dokanySupportEnd.message")
+ .descriptionKey("dokanySupportEnd.description")
+ .icon(FontAwesome5Icon.QUESTION)
+ .okButtonKey("generic.button.close")
+ .cancelButtonKey("dokanySupportEnd.preferencesBtn")
+ .okAction(Stage::close) //
+ .cancelAction(v -> {
showPreferencesWindow(SelectedPreferencesTab.VOLUME);
v.close();
}) //
- .buildAndShow(mainWindow.get().window());
+ .build();
}, Platform::runLater);
}
diff --git a/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailMissingVaultController.java b/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailMissingVaultController.java
index 537600616..14678fc18 100644
--- a/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailMissingVaultController.java
+++ b/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailMissingVaultController.java
@@ -3,7 +3,7 @@ package org.cryptomator.ui.mainwindow;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.ui.common.FxController;
-import org.cryptomator.ui.controls.CustomDialogBuilder;
+import org.cryptomator.ui.controls.CustomDialog;
import org.cryptomator.ui.controls.FontAwesome5Icon;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,22 +48,26 @@ public class VaultDetailMissingVaultController implements FxController {
@FXML
void didClickRemoveVault() {
- new CustomDialogBuilder() //
- .setTitle(String.format(resourceBundle.getString("removeVault.title"), vault.get().getDisplayName())) //
- .setMessage(resourceBundle.getString("removeVault.message")) //
- .setDescription(resourceBundle.getString("removeVault.description")) //
- .setIcon(FontAwesome5Icon.QUESTION) //
- .setOkButtonText(resourceBundle.getString("removeVault.confirmBtn")) //
- .setCancelButtonText(resourceBundle.getString("generic.button.cancel")) //
- .setOkAction(v -> {
+
+ new CustomDialog.Builder()
+ .setOwner(window)
+ .resourceBundle(resourceBundle)
+ .titleKey("removeVault.title", vault.get().getDisplayName())
+ .messageKey("removeVault.message")
+ .descriptionKey("removeVault.description")
+ .icon(FontAwesome5Icon.QUESTION)
+ .okButtonKey("removeVault.confirmBtn")
+ .cancelButtonKey("generic.button.cancel")
+ .okAction(v -> {
LOG.debug("Removing vault {}.", vault.get().getDisplayName());
vaults.remove(vault.get());
v.close();
}) //
- .setCancelAction(Stage::close) //
- .buildAndShow(window);
+ .cancelAction(Stage::close) //
+ .build();
}
+
@FXML
void changeLocation() {
// copied from ChooseExistingVaultController class
diff --git a/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnknownErrorController.java b/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnknownErrorController.java
index df2947f6b..b29beb450 100644
--- a/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnknownErrorController.java
+++ b/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnknownErrorController.java
@@ -3,7 +3,7 @@ package org.cryptomator.ui.mainwindow;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.ui.common.FxController;
-import org.cryptomator.ui.controls.CustomDialogBuilder;
+import org.cryptomator.ui.controls.CustomDialog;
import org.cryptomator.ui.controls.FontAwesome5Icon;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.slf4j.Logger;
@@ -54,19 +54,22 @@ public class VaultDetailUnknownErrorController implements FxController {
@FXML
void didClickRemoveVault() {
- new CustomDialogBuilder() //
- .setTitle(String.format(resourceBundle.getString("removeVault.title"), vault.get().getDisplayName())) //
- .setMessage(resourceBundle.getString("removeVault.message")) //
- .setDescription(resourceBundle.getString("removeVault.description")) //
- .setIcon(FontAwesome5Icon.QUESTION) //
- .setOkButtonText(resourceBundle.getString("removeVault.confirmBtn")) //
- .setCancelButtonText(resourceBundle.getString("generic.button.cancel")) //
- .setOkAction(v -> {
- LOG.debug("Removing vault {}.", vault.get().getDisplayName());
- vaults.remove(vault.get());
- v.close();
- }) //
- .setCancelAction(Stage::close) //
- .buildAndShow(mainWindow);
+ new CustomDialog.Builder()
+ .setOwner(mainWindow)
+ .resourceBundle(resourceBundle)
+ .titleKey("removeVault.title", vault.get().getDisplayName())
+ .messageKey("removeVault.message")
+ .descriptionKey("removeVault.description")
+ .icon(FontAwesome5Icon.QUESTION)
+ .okButtonKey("removeVault.confirmBtn")
+ .cancelButtonKey("generic.button.cancel")
+ .okAction(v -> {
+ LOG.debug("Removing vault {}.", vault.get().getDisplayName());
+ vaults.remove(vault.get());
+ v.close();
+ }) //
+ .cancelAction(Stage::close) //
+ .build();
+
}
}
diff --git a/src/main/java/org/cryptomator/ui/mainwindow/VaultListContextMenuController.java b/src/main/java/org/cryptomator/ui/mainwindow/VaultListContextMenuController.java
index 80d731c80..8ee588964 100644
--- a/src/main/java/org/cryptomator/ui/mainwindow/VaultListContextMenuController.java
+++ b/src/main/java/org/cryptomator/ui/mainwindow/VaultListContextMenuController.java
@@ -5,7 +5,7 @@ import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.VaultService;
-import org.cryptomator.ui.controls.CustomDialogBuilder;
+import org.cryptomator.ui.controls.CustomDialog;
import org.cryptomator.ui.controls.FontAwesome5Icon;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.vaultoptions.SelectedVaultOptionsTab;
@@ -80,20 +80,22 @@ public class VaultListContextMenuController implements FxController {
public void didClickRemoveVault() {
var vault = Objects.requireNonNull(selectedVault.get());
- new CustomDialogBuilder() //
- .setTitle(String.format(resourceBundle.getString("removeVault.title"), vault.getDisplayName())) //
- .setMessage(resourceBundle.getString("removeVault.message")) //
- .setDescription(resourceBundle.getString("removeVault.description")) //
- .setIcon(FontAwesome5Icon.QUESTION) //
- .setOkButtonText(resourceBundle.getString("removeVault.confirmBtn")) //
- .setCancelButtonText(resourceBundle.getString("generic.button.cancel")) //
- .setOkAction(v -> {
+ new CustomDialog.Builder()
+ .setOwner(mainWindow)
+ .resourceBundle(resourceBundle)
+ .titleKey("removeVault.title", vault.getDisplayName())
+ .messageKey("removeVault.message")
+ .descriptionKey("removeVault.description")
+ .icon(FontAwesome5Icon.QUESTION)
+ .okButtonKey("removeVault.confirmBtn")
+ .cancelButtonKey("generic.button.cancel")
+ .okAction(v -> {
LOG.debug("Removing vault {}.", vault.getDisplayName());
vaults.remove(vault);
v.close();
}) //
- .setCancelAction(Stage::close) //
- .buildAndShow(mainWindow);
+ .cancelAction(Stage::close) //
+ .build();
}
@FXML
diff --git a/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java b/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java
index e7318792a..1a1f621c8 100644
--- a/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java
+++ b/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java
@@ -9,7 +9,7 @@ import org.cryptomator.cryptofs.DirStructure;
import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.VaultService;
-import org.cryptomator.ui.controls.CustomDialogBuilder;
+import org.cryptomator.ui.controls.CustomDialog;
import org.cryptomator.ui.controls.FontAwesome5Icon;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
@@ -206,20 +206,22 @@ public class VaultListController implements FxController {
private void pressedShortcutToRemoveVault() {
final var vault = selectedVault.get();
if (vault != null && EnumSet.of(LOCKED, MISSING, ERROR, NEEDS_MIGRATION).contains(vault.getState())) {
- new CustomDialogBuilder() //
- .setTitle(String.format(resourceBundle.getString("removeVault.title"), vault.getDisplayName())) //
- .setMessage(resourceBundle.getString("removeVault.message")) //
- .setDescription(resourceBundle.getString("removeVault.description")) //
- .setIcon(FontAwesome5Icon.QUESTION) //
- .setOkButtonText(resourceBundle.getString("removeVault.confirmBtn")) //
- .setCancelButtonText(resourceBundle.getString("generic.button.cancel")) //
- .setOkAction(v -> {
+ new CustomDialog.Builder()
+ .setOwner(mainWindow)
+ .resourceBundle(resourceBundle)
+ .titleKey("removeVault.title", vault.getDisplayName())
+ .messageKey("removeVault.message")
+ .descriptionKey("removeVault.description")
+ .icon(FontAwesome5Icon.QUESTION)
+ .okButtonKey("removeVault.confirmBtn")
+ .cancelButtonKey("generic.button.cancel")
+ .okAction(v -> {
LOG.debug("Removing vault {}.", vault.getDisplayName());
vaults.remove(vault);
v.close();
}) //
- .setCancelAction(Stage::close) //
- .buildAndShow(mainWindow);
+ .cancelAction(Stage::close) //
+ .build();
}
}
diff --git a/src/main/java/org/cryptomator/ui/preferences/SupporterCertificateController.java b/src/main/java/org/cryptomator/ui/preferences/SupporterCertificateController.java
index a145bdc8a..638be351f 100644
--- a/src/main/java/org/cryptomator/ui/preferences/SupporterCertificateController.java
+++ b/src/main/java/org/cryptomator/ui/preferences/SupporterCertificateController.java
@@ -5,7 +5,7 @@ import org.cryptomator.common.LicenseHolder;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.UiTheme;
import org.cryptomator.ui.common.FxController;
-import org.cryptomator.ui.controls.CustomDialogBuilder;
+import org.cryptomator.ui.controls.CustomDialog;
import org.cryptomator.ui.controls.FontAwesome5Icon;
import javax.inject.Inject;
@@ -86,19 +86,21 @@ public class SupporterCertificateController implements FxController {
@FXML
void didClickRemoveCert() {
- new CustomDialogBuilder()
- .setTitle(resourceBundle.getString("removeCert.title"))
- .setMessage(resourceBundle.getString("removeCert.message"))
- .setDescription(resourceBundle.getString("removeCert.description"))
- .setIcon(FontAwesome5Icon.QUESTION)
- .setOkButtonText(resourceBundle.getString("removeCert.confirmBtn"))
- .setCancelButtonText(resourceBundle.getString("generic.button.cancel"))
- .setOkAction(v -> {
+ new CustomDialog.Builder()
+ .setOwner(window)
+ .resourceBundle(resourceBundle)
+ .titleKey("removeCert.title")
+ .messageKey("removeCert.message")
+ .descriptionKey("removeCert.description")
+ .icon(FontAwesome5Icon.QUESTION)
+ .okButtonKey("removeCert.confirmBtn")
+ .cancelButtonKey("generic.button.cancel")
+ .okAction(v -> {
settings.licenseKey.set(null);
v.close();
- })
- .setCancelAction(Stage::close)
- .buildAndShow(window);
+ }) //
+ .cancelAction(Stage::close) //
+ .build();
}
public LicenseHolder getLicenseHolder() {