Skip to content

Commit

Permalink
TextComponents:
Browse files Browse the repository at this point in the history
- 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)
  • Loading branch information
DevCharly committed Jun 12, 2021
1 parent b99fb8b commit a51294d
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -53,6 +54,7 @@
*
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault EditorPane.focusedBackground Color optional
*
* @author Karl Tauber
*/
Expand All @@ -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();
Expand All @@ -72,8 +76,10 @@ public static ComponentUI createUI( JComponent c ) {
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 );
Expand All @@ -84,9 +90,28 @@ protected void installDefaults() {
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 );
Expand Down Expand Up @@ -128,14 +153,11 @@ protected void paintSafely( Graphics g ) {

@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() );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* @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
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
* @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
Expand All @@ -61,6 +60,7 @@
* @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
Expand Down Expand Up @@ -117,7 +117,10 @@ protected void uninstallDefaults() {
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 ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
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;
Expand All @@ -42,7 +43,6 @@
* @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
Expand All @@ -53,6 +53,7 @@
* @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
*/
Expand All @@ -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();
}
Expand Down Expand Up @@ -99,6 +102,23 @@ protected void uninstallDefaults() {
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 );
Expand Down Expand Up @@ -160,20 +180,6 @@ protected void paintSafely( Graphics g ) {

@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 );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
* @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
Expand All @@ -65,6 +64,7 @@
* @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
*
Expand Down Expand Up @@ -113,7 +113,8 @@ protected void uninstallDefaults() {
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 );
}

Expand Down Expand Up @@ -184,18 +185,31 @@ static void paintBackground( Graphics g, JTextComponent c, boolean isIntelliJThe
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 )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -51,6 +51,7 @@
*
* @uiDefault Component.minimumWidth int
* @uiDefault Component.isIntelliJTheme boolean
* @uiDefault TextPane.focusedBackground Color optional
*
* @author Karl Tauber
*/
Expand All @@ -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();
Expand All @@ -70,8 +73,10 @@ public static ComponentUI createUI( JComponent c ) {
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 );
Expand All @@ -82,9 +87,28 @@ protected void installDefaults() {
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 );
Expand All @@ -108,14 +132,6 @@ protected void paintSafely( Graphics g ) {

@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 );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -837,19 +837,23 @@ public static class RepaintFocusListener
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 ) {
repaintComponent.repaint();
if( repaintCondition == null || repaintCondition.test( repaintComponent ) )
repaintComponent.repaint();
}

@Override
public void focusLost( FocusEvent e ) {
repaintComponent.repaint();
if( repaintCondition == null || repaintCondition.test( repaintComponent ) )
repaintComponent.repaint();
}
}
}
Loading

0 comments on commit a51294d

Please sign in to comment.