Styling: support CheckBox and RadioButton (without icons)

This commit is contained in:
Karl Tauber
2021-06-16 12:07:13 +02:00
parent c99be13697
commit db56486506
4 changed files with 116 additions and 7 deletions

View File

@@ -43,7 +43,16 @@ public class FlatCheckBoxUI
extends FlatRadioButtonUI
{
public static ComponentUI createUI( JComponent c ) {
return FlatUIUtils.createSharedUI( FlatCheckBoxUI.class, FlatCheckBoxUI::new );
return FlatUIUtils.canUseSharedUI( c )
? FlatUIUtils.createSharedUI( FlatCheckBoxUI.class, () -> new FlatCheckBoxUI( true ) )
: new FlatCheckBoxUI( false );
}
/**
* @since TODO
*/
protected FlatCheckBoxUI( boolean shared ) {
super( shared );
}
@Override

View File

@@ -23,6 +23,8 @@ import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.util.Map;
import java.util.Objects;
import javax.swing.AbstractButton;
import javax.swing.CellRendererPane;
@@ -30,7 +32,9 @@ import javax.swing.JComponent;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicButtonListener;
import javax.swing.plaf.basic.BasicRadioButtonUI;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
import com.formdev.flatlaf.util.UIScale;
@@ -62,10 +66,28 @@ public class FlatRadioButtonUI
private Color defaultBackground;
private final boolean shared;
private boolean defaults_initialized = false;
private Map<String, Object> oldStyleValues;
public static ComponentUI createUI( JComponent c ) {
return FlatUIUtils.createSharedUI( FlatRadioButtonUI.class, FlatRadioButtonUI::new );
return FlatUIUtils.canUseSharedUI( c )
? FlatUIUtils.createSharedUI( FlatRadioButtonUI.class, () -> new FlatRadioButtonUI( true ) )
: new FlatRadioButtonUI( false );
}
/**
* @since TODO
*/
protected FlatRadioButtonUI( boolean shared ) {
this.shared = shared;
}
@Override
public void installUI( JComponent c ) {
super.installUI( c );
applyStyle( FlatStyleSupport.getStyle( c ) );
}
@Override
@@ -97,6 +119,56 @@ public class FlatRadioButtonUI
defaults_initialized = false;
}
@Override
protected BasicButtonListener createButtonListener( AbstractButton b ) {
return new FlatRadioButtonListener( b );
}
/**
* @since TODO
*/
protected void propertyChange( AbstractButton b, PropertyChangeEvent e ) {
switch( e.getPropertyName() ) {
case FlatClientProperties.COMPONENT_STYLE:
applyStyle( b, this, e.getNewValue() );
break;
}
}
private static void applyStyle( AbstractButton b, FlatRadioButtonUI ui, Object style ) {
// unshare component UI if necessary
if( style != null && ui.shared ) {
b.updateUI();
ui = (FlatRadioButtonUI) b.getUI();
}
ui.applyStyle( style );
b.revalidate();
b.repaint();
}
/**
* @since TODO
*/
protected void applyStyle( Object style ) {
oldStyleValues = FlatStyleSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
}
/**
* @since TODO
*/
protected Object applyStyleProperty( String key, Object value ) {
Object oldValue;
switch( key ) {
case "disabledText": oldValue = disabledText; disabledText = (Color) value; break;
//TODO style icon
default: throw new IllegalArgumentException( "unknown style '" + key + "'" );
}
return oldValue;
}
private static Insets tempInsets = new Insets( 0, 0, 0, 0 );
@Override
@@ -182,4 +254,26 @@ public class FlatRadioButtonUI
? UIScale.scale( ((FlatCheckBoxIcon)getDefaultIcon()).focusWidth )
: 0;
}
//---- class FlatRadioButtonListener --------------------------------------
/**
* @since TODO
*/
protected class FlatRadioButtonListener
extends BasicButtonListener
{
private final AbstractButton b;
protected FlatRadioButtonListener( AbstractButton b ) {
super( b );
this.b = b;
}
@Override
public void propertyChange( PropertyChangeEvent e ) {
super.propertyChange( e );
FlatRadioButtonUI.this.propertyChange( b, e );
}
}
}

View File

@@ -108,7 +108,7 @@ public class FlatStyleSupport
if( style == null || style.trim().isEmpty() )
return null;
Map<String, Object> map = new LinkedHashMap<>();
Map<String, Object> map = null;
// split style into parts and process them
for( String part : StringUtils.split( style, ';' ) ) {
@@ -131,6 +131,8 @@ public class FlatStyleSupport
throw new IllegalArgumentException( "missing value in '" + part + "'" );
// parse value string and convert it into binary value
if( map == null )
map = new LinkedHashMap<>();
map.put( key, parseValue( key, value ) );
}
@@ -144,10 +146,6 @@ public class FlatStyleSupport
return FlatLaf.parseDefaultsValue( key, value );
}
public static boolean hasStyle( JComponent c ) {
return getStyle( c ) != null;
}
public static Object getStyle( JComponent c ) {
return c.getClientProperty( FlatClientProperties.COMPONENT_STYLE );
}

View File

@@ -831,6 +831,14 @@ debug*/
.computeIfAbsent( key, k -> newInstanceSupplier.get() );
}
/**
* Returns whether the component UI for the given component can be shared
* with other components. This is only possible if it does not have styles.
*/
public static boolean canUseSharedUI( JComponent c ) {
return FlatStyleSupport.getStyle( c ) == null;
}
//---- class RepaintFocusListener -----------------------------------------
public static class RepaintFocusListener