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]