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.Insets;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Map;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JSplitPane; import javax.swing.JSplitPane;
@@ -32,6 +34,9 @@ import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicSplitPaneDivider; import javax.swing.plaf.basic.BasicSplitPaneDivider;
import javax.swing.plaf.basic.BasicSplitPaneUI; 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; import com.formdev.flatlaf.util.UIScale;
/** /**
@@ -67,15 +72,25 @@ import com.formdev.flatlaf.util.UIScale;
public class FlatSplitPaneUI public class FlatSplitPaneUI
extends BasicSplitPaneUI extends BasicSplitPaneUI
{ {
protected String arrowType; @Styleable protected String arrowType;
protected Color oneTouchArrowColor; @Styleable protected Color oneTouchArrowColor;
protected Color oneTouchHoverArrowColor; @Styleable protected Color oneTouchHoverArrowColor;
protected Color oneTouchPressedArrowColor; @Styleable protected Color oneTouchPressedArrowColor;
private PropertyChangeListener propertyChangeListener;
private Map<String, Object> oldStyleValues;
public static ComponentUI createUI( JComponent c ) { public static ComponentUI createUI( JComponent c ) {
return new FlatSplitPaneUI(); return new FlatSplitPaneUI();
} }
@Override
public void installUI( JComponent c ) {
super.installUI( c );
applyStyle( FlatStyleSupport.getStyle( splitPane ) );
}
@Override @Override
protected void installDefaults() { protected void installDefaults() {
arrowType = UIManager.getString( "Component.arrowType" ); arrowType = UIManager.getString( "Component.arrowType" );
@@ -98,21 +113,68 @@ public class FlatSplitPaneUI
oneTouchPressedArrowColor = null; 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 @Override
public BasicSplitPaneDivider createDefaultDivider() { public BasicSplitPaneDivider createDefaultDivider() {
return new FlatSplitPaneDivider( this ); 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 ----------------------------------------- //---- class FlatSplitPaneDivider -----------------------------------------
protected class FlatSplitPaneDivider protected class FlatSplitPaneDivider
extends BasicSplitPaneDivider extends BasicSplitPaneDivider
{ {
protected final String style = UIManager.getString( "SplitPaneDivider.style" ); @Styleable protected String style = UIManager.getString( "SplitPaneDivider.style" );
protected final Color gripColor = UIManager.getColor( "SplitPaneDivider.gripColor" ); @Styleable protected Color gripColor = UIManager.getColor( "SplitPaneDivider.gripColor" );
protected final int gripDotCount = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotCount", 3 ); @Styleable protected int gripDotCount = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotCount", 3 );
protected final int gripDotSize = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotSize", 3 ); @Styleable protected int gripDotSize = FlatUIUtils.getUIInt( "SplitPaneDivider.gripDotSize", 3 );
protected final int gripGap = FlatUIUtils.getUIInt( "SplitPaneDivider.gripGap", 2 ); @Styleable protected int gripGap = FlatUIUtils.getUIInt( "SplitPaneDivider.gripGap", 2 );
protected FlatSplitPaneDivider( BasicSplitPaneUI ui ) { protected FlatSplitPaneDivider( BasicSplitPaneUI ui ) {
super( ui ); super( ui );
@@ -120,6 +182,20 @@ public class FlatSplitPaneUI
setLayout( new FlatDividerLayout() ); 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 @Override
public void setDividerSize( int newSize ) { public void setDividerSize( int newSize ) {
super.setDividerSize( UIScale.scale( newSize ) ); super.setDividerSize( UIScale.scale( newSize ) );
@@ -200,6 +276,11 @@ public class FlatSplitPaneUI
this.left = left; this.left = left;
} }
protected void update() {
update( arrowType, oneTouchArrowColor, null,
oneTouchHoverArrowColor, null, oneTouchPressedArrowColor, null );
}
@Override @Override
public int getDirection() { public int getDirection() {
return (orientation == JSplitPane.VERTICAL_SPLIT) return (orientation == JSplitPane.VERTICAL_SPLIT)

View File

@@ -61,11 +61,13 @@ public class FlatStyleSupport
* first parameter is the key, second the binary value; * first parameter is the key, second the binary value;
* the function must return the old value * the function must return the old value
* @return map of old values modified by the given style, or {@code null} * @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 IllegalArgumentException on syntax errors
* @throws ClassCastException if value type does not fit to expected type  * @throws ClassCastException if value type does not fit to expected type 
*/ */
public static Map<String, Object> parseAndApply( Map<String, Object> oldStyleValues, 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 // restore previous values
if( oldStyleValues != null ) { if( oldStyleValues != null ) {
@@ -170,11 +172,11 @@ public class FlatStyleSupport
* @param key the name of the field * @param key the name of the field
* @param value the new value * @param value the new value
* @return the old value of the field * @return the old value of the field
* @throws IllegalArgumentException if object does not have a annotated field with given name * @throws UnknownStyleException if object does not have a annotated field with given name
* or if value type does not fit to expected type  * @throws IllegalArgumentException if value type does not fit to expected type 
*/ */
public static Object applyToAnnotatedObject( Object obj, String key, Object value ) public static Object applyToAnnotatedObject( Object obj, String key, Object value )
throws IllegalArgumentException throws UnknownStyleException, IllegalArgumentException
{ {
Class<?> cls = obj.getClass(); Class<?> cls = obj.getClass();
@@ -203,19 +205,30 @@ public class FlatStyleSupport
cls = cls.getSuperclass(); cls = cls.getSuperclass();
if( cls == null ) if( cls == null )
throw newUnknownStyleException( key ); throw new UnknownStyleException( key );
String superclassName = cls.getName(); String superclassName = cls.getName();
if( superclassName.startsWith( "java." ) || superclassName.startsWith( "javax." ) ) 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 ) { public static Object getStyle( JComponent c ) {
return c.getClientProperty( FlatClientProperties.COMPONENT_STYLE ); 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 java.util.Map;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JRadioButton; import javax.swing.JRadioButton;
import javax.swing.JSplitPane;
import javax.swing.UIManager; import javax.swing.UIManager;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import com.formdev.flatlaf.icons.FlatCheckBoxIcon; import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
@@ -208,6 +209,25 @@ public class FlatStylingTests
ui.applyStyle( "tickColor: #fff" ); 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 -------------------------------------------------------------- //---- icons --------------------------------------------------------------
@Test @Test