diff --git a/.gitignore b/.gitignore index 246e7ffff..5ddd9fc95 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,9 @@ .classpath target/ test-output/ + +# IntelliJ Settings Files # +.idea/ +out/ +.idea_modules/ +*.iws diff --git a/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java b/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java index f316fe2c2..223a7ef13 100644 --- a/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java +++ b/main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java @@ -5,6 +5,7 @@ * * Contributors: * Sebastian Stenzel - initial API and implementation + * Jean-Noël Charon - confirmation dialog on vault removal ******************************************************************************/ package org.cryptomator.ui.controllers; @@ -16,17 +17,20 @@ import java.nio.file.Path; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; +import org.apache.commons.lang3.SystemUtils; import org.cryptomator.ui.controls.DirectoryListCell; import org.cryptomator.ui.model.Vault; import org.cryptomator.ui.model.VaultFactory; import org.cryptomator.ui.settings.Localization; import org.cryptomator.ui.settings.Settings; +import org.cryptomator.ui.util.DialogBuilderUtil; import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.monadic.MonadicBinding; import org.slf4j.Logger; @@ -46,7 +50,9 @@ import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.geometry.Side; import javafx.scene.Parent; +import javafx.scene.control.Alert; import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; import javafx.scene.control.ContextMenu; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; @@ -228,9 +234,18 @@ public class MainController extends LocalizedFXMLViewController { @FXML private void didClickRemoveSelectedEntry(ActionEvent e) { - vaults.remove(selectedVault.get()); - if (vaults.isEmpty()) { - activeController.set(welcomeController.get()); + Alert confirmDialog = DialogBuilderUtil.buildConfirmationDialog( // + localization.getString("main.directoryList.remove.confirmation.title"), // + localization.getString("main.directoryList.remove.confirmation.header"), // + localization.getString("main.directoryList.remove.confirmation.content"), // + SystemUtils.IS_OS_MAC_OSX ? ButtonType.CANCEL : ButtonType.OK); + + Optional choice = confirmDialog.showAndWait(); + if (ButtonType.OK.equals(choice.get())) { + vaults.remove(selectedVault.get()); + if (vaults.isEmpty()) { + activeController.set(welcomeController.get()); + } } } diff --git a/main/ui/src/main/java/org/cryptomator/ui/util/DialogBuilderUtil.java b/main/ui/src/main/java/org/cryptomator/ui/util/DialogBuilderUtil.java new file mode 100644 index 000000000..e9f1b99fe --- /dev/null +++ b/main/ui/src/main/java/org/cryptomator/ui/util/DialogBuilderUtil.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2016 Sebastian Stenzel and others. + * This file is licensed under the terms of the MIT license. + * See the LICENSE.txt file for more info. + * + * Contributors: + * Jean-Noël Charon - initial API and implementation + *******************************************************************************/ +package org.cryptomator.ui.util; + +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.text.Text; + +public class DialogBuilderUtil { + + public DialogBuilderUtil() { + } + + public static Alert buildInformationDialog(String title, String header, String content, ButtonType defaultButton) { + return buildDialog(title, header, content, Alert.AlertType.INFORMATION, defaultButton); + } + + public static Alert buildWarningDialog(String title, String header, String content, ButtonType defaultButton) { + return buildDialog(title, header, content, Alert.AlertType.WARNING, defaultButton); + } + + public static Alert buildErrorDialog(String title, String header, String content, ButtonType defaultButton) { + return buildDialog(title, header, content, Alert.AlertType.ERROR, defaultButton); + } + + public static Alert buildConfirmationDialog(String title, String header, String content, ButtonType defaultButton) { + return buildDialog(title, header, content, Alert.AlertType.CONFIRMATION, defaultButton); + } + + private static Alert buildDialog(String title, String header, String content, Alert.AlertType type, ButtonType defaultButton) { + Text contentText = new Text(content); + contentText.setWrappingWidth(360.0); + + Alert alert = new Alert(type); + alert.setTitle(title); + alert.setHeaderText(header); + alert.getDialogPane().setContent(contentText); + + alert.getDialogPane().getButtonTypes().stream().forEach(buttonType -> { + Button btn = (Button) alert.getDialogPane().lookupButton(buttonType); + btn.setDefaultButton(buttonType.equals(defaultButton)); + }); + + return alert; + } +} diff --git a/main/ui/src/main/resources/css/linux_theme.css b/main/ui/src/main/resources/css/linux_theme.css index 9c8fc2f3a..cb3c407f0 100644 --- a/main/ui/src/main/resources/css/linux_theme.css +++ b/main/ui/src/main/resources/css/linux_theme.css @@ -5,6 +5,7 @@ * * Contributors: * Sebastian Stenzel - initial API and implementation + * Jean-Noël Charon - implementation of the dialog css * */ @@ -80,7 +81,7 @@ -fx-pref-height: 25px; -fx-background-color: COLOR_BORDER, COLOR_VGRAD_LIGHT; -fx-background-insets: 0, 1; - -fx-padding: 4px 8px 4px 8px; + -fx-padding: 4px 12px 6px 12px; -fx-text-fill: COLOR_TEXT; -fx-alignment: CENTER; } @@ -444,4 +445,65 @@ -fx-stroke-width: 2px; } .default-color0.chart-series-line { -fx-stroke: COLOR_CHART_GREEN; } -.default-color1.chart-series-line { -fx-stroke: COLOR_CHART_RED; } \ No newline at end of file +.default-color1.chart-series-line { -fx-stroke: COLOR_CHART_RED; } + +/******************************************************************************* + * * + * Dialog * + * * + ******************************************************************************/ + +.dialog-pane { + -fx-background-color: COLOR_BACKGROUND; + -fx-padding: 20px 20px 20px 96px; + + -fx-background-image: url("/img/dialog-appicon.png"); + -fx-background-repeat: no-repeat; + -fx-background-position: 20px 20px; +} + +/* HEADER */ +.dialog-pane:header .header-panel { + -fx-padding: 0 0 12px 0; +} + +/* TITLE */ +.dialog-pane:header .header-panel .label { + -fx-font-weight: bold; + -fx-wrap-text: true; + -fx-font-size: 14px; +} + +/* CONTENT LABEL */ +.dialog-pane > .content { + -fx-alignment: top-left; + -fx-wrap-text: true; + -fx-font-size: 12px; +} + +/* BUTTONS */ +.dialog-pane > .button-bar > .container { + -fx-padding: 20px 0 0 0; +} + +.alert.confirmation.dialog-pane, +.text-input-dialog.dialog-pane, +.choice-dialog.dialog-pane { + -fx-padding: 20px 20px 20px 80px; + -fx-background-image: url("/img/dialog-confirm.png"); +} + +.alert.information.dialog-pane { + -fx-padding: 20px 20px 20px 80px; + -fx-background-image: url("/img/dialog-information.png"); +} + +.alert.error.dialog-pane { + -fx-padding: 20px 20px 20px 80px; + -fx-background-image: url("/img/dialog-error.png"); +} + +.alert.warning.dialog-pane { + -fx-padding: 20px 20px 20px 80px; + -fx-background-image: url("/img/dialog-warning.png"); +} \ No newline at end of file diff --git a/main/ui/src/main/resources/css/mac_theme.css b/main/ui/src/main/resources/css/mac_theme.css index 33d1e223e..bb5fa2053 100644 --- a/main/ui/src/main/resources/css/mac_theme.css +++ b/main/ui/src/main/resources/css/mac_theme.css @@ -5,11 +5,12 @@ * * Contributors: * Sebastian Stenzel - initial API and implementation + * Jean-Noël Charon - implementation of the dialog css * */ .root { - -fx-font-family: 'lucida-grande'; + -fx-font-family: 'lucida-grande', sans-serif; -fx-font-smoothing-type: lcd; -fx-font-size: 13px; @@ -534,4 +535,53 @@ -fx-stroke-width: 2px; } .default-color0.chart-series-line { -fx-stroke: COLOR_CHART_GREEN; } -.default-color1.chart-series-line { -fx-stroke: COLOR_CHART_RED; } \ No newline at end of file +.default-color1.chart-series-line { -fx-stroke: COLOR_CHART_RED; } + +/******************************************************************************* + * * + * Dialog * + * * + ******************************************************************************/ + +.dialog-pane { + -fx-background-color: COLOR_BACKGROUND; + -fx-padding: 20px 20px 20px 96px; + + -fx-background-image: url("/img/dialog-appicon.png"); + -fx-background-repeat: no-repeat; + -fx-background-position: 20px 20px; +} + +/* HEADER */ +.dialog-pane:header .header-panel { + -fx-padding: 0 0 12px 0; +} + +/* TITLE */ +.dialog-pane:header .header-panel .label { + -fx-font-weight: bold; + -fx-wrap-text: true; +} + +/* CONTENT LABEL */ +.dialog-pane > .content { + -fx-alignment: top-left; + -fx-wrap-text: true; + -fx-font-size: 11px; + -fx-line-spacing: 1.0; +} + +/* BUTTONS */ +.dialog-pane > .button-bar > .container { + -fx-padding: 12px 0 0 0; +} + +.dialog-pane > .button-bar .button:default { + -fx-background-color: COLOR_HGRAD_BTN_DEF_BORDER, COLOR_HGRAD_BTN_DEF_BACKGROUND; + -fx-text-fill: #FFF; +} + +.dialog-pane > .button-bar .button:default:armed { + -fx-background-color: COLOR_HGRAD_BTN_ARMED_BORDER, COLOR_HGRAD_BTN_ARMED_BACKGROUND; + -fx-text-fill: #FFF; +} \ No newline at end of file diff --git a/main/ui/src/main/resources/css/win_theme.css b/main/ui/src/main/resources/css/win_theme.css index bfd569b54..72fa8cb53 100644 --- a/main/ui/src/main/resources/css/win_theme.css +++ b/main/ui/src/main/resources/css/win_theme.css @@ -5,6 +5,7 @@ * * Contributors: * Sebastian Stenzel - initial API and implementation + * Jean-Noël Charon - implementation of the dialog css * */ @@ -24,6 +25,10 @@ COLOR_CHART_GREEN: #A1CD5f; COLOR_CHART_RED: #C75050; + COLOR_HGRAD_BTN_BACKGROUND: linear-gradient(to bottom, #F0F0F0 0%, #E5E5E5 100%); + COLOR_HGRAD_BTN_DISABLED_BORDER: linear-gradient(to bottom, #D2D2D2 0%, #C4C4C4 100%); + COLOR_HGRAD_BTN_ARMED_BACKGROUND: linear-gradient(to bottom, #DAECFC 0%, #C4E0FC 100%); + -fx-background-color: COLOR_BACKGROUND; -fx-text-fill: COLOR_TEXT; } @@ -70,7 +75,7 @@ .button, .toggle-button { -fx-pref-height: 27px; - -fx-background-color: COLOR_BORDER, linear-gradient(to bottom, #F0F0F0 0%, #E5E5E5 100%); + -fx-background-color: COLOR_BORDER, COLOR_HGRAD_BTN_BACKGROUND; -fx-background-insets: 0, 1; -fx-padding: 2px 12px 2px 12px; -fx-text-fill: COLOR_TEXT; @@ -80,12 +85,12 @@ } .button:default { - -fx-background-color: COLOR_BORDER_FOCUS, linear-gradient(to bottom, #F0F0F0 0%, #E5E5E5 100%); + -fx-background-color: COLOR_BORDER_FOCUS, COLOR_HGRAD_BTN_BACKGROUND; } .button:disabled, .button:default:disabled { - -fx-background-color: linear-gradient(to bottom, #D2D2D2 0%, #C4C4C4 100%), #F2F2F2; + -fx-background-color: COLOR_HGRAD_BTN_DISABLED_BORDER, #F2F2F2; -fx-text-fill: #8B8B8B; } @@ -93,7 +98,7 @@ .button:default:armed, .toggle-button:armed, .toggle-button:selected { - -fx-background-color: COLOR_BORDER_FOCUS, linear-gradient(to bottom, #DAECFC 0%, #C4E0FC 100%); + -fx-background-color: COLOR_BORDER_FOCUS, COLOR_HGRAD_BTN_ARMED_BACKGROUND; } .button:focused, @@ -516,4 +521,73 @@ -fx-stroke-width: 2px; } .default-color0.chart-series-line { -fx-stroke: COLOR_CHART_GREEN; } -.default-color1.chart-series-line { -fx-stroke: COLOR_CHART_RED; } \ No newline at end of file +.default-color1.chart-series-line { -fx-stroke: COLOR_CHART_RED; } + +/******************************************************************************* + * * + * Dialog * + * * + ******************************************************************************/ + +.dialog-pane { + -fx-background-color: COLOR_BACKGROUND; + -fx-padding: 20px 20px 20px 96px; + + -fx-background-image: url("/img/dialog-appicon.png"); + -fx-background-repeat: no-repeat; + -fx-background-position: 20px 20px; +} + +/* HEADER */ +.dialog-pane:header .header-panel { + -fx-padding: 0 0 12px 0; +} + +/* TITLE */ +.dialog-pane:header .header-panel .label { + -fx-font-weight: bold; + -fx-wrap-text: true; +} + +/* CONTENT LABEL */ +.dialog-pane > .content { + -fx-alignment: top-left; + -fx-wrap-text: true; + -fx-font-size: 11px; + -fx-line-spacing: 1.0; +} + +/* BUTTONS */ +.dialog-pane > .button-bar > .container { + -fx-padding: 20px 0 0 0; +} + +.dialog-pane > .button-bar .button:default { + -fx-background-color: COLOR_BORDER_FOCUS, COLOR_HGRAD_BTN_BACKGROUND; +} + +.dialog-pane > .button-bar .button:default:armed { + -fx-background-color: COLOR_BORDER_FOCUS, COLOR_HGRAD_BTN_ARMED_BACKGROUND; +} + +.alert.confirmation.dialog-pane, +.text-input-dialog.dialog-pane, +.choice-dialog.dialog-pane { + -fx-padding: 20px 20px 20px 80px; + -fx-background-image: url("/img/dialog-confirm.png"); +} + +.alert.information.dialog-pane { + -fx-padding: 20px 20px 20px 80px; + -fx-background-image: url("/img/dialog-information.png"); +} + +.alert.error.dialog-pane { + -fx-padding: 20px 20px 20px 80px; + -fx-background-image: url("/img/dialog-error.png"); +} + +.alert.warning.dialog-pane { + -fx-padding: 20px 20px 20px 80px; + -fx-background-image: url("/img/dialog-warning.png"); +} \ No newline at end of file diff --git a/main/ui/src/main/resources/img/dialog-appicon.png b/main/ui/src/main/resources/img/dialog-appicon.png new file mode 100644 index 000000000..ea82817bb Binary files /dev/null and b/main/ui/src/main/resources/img/dialog-appicon.png differ diff --git a/main/ui/src/main/resources/img/dialog-appicon@2x.png b/main/ui/src/main/resources/img/dialog-appicon@2x.png new file mode 100644 index 000000000..cb7da4c37 Binary files /dev/null and b/main/ui/src/main/resources/img/dialog-appicon@2x.png differ diff --git a/main/ui/src/main/resources/img/dialog-confirm.png b/main/ui/src/main/resources/img/dialog-confirm.png new file mode 100644 index 000000000..adb569bec Binary files /dev/null and b/main/ui/src/main/resources/img/dialog-confirm.png differ diff --git a/main/ui/src/main/resources/img/dialog-error.png b/main/ui/src/main/resources/img/dialog-error.png new file mode 100644 index 000000000..769d7df71 Binary files /dev/null and b/main/ui/src/main/resources/img/dialog-error.png differ diff --git a/main/ui/src/main/resources/img/dialog-information.png b/main/ui/src/main/resources/img/dialog-information.png new file mode 100644 index 000000000..a220108dc Binary files /dev/null and b/main/ui/src/main/resources/img/dialog-information.png differ diff --git a/main/ui/src/main/resources/img/dialog-warning.png b/main/ui/src/main/resources/img/dialog-warning.png new file mode 100644 index 000000000..a374f4f70 Binary files /dev/null and b/main/ui/src/main/resources/img/dialog-warning.png differ diff --git a/main/ui/src/main/resources/localization/en.txt b/main/ui/src/main/resources/localization/en.txt index ac96c349e..36ab4f521 100644 --- a/main/ui/src/main/resources/localization/en.txt +++ b/main/ui/src/main/resources/localization/en.txt @@ -13,6 +13,9 @@ main.directoryList.contextMenu.remove=Remove from list main.directoryList.contextMenu.changePassword=Change password main.addDirectory.contextMenu.new=Create new vault main.addDirectory.contextMenu.open=Open existing vault +main.directoryList.remove.confirmation.title=Remove Vault +main.directoryList.remove.confirmation.header=Do you really want to remove this vault? +main.directoryList.remove.confirmation.content=The vault will only be removed from the list. To permanently delete it, please delete the files from your filesystem. Lorem ipsum, wie das duftet, kräftig, deftig, würzig, gut. Pommersche aus dem Buchenrauch, naturgewürzt und das schmeckt man auch. # welcome.fxml welcome.checkForUpdates.label.currentlyChecking=Checking for Updates...