TextComponents:

- use focusedBackground only if editable (and enabled)
- prefer explicit set background color over focusedBackground
- added FlatTextFieldUI.getBackground() used by all text components
- support EditorPane.focusedBackground
- support TextPane.focusedBackground

(issue #335)
This commit is contained in:
Karl Tauber
2021-06-12 20:46:59 +02:00
parent b99fb8b11f
commit a51294d570
9 changed files with 146 additions and 50 deletions

View File

@@ -17,15 +17,16 @@
package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicEditorPaneUI;
import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.FlatClientProperties;
@@ -53,6 +54,7 @@ import com.formdev.flatlaf.util.HiDPIUtils;
*
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault EditorPane.focusedBackground Color optional
*
* @author Karl Tauber
*/
@@ -61,8 +63,10 @@ public class FlatEditorPaneUI
{
protected int minimumWidth;
protected boolean isIntelliJTheme;
protected Color focusedBackground;
private Object oldHonorDisplayProperties;
private FocusListener focusListener;
public static ComponentUI createUI( JComponent c ) {
return new FlatEditorPaneUI();
@@ -72,8 +76,10 @@ public class FlatEditorPaneUI
protected void installDefaults() {
super.installDefaults();
String prefix = getPropertyPrefix();
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
focusedBackground = UIManager.getColor( prefix + ".focusedBackground" );
// use component font and foreground for HTML text
oldHonorDisplayProperties = getComponent().getClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES );
@@ -84,9 +90,28 @@ public class FlatEditorPaneUI
protected void uninstallDefaults() {
super.uninstallDefaults();
focusedBackground = null;
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, oldHonorDisplayProperties );
}
@Override
protected void installListeners() {
super.installListeners();
// necessary to update focus background
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), c -> focusedBackground != null );
getComponent().addFocusListener( focusListener );
}
@Override
protected void uninstallListeners() {
super.uninstallListeners();
getComponent().removeFocusListener( focusListener );
focusListener = null;
}
@Override
protected void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
@@ -128,14 +153,11 @@ public class FlatEditorPaneUI
@Override
protected void paintBackground( Graphics g ) {
JTextComponent c = getComponent();
// for compatibility with IntelliJ themes
if( isIntelliJTheme && (!c.isEnabled() || !c.isEditable()) && (c.getBackground() instanceof UIResource) ) {
FlatUIUtils.paintParentBackground( g, c );
return;
paintBackground( g, getComponent(), isIntelliJTheme, focusedBackground );
}
super.paintBackground( g );
static void paintBackground( Graphics g, JTextComponent c, boolean isIntelliJTheme, Color focusedBackground ) {
g.setColor( FlatTextFieldUI.getBackground( c, isIntelliJTheme, focusedBackground ) );
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
}
}

View File

@@ -44,6 +44,7 @@ import javax.swing.plaf.ComponentUI;
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault FormattedTextField.placeholderForeground Color
* @uiDefault FormattedTextField.focusedBackground Color optional
* @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always
* @uiDefault TextComponent.selectAllOnMouseClick boolean
*

View File

