Explorar o código

#458, #841: Improved layout of the indicator inside SecPasswordField

Tobias Hagemann %!s(int64=6) %!d(string=hai) anos
pai
achega
ab198271a1

+ 32 - 27
main/ui/src/main/java/org/cryptomator/ui/controls/SecPasswordField.java

@@ -9,9 +9,9 @@
 package org.cryptomator.ui.controls;
 
 import com.google.common.base.Strings;
+import javafx.beans.NamedArg;
 import javafx.beans.Observable;
-import javafx.beans.property.SimpleStringProperty;
-import javafx.beans.property.StringProperty;
+import javafx.geometry.Insets;
 import javafx.geometry.Pos;
 import javafx.scene.control.Label;
 import javafx.scene.control.OverrunStyle;
@@ -22,6 +22,9 @@ import javafx.scene.input.Dragboard;
 import javafx.scene.input.KeyCode;
 import javafx.scene.input.KeyEvent;
 import javafx.scene.input.TransferMode;
+import javafx.scene.paint.Color;
+import javafx.scene.text.Font;
+import javafx.scene.text.Text;
 
 import java.awt.Toolkit;
 import java.nio.CharBuffer;
@@ -40,19 +43,31 @@ public class SecPasswordField extends PasswordField {
 	private static final int INITIAL_BUFFER_SIZE = 50;
 	private static final int GROW_BUFFER_SIZE = 50;
 	private static final String PLACEHOLDER = "*";
+	private static final double PADDING = 2.0;
+	private static final double INDICATOR_PADDING = 4.0;
+	private static final Color INDICATOR_COLOR = new Color(0.901, 0.494, 0.133, 1.0);
 
 	private final Tooltip tooltip = new Tooltip();
 	private final Label indicator = new Label();
-	private final StringProperty nonPrintableCharsWarning = new SimpleStringProperty();
-	private final StringProperty capslockWarning = new SimpleStringProperty();
+	private final String nonPrintableCharsWarning;
+	private final String capslockWarning;
 
 	private char[] content = new char[INITIAL_BUFFER_SIZE];
 	private int length = 0;
 
 	public SecPasswordField() {
+		this("", "");
+	}
+
+	public SecPasswordField(@NamedArg("nonPrintableCharsWarning") String nonPrintableCharsWarning, @NamedArg("capslockWarning") String capslockWarning) {
+		this.nonPrintableCharsWarning = nonPrintableCharsWarning;
+		this.capslockWarning = capslockWarning;
+		indicator.setPadding(new Insets(PADDING, INDICATOR_PADDING, PADDING, INDICATOR_PADDING));
 		indicator.setAlignment(Pos.CENTER_RIGHT);
 		indicator.setMouseTransparent(true);
 		indicator.setTextOverrun(OverrunStyle.CLIP);
+		indicator.setTextFill(INDICATOR_COLOR);
+		indicator.setFont(Font.font(indicator.getFont().getFamily(), 15.0));
 		this.getChildren().add(indicator);
 		this.setTooltip(tooltip);
 		this.addEventHandler(DragEvent.DRAG_OVER, this::handleDragOver);
@@ -64,9 +79,8 @@ public class SecPasswordField extends PasswordField {
 	@Override
 	protected void layoutChildren() {
 		super.layoutChildren();
-		indicator.resize(50.0, getHeight());
-		indicator.relocate(getWidth() - indicator.getWidth(), 0);
-		indicator.layout();
+		indicator.relocate(0.0, 0.0);
+		indicator.resize(getWidth(), getHeight());
 	}
 
 	private void handleDragOver(DragEvent event) {
@@ -100,14 +114,19 @@ public class SecPasswordField extends PasswordField {
 		StringBuilder indicatorSb = new StringBuilder();
 		if (containsNonPrintableCharacters()) {
 			indicatorSb.append('⚠');
-			tooltipSb.append(nonPrintableCharsWarning.get()).append('\n');
+			tooltipSb.append("- ").append(nonPrintableCharsWarning).append('\n');
 		}
 		// AWT code needed until https://bugs.openjdk.java.net/browse/JDK-8090882 is closed:
 		if (focused && Toolkit.getDefaultToolkit().getLockingKeyState(java.awt.event.KeyEvent.VK_CAPS_LOCK)) {
 			indicatorSb.append('⇪');
-			tooltipSb.append(capslockWarning.get()).append('\n');
+			tooltipSb.append("- ").append(capslockWarning).append('\n');
 		}
 		indicator.setText(indicatorSb.toString());
+		if (!indicator.getText().isEmpty()) {
+			setPadding(new Insets(PADDING, getIndicatorWidth(), PADDING, PADDING));
+		} else {
+			setPadding(new Insets(PADDING));
+		}
 		tooltip.setText(tooltipSb.toString());
 		if (tooltip.getText().isEmpty()) {
 			setTooltip(null);
@@ -116,6 +135,10 @@ public class SecPasswordField extends PasswordField {
 		}
 	}
 
+	private double getIndicatorWidth() {
+		return new Text(indicator.getText()).getLayoutBounds().getWidth() + INDICATOR_PADDING * 2.0;
+	}
+
 	/**
 	 * @return <code>true</code> if any {@link Character#isISOControl(char) control character} is present in the current value of this password field.
 	 * @implNote runs in O(n)
@@ -232,22 +255,4 @@ public class SecPasswordField extends PasswordField {
 		Arrays.fill(buffer, SWIPE_CHAR);
 	}
 
-	/* Getter/Setter */
-
-	public void setNonPrintableCharsWarning(String value) {
-		nonPrintableCharsWarning.set(value);
-	}
-
-	public String getNonPrintableCharsWarning() {
-		return nonPrintableCharsWarning.get();
-	}
-
-	public void setCapslockWarning(String value) {
-		capslockWarning.set(value);
-	}
-
-	public String getCapslockWarning() {
-		return capslockWarning.get();
-	}
-
 }

+ 1 - 1
main/ui/src/main/resources/localization/en.txt

@@ -7,7 +7,7 @@
 
 app.name=Cryptomator
 
-ctrl.secPasswordField.nonPrintableChars=Password contains control characters. Recommendation: Remove them to ensure compatibility with other clients.
+ctrl.secPasswordField.nonPrintableChars=Password contains control characters.\nRecommendation: Remove them to ensure compatibility with other clients.
 ctrl.secPasswordField.capsLocked=Caps Lock is activated.
 
 # main.fxml