Skip to content

Commit

Permalink
CheckBox: support styling indeterminate state of tri-state check boxe…
Browse files Browse the repository at this point in the history
…s (issue #919)
  • Loading branch information
DevCharly committed Dec 11, 2024
1 parent 7bdfd49 commit b9c68fb
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 52 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,8 @@ private void radioButton( Map<String, Class<?>> 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
Expand All @@ -525,34 +527,49 @@ private void radioButton( Map<String, Class<?>> 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,
"icon.disabledBackground", Color.class,
"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,
"icon.focusedBackground", Color.class,
"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,
"icon.hoverBackground", Color.class,
"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
);
}

Expand Down Expand Up @@ -1146,6 +1163,8 @@ private void flatCheckBoxIcon( Map<String, Class<?>> expected ) {
"borderWidth", float.class,
"selectedBorderWidth", float.class,
"disabledSelectedBorderWidth", float.class,
"indeterminateBorderWidth", float.class,
"disabledIndeterminateBorderWidth", float.class,
"arc", int.class,

// enabled
Expand All @@ -1154,34 +1173,49 @@ private void flatCheckBoxIcon( Map<String, Class<?>> expected ) {
"selectedBorderColor", Color.class,
"selectedBackground", Color.class,
"checkmarkColor", Color.class,
"indeterminateBorderColor", Color.class,
"indeterminateBackground", Color.class,
"indeterminateCheckmarkColor", Color.class,

// disabled
"disabledBorderColor", Color.class,
"disabledBackground", Color.class,
"disabledSelectedBorderColor", Color.class,
"disabledSelectedBackground", Color.class,
"disabledCheckmarkColor", Color.class,
"disabledIndeterminateBorderColor", Color.class,
"disabledIndeterminateBackground", Color.class,
"disabledIndeterminateCheckmarkColor", Color.class,

// focused
"focusedBorderColor", Color.class,
"focusedBackground", Color.class,
"focusedSelectedBorderColor", Color.class,
"focusedSelectedBackground", Color.class,
"focusedCheckmarkColor", Color.class,
"focusedIndeterminateBorderColor", Color.class,
"focusedIndeterminateBackground", Color.class,
"focusedIndeterminateCheckmarkColor", Color.class,

// hover
"hoverBorderColor", Color.class,
"hoverBackground", Color.class,
"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
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -1156,34 +1158,49 @@ 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 );
testValue( icon, "disabledBackground", Color.WHITE );
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 );
testValue( icon, "focusedBackground", Color.WHITE );
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 );
testValue( icon, "hoverBackground", Color.WHITE );
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 );
testValue( icon, "pressedBackground", Color.WHITE );
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -1398,34 +1400,49 @@ 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 );
icon.applyStyleProperty( "disabledBackground", Color.WHITE );
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 );
icon.applyStyleProperty( "focusedBackground", Color.WHITE );
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 );
icon.applyStyleProperty( "hoverBackground", Color.WHITE );
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 );
icon.applyStyleProperty( "pressedBackground", Color.WHITE );
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 ----

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ public boolean isPressed() {
}
@Override
public boolean isSelected() {
return isStateSelected();
return isStateSelected() || isStateIndeterminate();
}
} );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -130,23 +147,40 @@ 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
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
Expand Down

0 comments on commit b9c68fb

Please sign in to comment.