@@ -50,7 +50,6 @@ import com.formdev.flatlaf.util.HiDPIUtils;
* @uiDefault PasswordField.disabledBackground Color used if not enabled
* @uiDefault PasswordField.inactiveBackground Color used if not editable
* @uiDefault PasswordField.inactiveForeground Color used if not enabled (yes, this is confusing; this should be named disabledForeground)
* @uiDefault PasswordField.focusedBackground Color optional
* @uiDefault PasswordField.border Border
* @uiDefault PasswordField.margin Insets
* @uiDefault PasswordField.echoChar character
@@ -61,6 +60,7 @@ import com.formdev.flatlaf.util.HiDPIUtils;
* @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
@@ -117,7 +117,10 @@ public class FlatPasswordFieldUI
protected void installListeners() {
super.installListeners();
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent() );
// necessary to update focus border and background
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), null );
// update caps lock indicator
capsLockListener = new KeyAdapter() {
@Override
public void keyPressed( KeyEvent e ) {

View File

@@ -20,6 +20,7 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import javax.swing.JComponent;
import javax.swing.JTextArea;
@@ -42,7 +43,6 @@ import com.formdev.flatlaf.util.HiDPIUtils;
* @uiDefault TextArea.selectionBackground Color
* @uiDefault TextArea.selectionForeground Color
* @uiDefault TextArea.inactiveForeground Color used if not enabled (yes, this is confusing; this should be named disabledForeground)
* @uiDefault TextArea.focusedBackground Color optional
* @uiDefault TextArea.border Border
* @uiDefault TextArea.margin Insets
* @uiDefault TextArea.caretBlinkRate int default is 500 milliseconds
@@ -53,6 +53,7 @@ import com.formdev.flatlaf.util.HiDPIUtils;
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault TextArea.disabledBackground Color used if not enabled
* @uiDefault TextArea.inactiveBackground Color used if not editable
* @uiDefault TextArea.focusedBackground Color optional
*
* @author Karl Tauber
*/
@@ -66,6 +67,8 @@ public class FlatTextAreaUI
protected Color inactiveBackground;
protected Color focusedBackground;
private FocusListener focusListener;
public static ComponentUI createUI( JComponent c ) {
return new FlatTextAreaUI();
}
@@ -99,6 +102,23 @@ public class FlatTextAreaUI
focusedBackground = null;
}
@Override
protected void installListeners() {
super.installListeners();
// necessary to update focus background
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), c -> focusedBackground != null );
getComponent().addFocusListener( focusListener );
}
@Override
protected void uninstallListeners() {
super.uninstallListeners();
getComponent().removeFocusListener( focusListener );
focusListener = null;
}
@Override
protected void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
@@ -160,20 +180,6 @@ public class FlatTextAreaUI
@Override
protected void paintBackground( Graphics g ) {
JTextComponent c = getComponent();
// for compatibility with IntelliJ themes
if( isIntelliJTheme && (!c.isEnabled() || !c.isEditable()) && (c.getBackground() instanceof UIResource) ) {
FlatUIUtils.paintParentBackground( g, c );
return;
}
if( focusedBackground != null && FlatUIUtils.isPermanentFocusOwner( c ) ) {
g.setColor( focusedBackground );
g.fillRect( 0, 0, c.getWidth(), c.getHeight() );
return;
}
super.paintBackground( g );
FlatEditorPaneUI.paintBackground( g, getComponent(), isIntelliJTheme, focusedBackground );
}
}

View File

