From 30f0c5e697ed54893a0939921bbb8a02c0d236b5 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Tue, 30 Mar 2021 13:43:37 +0200 Subject: [PATCH] split VaultList and ContextMenu into two separate controllers --- .../ui/mainwindow/MainWindowModule.java | 5 + .../VaultListContextMenuController.java | 157 ++++++++++++++++++ .../ui/mainwindow/VaultListController.java | 135 +-------------- .../src/main/resources/fxml/vault_list.fxml | 13 +- .../fxml/vault_list_contextmenu.fxml | 16 ++ 5 files changed, 180 insertions(+), 146 deletions(-) create mode 100644 main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListContextMenuController.java create mode 100644 main/ui/src/main/resources/fxml/vault_list_contextmenu.fxml diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java index f8316d289..fad1b3c85 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java @@ -86,6 +86,11 @@ abstract class MainWindowModule { @FxControllerKey(VaultListController.class) abstract FxController bindVaultListController(VaultListController controller); + @Binds + @IntoMap + @FxControllerKey(VaultListContextMenuController.class) + abstract FxController bindVaultListContextMenuController(VaultListContextMenuController controller); + @Binds @IntoMap @FxControllerKey(VaultDetailController.class) diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListContextMenuController.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListContextMenuController.java new file mode 100644 index 000000000..4cccdf5d8 --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListContextMenuController.java @@ -0,0 +1,157 @@ +package org.cryptomator.ui.mainwindow; + +import com.tobiasdiez.easybind.EasyBind; +import org.cryptomator.common.keychain.KeychainManager; +import org.cryptomator.common.vaults.Vault; +import org.cryptomator.common.vaults.VaultState; +import org.cryptomator.ui.common.FxController; +import org.cryptomator.ui.fxapp.FxApplication; +import org.cryptomator.ui.removevault.RemoveVaultComponent; +import org.cryptomator.ui.vaultoptions.SelectedVaultOptionsTab; +import org.cryptomator.ui.vaultoptions.VaultOptionsComponent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javafx.beans.binding.Binding; +import javafx.beans.binding.Bindings; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.fxml.FXML; +import javafx.stage.Stage; +import java.util.Arrays; +import java.util.Optional; + +import static org.cryptomator.common.vaults.VaultState.ERROR; +import static org.cryptomator.common.vaults.VaultState.LOCKED; +import static org.cryptomator.common.vaults.VaultState.MISSING; +import static org.cryptomator.common.vaults.VaultState.NEEDS_MIGRATION; +import static org.cryptomator.common.vaults.VaultState.UNLOCKED; + +@MainWindowScoped +public class VaultListContextMenuController implements FxController { + + private static final Logger LOG = LoggerFactory.getLogger(VaultListContextMenuController.class); + + private final ReadOnlyObjectProperty selectedVault; + private final Stage mainWindow; + private final FxApplication application; + private final KeychainManager keychain; + private final RemoveVaultComponent.Builder removeVault; + private final VaultOptionsComponent.Builder vaultOptionsWindow; + private final Binding selectedVaultState; + private final BooleanBinding selectedVaultPassphraseStored; + private final BooleanBinding selectedVaultRemovable; + private final BooleanBinding selectedVaultUnlockable; + private final BooleanBinding selectedVaultLockable; + + @Inject + VaultListContextMenuController(ObjectProperty selectedVault, @MainWindow Stage mainWindow, FxApplication application, KeychainManager keychain, RemoveVaultComponent.Builder removeVault, VaultOptionsComponent.Builder vaultOptionsWindow) { + this.selectedVault = selectedVault; + this.mainWindow = mainWindow; + this.application = application; + this.keychain = keychain; + this.removeVault = removeVault; + this.vaultOptionsWindow = vaultOptionsWindow; + + this.selectedVaultState = EasyBind.wrapNullable(selectedVault).mapObservable(Vault::stateProperty).orElse((VaultState) null); + this.selectedVaultPassphraseStored = Bindings.createBooleanBinding(this::isSelectedVaultPassphraseStored, selectedVault); + this.selectedVaultRemovable = Bindings.createBooleanBinding(() -> selectedVaultIsInState(LOCKED, MISSING, ERROR, NEEDS_MIGRATION), selectedVaultState); + this.selectedVaultUnlockable = Bindings.createBooleanBinding(() -> selectedVaultIsInState(LOCKED), selectedVaultState); + this.selectedVaultLockable = Bindings.createBooleanBinding(() -> selectedVaultIsInState(UNLOCKED), selectedVaultState); + } + + private boolean selectedVaultIsInState(VaultState... states) { + var state = selectedVaultState.getValue(); + return Arrays.stream(states).anyMatch(s -> state == s); + } + + @FXML + public void didClickRemoveVault() { + Vault v = selectedVault.get(); + if (v != null) { + removeVault.vault(v).build().showRemoveVault(); + } else { + LOG.debug("Cannot remove a vault if none is selected."); + } + } + + @FXML + public void didClickShowVaultOptions() { + Vault v = selectedVault.get(); + if (v != null) { + vaultOptionsWindow.vault(v).build().showVaultOptionsWindow(SelectedVaultOptionsTab.ANY); + } else { + LOG.debug("Cannot open vault options if none is selected."); + } + } + + @FXML + public void didClickUnlockVault() { + Vault v = selectedVault.get(); + if (v != null) { + application.startUnlockWorkflow(v, Optional.of(mainWindow)); + } else { + LOG.debug("Cannot unlock vault if none is selected."); + } + } + + @FXML + public void didClickLockVault() { + Vault v = selectedVault.get(); + if (v != null) { + application.startLockWorkflow(v, Optional.of(mainWindow)); + } else { + LOG.debug("Cannot lock vault if none is selected."); + } + } + + @FXML + public void didClickRevealVault() { + Vault v = selectedVault.get(); + if (v != null) { + application.getVaultService().reveal(v); + } else { + LOG.debug("Cannot reveal vault if none is selected."); + } + } + + // Getter and Setter + + public BooleanBinding selectedVaultUnlockableProperty() { + return selectedVaultUnlockable; + } + + public boolean isSelectedVaultUnlockable() { + return selectedVaultUnlockable.get(); + } + + public BooleanBinding selectedVaultLockableProperty() { + return selectedVaultLockable; + } + + public boolean isSelectedVaultLockable() { + return selectedVaultLockable.get(); + } + + public BooleanBinding selectedVaultRemovableProperty() { + return selectedVaultRemovable; + } + + public boolean isSelectedVaultRemovable() { + return selectedVaultRemovable.get(); + } + + public BooleanBinding selectedVaultPassphraseStoredProperty() { + return selectedVaultPassphraseStored; + } + + public boolean isSelectedVaultPassphraseStored() { + if (selectedVault.get() == null) { + return false; + } else { + return keychain.getPassphraseStoredProperty(selectedVault.get().getId()).get(); + } + } +} diff --git a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java index d15a33510..04ea9f152 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java @@ -1,25 +1,14 @@ package org.cryptomator.ui.mainwindow; -import org.cryptomator.common.keychain.KeychainManager; import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.VaultListManager; -import org.cryptomator.common.vaults.VaultState; import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent; import org.cryptomator.ui.common.FxController; -import org.cryptomator.ui.fxapp.FxApplication; -import org.cryptomator.ui.removevault.RemoveVaultComponent; -import org.cryptomator.ui.vaultoptions.SelectedVaultOptionsTab; -import org.cryptomator.ui.vaultoptions.VaultOptionsComponent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.inject.Inject; import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanBinding; -import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.beans.property.SimpleObjectProperty; import javafx.beans.value.ObservableValue; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; @@ -27,53 +16,27 @@ import javafx.fxml.FXML; import javafx.scene.control.ListView; import javafx.scene.input.ContextMenuEvent; import javafx.scene.input.MouseEvent; -import javafx.stage.Stage; -import java.util.Arrays; -import java.util.Optional; - -import static org.cryptomator.common.vaults.VaultState.*; @MainWindowScoped public class VaultListController implements FxController { - private static final Logger LOG = LoggerFactory.getLogger(VaultListController.class); private final ObservableList vaults; private final ObjectProperty selectedVault; - private final ObjectProperty selectedVaultState; - private final BooleanProperty selectedVaultPassphraseStored; private final VaultListCellFactory cellFactory; - private final Stage mainWindow; - private final FxApplication application; - private final KeychainManager keychain; private final AddVaultWizardComponent.Builder addVaultWizard; - private final RemoveVaultComponent.Builder removeVault; - private final VaultOptionsComponent.Builder vaultOptionsWindow; private final BooleanBinding emptyVaultList; - private final BooleanBinding selectedVaultRemovable; - private final BooleanBinding selectedVaultUnlockable; - private final BooleanBinding selectedVaultLockable; public ListView vaultList; @Inject - VaultListController(ObservableList vaults, ObjectProperty selectedVault, VaultListCellFactory cellFactory, @MainWindow Stage mainWindow, FxApplication application, KeychainManager keychain, AddVaultWizardComponent.Builder addVaultWizard, RemoveVaultComponent.Builder removeVault, VaultOptionsComponent.Builder vaultOptionsWindow) { + VaultListController(ObservableList vaults, ObjectProperty selectedVault, VaultListCellFactory cellFactory, AddVaultWizardComponent.Builder addVaultWizard) { this.vaults = vaults; this.selectedVault = selectedVault; this.cellFactory = cellFactory; - this.mainWindow = mainWindow; - this.application = application; - this.keychain = keychain; this.addVaultWizard = addVaultWizard; - this.removeVault = removeVault; - this.vaultOptionsWindow = vaultOptionsWindow; this.emptyVaultList = Bindings.isEmpty(vaults); - this.selectedVaultState = new SimpleObjectProperty<>(null); - this.selectedVaultPassphraseStored = new SimpleBooleanProperty(false); - this.selectedVaultRemovable = Bindings.createBooleanBinding(() -> selectedVaultIsInState(LOCKED, MISSING, ERROR, NEEDS_MIGRATION), selectedVaultState); - this.selectedVaultUnlockable = Bindings.createBooleanBinding(() -> selectedVaultIsInState(LOCKED), selectedVaultState); - this.selectedVaultLockable = Bindings.createBooleanBinding(() -> selectedVaultIsInState(UNLOCKED), selectedVaultState); selectedVault.addListener(this::selectedVaultDidChange); } @@ -82,10 +45,6 @@ public class VaultListController implements FxController { vaultList.setItems(vaults); vaultList.setCellFactory(cellFactory); selectedVault.bind(vaultList.getSelectionModel().selectedItemProperty()); - if (selectedVault.get() != null) { - selectedVaultState.set(selectedVault.get().getState()); - selectedVaultPassphraseStored.bind(keychain.getPassphraseStoredProperty(selectedVault.get().getId())); - } vaults.addListener((ListChangeListener.Change c) -> { while (c.next()) { if (c.wasAdded()) { @@ -110,21 +69,10 @@ public class VaultListController implements FxController { } private void selectedVaultDidChange(@SuppressWarnings("unused") ObservableValue observableValue, @SuppressWarnings("unused") Vault oldValue, Vault newValue) { - if (oldValue != null) { - selectedVaultState.unbind(); - selectedVaultPassphraseStored.unbind(); - } if (newValue == null) { return; } VaultListManager.redetermineVaultState(newValue); - selectedVaultState.bind(newValue.stateProperty()); - selectedVaultPassphraseStored.bind(keychain.getPassphraseStoredProperty(newValue.getId())); - } - - private boolean selectedVaultIsInState(VaultState... states) { - var state = selectedVaultState.get(); - return Arrays.stream(states).anyMatch(s -> state == s); } @FXML @@ -132,56 +80,6 @@ public class VaultListController implements FxController { addVaultWizard.build().showAddVaultWizard(); } - @FXML - public void didClickRemoveVault() { - Vault v = selectedVault.get(); - if (v != null) { - removeVault.vault(v).build().showRemoveVault(); - } else { - LOG.debug("Cannot remove a vault if none is selected."); - } - } - - @FXML - public void didClickShowVaultOptions() { - Vault v = selectedVault.get(); - if (v != null) { - vaultOptionsWindow.vault(v).build().showVaultOptionsWindow(SelectedVaultOptionsTab.ANY); - } else { - LOG.debug("Cannot open vault options if none is selected."); - } - } - - @FXML - public void didClickUnlockVault() { - Vault v = selectedVault.get(); - if (v != null) { - application.startUnlockWorkflow(v, Optional.of(mainWindow)); - } else { - LOG.debug("Cannot unlock vault if none is selected."); - } - } - - @FXML - public void didClickLockVault() { - Vault v = selectedVault.get(); - if (v != null) { - application.startLockWorkflow(v, Optional.of(mainWindow)); - } else { - LOG.debug("Cannot lock vault if none is selected."); - } - } - - @FXML - public void didClickRevealVault() { - Vault v = selectedVault.get(); - if (v != null) { - application.getVaultService().reveal(v); - } else { - LOG.debug("Cannot reveal vault if none is selected."); - } - } - // Getter and Setter public BooleanBinding emptyVaultListProperty() { @@ -192,35 +90,4 @@ public class VaultListController implements FxController { return emptyVaultList.get(); } - public BooleanBinding selectedVaultUnlockableProperty() { - return selectedVaultUnlockable; - } - - public boolean isSelectedVaultUnlockable() { - return selectedVaultUnlockable.get(); - } - - public BooleanBinding selectedVaultLockableProperty() { - return selectedVaultLockable; - } - - public boolean isSelectedVaultLockable() { - return selectedVaultLockable.get(); - } - - public BooleanBinding selectedVaultRemovableProperty() { - return selectedVaultRemovable; - } - - public boolean isSelectedVaultRemovable() { - return selectedVaultRemovable.get(); - } - - public BooleanProperty selectedVaultPassphraseStoredProperty() { - return selectedVaultPassphraseStored; - } - - public boolean isSelectedVaultPassphraseStored() { - return selectedVaultPassphraseStored.get(); - } } diff --git a/main/ui/src/main/resources/fxml/vault_list.fxml b/main/ui/src/main/resources/fxml/vault_list.fxml index 68d8b9fde..f01aa710c 100644 --- a/main/ui/src/main/resources/fxml/vault_list.fxml +++ b/main/ui/src/main/resources/fxml/vault_list.fxml @@ -2,10 +2,8 @@ - - @@ -17,16 +15,7 @@ - - - - - - - - - - + diff --git a/main/ui/src/main/resources/fxml/vault_list_contextmenu.fxml b/main/ui/src/main/resources/fxml/vault_list_contextmenu.fxml new file mode 100644 index 000000000..bd8f19204 --- /dev/null +++ b/main/ui/src/main/resources/fxml/vault_list_contextmenu.fxml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + +