custom dialog init

This commit is contained in:
Jan-Peter Klein
2024-11-14 11:35:23 +01:00
parent 2430526ee7
commit 18ca563865
8 changed files with 146 additions and 125 deletions

View File

@@ -5,6 +5,7 @@ import org.cryptomator.ui.common.FxmlLoaderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
@@ -16,46 +17,55 @@ import java.util.function.Consumer;
public class CustomDialog {
private static final Logger LOG = LoggerFactory.getLogger(CustomDialog.class);
private final ResourceBundle resourceBundle;
private final Stage dialogStage;
private Stage dialogStage;
CustomDialog(Builder builder){
CustomDialog(Builder builder) {
this.resourceBundle = builder.resourceBundle;
dialogStage = new Stage();
dialogStage.initOwner(builder.owner);
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.setTitle(resolveText(builder.resourceBundle, builder.titleKey, builder.titleArgs));
dialogStage.setTitle(resolveText(builder.titleKey, builder.titleArgs));
try{
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.setMessage(resolveText(builder.messageKey, null));
controller.setDescription(resolveText(builder.descriptionKey, null));
controller.setIcon(builder.icon);
controller.setOkButtonText(resolveText(builder.resourceBundle, builder.okButtonKey, null));
controller.setCancelButtonText(resolveText(builder.resourceBundle, builder.cancelButtonKey, null));
controller.setOkButtonText(resolveText(builder.okButtonKey, null));
controller.setCancelButtonText(resolveText(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);
public void showAndWait() {
dialogStage.showAndWait();
}
private String resolveText(String key, String[] args) {
String text = (key == null || key.isEmpty() || !resourceBundle.containsKey(key))
? String.format("N/A - Key '%s' not found", key)
: 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 final ResourceBundle resourceBundle;
private String titleKey;
private String[] titleArgs;
private String messageKey;
@@ -67,57 +77,58 @@ public class CustomDialog {
private Consumer<Stage> okAction = Stage::close;
private Consumer<Stage> cancelAction = Stage::close;
@Inject
public Builder(ResourceBundle resourceBundle) {
this.resourceBundle = resourceBundle;
}
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) {
public Builder setTitleKey(String titleKey, String... args) {
this.titleKey = titleKey;
this.titleArgs = args;
return this;
}
public Builder messageKey(String messageKey) {
public Builder setMessageKey(String messageKey) {
this.messageKey = messageKey;
return this;
}
public Builder descriptionKey(String descriptionKey) {
public Builder setDescriptionKey(String descriptionKey) {
this.descriptionKey = descriptionKey;
return this;
}
public Builder icon(FontAwesome5Icon icon) {
public Builder setIcon(FontAwesome5Icon icon) {
this.icon = icon;
return this;
}
public Builder okButtonKey(String okButtonKey) {
public Builder setOkButtonKey(String okButtonKey) {
this.okButtonKey = okButtonKey;
return this;
}
public Builder cancelButtonKey(String cancelButtonKey) {
public Builder setCancelButtonKey(String cancelButtonKey) {
this.cancelButtonKey = cancelButtonKey;
return this;
}
public Builder okAction(Consumer<Stage> okAction) {
public Builder setOkAction(Consumer<Stage> okAction) {
this.okAction = okAction;
return this;
}
public Builder cancelAction(Consumer<Stage> cancelAction) {
public Builder setCancelAction(Consumer<Stage> cancelAction) {
this.cancelAction = cancelAction;
return this;
}
public CustomDialog build(){
public CustomDialog build() {
return new CustomDialog(this);
}
}

View File

@@ -7,6 +7,7 @@ package org.cryptomator.ui.fxapp;
import dagger.Module;
import dagger.Provides;
import org.cryptomator.ui.controls.CustomDialog;
import org.cryptomator.ui.dokanysupportend.DokanySupportEndComponent;
import org.cryptomator.ui.error.ErrorComponent;
import org.cryptomator.ui.health.HealthCheckComponent;
@@ -24,6 +25,7 @@ import org.cryptomator.ui.vaultoptions.VaultOptionsComponent;
import javafx.scene.image.Image;
import java.io.IOException;
import java.io.InputStream;
import java.util.ResourceBundle;
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, //
MainWindowComponent.class, //
@@ -70,4 +72,10 @@ abstract class FxApplicationModule {
return builder.build();
}
@Provides
@FxApplicationScoped
static CustomDialog.Builder provideCustomDialog(ResourceBundle resourceBundle) {
return new CustomDialog.Builder(resourceBundle);
}
}

View File

@@ -35,7 +35,6 @@ import java.awt.Desktop;
import java.awt.desktop.AppReopenedListener;
import java.awt.desktop.QuitResponse;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutorService;
@@ -59,7 +58,7 @@ public class FxApplicationWindows {
private final VaultOptionsComponent.Factory vaultOptionsWindow;
private final ShareVaultComponent.Factory shareVaultWindow;
private final FilteredList<Window> visibleWindows;
private final ResourceBundle resourceBundle;
private final CustomDialog.Builder customDialog;
@Inject
public FxApplicationWindows(@PrimaryStage Stage primaryStage, //
@@ -75,7 +74,7 @@ public class FxApplicationWindows {
VaultOptionsComponent.Factory vaultOptionsWindow, //
ShareVaultComponent.Factory shareVaultWindow, //
ExecutorService executor, //
ResourceBundle resourceBundle) {
CustomDialog.Builder customDialog) {
this.primaryStage = primaryStage;
this.trayIntegration = trayIntegration;
this.mainWindow = mainWindow;
@@ -90,8 +89,7 @@ public class FxApplicationWindows {
this.vaultOptionsWindow = vaultOptionsWindow;
this.shareVaultWindow = shareVaultWindow;
this.visibleWindows = Window.getWindows().filtered(Window::isShowing);
this.resourceBundle = resourceBundle;
this.customDialog = customDialog;
}
public void initialize() {
@@ -155,21 +153,20 @@ public class FxApplicationWindows {
public void showDokanySupportEndWindow() {
CompletableFuture.runAsync(() -> {
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 -> {
customDialog.setOwner(mainWindow.get().window())
.setTitleKey("dokanySupportEnd.title")
.setMessageKey("dokanySupportEnd.message")
.setDescriptionKey("dokanySupportEnd.description")
.setIcon(FontAwesome5Icon.QUESTION)
.setOkButtonKey("generic.button.close")
.setCancelButtonKey("dokanySupportEnd.preferencesBtn")
.setOkAction(Stage::close) //
.setCancelAction(v -> {
showPreferencesWindow(SelectedPreferencesTab.VOLUME);
v.close();
}) //
.build();
.build()
.showAndWait();
}, Platform::runLater);
}

View File

@@ -28,17 +28,20 @@ public class VaultDetailMissingVaultController implements FxController {
private final ObservableList<Vault> vaults;
private final ResourceBundle resourceBundle;
private final Stage window;
private final CustomDialog.Builder customDialog;
@Inject
public VaultDetailMissingVaultController(ObjectProperty<Vault> vault, //
ObservableList<Vault> vaults, //
ResourceBundle resourceBundle, //
@MainWindow Stage window) {
@MainWindow Stage window, //
CustomDialog.Builder customDialog) {
this.vault = vault;
this.vaults = vaults;
this.resourceBundle = resourceBundle;
this.window = window;
this.customDialog = customDialog;
}
@FXML
@@ -48,23 +51,23 @@ public class VaultDetailMissingVaultController implements FxController {
@FXML
void didClickRemoveVault() {
new CustomDialog.Builder()
customDialog
.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 -> {
.setTitleKey("removeVault.title", vault.get().getDisplayName())
.setMessageKey("removeVault.message")
.setDescriptionKey("removeVault.description")
.setIcon(FontAwesome5Icon.QUESTION)
.setOkButtonKey("removeVault.confirmBtn")
.setCancelButtonKey("generic.button.cancel")
.setOkAction(v -> {
LOG.debug("Removing vault {}.", vault.get().getDisplayName());
vaults.remove(vault.get());
v.close();
}) //
.cancelAction(Stage::close) //
.build();
.setCancelAction(Stage::close) //
.build()
.showAndWait();
;
}

View File

@@ -15,7 +15,6 @@ import javafx.beans.property.ObjectProperty;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.stage.Stage;
import java.util.ResourceBundle;
@MainWindowScoped
public class VaultDetailUnknownErrorController implements FxController {
@@ -26,20 +25,21 @@ public class VaultDetailUnknownErrorController implements FxController {
private final FxApplicationWindows appWindows;
private final Stage errorWindow;
private final ObservableList<Vault> vaults;
private final ResourceBundle resourceBundle;
private final Stage mainWindow;
private final CustomDialog.Builder customDialog;
@Inject
public VaultDetailUnknownErrorController(@MainWindow Stage mainWindow,
ObjectProperty<Vault> vault, ObservableList<Vault> vaults, //
ResourceBundle resourceBundle, //
FxApplicationWindows appWindows, @Named("errorWindow") Stage errorWindow) {
FxApplicationWindows appWindows, //
@Named("errorWindow") Stage errorWindow, //
CustomDialog.Builder customDialog) {
this.mainWindow = mainWindow;
this.vault = vault;
this.vaults = vaults;
this.resourceBundle = resourceBundle;
this.appWindows = appWindows;
this.errorWindow = errorWindow;
this.customDialog = customDialog;
}
@FXML
@@ -54,22 +54,22 @@ public class VaultDetailUnknownErrorController implements FxController {
@FXML
void didClickRemoveVault() {
new CustomDialog.Builder()
customDialog
.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 -> {
.setTitleKey("removeVault.title", vault.get().getDisplayName())
.setMessageKey("removeVault.message")
.setDescriptionKey("removeVault.description")
.setIcon(FontAwesome5Icon.QUESTION)
.setOkButtonKey("removeVault.confirmBtn")
.setCancelButtonKey("generic.button.cancel")
.setOkAction(v -> {
LOG.debug("Removing vault {}.", vault.get().getDisplayName());
vaults.remove(vault.get());
v.close();
}) //
.cancelAction(Stage::close) //
.build();
.setCancelAction(Stage::close) //
.build()
.showAndWait();
}
}

View File

@@ -22,7 +22,6 @@ import javafx.fxml.FXML;
import javafx.stage.Stage;
import java.util.EnumSet;
import java.util.Objects;
import java.util.ResourceBundle;
import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
@@ -48,22 +47,26 @@ public class VaultListContextMenuController implements FxController {
private final ObservableValue<Boolean> selectedVaultUnlockable;
private final ObservableValue<Boolean> selectedVaultLockable;
private final ObservableList<Vault> vaults;
private final ResourceBundle resourceBundle;
private final CustomDialog.Builder customDialog;
@Inject
VaultListContextMenuController(ObjectProperty<Vault> selectedVault,
ObservableList<Vault> vaults, //
ResourceBundle resourceBundle, //
@MainWindow Stage mainWindow, FxApplicationWindows appWindows, VaultService vaultService, KeychainManager keychain, VaultOptionsComponent.Factory vaultOptionsWindow) {
@MainWindow Stage mainWindow, //
FxApplicationWindows appWindows, //
VaultService vaultService, //
KeychainManager keychain, //
VaultOptionsComponent.Factory vaultOptionsWindow, //
CustomDialog.Builder customDialog) {
this.selectedVault = selectedVault;
this.vaults = vaults;
this.resourceBundle = resourceBundle;
this.mainWindow = mainWindow;
this.appWindows = appWindows;
this.vaultService = vaultService;
this.keychain = keychain;
this.vaultOptionsWindow = vaultOptionsWindow;
this.customDialog = customDialog;
this.selectedVaultState = selectedVault.flatMap(Vault::stateProperty).orElse(null);
this.selectedVaultPassphraseStored = selectedVault.map(this::isPasswordStored).orElse(false);
@@ -79,23 +82,20 @@ public class VaultListContextMenuController implements FxController {
@FXML
public void didClickRemoveVault() {
var vault = Objects.requireNonNull(selectedVault.get());
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();
}) //
.cancelAction(Stage::close) //
.build();
customDialog.setOwner(mainWindow)
.setTitleKey("removeVault.title", vault.getDisplayName())
.setMessageKey("removeVault.message")
.setDescriptionKey("removeVault.description")
.setIcon(FontAwesome5Icon.QUESTION)
.setOkButtonKey("removeVault.confirmBtn")
.setCancelButtonKey("generic.button.cancel")
.setOkAction(v -> {
LOG.debug("Removing vault {}.", vault.getDisplayName());
vaults.remove(vault);
v.close();
}) //
.build()
.showAndWait();
}
@FXML

View File

@@ -72,6 +72,8 @@ public class VaultListController implements FxController {
private final ResourceBundle resourceBundle;
private final FxApplicationWindows appWindows;
private final ObservableValue<Double> cellSize;
private final CustomDialog.Builder customDialog;
public ListView<Vault> vaultList;
public StackPane root;
@FXML
@@ -89,7 +91,8 @@ public class VaultListController implements FxController {
VaultListManager vaultListManager, //
ResourceBundle resourceBundle, //
FxApplicationWindows appWindows, //
Settings settings) {
Settings settings,
CustomDialog.Builder customDialog) {
this.mainWindow = mainWindow;
this.vaults = vaults;
this.selectedVault = selectedVault;
@@ -99,6 +102,7 @@ public class VaultListController implements FxController {
this.vaultListManager = vaultListManager;
this.resourceBundle = resourceBundle;
this.appWindows = appWindows;
this.customDialog = customDialog;
this.emptyVaultList = Bindings.isEmpty(vaults);
@@ -206,22 +210,21 @@ 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 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 -> {
customDialog.setOwner(mainWindow)
.setTitleKey("removeVault.title", vault.getDisplayName())
.setMessageKey("removeVault.message")
.setDescriptionKey("removeVault.description")
.setIcon(FontAwesome5Icon.QUESTION)
.setOkButtonKey("removeVault.confirmBtn")
.setCancelButtonKey("generic.button.cancel")
.setOkAction(v -> {
LOG.debug("Removing vault {}.", vault.getDisplayName());
vaults.remove(vault);
v.close();
}) //
.cancelAction(Stage::close) //
.build();
.setCancelAction(Stage::close) //
.build()
.showAndWait();
}
}

View File

@@ -15,7 +15,6 @@ import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextFormatter;
import javafx.stage.Stage;
import java.util.ResourceBundle;
@PreferencesScoped
public class SupporterCertificateController implements FxController {
@@ -28,18 +27,18 @@ public class SupporterCertificateController implements FxController {
private final Stage window;
private final LicenseHolder licenseHolder;
private final Settings settings;
private final ResourceBundle resourceBundle;
private final CustomDialog.Builder customDialog;
@FXML
private TextArea supporterCertificateField;
@Inject
SupporterCertificateController(Application application, @PreferencesWindow Stage window, LicenseHolder licenseHolder, Settings settings, ResourceBundle resourceBundle) {
SupporterCertificateController(Application application, @PreferencesWindow Stage window, LicenseHolder licenseHolder, Settings settings, CustomDialog.Builder customDialog) {
this.application = application;
this.window = window;
this.licenseHolder = licenseHolder;
this.settings = settings;
this.resourceBundle = resourceBundle;
this.customDialog = customDialog;
}
@FXML
@@ -86,21 +85,21 @@ public class SupporterCertificateController implements FxController {
@FXML
void didClickRemoveCert() {
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();
}) //
.cancelAction(Stage::close) //
.build();
customDialog.setOwner(window)
.setTitleKey("removeCert.title")
.setMessageKey("removeCert.message")
.setDescriptionKey("removeCert.description")
.setIcon(FontAwesome5Icon.QUESTION)
.setOkButtonKey("removeCert.confirmBtn")
.setCancelButtonKey("generic.button.cancel")
.setOkAction(v -> {
settings.licenseKey.set(null);
v.close();
}) //
.setCancelAction(Stage::close) //
.build()
.showAndWait();
}
public LicenseHolder getLicenseHolder() {