@@ -55,7 +55,6 @@ import com.formdev.flatlaf.util.JavaCompatibility;
* @uiDefault TextField.disabledBackground Color used if not enabled
* @uiDefault TextField.inactiveBackground Color used if not editable
* @uiDefault TextField.inactiveForeground Color used if not enabled (yes, this is confusing; this should be named disabledForeground)
* @uiDefault TextField.focusedBackground Color optional
* @uiDefault TextField.border Border
* @uiDefault TextField.margin Insets
* @uiDefault TextField.caretBlinkRate int default is 500 milliseconds
@@ -65,6 +64,7 @@ import com.formdev.flatlaf.util.JavaCompatibility;
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault TextField.placeholderForeground Color
* @uiDefault TextField.focusedBackground Color optional
* @uiDefault TextComponent.selectAllOnFocusPolicy String never, once (default) or always
* @uiDefault TextComponent.selectAllOnMouseClick boolean
*
@@ -113,7 +113,8 @@ public class FlatTextFieldUI
protected void installListeners() {
super.installListeners();
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent() );
// necessary to update focus border and background
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), null );
getComponent().addFocusListener( focusListener );
}
@@ -184,18 +185,31 @@ public class FlatTextFieldUI
try {
FlatUIUtils.setRenderingHints( g2 );
Color background = focusedBackground != null && FlatUIUtils.isPermanentFocusOwner( c ) ? focusedBackground : c.getBackground();
g2.setColor( !(background instanceof UIResource)
? background
: (isIntelliJTheme && (!c.isEnabled() || !c.isEditable())
? FlatUIUtils.getParentBackground( c )
: background) );
g2.setColor( getBackground( c, isIntelliJTheme, focusedBackground ) );
FlatUIUtils.paintComponentBackground( g2, 0, 0, c.getWidth(), c.getHeight(), focusWidth, arc );
} finally {
g2.dispose();
}
}
static Color getBackground( JTextComponent c, boolean isIntelliJTheme, Color focusedBackground ) {
Color background = c.getBackground();
// always use explicitly set color
if( !(background instanceof UIResource) )
return background;
// for compatibility with IntelliJ themes
if( isIntelliJTheme && (!c.isEnabled() || !c.isEditable()) )
return FlatUIUtils.getParentBackground( c );
// focused and editable
if( focusedBackground != null && c.isEditable() && FlatUIUtils.isPermanentFocusOwner( c ) )
return focusedBackground;
return background;
}
static void paintPlaceholder( Graphics g, JTextComponent c, Color placeholderForeground ) {
// check whether text component is empty
if( c.getDocument().getLength() > 0 )

View File

@@ -16,17 +16,17 @@
package com.formdev.flatlaf.ui;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTextPaneUI;
import javax.swing.text.JTextComponent;
import com.formdev.flatlaf.util.HiDPIUtils;
/**
@@ -51,6 +51,7 @@ import com.formdev.flatlaf.util.HiDPIUtils;
*
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault TextPane.focusedBackground Color optional
*
* @author Karl Tauber
*/
@@ -59,8 +60,10 @@ public class FlatTextPaneUI
{
protected int minimumWidth;
protected boolean isIntelliJTheme;
protected Color focusedBackground;
private Object oldHonorDisplayProperties;
private FocusListener focusListener;
public static ComponentUI createUI( JComponent c ) {
return new FlatTextPaneUI();
@@ -70,8 +73,10 @@ public class FlatTextPaneUI
protected void installDefaults() {
super.installDefaults();
String prefix = getPropertyPrefix();
minimumWidth = UIManager.getInt( "Component.minimumWidth" );
isIntelliJTheme = UIManager.getBoolean( "Component.isIntelliJTheme" );
focusedBackground = UIManager.getColor( prefix + ".focusedBackground" );
// use component font and foreground for HTML text
oldHonorDisplayProperties = getComponent().getClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES );
@@ -82,9 +87,28 @@ public class FlatTextPaneUI
protected void uninstallDefaults() {
super.uninstallDefaults();
focusedBackground = null;
getComponent().putClientProperty( JEditorPane.HONOR_DISPLAY_PROPERTIES, oldHonorDisplayProperties );
}
@Override
protected void installListeners() {
super.installListeners();
// necessary to update focus background
focusListener = new FlatUIUtils.RepaintFocusListener( getComponent(), c -> focusedBackground != null );
getComponent().addFocusListener( focusListener );
}
@Override
protected void uninstallListeners() {
super.uninstallListeners();
getComponent().removeFocusListener( focusListener );
focusListener = null;
}
@Override
protected void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
@@ -108,14 +132,6 @@ public class FlatTextPaneUI
@Override
protected void paintBackground( Graphics g ) {
JTextComponent c = getComponent();
// for compatibility with IntelliJ themes
if( isIntelliJTheme && (!c.isEnabled() || !c.isEditable()) && (c.getBackground() instanceof UIResource) ) {
FlatUIUtils.paintParentBackground( g, c );
return;
}
super.paintBackground( g );
FlatEditorPaneUI.paintBackground( g, getComponent(), isIntelliJTheme, focusedBackground );
}
}

View File

@@ -837,18 +837,22 @@ debug*/
implements FocusListener
{
private final Component repaintComponent;
private final Predicate<Component> repaintCondition;
public RepaintFocusListener( Component repaintComponent ) {
public RepaintFocusListener( Component repaintComponent, Predicate<Component> repaintCondition ) {
this.repaintComponent = repaintComponent;
this.repaintCondition = repaintCondition;
}
@Override
public void focusGained( FocusEvent e ) {
if( repaintCondition == null || repaintCondition.test( repaintComponent ) )
repaintComponent.repaint();
}
@Override
public void focusLost( FocusEvent e ) {
if( repaintCondition == null || repaintCondition.test( repaintComponent ) )
repaintComponent.repaint();
}
}

View File

@@ -156,7 +156,7 @@ public class FlatDatePickerUI
editor.setName( "dateField" );
editor.setBorder( BorderFactory.createEmptyBorder() );
editor.setOpaque( false );
editor.addFocusListener( new FlatUIUtils.RepaintFocusListener( datePicker ) );
editor.addFocusListener( new FlatUIUtils.RepaintFocusListener( datePicker, null ) );
return editor;
}

View File

@@ -152,6 +152,16 @@ Desktop.background = #afe
DesktopIcon.background = darken($Desktop.background,20%)
#---- EditorPane ----
EditorPane.focusedBackground = #ff8
#---- FormattedTextField ----
FormattedTextField.focusedBackground = #ff8
#---- HelpButton ----
HelpButton.focusedBackground = #0ff
@@ -223,6 +233,11 @@ OptionPane.icon.warningColor = #fc0
OptionPane.icon.foreground = #fff
#---- PasswordField ----
PasswordField.focusedBackground = #ff8
#---- Popup ----
Popup.dropShadowColor = #0f0
@@ -332,6 +347,21 @@ TableHeader.separatorColor = #0f0
TableHeader.bottomSeparatorColor = #0f0
#---- TextArea ----
TextArea.focusedBackground = #ff8
#---- TextField ----
TextField.focusedBackground = #ff8
#---- TextPane ----
TextPane.focusedBackground = #ff8
#---- TitledBorder ----
TitledBorder.titleColor = #f0f