From b9c68fbe77e1362422525c69953fa8511319d358 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Wed, 11 Dec 2024 16:54:03 +0100 Subject: [PATCH 1/6] CheckBox: support styling indeterminate state of tri-state check boxes (issue #919) --- CHANGELOG.md | 3 + .../flatlaf/icons/FlatCheckBoxIcon.java | 140 ++++++++++++------ .../com/formdev/flatlaf/ui/FlatUIUtils.java | 14 ++ .../flatlaf/ui/TestFlatStyleableInfo.java | 38 ++++- .../flatlaf/ui/TestFlatStyleableValue.java | 17 +++ .../formdev/flatlaf/ui/TestFlatStyling.java | 17 +++ .../resources/DerivedColorKeys.properties | 7 +- .../themeeditor/FlatThemePreviewSwitches.java | 2 +- .../flatlaf/themeeditor/FlatLafUIKeys.txt | 34 +++++ 9 files changed, 220 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f724e854..27a602baa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ FlatLaf Change Log #### New features and improvements +- CheckBox: Support styling indeterminate state of + [tri-state check boxes](https://www.javadoc.io/doc/com.formdev/flatlaf-extras/latest/com/formdev/flatlaf/extras/components/FlatTriStateCheckBox.html). + (issue #919) - Tree: Support for alternate row highlighting. (PR #903) - Tree: Support wide cell renderer. (issue #922) - Extras: `FlatSVGIcon` color filters now can access painting component to diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCheckBoxIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCheckBoxIcon.java index 28afd50ab..f2fa02548 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCheckBoxIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCheckBoxIcon.java @@ -17,6 +17,7 @@ package com.formdev.flatlaf.icons; import static com.formdev.flatlaf.FlatClientProperties.*; +import static com.formdev.flatlaf.ui.FlatUIUtils.stateColor; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Component; @@ -48,6 +49,8 @@ * @uiDefault CheckBox.icon.borderWidth int or float optional; defaults to Component.borderWidth * @uiDefault CheckBox.icon.selectedBorderWidth int or float optional; defaults to CheckBox.icon.borderWidth * @uiDefault CheckBox.icon.disabledSelectedBorderWidth int or float optional; defaults to CheckBox.icon.selectedBorderWidth + * @uiDefault CheckBox.icon.indeterminateBorderWidth int or float optional; defaults to CheckBox.icon.selectedBorderWidth + * @uiDefault CheckBox.icon.disabledIndeterminateBorderWidth int or float optional; defaults to CheckBox.icon.disabledSelectedBorderWidth * @uiDefault CheckBox.arc int * * @uiDefault CheckBox.icon.focusColor Color optional; defaults to Component.focusColor @@ -56,30 +59,45 @@ * @uiDefault CheckBox.icon.selectedBorderColor Color * @uiDefault CheckBox.icon.selectedBackground Color * @uiDefault CheckBox.icon.checkmarkColor Color + * @uiDefault CheckBox.icon.indeterminateBorderColor Color optional; defaults to CheckBox.icon.selectedBorderColor + * @uiDefault CheckBox.icon.indeterminateBackground Color optional; defaults to CheckBox.icon.selectedBackground + * @uiDefault CheckBox.icon.indeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.checkmarkColor * - * @uiDefault CheckBox.icon.disabledBorderColor Color - * @uiDefault CheckBox.icon.disabledBackground Color - * @uiDefault CheckBox.icon.disabledSelectedBorderColor Color optional; CheckBox.icon.disabledBorderColor is used if not specified - * @uiDefault CheckBox.icon.disabledSelectedBackground Color optional; CheckBox.icon.disabledBackground is used if not specified - * @uiDefault CheckBox.icon.disabledCheckmarkColor Color + * @uiDefault CheckBox.icon.disabledBorderColor Color + * @uiDefault CheckBox.icon.disabledBackground Color + * @uiDefault CheckBox.icon.disabledSelectedBorderColor Color optional; defaults to CheckBox.icon.disabledBorderColor + * @uiDefault CheckBox.icon.disabledSelectedBackground Color optional; defaults to CheckBox.icon.disabledBackground + * @uiDefault CheckBox.icon.disabledCheckmarkColor Color + * @uiDefault CheckBox.icon.disabledIndeterminateBorderColor Color optional; defaults to CheckBox.icon.disabledSelectedBorderColor + * @uiDefault CheckBox.icon.disabledIndeterminateBackground Color optional; defaults to CheckBox.icon.disabledSelectedBackground + * @uiDefault CheckBox.icon.disabledIndeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.disabledCheckmarkColor * - * @uiDefault CheckBox.icon.focusedBorderColor Color optional - * @uiDefault CheckBox.icon.focusedBackground Color optional - * @uiDefault CheckBox.icon.focusedSelectedBorderColor Color optional; CheckBox.icon.focusedBorderColor is used if not specified - * @uiDefault CheckBox.icon.focusedSelectedBackground Color optional; CheckBox.icon.focusedBackground is used if not specified - * @uiDefault CheckBox.icon.focusedCheckmarkColor Color optional; CheckBox.icon.checkmarkColor is used if not specified + * @uiDefault CheckBox.icon.focusedBorderColor Color optional + * @uiDefault CheckBox.icon.focusedBackground Color optional + * @uiDefault CheckBox.icon.focusedSelectedBorderColor Color optional; defaults to CheckBox.icon.focusedBorderColor + * @uiDefault CheckBox.icon.focusedSelectedBackground Color optional; defaults to CheckBox.icon.focusedBackground + * @uiDefault CheckBox.icon.focusedCheckmarkColor Color optional; defaults to CheckBox.icon.checkmarkColor + * @uiDefault CheckBox.icon.focusedIndeterminateBorderColor Color optional; defaults to CheckBox.icon.focusedSelectedBorderColor + * @uiDefault CheckBox.icon.focusedIndeterminateBackground Color optional; defaults to CheckBox.icon.focusedSelectedBackground + * @uiDefault CheckBox.icon.focusedIndeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.focusedCheckmarkColor * - * @uiDefault CheckBox.icon.hoverBorderColor Color optional - * @uiDefault CheckBox.icon.hoverBackground Color optional - * @uiDefault CheckBox.icon.hoverSelectedBorderColor Color optional; CheckBox.icon.hoverBorderColor is used if not specified - * @uiDefault CheckBox.icon.hoverSelectedBackground Color optional; CheckBox.icon.hoverBackground is used if not specified - * @uiDefault CheckBox.icon.hoverCheckmarkColor Color optional; CheckBox.icon.checkmarkColor is used if not specified + * @uiDefault CheckBox.icon.hoverBorderColor Color optional + * @uiDefault CheckBox.icon.hoverBackground Color optional + * @uiDefault CheckBox.icon.hoverSelectedBorderColor Color optional; defaults to CheckBox.icon.hoverBorderColor + * @uiDefault CheckBox.icon.hoverSelectedBackground Color optional; defaults to CheckBox.icon.hoverBackground + * @uiDefault CheckBox.icon.hoverCheckmarkColor Color optional; defaults to CheckBox.icon.checkmarkColor + * @uiDefault CheckBox.icon.hoverIndeterminateBorderColor Color optional; defaults to CheckBox.icon.hoverSelectedBorderColor + * @uiDefault CheckBox.icon.hoverIndeterminateBackground Color optional; defaults to CheckBox.icon.hoverSelectedBackground + * @uiDefault CheckBox.icon.hoverIndeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.hoverCheckmarkColor * - * @uiDefault CheckBox.icon.pressedBorderColor Color optional - * @uiDefault CheckBox.icon.pressedBackground Color optional - * @uiDefault CheckBox.icon.pressedSelectedBorderColor Color optional; CheckBox.icon.pressedBorderColor is used if not specified - * @uiDefault CheckBox.icon.pressedSelectedBackground Color optional; CheckBox.icon.pressedBackground is used if not specified - * @uiDefault CheckBox.icon.pressedCheckmarkColor Color optional; CheckBox.icon.checkmarkColor is used if not specified + * @uiDefault CheckBox.icon.pressedBorderColor Color optional + * @uiDefault CheckBox.icon.pressedBackground Color optional + * @uiDefault CheckBox.icon.pressedSelectedBorderColor Color optional; defaults to CheckBox.icon.pressedBorderColor + * @uiDefault CheckBox.icon.pressedSelectedBackground Color optional; defaults to CheckBox.icon.pressedBackground + * @uiDefault CheckBox.icon.pressedCheckmarkColor Color optional; defaults to CheckBox.icon.checkmarkColor + * @uiDefault CheckBox.icon.pressedIndeterminateBorderColor Color optional; defaults to CheckBox.icon.pressedSelectedBorderColor + * @uiDefault CheckBox.icon.pressedIndeterminateBackground Color optional; defaults to CheckBox.icon.pressedSelectedBackground + * @uiDefault CheckBox.icon.pressedIndeterminateCheckmarkColor Color optional; defaults to CheckBox.icon.pressedCheckmarkColor * * @author Karl Tauber */ @@ -92,6 +110,8 @@ public class FlatCheckBoxIcon /** @since 2 */ @Styleable protected float borderWidth = getUIFloat( "CheckBox.icon.borderWidth", FlatUIUtils.getUIFloat( "Component.borderWidth", 1 ), style ); /** @since 2 */ @Styleable protected float selectedBorderWidth = getUIFloat( "CheckBox.icon.selectedBorderWidth", Float.MIN_VALUE, style ); /** @since 2 */ @Styleable protected float disabledSelectedBorderWidth = getUIFloat( "CheckBox.icon.disabledSelectedBorderWidth", Float.MIN_VALUE, style ); + /** @since 3.6 */ @Styleable protected float indeterminateBorderWidth = getUIFloat( "CheckBox.icon.indeterminateBorderWidth", Float.MIN_VALUE, style ); + /** @since 3.6 */ @Styleable protected float disabledIndeterminateBorderWidth = getUIFloat( "CheckBox.icon.disabledIndeterminateBorderWidth", Float.MIN_VALUE, style ); @Styleable protected int arc = FlatUIUtils.getUIInt( "CheckBox.arc", 2 ); // enabled @@ -100,6 +120,9 @@ public class FlatCheckBoxIcon @Styleable protected Color selectedBorderColor = getUIColor( "CheckBox.icon.selectedBorderColor", style ); @Styleable protected Color selectedBackground = getUIColor( "CheckBox.icon.selectedBackground", style ); @Styleable protected Color checkmarkColor = getUIColor( "CheckBox.icon.checkmarkColor", style ); + /** @since 3.6 */ @Styleable protected Color indeterminateBorderColor = getUIColor( "CheckBox.icon.indeterminateBorderColor", style ); + /** @since 3.6 */ @Styleable protected Color indeterminateBackground = getUIColor( "CheckBox.icon.indeterminateBackground", style ); + /** @since 3.6 */ @Styleable protected Color indeterminateCheckmarkColor = getUIColor( "CheckBox.icon.indeterminateCheckmarkColor", style ); // disabled @Styleable protected Color disabledBorderColor = getUIColor( "CheckBox.icon.disabledBorderColor", style ); @@ -107,6 +130,9 @@ public class FlatCheckBoxIcon /** @since 2 */ @Styleable protected Color disabledSelectedBorderColor = getUIColor( "CheckBox.icon.disabledSelectedBorderColor", style ); /** @since 2 */ @Styleable protected Color disabledSelectedBackground = getUIColor( "CheckBox.icon.disabledSelectedBackground", style ); @Styleable protected Color disabledCheckmarkColor = getUIColor( "CheckBox.icon.disabledCheckmarkColor", style ); + /** @since 3.6 */ @Styleable protected Color disabledIndeterminateBorderColor = getUIColor( "CheckBox.icon.disabledIndeterminateBorderColor", style ); + /** @since 3.6 */ @Styleable protected Color disabledIndeterminateBackground = getUIColor( "CheckBox.icon.disabledIndeterminateBackground", style ); + /** @since 3.6 */ @Styleable protected Color disabledIndeterminateCheckmarkColor = getUIColor( "CheckBox.icon.disabledIndeterminateCheckmarkColor", style ); // focused @Styleable protected Color focusedBorderColor = getUIColor( "CheckBox.icon.focusedBorderColor", style ); @@ -114,6 +140,9 @@ public class FlatCheckBoxIcon /** @since 2 */ @Styleable protected Color focusedSelectedBorderColor = getUIColor( "CheckBox.icon.focusedSelectedBorderColor", style ); /** @since 2 */ @Styleable protected Color focusedSelectedBackground = getUIColor( "CheckBox.icon.focusedSelectedBackground", style ); /** @since 2 */ @Styleable protected Color focusedCheckmarkColor = getUIColor( "CheckBox.icon.focusedCheckmarkColor", style ); + /** @since 3.6 */ @Styleable protected Color focusedIndeterminateBorderColor = getUIColor( "CheckBox.icon.focusedIndeterminateBorderColor", style ); + /** @since 3.6 */ @Styleable protected Color focusedIndeterminateBackground = getUIColor( "CheckBox.icon.focusedIndeterminateBackground", style ); + /** @since 3.6 */ @Styleable protected Color focusedIndeterminateCheckmarkColor = getUIColor( "CheckBox.icon.focusedIndeterminateCheckmarkColor", style ); // hover @Styleable protected Color hoverBorderColor = getUIColor( "CheckBox.icon.hoverBorderColor", style ); @@ -121,6 +150,9 @@ public class FlatCheckBoxIcon /** @since 2 */ @Styleable protected Color hoverSelectedBorderColor = getUIColor( "CheckBox.icon.hoverSelectedBorderColor", style ); /** @since 2 */ @Styleable protected Color hoverSelectedBackground = getUIColor( "CheckBox.icon.hoverSelectedBackground", style ); /** @since 2 */ @Styleable protected Color hoverCheckmarkColor = getUIColor( "CheckBox.icon.hoverCheckmarkColor", style ); + /** @since 3.6 */ @Styleable protected Color hoverIndeterminateBorderColor = getUIColor( "CheckBox.icon.hoverIndeterminateBorderColor", style ); + /** @since 3.6 */ @Styleable protected Color hoverIndeterminateBackground = getUIColor( "CheckBox.icon.hoverIndeterminateBackground", style ); + /** @since 3.6 */ @Styleable protected Color hoverIndeterminateCheckmarkColor = getUIColor( "CheckBox.icon.hoverIndeterminateCheckmarkColor", style ); // pressed /** @since 2 */ @Styleable protected Color pressedBorderColor = getUIColor( "CheckBox.icon.pressedBorderColor", style ); @@ -128,6 +160,9 @@ public class FlatCheckBoxIcon /** @since 2 */ @Styleable protected Color pressedSelectedBorderColor = getUIColor( "CheckBox.icon.pressedSelectedBorderColor", style ); /** @since 2 */ @Styleable protected Color pressedSelectedBackground = getUIColor( "CheckBox.icon.pressedSelectedBackground", style ); /** @since 2 */ @Styleable protected Color pressedCheckmarkColor = getUIColor( "CheckBox.icon.pressedCheckmarkColor", style ); + /** @since 3.6 */ @Styleable protected Color pressedIndeterminateBorderColor = getUIColor( "CheckBox.icon.pressedIndeterminateBorderColor", style ); + /** @since 3.6 */ @Styleable protected Color pressedIndeterminateBackground = getUIColor( "CheckBox.icon.pressedIndeterminateBackground", style ); + /** @since 3.6 */ @Styleable protected Color pressedIndeterminateCheckmarkColor = getUIColor( "CheckBox.icon.pressedIndeterminateCheckmarkColor", style ); protected String getPropertyPrefix() { return "CheckBox."; @@ -182,11 +217,17 @@ protected void paintIcon( Component c, Graphics2D g ) { boolean indeterminate = isIndeterminate( c ); boolean selected = indeterminate || isSelected( c ); boolean isFocused = FlatUIUtils.isPermanentFocusOwner( c ); - float bw = selected - ? (disabledSelectedBorderWidth != Float.MIN_VALUE && !c.isEnabled() - ? disabledSelectedBorderWidth - : (selectedBorderWidth != Float.MIN_VALUE ? selectedBorderWidth : borderWidth)) - : borderWidth; + float bw = Float.MIN_VALUE; + if( !c.isEnabled() ) { + bw = (indeterminate && disabledIndeterminateBorderWidth != Float.MIN_VALUE) + ? disabledIndeterminateBorderWidth + : (selected ? disabledSelectedBorderWidth : selectedBorderWidth); + } + if( bw == Float.MIN_VALUE ) { + bw = (indeterminate && indeterminateBorderWidth != Float.MIN_VALUE) + ? indeterminateBorderWidth + : ((selected && selectedBorderWidth != Float.MIN_VALUE) ? selectedBorderWidth : borderWidth); + } // paint focused border if( isFocused && focusWidth > 0 && FlatButtonUI.isFocusPainted( c ) ) { @@ -195,15 +236,15 @@ protected void paintIcon( Component c, Graphics2D g ) { } // paint border - g.setColor( getBorderColor( c, selected ) ); + g.setColor( getBorderColor( c, selected, indeterminate ) ); paintBorder( c, g, bw ); // paint background - Color bg = FlatUIUtils.deriveColor( getBackground( c, selected ), - selected ? selectedBackground : background ); + Color baseBg = stateColor( indeterminate, indeterminateBackground, selected, selectedBackground, background ); + Color bg = FlatUIUtils.deriveColor( getBackground( c, selected, indeterminate ), baseBg ); if( bg.getAlpha() < 255 ) { // fill background with default color before filling with non-opaque background - g.setColor( selected ? selectedBackground : background ); + g.setColor( baseBg ); paintBackground( c, g, bw ); } g.setColor( bg ); @@ -211,7 +252,7 @@ protected void paintIcon( Component c, Graphics2D g ) { // paint checkmark if( selected ) { - g.setColor( getCheckmarkColor( c ) ); + g.setColor( getCheckmarkColor( c, indeterminate ) ); if( indeterminate ) paintIndeterminate( c, g ); else @@ -272,30 +313,33 @@ protected Color getFocusColor( Component c ) { return focusColor; } - protected Color getBorderColor( Component c, boolean selected ) { + /** @since 3.6 */ + protected Color getBorderColor( Component c, boolean selected, boolean indeterminate ) { return FlatButtonUI.buttonStateColor( c, - selected ? selectedBorderColor : borderColor, - (selected && disabledSelectedBorderColor != null) ? disabledSelectedBorderColor : disabledBorderColor, - (selected && focusedSelectedBorderColor != null) ? focusedSelectedBorderColor : focusedBorderColor, - (selected && hoverSelectedBorderColor != null) ? hoverSelectedBorderColor : hoverBorderColor, - (selected && pressedSelectedBorderColor != null) ? pressedSelectedBorderColor : pressedBorderColor ); + stateColor( indeterminate, indeterminateBorderColor, selected, selectedBorderColor, borderColor ), + stateColor( indeterminate, disabledIndeterminateBorderColor, selected, disabledSelectedBorderColor, disabledBorderColor ), + stateColor( indeterminate, focusedIndeterminateBorderColor, selected, focusedSelectedBorderColor, focusedBorderColor ), + stateColor( indeterminate, hoverIndeterminateBorderColor, selected, hoverSelectedBorderColor, hoverBorderColor ), + stateColor( indeterminate, pressedIndeterminateBorderColor, selected, pressedSelectedBorderColor, pressedBorderColor ) ); } - protected Color getBackground( Component c, boolean selected ) { + /** @since 3.6 */ + protected Color getBackground( Component c, boolean selected, boolean indeterminate ) { return FlatButtonUI.buttonStateColor( c, - selected ? selectedBackground : background, - (selected && disabledSelectedBackground != null) ? disabledSelectedBackground : disabledBackground, - (selected && focusedSelectedBackground != null) ? focusedSelectedBackground : focusedBackground, - (selected && hoverSelectedBackground != null) ? hoverSelectedBackground : hoverBackground, - (selected && pressedSelectedBackground != null) ? pressedSelectedBackground : pressedBackground ); + stateColor( indeterminate, indeterminateBackground, selected, selectedBackground, background ), + stateColor( indeterminate, disabledIndeterminateBackground, selected, disabledSelectedBackground, disabledBackground ), + stateColor( indeterminate, focusedIndeterminateBackground, selected, focusedSelectedBackground, focusedBackground ), + stateColor( indeterminate, hoverIndeterminateBackground, selected, hoverSelectedBackground, hoverBackground ), + stateColor( indeterminate, pressedIndeterminateBackground, selected, pressedSelectedBackground, pressedBackground ) ); } - protected Color getCheckmarkColor( Component c ) { + /** @since 3.6 */ + protected Color getCheckmarkColor( Component c, boolean indeterminate ) { return FlatButtonUI.buttonStateColor( c, - checkmarkColor, - disabledCheckmarkColor, - focusedCheckmarkColor, - hoverCheckmarkColor, - pressedCheckmarkColor ); + stateColor( indeterminate, indeterminateCheckmarkColor, checkmarkColor ), + stateColor( indeterminate, disabledIndeterminateCheckmarkColor, disabledCheckmarkColor ), + stateColor( indeterminate, focusedIndeterminateCheckmarkColor, focusedCheckmarkColor ), + stateColor( indeterminate, hoverIndeterminateCheckmarkColor, hoverCheckmarkColor ), + stateColor( indeterminate, pressedIndeterminateCheckmarkColor, pressedCheckmarkColor ) ); } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java index b6cf2e95e..706e45460 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java @@ -129,6 +129,20 @@ public static boolean isInsetsEmpty( Insets insets ) { return insets.top == 0 && insets.left == 0 && insets.bottom == 0 && insets.right == 0; } + /** @since 3.6 */ + public static Color stateColor( boolean state, Color stateColor, Color defaultColor ) { + return (state && stateColor != null) ? stateColor : defaultColor; + } + + /** @since 3.6 */ + public static Color stateColor( boolean state1, Color state1Color, + boolean state2, Color state2Color, Color defaultColor ) + { + return (state1 && state1Color != null) + ? state1Color + : ((state2 && state2Color != null) ? state2Color : defaultColor); + } + public static Color getUIColor( String key, int defaultColorRGB ) { Color color = UIManager.getColor( key ); return (color != null) ? color : new Color( defaultColorRGB ); diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java index 596ac6c8e..f64868969 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java @@ -517,6 +517,8 @@ private void radioButton( Map> expected ) { "icon.borderWidth", float.class, "icon.selectedBorderWidth", float.class, "icon.disabledSelectedBorderWidth", float.class, + "icon.indeterminateBorderWidth", float.class, + "icon.disabledIndeterminateBorderWidth", float.class, "icon.arc", int.class, // enabled @@ -525,6 +527,9 @@ private void radioButton( Map> expected ) { "icon.selectedBorderColor", Color.class, "icon.selectedBackground", Color.class, "icon.checkmarkColor", Color.class, + "icon.indeterminateBorderColor", Color.class, + "icon.indeterminateBackground", Color.class, + "icon.indeterminateCheckmarkColor", Color.class, // disabled "icon.disabledBorderColor", Color.class, @@ -532,6 +537,9 @@ private void radioButton( Map> expected ) { "icon.disabledSelectedBorderColor", Color.class, "icon.disabledSelectedBackground", Color.class, "icon.disabledCheckmarkColor", Color.class, + "icon.disabledIndeterminateBorderColor", Color.class, + "icon.disabledIndeterminateBackground", Color.class, + "icon.disabledIndeterminateCheckmarkColor", Color.class, // focused "icon.focusedBorderColor", Color.class, @@ -539,6 +547,9 @@ private void radioButton( Map> expected ) { "icon.focusedSelectedBorderColor", Color.class, "icon.focusedSelectedBackground", Color.class, "icon.focusedCheckmarkColor", Color.class, + "icon.focusedIndeterminateBorderColor", Color.class, + "icon.focusedIndeterminateBackground", Color.class, + "icon.focusedIndeterminateCheckmarkColor", Color.class, // hover "icon.hoverBorderColor", Color.class, @@ -546,13 +557,19 @@ private void radioButton( Map> expected ) { "icon.hoverSelectedBorderColor", Color.class, "icon.hoverSelectedBackground", Color.class, "icon.hoverCheckmarkColor", Color.class, + "icon.hoverIndeterminateBorderColor", Color.class, + "icon.hoverIndeterminateBackground", Color.class, + "icon.hoverIndeterminateCheckmarkColor", Color.class, // pressed "icon.pressedBorderColor", Color.class, "icon.pressedBackground", Color.class, "icon.pressedSelectedBorderColor", Color.class, "icon.pressedSelectedBackground", Color.class, - "icon.pressedCheckmarkColor", Color.class + "icon.pressedCheckmarkColor", Color.class, + "icon.pressedIndeterminateBorderColor", Color.class, + "icon.pressedIndeterminateBackground", Color.class, + "icon.pressedIndeterminateCheckmarkColor", Color.class ); } @@ -1146,6 +1163,8 @@ private void flatCheckBoxIcon( Map> expected ) { "borderWidth", float.class, "selectedBorderWidth", float.class, "disabledSelectedBorderWidth", float.class, + "indeterminateBorderWidth", float.class, + "disabledIndeterminateBorderWidth", float.class, "arc", int.class, // enabled @@ -1154,6 +1173,9 @@ private void flatCheckBoxIcon( Map> expected ) { "selectedBorderColor", Color.class, "selectedBackground", Color.class, "checkmarkColor", Color.class, + "indeterminateBorderColor", Color.class, + "indeterminateBackground", Color.class, + "indeterminateCheckmarkColor", Color.class, // disabled "disabledBorderColor", Color.class, @@ -1161,6 +1183,9 @@ private void flatCheckBoxIcon( Map> expected ) { "disabledSelectedBorderColor", Color.class, "disabledSelectedBackground", Color.class, "disabledCheckmarkColor", Color.class, + "disabledIndeterminateBorderColor", Color.class, + "disabledIndeterminateBackground", Color.class, + "disabledIndeterminateCheckmarkColor", Color.class, // focused "focusedBorderColor", Color.class, @@ -1168,6 +1193,9 @@ private void flatCheckBoxIcon( Map> expected ) { "focusedSelectedBorderColor", Color.class, "focusedSelectedBackground", Color.class, "focusedCheckmarkColor", Color.class, + "focusedIndeterminateBorderColor", Color.class, + "focusedIndeterminateBackground", Color.class, + "focusedIndeterminateCheckmarkColor", Color.class, // hover "hoverBorderColor", Color.class, @@ -1175,13 +1203,19 @@ private void flatCheckBoxIcon( Map> expected ) { "hoverSelectedBorderColor", Color.class, "hoverSelectedBackground", Color.class, "hoverCheckmarkColor", Color.class, + "hoverIndeterminateBorderColor", Color.class, + "hoverIndeterminateBackground", Color.class, + "hoverIndeterminateCheckmarkColor", Color.class, // pressed "pressedBorderColor", Color.class, "pressedBackground", Color.class, "pressedSelectedBorderColor", Color.class, "pressedSelectedBackground", Color.class, - "pressedCheckmarkColor", Color.class + "pressedCheckmarkColor", Color.class, + "pressedIndeterminateBorderColor", Color.class, + "pressedIndeterminateBackground", Color.class, + "pressedIndeterminateCheckmarkColor", Color.class ); } diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java index f0ae44841..3e4fb0fd2 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java @@ -1148,6 +1148,8 @@ private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { testValue( icon, "borderWidth", 1.5f ); testValue( icon, "selectedBorderWidth", 1.5f ); testValue( icon, "disabledSelectedBorderWidth", 1.5f ); + testValue( icon, "indeterminateBorderWidth", 1.5f ); + testValue( icon, "disabledIndeterminateBorderWidth", 1.5f ); testValue( icon, "arc", 5 ); // enabled @@ -1156,6 +1158,9 @@ private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { testValue( icon, "selectedBorderColor", Color.WHITE ); testValue( icon, "selectedBackground", Color.WHITE ); testValue( icon, "checkmarkColor", Color.WHITE ); + testValue( icon, "indeterminateBorderColor", Color.WHITE ); + testValue( icon, "indeterminateBackground", Color.WHITE ); + testValue( icon, "indeterminateCheckmarkColor", Color.WHITE ); // disabled testValue( icon, "disabledBorderColor", Color.WHITE ); @@ -1163,6 +1168,9 @@ private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { testValue( icon, "disabledSelectedBorderColor", Color.WHITE ); testValue( icon, "disabledSelectedBackground", Color.WHITE ); testValue( icon, "disabledCheckmarkColor", Color.WHITE ); + testValue( icon, "disabledIndeterminateBorderColor", Color.WHITE ); + testValue( icon, "disabledIndeterminateBackground", Color.WHITE ); + testValue( icon, "disabledIndeterminateCheckmarkColor", Color.WHITE ); // focused testValue( icon, "focusedBorderColor", Color.WHITE ); @@ -1170,6 +1178,9 @@ private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { testValue( icon, "focusedSelectedBorderColor", Color.WHITE ); testValue( icon, "focusedSelectedBackground", Color.WHITE ); testValue( icon, "focusedCheckmarkColor", Color.WHITE ); + testValue( icon, "focusedIndeterminateBorderColor", Color.WHITE ); + testValue( icon, "focusedIndeterminateBackground", Color.WHITE ); + testValue( icon, "focusedIndeterminateCheckmarkColor", Color.WHITE ); // hover testValue( icon, "hoverBorderColor", Color.WHITE ); @@ -1177,6 +1188,9 @@ private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { testValue( icon, "hoverSelectedBorderColor", Color.WHITE ); testValue( icon, "hoverSelectedBackground", Color.WHITE ); testValue( icon, "hoverCheckmarkColor", Color.WHITE ); + testValue( icon, "hoverIndeterminateBorderColor", Color.WHITE ); + testValue( icon, "hoverIndeterminateBackground", Color.WHITE ); + testValue( icon, "hoverIndeterminateCheckmarkColor", Color.WHITE ); // pressed testValue( icon, "pressedBorderColor", Color.WHITE ); @@ -1184,6 +1198,9 @@ private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { testValue( icon, "pressedSelectedBorderColor", Color.WHITE ); testValue( icon, "pressedSelectedBackground", Color.WHITE ); testValue( icon, "pressedCheckmarkColor", Color.WHITE ); + testValue( icon, "pressedIndeterminateBorderColor", Color.WHITE ); + testValue( icon, "pressedIndeterminateBackground", Color.WHITE ); + testValue( icon, "pressedIndeterminateCheckmarkColor", Color.WHITE ); } @Test diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java index d20e49fb0..209cad9be 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java @@ -1390,6 +1390,8 @@ private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { icon.applyStyleProperty( "borderWidth", 1.5f ); icon.applyStyleProperty( "selectedBorderWidth", 1.5f ); icon.applyStyleProperty( "disabledSelectedBorderWidth", 1.5f ); + icon.applyStyleProperty( "indeterminateBorderWidth", 1.5f ); + icon.applyStyleProperty( "disabledIndeterminateBorderWidth", 1.5f ); icon.applyStyleProperty( "arc", 5 ); // enabled @@ -1398,6 +1400,9 @@ private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { icon.applyStyleProperty( "selectedBorderColor", Color.WHITE ); icon.applyStyleProperty( "selectedBackground", Color.WHITE ); icon.applyStyleProperty( "checkmarkColor", Color.WHITE ); + icon.applyStyleProperty( "indeterminateBorderColor", Color.WHITE ); + icon.applyStyleProperty( "indeterminateBackground", Color.WHITE ); + icon.applyStyleProperty( "indeterminateCheckmarkColor", Color.WHITE ); // disabled icon.applyStyleProperty( "disabledBorderColor", Color.WHITE ); @@ -1405,6 +1410,9 @@ private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { icon.applyStyleProperty( "disabledSelectedBorderColor", Color.WHITE ); icon.applyStyleProperty( "disabledSelectedBackground", Color.WHITE ); icon.applyStyleProperty( "disabledCheckmarkColor", Color.WHITE ); + icon.applyStyleProperty( "disabledIndeterminateBorderColor", Color.WHITE ); + icon.applyStyleProperty( "disabledIndeterminateBackground", Color.WHITE ); + icon.applyStyleProperty( "disabledIndeterminateCheckmarkColor", Color.WHITE ); // focused icon.applyStyleProperty( "focusedBorderColor", Color.WHITE ); @@ -1412,6 +1420,9 @@ private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { icon.applyStyleProperty( "focusedSelectedBorderColor", Color.WHITE ); icon.applyStyleProperty( "focusedSelectedBackground", Color.WHITE ); icon.applyStyleProperty( "focusedCheckmarkColor", Color.WHITE ); + icon.applyStyleProperty( "focusedIndeterminateBorderColor", Color.WHITE ); + icon.applyStyleProperty( "focusedIndeterminateBackground", Color.WHITE ); + icon.applyStyleProperty( "focusedIndeterminateCheckmarkColor", Color.WHITE ); // hover icon.applyStyleProperty( "hoverBorderColor", Color.WHITE ); @@ -1419,6 +1430,9 @@ private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { icon.applyStyleProperty( "hoverSelectedBorderColor", Color.WHITE ); icon.applyStyleProperty( "hoverSelectedBackground", Color.WHITE ); icon.applyStyleProperty( "hoverCheckmarkColor", Color.WHITE ); + icon.applyStyleProperty( "hoverIndeterminateBorderColor", Color.WHITE ); + icon.applyStyleProperty( "hoverIndeterminateBackground", Color.WHITE ); + icon.applyStyleProperty( "hoverIndeterminateCheckmarkColor", Color.WHITE ); // pressed icon.applyStyleProperty( "pressedBorderColor", Color.WHITE ); @@ -1426,6 +1440,9 @@ private void flatCheckBoxIcon( FlatCheckBoxIcon icon ) { icon.applyStyleProperty( "pressedSelectedBorderColor", Color.WHITE ); icon.applyStyleProperty( "pressedSelectedBackground", Color.WHITE ); icon.applyStyleProperty( "pressedCheckmarkColor", Color.WHITE ); + icon.applyStyleProperty( "pressedIndeterminateBorderColor", Color.WHITE ); + icon.applyStyleProperty( "pressedIndeterminateBackground", Color.WHITE ); + icon.applyStyleProperty( "pressedIndeterminateCheckmarkColor", Color.WHITE ); } @Test diff --git a/flatlaf-extras/src/main/resources/com/formdev/flatlaf/extras/resources/DerivedColorKeys.properties b/flatlaf-extras/src/main/resources/com/formdev/flatlaf/extras/resources/DerivedColorKeys.properties index c7e0eccfa..c1231de49 100644 --- a/flatlaf-extras/src/main/resources/com/formdev/flatlaf/extras/resources/DerivedColorKeys.properties +++ b/flatlaf-extras/src/main/resources/com/formdev/flatlaf/extras/resources/DerivedColorKeys.properties @@ -62,6 +62,9 @@ CheckBox.icon.pressedBackground = CheckBox.icon.background CheckBox.icon.focusedSelectedBackground = CheckBox.icon.selectedBackground CheckBox.icon.hoverSelectedBackground = CheckBox.icon.selectedBackground CheckBox.icon.pressedSelectedBackground = CheckBox.icon.selectedBackground +CheckBox.icon.focusedIndeterminateBackground = CheckBox.icon.indeterminateBackground +CheckBox.icon.hoverIndeterminateBackground = CheckBox.icon.indeterminateBackground +CheckBox.icon.pressedIndeterminateBackground = CheckBox.icon.indeterminateBackground CheckBox.icon[filled].disabledBackground = CheckBox.icon[filled].background CheckBox.icon[filled].focusedBackground = CheckBox.icon[filled].background @@ -70,7 +73,9 @@ CheckBox.icon[filled].pressedBackground = CheckBox.icon[filled].background CheckBox.icon[filled].focusedSelectedBackground = CheckBox.icon[filled].selectedBackground CheckBox.icon[filled].hoverSelectedBackground = CheckBox.icon[filled].selectedBackground CheckBox.icon[filled].pressedSelectedBackground = CheckBox.icon[filled].selectedBackground - +CheckBox.icon[filled].focusedIndeterminateBackground = CheckBox.icon[filled].indeterminateBackground +CheckBox.icon[filled].hoverIndeterminateBackground = CheckBox.icon[filled].indeterminateBackground +CheckBox.icon[filled].pressedIndeterminateBackground = CheckBox.icon[filled].indeterminateBackground #---- CheckBoxMenuItem ---- diff --git a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemePreviewSwitches.java b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemePreviewSwitches.java index 6c840b767..76edcb71f 100644 --- a/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemePreviewSwitches.java +++ b/flatlaf-theme-editor/src/main/java/com/formdev/flatlaf/themeeditor/FlatThemePreviewSwitches.java @@ -672,7 +672,7 @@ public boolean isPressed() { } @Override public boolean isSelected() { - return isStateSelected(); + return isStateSelected() || isStateIndeterminate(); } } ); diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt index 7f3ec73a4..4b765662b 100644 --- a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt +++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt @@ -98,6 +98,10 @@ CheckBox.icon.checkmarkColor CheckBox.icon.disabledBackground CheckBox.icon.disabledBorderColor CheckBox.icon.disabledCheckmarkColor +CheckBox.icon.disabledIndeterminateBackground +CheckBox.icon.disabledIndeterminateBorderColor +CheckBox.icon.disabledIndeterminateBorderWidth +CheckBox.icon.disabledIndeterminateCheckmarkColor CheckBox.icon.disabledSelectedBackground CheckBox.icon.disabledSelectedBorderColor CheckBox.icon.disabledSelectedBorderWidth @@ -106,16 +110,29 @@ CheckBox.icon.focusWidth CheckBox.icon.focusedBackground CheckBox.icon.focusedBorderColor CheckBox.icon.focusedCheckmarkColor +CheckBox.icon.focusedIndeterminateBackground +CheckBox.icon.focusedIndeterminateBorderColor +CheckBox.icon.focusedIndeterminateCheckmarkColor CheckBox.icon.focusedSelectedBackground CheckBox.icon.focusedSelectedBorderColor CheckBox.icon.hoverBackground CheckBox.icon.hoverBorderColor CheckBox.icon.hoverCheckmarkColor +CheckBox.icon.hoverIndeterminateBackground +CheckBox.icon.hoverIndeterminateBorderColor +CheckBox.icon.hoverIndeterminateCheckmarkColor CheckBox.icon.hoverSelectedBackground CheckBox.icon.hoverSelectedBorderColor +CheckBox.icon.indeterminateBackground +CheckBox.icon.indeterminateBorderColor +CheckBox.icon.indeterminateBorderWidth +CheckBox.icon.indeterminateCheckmarkColor CheckBox.icon.pressedBackground CheckBox.icon.pressedBorderColor CheckBox.icon.pressedCheckmarkColor +CheckBox.icon.pressedIndeterminateBackground +CheckBox.icon.pressedIndeterminateBorderColor +CheckBox.icon.pressedIndeterminateCheckmarkColor CheckBox.icon.pressedSelectedBackground CheckBox.icon.pressedSelectedBorderColor CheckBox.icon.selectedBackground @@ -130,6 +147,10 @@ CheckBox.icon[filled].checkmarkColor CheckBox.icon[filled].disabledBackground CheckBox.icon[filled].disabledBorderColor CheckBox.icon[filled].disabledCheckmarkColor +CheckBox.icon[filled].disabledIndeterminateBackground +CheckBox.icon[filled].disabledIndeterminateBorderColor +CheckBox.icon[filled].disabledIndeterminateBorderWidth +CheckBox.icon[filled].disabledIndeterminateCheckmarkColor CheckBox.icon[filled].disabledSelectedBackground CheckBox.icon[filled].disabledSelectedBorderColor CheckBox.icon[filled].disabledSelectedBorderWidth @@ -137,16 +158,29 @@ CheckBox.icon[filled].focusWidth CheckBox.icon[filled].focusedBackground CheckBox.icon[filled].focusedBorderColor CheckBox.icon[filled].focusedCheckmarkColor +CheckBox.icon[filled].focusedIndeterminateBackground +CheckBox.icon[filled].focusedIndeterminateBorderColor +CheckBox.icon[filled].focusedIndeterminateCheckmarkColor CheckBox.icon[filled].focusedSelectedBackground CheckBox.icon[filled].focusedSelectedBorderColor CheckBox.icon[filled].hoverBackground CheckBox.icon[filled].hoverBorderColor CheckBox.icon[filled].hoverCheckmarkColor +CheckBox.icon[filled].hoverIndeterminateBackground +CheckBox.icon[filled].hoverIndeterminateBorderColor +CheckBox.icon[filled].hoverIndeterminateCheckmarkColor CheckBox.icon[filled].hoverSelectedBackground CheckBox.icon[filled].hoverSelectedBorderColor +CheckBox.icon[filled].indeterminateBackground +CheckBox.icon[filled].indeterminateBorderColor +CheckBox.icon[filled].indeterminateBorderWidth +CheckBox.icon[filled].indeterminateCheckmarkColor CheckBox.icon[filled].pressedBackground CheckBox.icon[filled].pressedBorderColor CheckBox.icon[filled].pressedCheckmarkColor +CheckBox.icon[filled].pressedIndeterminateBackground +CheckBox.icon[filled].pressedIndeterminateBorderColor +CheckBox.icon[filled].pressedIndeterminateCheckmarkColor CheckBox.icon[filled].pressedSelectedBackground CheckBox.icon[filled].pressedSelectedBorderColor CheckBox.icon[filled].selectedBackground From c12adf12e7eebd57976702178e449041341fdb9c Mon Sep 17 00:00:00 2001 From: Dar Date: Thu, 28 Nov 2024 10:18:22 +0100 Subject: [PATCH 2/6] new: support for alternate row color in JList --- .../java/com/formdev/flatlaf/ui/FlatListUI.java | 13 +++++++++++++ .../formdev/flatlaf/ui/TestFlatStyleableInfo.java | 1 + .../formdev/flatlaf/ui/TestFlatStyleableValue.java | 1 + .../com/formdev/flatlaf/ui/TestFlatStyling.java | 1 + .../formdev/flatlaf/themeeditor/FlatLafUIKeys.txt | 1 + 5 files changed, 17 insertions(+) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java index b6d0b712a..c1fa40bce 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java @@ -57,6 +57,7 @@ * @uiDefault List.foreground Color * @uiDefault List.selectionBackground Color * @uiDefault List.selectionForeground Color + * @uiDefault List.alternateRowColor Color * @uiDefault List.dropLineColor Color * @uiDefault List.border Border * @uiDefault List.cellRenderer ListCellRenderer @@ -93,6 +94,7 @@ public class FlatListUI @Styleable protected Color selectionForeground; @Styleable protected Color selectionInactiveBackground; @Styleable protected Color selectionInactiveForeground; + /** @since 3.6 */ @Styleable protected Color alternateRowColor; /** @since 3 */ @Styleable protected Insets selectionInsets; /** @since 3 */ @Styleable protected int selectionArc; @@ -129,6 +131,7 @@ protected void installDefaults() { selectionForeground = UIManager.getColor( "List.selectionForeground" ); selectionInactiveBackground = UIManager.getColor( "List.selectionInactiveBackground" ); selectionInactiveForeground = UIManager.getColor( "List.selectionInactiveForeground" ); + alternateRowColor = UIManager.getColor( "List.alternateRowColor" ); selectionInsets = UIManager.getInsets( "List.selectionInsets" ); selectionArc = UIManager.getInt( "List.selectionArc" ); @@ -143,6 +146,7 @@ protected void uninstallDefaults() { selectionForeground = null; selectionInactiveBackground = null; selectionInactiveForeground = null; + alternateRowColor = null; oldStyleValues = null; } @@ -304,6 +308,15 @@ protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRend Component rendererComponent = cellRenderer.getListCellRendererComponent( list, dataModel.getElementAt( row ), row, isSelected, FlatUIUtils.isPermanentFocusOwner( list ) && (row == leadIndex) ); + + if( alternateRowColor != null && row % 2 != 0 ) { + g.setColor( alternateRowColor ); + + // paint respecting selection arc + final float arc = UIScale.scale( selectionArc / 2f ); + FlatUIUtils.paintSelection( (Graphics2D) g, 0, rowBounds.y, list.getWidth(), rowBounds.height, + UIScale.scale( selectionInsets ), arc, arc, arc, arc, 0 ); + } // boolean isFileList = Boolean.TRUE.equals( list.getClientProperty( "List.isFileList" ) ); diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java index 596ac6c8e..be7949a09 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java @@ -270,6 +270,7 @@ void list() { "selectionForeground", Color.class, "selectionInactiveBackground", Color.class, "selectionInactiveForeground", Color.class, + "alternateRowColor", Color.class, "selectionInsets", Insets.class, "selectionArc", int.class, diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java index f0ae44841..4ff652597 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java @@ -370,6 +370,7 @@ void list() { testColor( c, ui, "selectionForeground", 0x123456 ); testColor( c, ui, "selectionInactiveBackground", 0x123456 ); testColor( c, ui, "selectionInactiveForeground", 0x123456 ); + testColor( c, ui, "alternateRowColor", 0x123456 ); testInsets( c, ui, "selectionInsets", 1,2,3,4 ); testInteger( c, ui, "selectionArc", 123 ); diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java index d20e49fb0..d82714419 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java @@ -433,6 +433,7 @@ void list() { ui.applyStyle( "selectionForeground: #fff" ); ui.applyStyle( "selectionInactiveBackground: #fff" ); ui.applyStyle( "selectionInactiveForeground: #fff" ); + ui.applyStyle( "alternateRowColor: #fff" ); ui.applyStyle( "selectionInsets: 1,2,3,4" ); ui.applyStyle( "selectionArc: 8" ); diff --git a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt index 7f3ec73a4..3d7bd7d1f 100644 --- a/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt +++ b/flatlaf-theme-editor/src/main/resources/com/formdev/flatlaf/themeeditor/FlatLafUIKeys.txt @@ -443,6 +443,7 @@ List.cellNoFocusBorder List.cellRenderer List.dropCellBackground List.dropCellForeground +List.alternateRowColor List.dropLineColor List.focusCellHighlightBorder List.focusInputMap From 19055d5a187313a4d96ab3bb572900e3dbb1f991 Mon Sep 17 00:00:00 2001 From: Dar Date: Tue, 3 Dec 2024 17:08:04 +0100 Subject: [PATCH 3/6] mod: combobox does not support alternate row color --- .../com/formdev/flatlaf/ui/FlatListUI.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java index c1fa40bce..01a9896f1 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java @@ -28,6 +28,7 @@ import java.awt.event.FocusListener; import java.beans.PropertyChangeListener; import java.util.Map; +import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultListCellRenderer; import javax.swing.JComponent; import javax.swing.JList; @@ -308,16 +309,7 @@ protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRend Component rendererComponent = cellRenderer.getListCellRendererComponent( list, dataModel.getElementAt( row ), row, isSelected, FlatUIUtils.isPermanentFocusOwner( list ) && (row == leadIndex) ); - - if( alternateRowColor != null && row % 2 != 0 ) { - g.setColor( alternateRowColor ); - - // paint respecting selection arc - final float arc = UIScale.scale( selectionArc / 2f ); - FlatUIUtils.paintSelection( (Graphics2D) g, 0, rowBounds.y, list.getWidth(), rowBounds.height, - UIScale.scale( selectionInsets ), arc, arc, arc, arc, 0 ); - } - + // boolean isFileList = Boolean.TRUE.equals( list.getClientProperty( "List.isFileList" ) ); int cx, cw; @@ -331,6 +323,18 @@ protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRend cx = rowBounds.x; cw = rowBounds.width; } + + // filelist/combobox does not support alternate row color + if( !isFileList && !(dataModel instanceof DefaultComboBoxModel) ) { + if( alternateRowColor != null && row % 2 != 0 ) { + g.setColor( alternateRowColor ); + + // paint respecting selection arc + final float arc = UIScale.scale( selectionArc / 2f ); + FlatUIUtils.paintSelection( (Graphics2D) g, 0, rowBounds.y, list.getWidth(), rowBounds.height, + UIScale.scale( selectionInsets ), arc, arc, arc, arc, 0 ); + } + } // rounded selection or selection insets if( isSelected && From 6404b8de2ac8f4d60a71c085cb8c8be8a16c6bb3 Mon Sep 17 00:00:00 2001 From: Dar Date: Mon, 16 Dec 2024 15:48:54 +0100 Subject: [PATCH 4/6] fix: filter combobox by name --- .../src/main/java/com/formdev/flatlaf/ui/FlatListUI.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java index 01a9896f1..2fe2bab4d 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java @@ -324,8 +324,8 @@ protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRend cw = rowBounds.width; } - // filelist/combobox does not support alternate row color - if( !isFileList && !(dataModel instanceof DefaultComboBoxModel) ) { + // combobox does not support alternate row color + if ( !"ComboBox.list".equals( list.getName() ) ) { if( alternateRowColor != null && row % 2 != 0 ) { g.setColor( alternateRowColor ); From abf77d5399012c6dd4bdbf979e6e211522d4c92e Mon Sep 17 00:00:00 2001 From: Dar Date: Mon, 16 Dec 2024 15:55:15 +0100 Subject: [PATCH 5/6] mod: code format --- .../src/main/java/com/formdev/flatlaf/ui/FlatListUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java index 2fe2bab4d..1514a37a7 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java @@ -325,7 +325,7 @@ protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRend } // combobox does not support alternate row color - if ( !"ComboBox.list".equals( list.getName() ) ) { + if( !"ComboBox.list".equals( list.getName() ) ) { if( alternateRowColor != null && row % 2 != 0 ) { g.setColor( alternateRowColor ); From 80ba75fdeb42e108e532dcee83dd028c25ef7b9d Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Wed, 18 Dec 2024 12:22:04 +0100 Subject: [PATCH 6/6] List: - fixed wrong x/width bounds of alternating rows for multi-column lists (PR #939) - Demo: added "alternating rows" checkboxes to "Data Components" page --- CHANGELOG.md | 3 +- .../com/formdev/flatlaf/ui/FlatListUI.java | 25 ++--- .../flatlaf/demo/DataComponentsPanel.java | 105 ++++++++++++++++-- .../flatlaf/demo/DataComponentsPanel.jfd | 51 ++++++++- .../flatlaf/testing/FlatComponents2Test.java | 33 +++++- .../flatlaf/testing/FlatComponents2Test.jfd | 28 ++++- 6 files changed, 214 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27a602baa..e24a63988 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ FlatLaf Change Log - CheckBox: Support styling indeterminate state of [tri-state check boxes](https://www.javadoc.io/doc/com.formdev/flatlaf-extras/latest/com/formdev/flatlaf/extras/components/FlatTriStateCheckBox.html). - (issue #919) + (PR #936; issue #919) +- List: Support for alternate row highlighting. (PR #939) - Tree: Support for alternate row highlighting. (PR #903) - Tree: Support wide cell renderer. (issue #922) - Extras: `FlatSVGIcon` color filters now can access painting component to diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java index 13f3b9155..59e814e6c 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatListUI.java @@ -303,13 +303,24 @@ protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRend { boolean isSelected = selModel.isSelectedIndex( row ); + // paint alternating rows + if( alternateRowColor != null && row % 2 != 0 && + !"ComboBox.list".equals( list.getName() ) ) // combobox does not support alternate row color + { + g.setColor( alternateRowColor ); + + float arc = UIScale.scale( selectionArc / 2f ); + FlatUIUtils.paintSelection( (Graphics2D) g, rowBounds.x, rowBounds.y, rowBounds.width, rowBounds.height, + UIScale.scale( selectionInsets ), arc, arc, arc, arc, 0 ); + } + // get renderer component @SuppressWarnings( "unchecked" ) Component rendererComponent = cellRenderer.getListCellRendererComponent( list, dataModel.getElementAt( row ), row, isSelected, FlatUIUtils.isPermanentFocusOwner( list ) && (row == leadIndex) ); - // + // use smaller cell width if list is used in JFileChooser boolean isFileList = Boolean.TRUE.equals( list.getClientProperty( "List.isFileList" ) ); int cx, cw; if( isFileList ) { @@ -323,18 +334,6 @@ protected void paintCell( Graphics g, int row, Rectangle rowBounds, ListCellRend cw = rowBounds.width; } - // combobox does not support alternate row color - if( !"ComboBox.list".equals( list.getName() ) ) { - if( alternateRowColor != null && row % 2 != 0 ) { - g.setColor( alternateRowColor ); - - // paint respecting selection arc - float arc = UIScale.scale( selectionArc / 2f ); - FlatUIUtils.paintSelection( (Graphics2D) g, 0, rowBounds.y, list.getWidth(), rowBounds.height, - UIScale.scale( selectionInsets ), arc, arc, arc, arc, 0 ); - } - } - // rounded selection or selection insets if( isSelected && !isFileList && // rounded selection is not supported for file list diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.java b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.java index e936658b1..25aeb28b8 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.java +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.java @@ -22,6 +22,7 @@ import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; import javax.swing.*; +import javax.swing.UIDefaults.ActiveValue; import javax.swing.table.*; import javax.swing.tree.*; import com.formdev.flatlaf.FlatClientProperties; @@ -65,6 +66,45 @@ class DataComponentsPanel tree3.putClientProperty( FlatClientProperties.STYLE, "selectionInsets: 0,1,0,1; selectionArc: 6" ); } + private void listAlternatingRowsChanged() { + ActiveValue alternateRowColor = null; + if( listAlternatingRowsCheckBox.isSelected() ) { + alternateRowColor = table -> { + Color background = list1.getBackground(); + return FlatLaf.isLafDark() + ? ColorFunctions.lighten( background, 0.05f ) + : ColorFunctions.darken( background, 0.05f ); + }; + } + UIManager.put( "List.alternateRowColor", alternateRowColor ); + list1.updateUI(); + list2.updateUI(); + list3.updateUI(); + } + + private void treeWideSelectionChanged() { + boolean wideSelection = treeWideSelectionCheckBox.isSelected(); + tree1.putClientProperty( FlatClientProperties.TREE_WIDE_SELECTION, wideSelection ); + tree2.putClientProperty( FlatClientProperties.TREE_WIDE_SELECTION, wideSelection ); + tree3.putClientProperty( FlatClientProperties.TREE_WIDE_SELECTION, wideSelection ); + } + + private void treeAlternatingRowsChanged() { + ActiveValue alternateRowColor = null; + if( treeAlternatingRowsCheckBox.isSelected() ) { + alternateRowColor = table -> { + Color background = tree1.getBackground(); + return FlatLaf.isLafDark() + ? ColorFunctions.lighten( background, 0.05f ) + : ColorFunctions.darken( background, 0.05f ); + }; + } + UIManager.put( "Tree.alternateRowColor", alternateRowColor ); + tree1.updateUI(); + tree2.updateUI(); + tree3.updateUI(); + } + private void dndChanged() { boolean dnd = dndCheckBox.isSelected(); DropMode dropMode = dnd ? DropMode.ON_OR_INSERT : DropMode.USE_SELECTION; @@ -142,18 +182,20 @@ private void roundedSelectionChanged() { } private void alternatingRowsChanged() { - Color alternateRowColor = null; + ActiveValue alternateRowColor = null; if( alternatingRowsCheckBox.isSelected() ) { - Color background = table1.getBackground(); - alternateRowColor = FlatLaf.isLafDark() - ? ColorFunctions.lighten( background, 0.05f ) - : ColorFunctions.darken( background, 0.05f ); + alternateRowColor = table -> { + Color background = table1.getBackground(); + return FlatLaf.isLafDark() + ? ColorFunctions.lighten( background, 0.05f ) + : ColorFunctions.darken( background, 0.05f ); + }; } UIManager.put( "Table.alternateRowColor", alternateRowColor ); table1.repaint(); } - @SuppressWarnings( { "unchecked", "rawtypes" } ) + @SuppressWarnings( { "rawtypes" } ) private void initComponents() { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents JLabel label1 = new JLabel(); @@ -166,6 +208,8 @@ private void initComponents() { list3 = new JList<>(); JScrollPane scrollPane2 = new JScrollPane(); list2 = new JList<>(); + JPanel listOptionsPanel = new JPanel(); + listAlternatingRowsCheckBox = new JCheckBox(); JLabel treeLabel = new JLabel(); JScrollPane scrollPane3 = new JScrollPane(); tree1 = new JTree(); @@ -173,6 +217,9 @@ private void initComponents() { tree3 = new JTree(); JScrollPane scrollPane4 = new JScrollPane(); tree2 = new JTree(); + JPanel treeOptionsPanel = new JPanel(); + treeWideSelectionCheckBox = new JCheckBox(); + treeAlternatingRowsCheckBox = new JCheckBox(); JLabel tableLabel = new JLabel(); JScrollPane scrollPane5 = new JScrollPane(); table1 = new JTable(); @@ -273,6 +320,22 @@ private void initComponents() { } add(scrollPane2, "cell 3 1"); + //======== listOptionsPanel ======== + { + listOptionsPanel.setLayout(new MigLayout( + "insets 0,hidemode 3", + // columns + "[fill]", + // rows + "[]")); + + //---- listAlternatingRowsCheckBox ---- + listAlternatingRowsCheckBox.setText("alternating rows"); + listAlternatingRowsCheckBox.addActionListener(e -> listAlternatingRowsChanged()); + listOptionsPanel.add(listAlternatingRowsCheckBox, "cell 0 0"); + } + add(listOptionsPanel, "cell 4 1"); + //---- treeLabel ---- treeLabel.setText("JTree:"); add(treeLabel, "cell 0 2,aligny top,growy 0"); @@ -334,6 +397,29 @@ private void initComponents() { } add(scrollPane4, "cell 3 2"); + //======== treeOptionsPanel ======== + { + treeOptionsPanel.setLayout(new MigLayout( + "insets 0,hidemode 3", + // columns + "[fill]", + // rows + "[]0" + + "[]")); + + //---- treeWideSelectionCheckBox ---- + treeWideSelectionCheckBox.setText("wide selection"); + treeWideSelectionCheckBox.setSelected(true); + treeWideSelectionCheckBox.addActionListener(e -> treeWideSelectionChanged()); + treeOptionsPanel.add(treeWideSelectionCheckBox, "cell 0 0"); + + //---- treeAlternatingRowsCheckBox ---- + treeAlternatingRowsCheckBox.setText("alternating rows"); + treeAlternatingRowsCheckBox.addActionListener(e -> treeAlternatingRowsChanged()); + treeOptionsPanel.add(treeAlternatingRowsCheckBox, "cell 0 1"); + } + add(treeOptionsPanel, "cell 4 2"); + //---- tableLabel ---- tableLabel.setText("JTable:"); add(tableLabel, "cell 0 3,aligny top,growy 0"); @@ -379,7 +465,7 @@ public boolean isCellEditable(int rowIndex, int columnIndex) { { TableColumnModel cm = table1.getColumnModel(); cm.getColumn(2).setCellEditor(new DefaultCellEditor( - new JComboBox(new DefaultComboBoxModel(new String[] { + new JComboBox<>(new DefaultComboBoxModel<>(new String[] { "January", "February", "March", @@ -394,7 +480,7 @@ public boolean isCellEditable(int rowIndex, int columnIndex) { "December" })))); cm.getColumn(3).setCellEditor(new DefaultCellEditor( - new JComboBox(new DefaultComboBoxModel(new String[] { + new JComboBox<>(new DefaultComboBoxModel<>(new String[] { "January", "February", "March", @@ -513,9 +599,12 @@ public boolean isCellEditable(int rowIndex, int columnIndex) { private JList list1; private JList list3; private JList list2; + private JCheckBox listAlternatingRowsCheckBox; private JTree tree1; private JTree tree3; private JTree tree2; + private JCheckBox treeWideSelectionCheckBox; + private JCheckBox treeAlternatingRowsCheckBox; private JTable table1; private JCheckBox roundedSelectionCheckBox; private JCheckBox showHorizontalLinesCheckBox; diff --git a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.jfd b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.jfd index 0f729bb18..c51f3cfbf 100644 --- a/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.jfd +++ b/flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DataComponentsPanel.jfd @@ -1,4 +1,4 @@ -JFDML JFormDesigner: "8.2.0.0.331" Java: "21" encoding: "UTF-8" +JFDML JFormDesigner: "8.3" encoding: "UTF-8" new FormModel { contentType: "form/swing" @@ -92,6 +92,25 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 3 1" } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$layoutConstraints": "insets 0,hidemode 3" + "$columnConstraints": "[fill]" + "$rowConstraints": "[]" + } ) { + name: "listOptionsPanel" + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "listAlternatingRowsCheckBox" + "text": "alternating rows" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "listAlternatingRowsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 4 1" + } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "treeLabel" "text": "JTree:" @@ -192,6 +211,36 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 3 2" } ) + add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { + "$layoutConstraints": "insets 0,hidemode 3" + "$columnConstraints": "[fill]" + "$rowConstraints": "[]0[]" + } ) { + name: "treeOptionsPanel" + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "treeWideSelectionCheckBox" + "text": "wide selection" + "selected": true + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "treeWideSelectionChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 0" + } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "treeAlternatingRowsCheckBox" + "text": "alternating rows" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "treeAlternatingRowsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 1" + } ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 4 2" + } ) add( new FormComponent( "javax.swing.JLabel" ) { name: "tableLabel" "text": "JTable:" diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.java index f8fcade99..e5a2502f0 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.java @@ -494,6 +494,11 @@ private void listVisibleRowCountChanged() { list.setVisibleRowCount( visibleRowCount ); } + private void listAlternatingRowsChanged() { + UIManager.put( "List.alternateRowColor", listAlternatingRowsCheckBox.isSelected() ? Color.YELLOW : null ); + FlatLaf.updateUILater(); + } + private void treeRendererChanged() { Object sel = treeRendererComboBox.getSelectedItem(); if( !(sel instanceof String) ) @@ -530,6 +535,11 @@ private void treeWideCellRendererChanged() { tree.putClientProperty( FlatClientProperties.TREE_WIDE_CELL_RENDERER, wideCellRenderer ); } + private void treeAlternatingRowsChanged() { + UIManager.put( "Tree.alternateRowColor", treeAlternatingRowsCheckBox.isSelected() ? Color.cyan : null ); + FlatLaf.updateUILater(); + } + private void treePaintSelectionChanged() { boolean paintSelection = treePaintSelectionCheckBox.isSelected(); for( JTree tree : allTrees ) @@ -670,12 +680,14 @@ private void initComponents() { listLayoutOrientationField = new JComboBox<>(); JLabel listVisibleRowCountLabel = new JLabel(); listVisibleRowCountSpinner = new JSpinner(); + listAlternatingRowsCheckBox = new JCheckBox(); treeOptionsPanel = new JPanel(); JLabel treeRendererLabel = new JLabel(); treeRendererComboBox = new JComboBox<>(); treeWideSelectionCheckBox = new JCheckBox(); treeWideCellRendererCheckBox = new JCheckBox(); treePaintSelectionCheckBox = new JCheckBox(); + treeAlternatingRowsCheckBox = new JCheckBox(); treePaintLinesCheckBox = new JCheckBox(); treeRedLinesCheckBox = new JCheckBox(); treeEditableCheckBox = new JCheckBox(); @@ -737,7 +749,7 @@ private void initComponents() { // rows "[]" + "[grow]" + - "[]" + + "[]0" + "[]")); //---- listLabel ---- @@ -780,7 +792,7 @@ private void initComponents() { // rows "[]" + "[grow]" + - "[]" + + "[]0" + "[]")); //---- tableLabel ---- @@ -817,7 +829,7 @@ private void initComponents() { // rows "[]" + "[grow]" + - "[]" + + "[]0" + "[]")); //---- treeLabel ---- @@ -1006,6 +1018,7 @@ public void mouseClicked(MouseEvent e) { // rows "[]" + "[]" + + "[]" + "[]")); //---- listRendererLabel ---- @@ -1043,6 +1056,11 @@ public void mouseClicked(MouseEvent e) { listVisibleRowCountSpinner.setModel(new SpinnerNumberModel(8, 0, null, 1)); listVisibleRowCountSpinner.addChangeListener(e -> listVisibleRowCountChanged()); listOptionsPanel.add(listVisibleRowCountSpinner, "cell 1 2"); + + //---- listAlternatingRowsCheckBox ---- + listAlternatingRowsCheckBox.setText("alternating rows"); + listAlternatingRowsCheckBox.addActionListener(e -> listAlternatingRowsChanged()); + listOptionsPanel.add(listAlternatingRowsCheckBox, "cell 0 3 2 1,alignx left,growx 0"); } add(listOptionsPanel, "cell 0 4 4 1"); @@ -1096,6 +1114,11 @@ public void mouseClicked(MouseEvent e) { treePaintSelectionCheckBox.addActionListener(e -> treePaintSelectionChanged()); treeOptionsPanel.add(treePaintSelectionCheckBox, "cell 0 2"); + //---- treeAlternatingRowsCheckBox ---- + treeAlternatingRowsCheckBox.setText("alternating rows"); + treeAlternatingRowsCheckBox.addActionListener(e -> treeAlternatingRowsChanged()); + treeOptionsPanel.add(treeAlternatingRowsCheckBox, "cell 0 2"); + //---- treePaintLinesCheckBox ---- treePaintLinesCheckBox.setText("paint lines"); treePaintLinesCheckBox.addActionListener(e -> treePaintLinesChanged()); @@ -1253,11 +1276,13 @@ public void mouseClicked(MouseEvent e) { private JComboBox listRendererComboBox; private JComboBox listLayoutOrientationField; private JSpinner listVisibleRowCountSpinner; + private JCheckBox listAlternatingRowsCheckBox; private JPanel treeOptionsPanel; private JComboBox treeRendererComboBox; private JCheckBox treeWideSelectionCheckBox; private JCheckBox treeWideCellRendererCheckBox; private JCheckBox treePaintSelectionCheckBox; + private JCheckBox treeAlternatingRowsCheckBox; private JCheckBox treePaintLinesCheckBox; private JCheckBox treeRedLinesCheckBox; private JCheckBox treeEditableCheckBox; @@ -1363,7 +1388,7 @@ public int getSize() { @Override public String getElementAt( int index ) { return (index < 20) - ? "item " + (index + 1) + ? "item " + (index + 1) + ((index + 1) % 5 == 0 ? " ####" : "") : "item " + (index + 1) + " " + randomRowString( index ); } } diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.jfd index e1372a999..d8fd15a5f 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatComponents2Test.jfd @@ -33,7 +33,7 @@ new FormModel { } ) add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$columnConstraints": "[fill]" - "$rowConstraints": "[][grow][][]" + "$rowConstraints": "[][grow][]0[]" "$layoutConstraints": "ltr,insets 0,hidemode 3" } ) { name: "panel1" @@ -95,7 +95,7 @@ new FormModel { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "insets 0,hidemode 3" "$columnConstraints": "[fill]" - "$rowConstraints": "[][grow][][]" + "$rowConstraints": "[][grow][]0[]" } ) { name: "panel3" "$client.FlatLaf.internal.testing.ignore": true @@ -146,7 +146,7 @@ new FormModel { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "insets 0,hidemode 3" "$columnConstraints": "[fill]" - "$rowConstraints": "[][grow][][]" + "$rowConstraints": "[][grow][]0[]" } ) { name: "panel2" "$client.FlatLaf.internal.testing.ignore": true @@ -385,7 +385,7 @@ new FormModel { add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) { "$layoutConstraints": "insets 8,hidemode 3" "$columnConstraints": "[fill][fill]" - "$rowConstraints": "[][][]" + "$rowConstraints": "[][][][]" } ) { name: "listOptionsPanel" "border": new javax.swing.border.TitledBorder( "JList Control" ) @@ -455,6 +455,16 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 1 2" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "listAlternatingRowsCheckBox" + "text": "alternating rows" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "listAlternatingRowsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 3 2 1,alignx left,growx 0" + } ) }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 4 4 1" } ) @@ -527,6 +537,16 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 2" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "treeAlternatingRowsCheckBox" + "text": "alternating rows" + auxiliary() { + "JavaCodeGenerator.variableLocal": false + } + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "treeAlternatingRowsChanged", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 2" + } ) add( new FormComponent( "javax.swing.JCheckBox" ) { name: "treePaintLinesCheckBox" "text": "paint lines"