Skip to content

Commit 8bafa37

Browse files
committed
Merge PR #1060: Styling of wrong icon in FlatRadioButtonUI
2 parents 02636b2 + 04602ac commit 8bafa37

File tree

5 files changed

+126
-15
lines changed

5 files changed

+126
-15
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ FlatLaf Change Log
1111

1212
#### Fixed bugs
1313

14+
- CheckBox and RadioButton: Fixed styling of custom icon. Also fixed focus width
15+
(and preferred size) if using custom icon. (PR #1060)
1416
- TextField: Fixed wrong leading/trailing icon placement if border is set to
1517
`null`. (issue #1047)
1618
- Extras: UI defaults inspector: Exclude inspector window from being blocked by

flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatRadioButtonUI.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,12 @@ protected void applyStyle( AbstractButton b, Object style ) {
203203
protected Object applyStyleProperty( AbstractButton b, String key, Object value ) {
204204
// style icon
205205
if( key.startsWith( "icon." ) ) {
206+
Icon icon = getRealIcon( b );
206207
if( !(icon instanceof FlatCheckBoxIcon) )
207208
return new UnknownStyleException( key );
208209

209-
if( iconShared ) {
210-
icon = FlatStylingSupport.cloneIcon( icon );
210+
if( icon == this.icon && iconShared ) {
211+
this.icon = icon = FlatStylingSupport.cloneIcon( icon );
211212
iconShared = false;
212213
}
213214

@@ -225,6 +226,7 @@ protected Object applyStyleProperty( AbstractButton b, String key, Object value
225226
@Override
226227
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
227228
Map<String, Class<?>> infos = FlatStylingSupport.getAnnotatedStyleableInfos( this );
229+
Icon icon = getRealIcon( c );
228230
if( icon instanceof FlatCheckBoxIcon ) {
229231
for( Map.Entry<String, Class<?>> e : ((FlatCheckBoxIcon)icon).getStyleableInfos().entrySet() )
230232
infos.put( "icon.".concat( e.getKey() ), e.getValue() );
@@ -237,6 +239,7 @@ public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
237239
public Object getStyleableValue( JComponent c, String key ) {
238240
// style icon
239241
if( key.startsWith( "icon." ) ) {
242+
Icon icon = getRealIcon( c );
240243
return (icon instanceof FlatCheckBoxIcon)
241244
? ((FlatCheckBoxIcon)icon).getStyleableValue( key.substring( "icon.".length() ) )
242245
: null;
@@ -332,16 +335,18 @@ private Color getDefaultBackground( JComponent c ) {
332335
}
333336

334337
private int getIconFocusWidth( JComponent c ) {
335-
AbstractButton b = (AbstractButton) c;
336-
Icon icon = b.getIcon();
337-
if( icon == null )
338-
icon = getDefaultIcon();
339-
338+
Icon icon = getRealIcon( c );
340339
return (icon instanceof FlatCheckBoxIcon)
341340
? Math.round( UIScale.scale( ((FlatCheckBoxIcon)icon).getFocusWidth() ) )
342341
: 0;
343342
}
344343

344+
private Icon getRealIcon( JComponent c ) {
345+
AbstractButton b = (AbstractButton) c;
346+
Icon icon = b.getIcon();
347+
return (icon != null) ? icon : getDefaultIcon();
348+
}
349+
345350
@Override
346351
public int getBaseline( JComponent c, int width, int height ) {
347352
return FlatButtonUI.getBaselineImpl( c, width, height );

flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
import org.junit.jupiter.api.BeforeAll;
3131
import org.junit.jupiter.api.Test;
3232
import com.formdev.flatlaf.icons.*;
33+
import com.formdev.flatlaf.ui.TestFlatStyling.CustomCheckBoxIcon;
34+
import com.formdev.flatlaf.ui.TestFlatStyling.CustomIcon;
35+
import com.formdev.flatlaf.ui.TestFlatStyling.CustomRadioButtonIcon;
3336

3437
/**
3538
* @author Karl Tauber
@@ -144,7 +147,12 @@ private void button( Map<String, Class<?>> expected ) {
144147

145148
@Test
146149
void checkBox() {
147-
JCheckBox c = new JCheckBox();
150+
checkBox( new JCheckBox() );
151+
checkBox( new JCheckBox( new CustomIcon() ) );
152+
checkBox( new JCheckBox( new CustomCheckBoxIcon() ) );
153+
}
154+
155+
private void checkBox( JCheckBox c ) {
148156
FlatCheckBoxUI ui = (FlatCheckBoxUI) c.getUI();
149157

150158
assertTrue( ui.getDefaultIcon() instanceof FlatCheckBoxIcon );
@@ -153,6 +161,11 @@ void checkBox() {
153161
Map<String, Class<?>> expected = new LinkedHashMap<>();
154162
radioButton( expected );
155163

164+
// remove "icon." keys if check box has custom icon
165+
Icon icon = c.getIcon();
166+
if( icon != null && !(icon instanceof FlatCheckBoxIcon) )
167+
expected.keySet().removeIf( key -> key.startsWith( "icon." ) );
168+
156169
assertMapEquals( expected, ui.getStyleableInfos( c ) );
157170
}
158171

@@ -492,7 +505,12 @@ void progressBar() {
492505

493506
@Test
494507
void radioButton() {
495-
JRadioButton c = new JRadioButton();
508+
radioButton( new JRadioButton() );
509+
radioButton( new JRadioButton( new CustomIcon() ) );
510+
radioButton( new JRadioButton( new CustomRadioButtonIcon() ) );
511+
}
512+
513+
private void radioButton( JRadioButton c ) {
496514
FlatRadioButtonUI ui = (FlatRadioButtonUI) c.getUI();
497515

498516
assertTrue( ui.getDefaultIcon() instanceof FlatRadioButtonIcon );
@@ -504,6 +522,11 @@ void radioButton() {
504522
"icon.centerDiameter", float.class
505523
);
506524

525+
// remove "icon." keys if radio button has custom icon
526+
Icon icon = c.getIcon();
527+
if( icon != null && !(icon instanceof FlatRadioButtonIcon) )
528+
expected.keySet().removeIf( key -> key.startsWith( "icon." ) );
529+
507530
assertMapEquals( expected, ui.getStyleableInfos( c ) );
508531
}
509532

flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableValue.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@
7777
import com.formdev.flatlaf.icons.FlatSearchIcon;
7878
import com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon;
7979
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
80+
import com.formdev.flatlaf.ui.TestFlatStyling.CustomCheckBoxIcon;
81+
import com.formdev.flatlaf.ui.TestFlatStyling.CustomIcon;
82+
import com.formdev.flatlaf.ui.TestFlatStyling.CustomRadioButtonIcon;
8083

8184
/**
8285
* @author Karl Tauber
@@ -269,11 +272,20 @@ private void button( AbstractButton c, FlatButtonUI ui ) {
269272

270273
@Test
271274
void checkBox() {
272-
JCheckBox c = new JCheckBox();
275+
checkBox( new JCheckBox() );
276+
checkBox( new JCheckBox( new CustomCheckBoxIcon() ) );
277+
checkBox( new JCheckBox( new CustomIcon() ) );
278+
}
279+
280+
private void checkBox( JCheckBox c ) {
273281
FlatCheckBoxUI ui = (FlatCheckBoxUI) c.getUI();
274282

275283
// FlatCheckBoxUI extends FlatRadioButtonUI
276284
radioButton( ui, c );
285+
286+
// necessary to clear FlatRadioButtonUI.oldStyleValues because
287+
// ui.applyStyle(...) operates on shared instance
288+
ui.uninstallUI( c );
277289
}
278290

279291
@Test
@@ -536,21 +548,36 @@ void progressBar() {
536548

537549
@Test
538550
void radioButton() {
539-
JRadioButton c = new JRadioButton();
551+
radioButton( new JRadioButton() );
552+
radioButton( new JRadioButton( new CustomRadioButtonIcon() ) );
553+
radioButton( new JRadioButton( new CustomIcon() ) );
554+
}
555+
556+
private void radioButton( JRadioButton c ) {
540557
FlatRadioButtonUI ui = (FlatRadioButtonUI) c.getUI();
541558

542559
assertTrue( ui.getDefaultIcon() instanceof FlatRadioButtonIcon );
543560

544561
radioButton( ui, c );
545562

546-
testFloat( c, ui, "icon.centerDiameter", 1.23f );
563+
if( !(c.getIcon() instanceof CustomIcon) )
564+
testFloat( c, ui, "icon.centerDiameter", 1.23f );
565+
566+
// necessary to clear FlatRadioButtonUI.oldStyleValues because
567+
// ui.applyStyle(...) operates on shared instance
568+
ui.uninstallUI( c );
547569
}
548570

549571
private void radioButton( FlatRadioButtonUI ui, AbstractButton b ) {
550572
testColor( b, ui, "disabledText", 0x123456 );
551573

552574
//---- icon ----
553575

576+
if( b.getIcon() instanceof CustomIcon ) {
577+
assertEquals( null, ui.getStyleableValue( b, "icon.focusWidth" ) );
578+
return;
579+
}
580+
554581
testFloat( b, ui, "icon.focusWidth", 1.23f );
555582
testColor( b, ui, "icon.focusColor", 0x123456 );
556583
testFloat( b, ui, "icon.borderWidth", 1.23f );

flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
import static org.junit.jupiter.api.Assertions.assertEquals;
2020
import static org.junit.jupiter.api.Assertions.assertTrue;
2121
import java.awt.Color;
22+
import java.awt.Component;
2223
import java.awt.Dimension;
24+
import java.awt.Graphics;
2325
import java.awt.Insets;
2426
import java.util.HashMap;
2527
import java.util.Map;
@@ -294,13 +296,22 @@ private void button( AbstractButton b, FlatButtonUI ui ) {
294296

295297
@Test
296298
void checkBox() {
297-
JCheckBox c = new JCheckBox();
299+
checkBox( new JCheckBox() );
300+
checkBox( new JCheckBox( new CustomIcon() ) );
301+
checkBox( new JCheckBox( new CustomCheckBoxIcon() ) );
302+
}
303+
304+
private void checkBox( JCheckBox c ) {
298305
FlatCheckBoxUI ui = (FlatCheckBoxUI) c.getUI();
299306

300307
assertTrue( ui.getDefaultIcon() instanceof FlatCheckBoxIcon );
301308

302309
// FlatCheckBoxUI extends FlatRadioButtonUI
303310
radioButton( ui, c );
311+
312+
// necessary to clear FlatRadioButtonUI.oldStyleValues because
313+
// ui.applyStyle(...) operates on shared instance
314+
ui.uninstallUI( c );
304315
}
305316

306317
@Test
@@ -651,14 +662,24 @@ void progressBar() {
651662

652663
@Test
653664
void radioButton() {
654-
JRadioButton c = new JRadioButton();
665+
radioButton( new JRadioButton() );
666+
radioButton( new JRadioButton( new CustomIcon() ) );
667+
radioButton( new JRadioButton( new CustomRadioButtonIcon() ) );
668+
}
669+
670+
private void radioButton( JRadioButton c ) {
655671
FlatRadioButtonUI ui = (FlatRadioButtonUI) c.getUI();
656672

657673
assertTrue( ui.getDefaultIcon() instanceof FlatRadioButtonIcon );
658674

659675
radioButton( ui, c );
660676

661-
ui.applyStyle( c, "icon.centerDiameter: 8" );
677+
if( !(c.getIcon() instanceof CustomIcon) )
678+
ui.applyStyle( c, "icon.centerDiameter: 8" );
679+
680+
// necessary to clear FlatRadioButtonUI.oldStyleValues because
681+
// ui.applyStyle(...) operates on shared instance
682+
ui.uninstallUI( c );
662683
}
663684

664685
private void radioButton( FlatRadioButtonUI ui, AbstractButton b ) {
@@ -676,6 +697,9 @@ private void radioButton( FlatRadioButtonUI ui, AbstractButton b ) {
676697

677698
//---- icon ----
678699

700+
if( b.getIcon() instanceof CustomIcon )
701+
return;
702+
679703
ui.applyStyle( b, "icon.focusWidth: 1.5" );
680704
ui.applyStyle( b, "icon.focusColor: #fff" );
681705
ui.applyStyle( b, "icon.borderWidth: 1.5" );
@@ -1565,4 +1589,34 @@ void enumUIDefaults() {
15651589
UIManager.put( "test.enum", null );
15661590
assertEquals( SomeEnum.enumValue1, FlatUIUtils.getUIEnum( "test.enum", SomeEnum.class, SomeEnum.enumValue1 ) );
15671591
}
1592+
1593+
//---- class CustomIcon ---------------------------------------------------
1594+
1595+
static class CustomIcon
1596+
implements Icon
1597+
{
1598+
@Override public void paintIcon( Component c, Graphics g, int x, int y ) {}
1599+
@Override public int getIconWidth() { return 1; }
1600+
@Override public int getIconHeight() { return 1; }
1601+
}
1602+
1603+
//---- class CustomCheckBoxIcon ----------------------------------------
1604+
1605+
static class CustomCheckBoxIcon
1606+
extends FlatCheckBoxIcon
1607+
{
1608+
CustomCheckBoxIcon() {
1609+
background = Color.green;
1610+
}
1611+
}
1612+
1613+
//---- class CustomRadioButtonIcon ----------------------------------------
1614+
1615+
static class CustomRadioButtonIcon
1616+
extends FlatRadioButtonIcon
1617+
{
1618+
CustomRadioButtonIcon() {
1619+
background = Color.green;
1620+
}
1621+
}
15681622
}

0 commit comments

Comments
 (0)