ソースを参照

split VaultList and ContextMenu into two separate controllers

Sebastian Stenzel 4 年 前
コミット
30f0c5e697

+ 5 - 0
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)

+ 157 - 0
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<Vault> 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<VaultState> selectedVaultState;
+	private final BooleanBinding selectedVaultPassphraseStored;
+	private final BooleanBinding selectedVaultRemovable;
+	private final BooleanBinding selectedVaultUnlockable;
+	private final BooleanBinding selectedVaultLockable;
+
+	@Inject
+	VaultListContextMenuController(ObjectProperty<Vault> 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();
+		}
+	}
+}

+ 1 - 134
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<Vault> vaults;
 	private final ObjectProperty<Vault> selectedVault;
-	private final ObjectProperty<VaultState> 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<Vault> vaultList;
 
 	@Inject
-	VaultListController(ObservableList<Vault> vaults, ObjectProperty<Vault> selectedVault, VaultListCellFactory cellFactory, @MainWindow Stage mainWindow, FxApplication application, KeychainManager keychain, AddVaultWizardComponent.Builder addVaultWizard, RemoveVaultComponent.Builder removeVault, VaultOptionsComponent.Builder vaultOptionsWindow) {
+	VaultListController(ObservableList<Vault> vaults, ObjectProperty<Vault> 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<? extends Vault> c) -> {
 			while (c.next()) {
 				if (c.wasAdded()) {
@@ -110,21 +69,10 @@ public class VaultListController implements FxController {
 	}
 
 	private void selectedVaultDidChange(@SuppressWarnings("unused") ObservableValue<? extends Vault> 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();
-	}
 }

+ 1 - 12
main/ui/src/main/resources/fxml/vault_list.fxml

@@ -2,10 +2,8 @@
 
 <?import org.cryptomator.ui.controls.FontAwesome5IconView?>
 <?import javafx.scene.control.Button?>
-<?import javafx.scene.control.ContextMenu?>
 <?import javafx.scene.control.Label?>
 <?import javafx.scene.control.ListView?>
-<?import javafx.scene.control.MenuItem?>
 <?import javafx.scene.layout.Region?>
 <?import javafx.scene.layout.StackPane?>
 <?import javafx.scene.layout.VBox?>
@@ -17,16 +15,7 @@
 	<StackPane VBox.vgrow="ALWAYS">
 		<ListView fx:id="vaultList" editable="true" fixedCellSize="60">
 			<contextMenu>
-				<ContextMenu>
-					<items>
-						<MenuItem fx:id="revealEntry" text="%main.vaultlist.contextMenu.reveal" onAction="#didClickRevealVault" visible="${controller.selectedVaultLockable}"/>
-						<MenuItem fx:id="lockEntry" text="%main.vaultlist.contextMenu.lock" onAction="#didClickLockVault" visible="${controller.selectedVaultLockable}"/>
-						<MenuItem fx:id="unlockEntry" text="%main.vaultlist.contextMenu.unlock" onAction="#didClickUnlockVault" visible="${controller.selectedVaultUnlockable &amp;&amp; !controller.selectedVaultPassphraseStored}"/>
-						<MenuItem fx:id="unlockNowEntry" text="%main.vaultlist.contextMenu.unlockNow" onAction="#didClickUnlockVault" visible="${controller.selectedVaultUnlockable &amp;&amp; controller.selectedVaultPassphraseStored}"/>
-						<MenuItem fx:id="optionsEntry" text="%main.vaultlist.contextMenu.vaultoptions" onAction="#didClickShowVaultOptions" disable="${!controller.selectedVaultUnlockable}"/>
-						<MenuItem fx:id="removeEntry" text="%main.vaultlist.contextMenu.remove" onAction="#didClickRemoveVault" disable="${!controller.selectedVaultRemovable}"/>
-					</items>
-				</ContextMenu>
+				<fx:include source="vault_list_contextmenu.fxml"/>
 			</contextMenu>
 		</ListView>
 		<VBox visible="${controller.emptyVaultList}" spacing="6" alignment="CENTER">

+ 16 - 0
main/ui/src/main/resources/fxml/vault_list_contextmenu.fxml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.scene.control.ContextMenu?>
+<?import javafx.scene.control.MenuItem?>
+<ContextMenu xmlns:fx="http://javafx.com/fxml"
+			 xmlns="http://javafx.com/javafx"
+			 fx:controller="org.cryptomator.ui.mainwindow.VaultListContextMenuController">
+	<items>
+		<MenuItem fx:id="revealEntry" text="%main.vaultlist.contextMenu.reveal" onAction="#didClickRevealVault" visible="${controller.selectedVaultLockable}"/>
+		<MenuItem fx:id="lockEntry" text="%main.vaultlist.contextMenu.lock" onAction="#didClickLockVault" visible="${controller.selectedVaultLockable}"/>
+		<MenuItem fx:id="unlockEntry" text="%main.vaultlist.contextMenu.unlock" onAction="#didClickUnlockVault" visible="${controller.selectedVaultUnlockable &amp;&amp; !controller.selectedVaultPassphraseStored}"/>
+		<MenuItem fx:id="unlockNowEntry" text="%main.vaultlist.contextMenu.unlockNow" onAction="#didClickUnlockVault" visible="${controller.selectedVaultUnlockable &amp;&amp; controller.selectedVaultPassphraseStored}"/>
+		<MenuItem fx:id="optionsEntry" text="%main.vaultlist.contextMenu.vaultoptions" onAction="#didClickShowVaultOptions" disable="${!controller.selectedVaultUnlockable}"/>
+		<MenuItem fx:id="removeEntry" text="%main.vaultlist.contextMenu.remove" onAction="#didClickRemoveVault" disable="${!controller.selectedVaultRemovable}"/>
+	</items>
+</ContextMenu>