diff --git a/CHANGELOG.md b/CHANGELOG.md
index 56fba548..70f0e688 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@ FlatLaf Change Log
## Unreleased
+- PasswordField: Warn about enabled Caps Lock.
- TextField, FormattedTextField and PasswordField: Support round borders (see UI
default value `TextComponent.arc`). (issue #65)
- IntelliJ Themes: Added Gradianto themes to demo.
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java
new file mode 100644
index 00000000..2ceab38f
--- /dev/null
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 FormDev Software GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.formdev.flatlaf.icons;
+
+import java.awt.Component;
+import java.awt.Graphics2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import javax.swing.UIManager;
+import com.formdev.flatlaf.ui.FlatUIUtils;
+
+/**
+ * "caps lock" icon for {@link javax.swing.JPasswordField}.
+ *
+ * @uiDefault PasswordField.capsLockIconColor Color
+ *
+ * @author Karl Tauber
+ */
+public class FlatCapsLockIcon
+ extends FlatAbstractIcon
+{
+ public FlatCapsLockIcon() {
+ super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) );
+ }
+
+ @Override
+ protected void paintIcon( Component c, Graphics2D g ) {
+ /*
+
+ */
+
+ Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
+ path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false );
+ path.append( new Rectangle2D.Float( 5, 12, 6, 2 ), false );
+ path.append( FlatUIUtils.createPath( 2,8, 8,2, 14,8, 11,8, 11,10, 5,10, 5,8 ), false );
+ g.fill( path );
+ }
+}
diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java
index f0f6184f..abccabea 100644
--- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java
+++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPasswordFieldUI.java
@@ -20,14 +20,20 @@ import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
+import java.awt.Toolkit;
import java.awt.event.FocusListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
import java.beans.PropertyChangeEvent;
+import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicPasswordFieldUI;
import javax.swing.text.Caret;
+import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.FlatClientProperties;
/**
@@ -56,6 +62,7 @@ import com.formdev.flatlaf.FlatClientProperties;
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault PasswordField.placeholderForeground Color
+ * @uiDefault PasswordField.capsLockIcon Icon
* @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always
*
* @author Karl Tauber
@@ -68,8 +75,10 @@ public class FlatPasswordFieldUI
protected int minimumWidth;
protected boolean isIntelliJTheme;
protected Color placeholderForeground;
+ protected Icon capsLockIcon;
private FocusListener focusListener;
+ private KeyListener capsLockListener;
public static ComponentUI createUI( JComponent c ) {
return new FlatPasswordFieldUI();
@@ -85,6 +94,7 @@ public class FlatPasswordFieldUI
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
placeholderForeground = UIManager.getColor( prefix + ".placeholderForeground" );
+ capsLockIcon = UIManager.getIcon( "PasswordField.capsLockIcon" );
LookAndFeel.installProperty( getComponent(), "opaque", focusWidth == 0 );
@@ -96,6 +106,7 @@ public class FlatPasswordFieldUI
super.uninstallDefaults();
placeholderForeground = null;
+ capsLockIcon = null;
MigLayoutVisualPadding.uninstall( getComponent() );
}
@@ -105,7 +116,23 @@ public class FlatPasswordFieldUI
super.installListeners();
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent() );
+ capsLockListener = new KeyAdapter() {
+ @Override
+ public void keyPressed( KeyEvent e ) {
+ repaint( e );
+ }
+ @Override
+ public void keyReleased( KeyEvent e ) {
+ repaint( e );
+ }
+ private void repaint( KeyEvent e ) {
+ if( e.getKeyCode() == KeyEvent.VK_CAPS_LOCK )
+ e.getComponent().repaint();
+ }
+ };
+
getComponent().addFocusListener( focusListener );
+ getComponent().addKeyListener( capsLockListener );
}
@Override
@@ -113,7 +140,9 @@ public class FlatPasswordFieldUI
super.uninstallListeners();
getComponent().removeFocusListener( focusListener );
+ getComponent().removeKeyListener( capsLockListener );
focusListener = null;
+ capsLockListener = null;
}
@Override
@@ -133,9 +162,21 @@ public class FlatPasswordFieldUI
protected void paintSafely( Graphics g ) {
FlatTextFieldUI.paintBackground( g, getComponent(), focusWidth, arc, isIntelliJTheme );
FlatTextFieldUI.paintPlaceholder( g, getComponent(), placeholderForeground );
+ paintCapsLock( g );
super.paintSafely( g );
}
+ protected void paintCapsLock( Graphics g ) {
+ JTextComponent c = getComponent();
+ if( !c.isFocusOwner() ||
+ !Toolkit.getDefaultToolkit().getLockingKeyState( KeyEvent.VK_CAPS_LOCK ) )
+ return;
+
+ int y = (c.getHeight() - capsLockIcon.getIconHeight()) / 2;
+ int x = c.getWidth() - capsLockIcon.getIconWidth() - y;
+ capsLockIcon.paintIcon( c, g, x, y );
+ }
+
@Override
protected void paintBackground( Graphics g ) {
// background is painted elsewhere
diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties
index 4fdbfc5c..95847685 100644
--- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties
+++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatDarkLaf.properties
@@ -182,6 +182,11 @@ MenuItemCheckBox.icon.checkmarkColor=#A7A7A7
MenuItemCheckBox.icon.disabledCheckmarkColor=#606060
+#---- PasswordField ----
+
+PasswordField.capsLockIconColor=#ffffff64
+
+
#---- PopupMenu ----
PopupMenu.borderColor=#5e5e5e
diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties
index 496e64a8..09e01416 100644
--- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties
+++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLaf.properties
@@ -345,6 +345,7 @@ PasswordField.margin=@textComponentMargin
PasswordField.background=@textComponentBackground
PasswordField.placeholderForeground=@disabledText
PasswordField.echoChar=\u2022
+PasswordField.capsLockIcon=com.formdev.flatlaf.icons.FlatCapsLockIcon
#---- PopupMenu ----
diff --git a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties
index 4b84cc72..472f7b74 100644
--- a/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties
+++ b/flatlaf-core/src/main/resources/com/formdev/flatlaf/FlatLightLaf.properties
@@ -189,6 +189,11 @@ MenuItemCheckBox.icon.checkmarkColor=#4F9EE3
MenuItemCheckBox.icon.disabledCheckmarkColor=#ABABAB
+#---- PasswordField ----
+
+PasswordField.capsLockIconColor=#00000064
+
+
#---- PopupMenu ----
PopupMenu.borderColor=#adadad
diff --git a/flatlaf-core/svg/CapsLockIcon.svg b/flatlaf-core/svg/CapsLockIcon.svg
new file mode 100644
index 00000000..1c45373d
--- /dev/null
+++ b/flatlaf-core/svg/CapsLockIcon.svg
@@ -0,0 +1,7 @@
+
diff --git a/flatlaf-core/svg/FlatLaf Icons.sketch b/flatlaf-core/svg/FlatLaf Icons.sketch
index ea8b1465..c0fb85e5 100644
Binary files a/flatlaf-core/svg/FlatLaf Icons.sketch and b/flatlaf-core/svg/FlatLaf Icons.sketch differ
diff --git a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatDarkLaf_1.8.0_202-mac.txt b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatDarkLaf_1.8.0_202-mac.txt
index 55440701..7f036871 100644
--- a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatDarkLaf_1.8.0_202-mac.txt
+++ b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatDarkLaf_1.8.0_202-mac.txt
@@ -599,6 +599,8 @@ PanelUI com.formdev.flatlaf.ui.FlatPanelUI
PasswordField.background #45494a javax.swing.plaf.ColorUIResource [UI]
PasswordField.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatTextBorder [UI]
+PasswordField.capsLockIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatCapsLockIcon [UI]
+PasswordField.capsLockIconColor #64ffffff javax.swing.plaf.ColorUIResource [UI]
PasswordField.caretBlinkRate 500
PasswordField.caretForeground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
PasswordField.disabledBackground #3c3f41 javax.swing.plaf.ColorUIResource [UI]
diff --git a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatDarkLaf_1.8.0_202.txt b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatDarkLaf_1.8.0_202.txt
index 2f0a182f..ff8ae874 100644
--- a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatDarkLaf_1.8.0_202.txt
+++ b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatDarkLaf_1.8.0_202.txt
@@ -598,6 +598,8 @@ PanelUI com.formdev.flatlaf.ui.FlatPanelUI
PasswordField.background #45494a javax.swing.plaf.ColorUIResource [UI]
PasswordField.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatTextBorder [UI]
+PasswordField.capsLockIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatCapsLockIcon [UI]
+PasswordField.capsLockIconColor #64ffffff javax.swing.plaf.ColorUIResource [UI]
PasswordField.caretBlinkRate 500
PasswordField.caretForeground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
PasswordField.disabledBackground #3c3f41 javax.swing.plaf.ColorUIResource [UI]
diff --git a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatLightLaf_1.8.0_202-mac.txt b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatLightLaf_1.8.0_202-mac.txt
index 711a7adf..57e2207e 100644
--- a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatLightLaf_1.8.0_202-mac.txt
+++ b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatLightLaf_1.8.0_202-mac.txt
@@ -601,6 +601,8 @@ PanelUI com.formdev.flatlaf.ui.FlatPanelUI
PasswordField.background #ffffff javax.swing.plaf.ColorUIResource [UI]
PasswordField.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatTextBorder [UI]
+PasswordField.capsLockIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatCapsLockIcon [UI]
+PasswordField.capsLockIconColor #64000000 javax.swing.plaf.ColorUIResource [UI]
PasswordField.caretBlinkRate 500
PasswordField.caretForeground #000000 javax.swing.plaf.ColorUIResource [UI]
PasswordField.disabledBackground #f2f2f2 javax.swing.plaf.ColorUIResource [UI]
diff --git a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatLightLaf_1.8.0_202.txt b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatLightLaf_1.8.0_202.txt
index d48e7bee..3175e23f 100644
--- a/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatLightLaf_1.8.0_202.txt
+++ b/flatlaf-testing/src/main/resources/com/formdev/flatlaf/testing/uidefaults/FlatLightLaf_1.8.0_202.txt
@@ -600,6 +600,8 @@ PanelUI com.formdev.flatlaf.ui.FlatPanelUI
PasswordField.background #ffffff javax.swing.plaf.ColorUIResource [UI]
PasswordField.border [lazy] 1,1,1,1 false com.formdev.flatlaf.ui.FlatTextBorder [UI]
+PasswordField.capsLockIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatCapsLockIcon [UI]
+PasswordField.capsLockIconColor #64000000 javax.swing.plaf.ColorUIResource [UI]
PasswordField.caretBlinkRate 500
PasswordField.caretForeground #000000 javax.swing.plaf.ColorUIResource [UI]
PasswordField.disabledBackground #f2f2f2 javax.swing.plaf.ColorUIResource [UI]