Styling: support TableHeader

This commit is contained in:
Karl Tauber
2021-06-24 17:57:12 +02:00
parent 8ba7f7f961
commit 69061cd41c
5 changed files with 156 additions and 22 deletions

View File

@@ -21,7 +21,11 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.geom.Path2D;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.TableHeaderUI;
import javax.swing.table.JTableHeader;
import com.formdev.flatlaf.ui.FlatTableHeaderUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
/**
@@ -35,8 +39,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
public class FlatAscendingSortIcon
extends FlatAbstractIcon
{
protected final boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
protected final Color sortIconColor = UIManager.getColor( "Table.sortIconColor" );
protected boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
protected Color sortIconColor = UIManager.getColor( "Table.sortIconColor" );
public FlatAscendingSortIcon() {
super( 10, 5, null );
@@ -44,7 +48,28 @@ public class FlatAscendingSortIcon
@Override
protected void paintIcon( Component c, Graphics2D g ) {
boolean chevron = this.chevron;
Color sortIconColor = this.sortIconColor;
// Because this icons are always shared for all table headers,
// get icon specific style from FlatTableHeaderUI.
JTableHeader tableHeader = (JTableHeader) SwingUtilities.getAncestorOfClass( JTableHeader.class, c );
if( tableHeader != null ) {
TableHeaderUI ui = tableHeader.getUI();
if( ui instanceof FlatTableHeaderUI ) {
FlatTableHeaderUI fui = (FlatTableHeaderUI) ui;
if( fui.arrowType != null )
chevron = FlatUIUtils.isChevron( fui.arrowType );
if( fui.sortIconColor != null )
sortIconColor = fui.sortIconColor;
}
}
g.setColor( sortIconColor );
paintArrow( c, g, chevron );
}
protected void paintArrow( Component c, Graphics2D g, boolean chevron ) {
if( chevron ) {
// chevron arrow
Path2D path = FlatUIUtils.createPath( false, 1,4, 5,0, 9,4 );

View File

@@ -17,11 +17,9 @@
package com.formdev.flatlaf.icons;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.geom.Path2D;
import javax.swing.UIManager;
import com.formdev.flatlaf.ui.FlatUIUtils;
/**
@@ -33,18 +31,14 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
* @author Karl Tauber
*/
public class FlatDescendingSortIcon
extends FlatAbstractIcon
extends FlatAscendingSortIcon
{
protected final boolean chevron = FlatUIUtils.isChevron( UIManager.getString( "Component.arrowType" ) );
protected final Color sortIconColor = UIManager.getColor( "Table.sortIconColor" );
public FlatDescendingSortIcon() {
super( 10, 5, null );
super();
}
@Override
protected void paintIcon( Component c, Graphics2D g ) {
g.setColor( sortIconColor );
protected void paintArrow( Component c, Graphics2D g, boolean chevron ) {
if( chevron ) {
// chevron arrow
Path2D path = FlatUIUtils.createPath( false, 1,0, 5,4, 9,0 );

View File

@@ -21,6 +21,7 @@ import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.geom.Rectangle2D;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
@@ -49,12 +50,30 @@ public class FlatTableHeaderBorder
super( UIManager.getInsets( "TableHeader.cellMargins" ) );
}
@Override
public Insets getBorderInsets( Component c, Insets insets ) {
JTableHeader header = (JTableHeader) SwingUtilities.getAncestorOfClass( JTableHeader.class, c );
if( header != null ) {
if( header.getUI() instanceof FlatTableHeaderUI ) {
FlatTableHeaderUI ui = (FlatTableHeaderUI) header.getUI();
if( ui.cellMargins != null ) {
Insets m = ui.cellMargins;
return scaleInsets( c, insets, m.top, m.left, m.bottom, m.right );
}
}
}
return super.getBorderInsets( c, insets );
}
@Override
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
JTableHeader header = (JTableHeader) SwingUtilities.getAncestorOfClass( JTableHeader.class, c );
boolean leftToRight = (header != null ? header : c).getComponentOrientation().isLeftToRight();
boolean paintLeft = !leftToRight;
boolean paintRight = leftToRight;
Color separatorColor = this.separatorColor;
Color bottomSeparatorColor = this.bottomSeparatorColor;
if( header != null ) {
int hx = SwingUtilities.convertPoint( c, x, y, header ).x;
@@ -66,6 +85,16 @@ public class FlatTableHeaderBorder
if( hx + width >= header.getWidth() && leftToRight && hideTrailingVerticalLine( header ) )
paintRight = false;
}
// Because this border is always shared for all table headers,
// get border specific style from FlatTableHeaderUI.
if( header.getUI() instanceof FlatTableHeaderUI ) {
FlatTableHeaderUI ui = (FlatTableHeaderUI) header.getUI();
if( ui.separatorColor != null )
separatorColor = ui.separatorColor;
if( ui.bottomSeparatorColor != null )
bottomSeparatorColor = ui.bottomSeparatorColor;
}
}
float lineWidth = UIScale.scale( 1f );

View File

@@ -23,7 +23,8 @@ import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.geom.Rectangle2D;
import java.util.Objects;
import java.beans.PropertyChangeListener;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
@@ -36,6 +37,8 @@ import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicTableHeaderUI;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.ui.FlatStyleSupport.Styleable;
import com.formdev.flatlaf.util.UIScale;
/**
@@ -59,32 +62,50 @@ import com.formdev.flatlaf.util.UIScale;
* @uiDefault TableHeader.separatorColor Color
* @uiDefault TableHeader.bottomSeparatorColor Color
*
* <!-- FlatAscendingSortIcon and FlatDescendingSortIcon -->
*
* @uiDefault Component.arrowType String chevron (default) or triangle
* @uiDefault Table.sortIconColor Color
*
* @author Karl Tauber
*/
public class FlatTableHeaderUI
extends BasicTableHeaderUI
{
protected Color bottomSeparatorColor;
protected int height;
protected int sortIconPosition;
@Styleable protected Color bottomSeparatorColor;
@Styleable protected int height;
@Styleable protected int sortIconPosition;
// for FlatTableHeaderBorder
@Styleable protected Insets cellMargins;
@Styleable protected Color separatorColor;
// for FlatAscendingSortIcon and FlatDescendingSortIcon
// (needs to be public because icon classes are in another package)
@Styleable public String arrowType;
@Styleable public Color sortIconColor;
private PropertyChangeListener propertyChangeListener;
private Map<String, Object> oldStyleValues;
public static ComponentUI createUI( JComponent c ) {
return new FlatTableHeaderUI();
}
@Override
public void installUI( JComponent c ) {
super.installUI( c );
applyStyle( FlatStyleSupport.getStyle( c ) );
}
@Override
protected void installDefaults() {
super.installDefaults();
bottomSeparatorColor = UIManager.getColor( "TableHeader.bottomSeparatorColor" );
height = UIManager.getInt( "TableHeader.height" );
switch( Objects.toString( UIManager.getString( "TableHeader.sortIconPosition" ), "right" ) ) {
default:
case "right": sortIconPosition = SwingConstants.RIGHT; break;
case "left": sortIconPosition = SwingConstants.LEFT; break;
case "top": sortIconPosition = SwingConstants.TOP; break;
case "bottom": sortIconPosition = SwingConstants.BOTTOM; break;
}
sortIconPosition = parseSortIconPosition( UIManager.getString( "TableHeader.sortIconPosition" ) );
}
@Override
@@ -92,6 +113,54 @@ public class FlatTableHeaderUI
super.uninstallDefaults();
bottomSeparatorColor = null;
oldStyleValues = null;
}
@Override
protected void installListeners() {
super.installListeners();
propertyChangeListener = FlatStyleSupport.createPropertyChangeListener( header, this::applyStyle, null );
header.addPropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener );
}
@Override
protected void uninstallListeners() {
super.uninstallListeners();
header.removePropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener );
propertyChangeListener = null;
}
/**
* @since TODO
*/
protected void applyStyle( Object style ) {
oldStyleValues = FlatStyleSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
}
/**
* @since TODO
*/
protected Object applyStyleProperty( String key, Object value ) {
if( key.equals( "sortIconPosition" ) && value instanceof String )
value = parseSortIconPosition( (String) value );
return FlatStyleSupport.applyToAnnotatedObject( this, key, value );
}
private static int parseSortIconPosition( String str ) {
if( str == null )
str = "";
switch( str ) {
default:
case "right": return SwingConstants.RIGHT;
case "left": return SwingConstants.LEFT;
case "top": return SwingConstants.TOP;
case "bottom": return SwingConstants.BOTTOM;
}
}
@Override

View File

@@ -500,6 +500,23 @@ public class FlatStylingTests
ui.applyStyle( "showCellFocusIndicator: true" );
}
@Test
void tableHeader() {
FlatTableHeaderUI ui = new FlatTableHeaderUI();
ui.applyStyle( "bottomSeparatorColor: #fff" );
ui.applyStyle( "height: 20" );
ui.applyStyle( "sortIconPosition: top" );
// FlatTableHeaderBorder
ui.applyStyle( "cellMargins: 1,2,3,4" );
ui.applyStyle( "separatorColor: #fff" );
// FlatAscendingSortIcon and FlatDescendingSortIcon
ui.applyStyle( "arrowType: chevron" );
ui.applyStyle( "sortIconColor: #fff" );
}
@Test
void textArea() {
FlatTextAreaUI ui = new FlatTextAreaUI();