Styling: support SplitPane

This commit is contained in:
Karl Tauber
2021-06-17 20:59:09 +02:00
parent 50490ece84
commit 1938cb586d
3 changed files with 133 additions and 19 deletions

View File

@@ -23,6 +23,8 @@ import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JSplitPane;
@@ -32,6 +34,9 @@ import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.ui.FlatStyleSupport.Styleable;
import com.formdev.flatlaf.ui.FlatStyleSupport.UnknownStyleException;
import com.formdev.flatlaf.util.UIScale;
/**
@@ -67,15 +72,25 @@ import com.formdev.flatlaf.util.UIScale;
public class FlatSplitPaneUI
extends BasicSplitPaneUI
{
protected String arrowType;
protected Color oneTouchArrowColor;
protected Color oneTouchHoverArrowColor;
protected Color oneTouchPressedArrowColor;
@Styleable protected String arrowType;
@Styleable protected Color oneTouchArrowColor;
@Styleable protected Color oneTouchHoverArrowColor;
@Styleable protected Color oneTouchPressedArrowColor;
private PropertyChangeListener propertyChangeListener;
private Map<String, Object> oldStyleValues;
public static ComponentUI createUI( JComponent c ) {
return new FlatSplitPaneUI();
}
@Override
public void installUI( JComponent c ) {
super.installUI( c );
applyStyle( FlatStyleSupport.getStyle( splitPane ) );
}
@Override
protected void installDefaults() {
arrowType = UIManager.getString( "Component.arrowType" );
@@ -98,21 +113,68 @@ public class FlatSplitPaneUI
oneTouchPressedArrowColor = null;
}
@Override
protected void installListeners() {
super.installListeners();
propertyChangeListener = e -> {
switch( e.getPropertyName() ) {
case FlatClientProperties.COMPONENT_STYLE:
applyStyle( e.getNewValue() );
splitPane.revalidate();
splitPane.repaint();
break;
}
};
splitPane.addPropertyChangeListener( propertyChangeListener );
}
@Override
protected void uninstallListeners() {
super.uninstallListeners();
splitPane.removePropertyChangeListener( propertyChangeListener );
propertyChangeListener = null;
}
@Override
public BasicSplitPaneDivider createDefaultDivider() {
return new FlatSplitPaneDivider( this );
}
/**
* @since TODO
*/
protected void applyStyle( Object style ) {
oldStyleValues = FlatStyleSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
if( divider instanceof FlatSplitPaneDivider )
((FlatSplitPaneDivider)divider).updateButtons();
}
/**
* @since TODO
*/
protected Object applyStyleProperty( String key, Object value ) {
try {
if( divider instanceof FlatSplitPaneDivider )
return ((FlatSplitPaneDivider)divider).applyStyleProperty( key, value );
} catch( UnknownStyleException ex ) {
// ignore
}
return FlatStyleSupport.applyToAnnotatedObject( this, key, value );
}
//---- class FlatSplitPaneDivider -----------------------------------------
protected class FlatSplitPaneDivider
extends BasicSplitPaneDivider
{
protected final String style = UIManager.getString( "SplitPaneDivider.style" );
protected final Color gripColor = UIManager.getColor( "SplitPaneDivider.gripColor" );
protected final int gripDotCount = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotCount", 3 );
protected final int gripDotSize = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotSize", 3 );
protected final int gripGap = FlatUIUtils.getUIInt( "SplitPaneDivider.gripGap", 2 );
@Styleable protected String style = UIManager.getString( "SplitPaneDivider.style" );
@Styleable protected Color gripColor = UIManager.getColor( "SplitPaneDivider.gripColor" );
@Styleable protected int gripDotCount = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotCount", 3 );
@Styleable protected int gripDotSize = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotSize", 3 );
@Styleable protected int gripGap = FlatUIUtils.getUIInt( "SplitPaneDivider.gripGap", 2 );
protected FlatSplitPaneDivider( BasicSplitPaneUI ui ) {
super( ui );
@@ -120,6 +182,20 @@ public class FlatSplitPaneUI
setLayout( new FlatDividerLayout() );
}
/**
* @since TODO
*/
protected Object applyStyleProperty( String key, Object value ) {
return FlatStyleSupport.applyToAnnotatedObject( this, key, value );
}
void updateButtons() {
if( leftButton instanceof FlatOneTouchButton )
((FlatOneTouchButton)leftButton).update();
if( rightButton instanceof FlatOneTouchButton )
((FlatOneTouchButton)rightButton).update();
}
@Override
public void setDividerSize( int newSize ) {
super.setDividerSize( UIScale.scale( newSize ) );
@@ -200,6 +276,11 @@ public class FlatSplitPaneUI
this.left = left;
}
protected void update() {
update( arrowType, oneTouchArrowColor, null,
oneTouchHoverArrowColor, null, oneTouchPressedArrowColor, null );
}
@Override
public int getDirection() {
return (orientation == JSplitPane.VERTICAL_SPLIT)

View File

@@ -61,11 +61,13 @@ public class FlatStyleSupport
* first parameter is the key, second the binary value;
* the function must return the old value
* @return map of old values modified by the given style, or {@code null}
* @throws UnknownStyleException on unknown style keys
* @throws IllegalArgumentException on syntax errors
* @throws ClassCastException if value type does not fit to expected type 
*/
public static Map<String, Object> parseAndApply( Map<String, Object> oldStyleValues,
Object style, BiFunction<String, Object, Object> applyProperty ) throws IllegalArgumentException
Object style, BiFunction<String, Object, Object> applyProperty )
throws UnknownStyleException, IllegalArgumentException
{
// restore previous values
if( oldStyleValues != null ) {
@@ -170,11 +172,11 @@ public class FlatStyleSupport
* @param key the name of the field
* @param value the new value
* @return the old value of the field
* @throws IllegalArgumentException if object does not have a annotated field with given name
* or if value type does not fit to expected type 
* @throws UnknownStyleException if object does not have a annotated field with given name
* @throws IllegalArgumentException if value type does not fit to expected type 
*/
public static Object applyToAnnotatedObject( Object obj, String key, Object value )
throws IllegalArgumentException
throws UnknownStyleException, IllegalArgumentException
{
Class<?> cls = obj.getClass();
@@ -203,19 +205,30 @@ public class FlatStyleSupport
cls = cls.getSuperclass();
if( cls == null )
throw newUnknownStyleException( key );
throw new UnknownStyleException( key );
String superclassName = cls.getName();
if( superclassName.startsWith( "java." ) || superclassName.startsWith( "javax." ) )
throw newUnknownStyleException( key );
throw new UnknownStyleException( key );
}
}
public static IllegalArgumentException newUnknownStyleException( String key ) {
return new IllegalArgumentException( "unknown style '" + key + "'" );
}
public static Object getStyle( JComponent c ) {
return c.getClientProperty( FlatClientProperties.COMPONENT_STYLE );
}
//---- class UnknownStyleException ----------------------------------------
public static class UnknownStyleException
extends IllegalArgumentException
{
UnknownStyleException( String key ) {
super( key );
}
@Override
public String getMessage() {
return "unknown style '" + super.getMessage() + "'";
}
}
}

View File

@@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.Map;
import javax.swing.JCheckBox;
import javax.swing.JRadioButton;
import javax.swing.JSplitPane;
import javax.swing.UIManager;
import org.junit.jupiter.api.Test;
import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
@@ -208,6 +209,25 @@ public class FlatStylingTests
ui.applyStyle( "tickColor: #fff" );
}
@Test
void splitPane() {
FlatSplitPaneUI ui = new FlatSplitPaneUI();
// create divider and one-touch buttons
ui.installUI( new JSplitPane() );
ui.applyStyle( "arrowType: chevron" );
ui.applyStyle( "oneTouchArrowColor: #fff" );
ui.applyStyle( "oneTouchHoverArrowColor: #fff" );
ui.applyStyle( "oneTouchPressedArrowColor: #fff" );
ui.applyStyle( "style: grip" );
ui.applyStyle( "gripColor: #fff" );
ui.applyStyle( "gripDotCount: 3" );
ui.applyStyle( "gripDotSize: {integer}3" );
ui.applyStyle( "gripGap: 2" );
}
//---- icons --------------------------------------------------------------
@Test