From c8998c2bcf6db9b04cd0d2ba7ae116ccdeb0396f Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Fri, 2 Jul 2021 13:59:28 +0200 Subject: [PATCH] PasswordField: UI delegate `FlatPasswordFieldUI` now extends `FlatTextFieldUI` (instead of `BasicPasswordFieldUI`) to avoid duplicate code and for easier extensibility (e.g. for #173 and #341) --- CHANGELOG.md | 13 +++ .../flatlaf/ui/FlatFormattedTextFieldUI.java | 2 - .../flatlaf/ui/FlatPasswordFieldUI.java | 106 ++++++++---------- 3 files changed, 57 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8d317a3..eff57deb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,19 @@ FlatLaf Change Log ================== +## 1.4-SNAPSHOT + +#### New features and improvements + +- PasswordField: UI delegate `FlatPasswordFieldUI` now extends `FlatTextFieldUI` + (instead of `BasicPasswordFieldUI`) to avoid duplicate code and for easier + extensibility. + +#### Fixed bugs + +- TBD + + ## 1.3 #### New features and improvements diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatFormattedTextFieldUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatFormattedTextFieldUI.java index 11d91245..a016d7da 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatFormattedTextFieldUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatFormattedTextFieldUI.java @@ -39,8 +39,6 @@ import javax.swing.plaf.ComponentUI; * * * - * @uiDefault TextComponent.arc int - * @uiDefault Component.focusWidth int * @uiDefault Component.minimumWidth int * @uiDefault Component.isIntelliJTheme boolean * @uiDefault FormattedTextField.placeholderForeground Color 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 d338aa53..f15f9701 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 @@ -16,30 +16,30 @@ package com.formdev.flatlaf.ui; -import java.awt.Color; -import java.awt.Dimension; import java.awt.Graphics; -import java.awt.Graphics2D; +import java.awt.Shape; 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.Action; +import javax.swing.ActionMap; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.LookAndFeel; +import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; -import javax.swing.plaf.basic.BasicPasswordFieldUI; -import javax.swing.text.Caret; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.Element; import javax.swing.text.JTextComponent; -import com.formdev.flatlaf.util.HiDPIUtils; +import javax.swing.text.PasswordView; +import javax.swing.text.View; /** * Provides the Flat LaF UI delegate for {@link javax.swing.JPasswordField}. * - * + * * * @uiDefault PasswordField.font Font * @uiDefault PasswordField.background Color @@ -52,74 +52,66 @@ import com.formdev.flatlaf.util.HiDPIUtils; * @uiDefault PasswordField.inactiveForeground Color used if not enabled (yes, this is confusing; this should be named disabledForeground) * @uiDefault PasswordField.border Border * @uiDefault PasswordField.margin Insets - * @uiDefault PasswordField.echoChar character * @uiDefault PasswordField.caretBlinkRate int default is 500 milliseconds * - * + * * * @uiDefault Component.minimumWidth int * @uiDefault Component.isIntelliJTheme boolean * @uiDefault PasswordField.placeholderForeground Color * @uiDefault PasswordField.focusedBackground Color optional - * @uiDefault PasswordField.showCapsLock boolean - * @uiDefault PasswordField.capsLockIcon Icon * @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always * @uiDefault TextComponent.selectAllOnMouseClick boolean * + * + * + * @uiDefault PasswordField.echoChar character + * @uiDefault PasswordField.showCapsLock boolean + * @uiDefault PasswordField.capsLockIcon Icon + * * @author Karl Tauber */ public class FlatPasswordFieldUI - extends BasicPasswordFieldUI + extends FlatTextFieldUI { - protected int minimumWidth; - protected boolean isIntelliJTheme; - protected Color placeholderForeground; - protected Color focusedBackground; protected boolean showCapsLock; protected Icon capsLockIcon; - private FocusListener focusListener; private KeyListener capsLockListener; public static ComponentUI createUI( JComponent c ) { return new FlatPasswordFieldUI(); } + @Override + protected String getPropertyPrefix() { + return "PasswordField"; + } + @Override protected void installDefaults() { super.installDefaults(); String prefix = getPropertyPrefix(); - minimumWidth = UIManager.getInt( "Component.minimumWidth" ); - isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" ); - placeholderForeground = UIManager.getColor( prefix + ".placeholderForeground" ); - focusedBackground = UIManager.getColor( prefix + ".focusedBackground" ); + Character echoChar = (Character) UIManager.get( prefix + ".echoChar" ); + if( echoChar != null ) + LookAndFeel.installProperty( getComponent(), "echoChar", echoChar ); + showCapsLock = UIManager.getBoolean( "PasswordField.showCapsLock" ); capsLockIcon = UIManager.getIcon( "PasswordField.capsLockIcon" ); - - LookAndFeel.installProperty( getComponent(), "opaque", false ); - - MigLayoutVisualPadding.install( getComponent() ); } @Override protected void uninstallDefaults() { super.uninstallDefaults(); - placeholderForeground = null; - focusedBackground = null; capsLockIcon = null; - - MigLayoutVisualPadding.uninstall( getComponent() ); } @Override protected void installListeners() { super.installListeners(); - // necessary to update focus border and background - focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), null ); - // update caps lock indicator capsLockListener = new KeyAdapter() { @Override @@ -136,7 +128,6 @@ public class FlatPasswordFieldUI } }; - getComponent().addFocusListener( focusListener ); getComponent().addKeyListener( capsLockListener ); } @@ -144,31 +135,37 @@ public class FlatPasswordFieldUI protected void uninstallListeners() { super.uninstallListeners(); - getComponent().removeFocusListener( focusListener ); getComponent().removeKeyListener( capsLockListener ); - focusListener = null; capsLockListener = null; } @Override - protected Caret createCaret() { - return new FlatCaret( UIManager.getString( "TextComponent.selectAllOnFocusPolicy" ), - UIManager.getBoolean( "TextComponent.selectAllOnMouseClick" ) ); + protected void installKeyboardActions() { + super.installKeyboardActions(); + + // map "select-word" action (double-click) to "select-line" action + ActionMap map = SwingUtilities.getUIActionMap( getComponent() ); + if( map != null && map.get( DefaultEditorKit.selectWordAction ) != null ) { + Action selectLineAction = map.get( DefaultEditorKit.selectLineAction ); + if( selectLineAction != null ) + map.put( DefaultEditorKit.selectWordAction, selectLineAction ); + } } @Override - protected void propertyChange( PropertyChangeEvent e ) { - super.propertyChange( e ); - FlatTextFieldUI.propertyChange( getComponent(), e ); + public View create( Element elem ) { + return new PasswordView( elem ); } @Override protected void paintSafely( Graphics g ) { - FlatTextFieldUI.paintBackground( g, getComponent(), isIntelliJTheme, focusedBackground ); - FlatTextFieldUI.paintPlaceholder( g, getComponent(), placeholderForeground ); - paintCapsLock( g ); + // safe and restore clipping area because super.paintSafely() modifies it + // and the caps lock icon would be truncated + Shape oldClip = g.getClip(); + super.paintSafely( g ); + g.setClip( oldClip ); - super.paintSafely( HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ) ); + paintCapsLock( g ); } protected void paintCapsLock( Graphics g ) { @@ -184,19 +181,4 @@ public class FlatPasswordFieldUI int x = c.getWidth() - capsLockIcon.getIconWidth() - y; capsLockIcon.paintIcon( c, g, x, y ); } - - @Override - protected void paintBackground( Graphics g ) { - // background is painted elsewhere - } - - @Override - public Dimension getPreferredSize( JComponent c ) { - return FlatTextFieldUI.applyMinimumWidth( c, super.getPreferredSize( c ), minimumWidth ); - } - - @Override - public Dimension getMinimumSize( JComponent c ) { - return FlatTextFieldUI.applyMinimumWidth( c, super.getMinimumSize( c ), minimumWidth ); - } }