diff --git a/src/main/java/org/cryptomator/ui/eventview/EventListCellController.java b/src/main/java/org/cryptomator/ui/eventview/EventListCellController.java index 36b602f5e..57e115ff6 100644 --- a/src/main/java/org/cryptomator/ui/eventview/EventListCellController.java +++ b/src/main/java/org/cryptomator/ui/eventview/EventListCellController.java @@ -15,7 +15,9 @@ import org.slf4j.LoggerFactory; import javax.inject.Inject; import javafx.beans.binding.Bindings; +import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; @@ -26,6 +28,7 @@ import javafx.geometry.Side; import javafx.scene.control.Button; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; +import javafx.scene.layout.HBox; import java.nio.file.Path; import java.util.Optional; import java.util.ResourceBundle; @@ -46,9 +49,12 @@ public class EventListCellController implements FxController { private final ObservableValue message; private final ObservableValue description; private final ObservableValue icon; + private final BooleanProperty actionsButtonVisible; @FXML - ContextMenu eventActions; + HBox root; + @FXML + ContextMenu eventActionsMenu; @FXML Button eventActionsButton; @@ -65,13 +71,23 @@ public class EventListCellController implements FxController { this.message = Bindings.createStringBinding(this::selectMessage, vaultUnlocked, eventMessage); this.description = Bindings.createStringBinding(this::selectDescription, vaultUnlocked, eventDescription); this.icon = Bindings.createObjectBinding(this::selectIcon, vaultUnlocked, eventIcon); + this.actionsButtonVisible = new SimpleBooleanProperty(); + } + + @FXML + public void initialize() { + actionsButtonVisible.bind(Bindings.createBooleanBinding(this::determineActionsButtonVisibility, root.hoverProperty(), eventActionsMenu.showingProperty(), vaultUnlocked)); + vaultUnlocked.addListener((_,_,newValue) -> eventActionsMenu.hide()); + } + + private boolean determineActionsButtonVisibility() { + return vaultUnlocked.getValue() && (eventActionsMenu.isShowing() || root.isHover()); } public void setEvent(@NotNull VaultEvent item) { event.set(item); - eventDescription.setValue("Vault " + item.v().getDisplayName()); - eventActions.hide(); - eventActions.getItems().clear(); + eventActionsMenu.hide(); + eventActionsMenu.getItems().clear(); addAction("generic.action.dismiss", () -> events.remove(item)); switch (item.actualEvent()) { case ConflictResolvedEvent fse -> this.adjustToConflictResolvedEvent(fse); @@ -82,7 +98,8 @@ public class EventListCellController implements FxController { private void adjustToConflictResolvedEvent(ConflictResolvedEvent cre) { eventIcon.setValue(FontAwesome5Icon.FILE); - eventMessage.setValue("Resolved conflict, new file is " + cre.resolvedCleartextPath()); //TODO:localize + eventMessage.setValue(cre.resolvedCleartextPath().toString()); + eventDescription.setValue(resourceBundle.getString("event.conflictResolved.description")); if (revealService.isPresent()) { addAction("event.conflictResolved.showDecrypted", () -> this.showResolvedConflict(cre)); } @@ -90,15 +107,18 @@ public class EventListCellController implements FxController { private void adjustToConflictEvent(ConflictResolutionFailedEvent cfe) { eventIcon.setValue(FontAwesome5Icon.TIMES); - eventMessage.setValue("Failed to resolve conflict for " + cfe.conflictingCiphertextPath()); //TODO:localize + eventMessage.setValue(cfe.canonicalCleartextPath().toString()); + eventDescription.setValue(resourceBundle.getString("event.conflict.description")); if (revealService.isPresent()) { - addAction("event.conflictFailed.showEncrypted", () -> reveal(cfe.conflictingCiphertextPath())); + addAction("event.conflict.showDecrypted", () -> reveal(cfe.canonicalCleartextPath())); + addAction("event.conflict.showEncrypted", () -> reveal(cfe.conflictingCiphertextPath())); } } private void adjustToDecryptionFailedEvent(DecryptionFailedEvent dfe) { eventIcon.setValue(FontAwesome5Icon.BAN); - eventMessage.setValue("Cannot decrypt " + dfe.ciphertextPath()); //TODO:localize + eventMessage.setValue(dfe.ciphertextPath().toString()); + eventDescription.setValue(resourceBundle.getString("event.decryptionFailed.description")); if (revealService.isPresent()) { addAction("event.decryptionFailed.showEncrypted", () -> reveal(dfe.ciphertextPath())); } @@ -108,7 +128,7 @@ public class EventListCellController implements FxController { var entry = new MenuItem(resourceBundle.getString(localizationKey)); entry.getStyleClass().addLast("add-vault-menu-item"); entry.setOnAction(_ -> action.run()); - eventActions.getItems().addLast(entry); + eventActionsMenu.getItems().addLast(entry); } @@ -125,7 +145,7 @@ public class EventListCellController implements FxController { return eventMessage.getValue(); } else { var e = event.getValue(); - return "Event for " + (e != null ? e.v().getDisplayName() : ""); //TODO: localize + return resourceBundle.getString("event.vaultLocked.message"); } } @@ -133,7 +153,7 @@ public class EventListCellController implements FxController { if (vaultUnlocked.getValue()) { return eventDescription.getValue(); } else { - return "Unlock the vault to display details."; //TODO: localize + return resourceBundle.getString("event.vaultLocked.description"); } } @@ -142,10 +162,10 @@ public class EventListCellController implements FxController { public void toggleEventActionsMenu() { var e = event.get(); if (e != null) { - if (eventActions.isShowing()) { - eventActions.hide(); + if (eventActionsMenu.isShowing()) { + eventActionsMenu.hide(); } else { - eventActions.show(eventActionsButton, Side.BOTTOM, 0.0, 0.0); + eventActionsMenu.show(eventActionsButton, Side.BOTTOM, 0.0, 0.0); } } } @@ -165,11 +185,10 @@ public class EventListCellController implements FxController { revealService.orElseThrow(() -> new IllegalStateException("Function requiring revealService called, but service not available")) // .reveal(p); } catch (RevealFailedException e) { - LOG.warn("Failed to show path {}",p, e); + LOG.warn("Failed to show path {}", p, e); } } - //-- property accessors -- public ObservableValue messageProperty() { return message; @@ -195,4 +214,13 @@ public class EventListCellController implements FxController { return icon.getValue(); } + public ObservableValue actionsButtonVisibleProperty() { + return actionsButtonVisible; + } + + public boolean isActionsButtonVisible() { + return actionsButtonVisible.getValue(); + } + + } diff --git a/src/main/resources/fxml/eventview_cell.fxml b/src/main/resources/fxml/eventview_cell.fxml index 8e3d583db..a21af9f1d 100644 --- a/src/main/resources/fxml/eventview_cell.fxml +++ b/src/main/resources/fxml/eventview_cell.fxml @@ -14,7 +14,8 @@ prefHeight="60" prefWidth="200" spacing="12" - alignment="CENTER_LEFT"> + alignment="CENTER_LEFT" + fx:id="root"> @@ -26,15 +27,13 @@