浏览代码

changed to class Builder
used FxmlLoaderFactory.forController
set title and other string values by key

Jan-Peter Klein 5 月之前
父节点
当前提交
2430526ee7

+ 124 - 0
.idea/uiDesigner.xml

@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Palette2">
+    <group name="Swing">
+      <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+      </item>
+      <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
+        <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+        <initial-values>
+          <property name="text" value="Button" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="RadioButton" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="CheckBox" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="Label" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+          <preferred-size width="-1" height="20" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+      </item>
+    </group>
+  </component>
+</project>

+ 124 - 0
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<Stage> okAction = Stage::close;
+		private Consumer<Stage> 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<Stage> okAction) {
+			this.okAction = okAction;
+			return this;
+		}
+
+		public Builder cancelAction(Consumer<Stage> cancelAction) {
+			this.cancelAction = cancelAction;
+			return this;
+		}
+
+		public CustomDialog build(){
+			return new CustomDialog(this);
+		}
+	}
+}

+ 0 - 93
src/main/java/org/cryptomator/ui/controls/CustomDialogBuilder.java

@@ -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<Stage> okAction;
-	private Consumer<Stage> 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<Stage> okAction) {
-		this.okAction = okAction;
-		return this;
-	}
-
-	public CustomDialogBuilder setCancelAction(Consumer<Stage> 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);
-		}
-	}
-}

+ 3 - 1
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;

+ 13 - 11
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);
 	}
 

+ 15 - 11
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

+ 18 - 15
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();
+
 	}
 }

+ 13 - 11
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

+ 13 - 11
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();
 		}
 	}
 

+ 14 - 12
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() {