mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 14:00:55 +03:00
Panel: support painting background with rounded corners (issue #367)
FlatLineBorder: support rounded corners
This commit is contained in:
@@ -64,6 +64,7 @@ FlatLaf Change Log
|
|||||||
- MenuItem:
|
- MenuItem:
|
||||||
- Paint the selected icon when the item is selected. (PR #415)
|
- Paint the selected icon when the item is selected. (PR #415)
|
||||||
- Vertically align text if icons have different widths. (issue #437)
|
- Vertically align text if icons have different widths. (issue #437)
|
||||||
|
- Panel: Support painting background with rounded corners. (issue #367)
|
||||||
- Added more color functions to class `ColorFunctions` for easy use in
|
- Added more color functions to class `ColorFunctions` for easy use in
|
||||||
applications: `lighten()`, `darken()`, `saturate()`, `desaturate()`, `spin()`,
|
applications: `lighten()`, `darken()`, `saturate()`, `desaturate()`, `spin()`,
|
||||||
`tint()`, `shade()` and `luma()`.
|
`tint()`, `shade()` and `luma()`.
|
||||||
|
|||||||
@@ -582,17 +582,18 @@ class UIDefaultsLoader
|
|||||||
|
|
||||||
private static Object parseBorder( String value, Function<String, String> resolver, List<ClassLoader> addonClassLoaders ) {
|
private static Object parseBorder( String value, Function<String, String> resolver, List<ClassLoader> addonClassLoaders ) {
|
||||||
if( value.indexOf( ',' ) >= 0 ) {
|
if( value.indexOf( ',' ) >= 0 ) {
|
||||||
// top,left,bottom,right[,lineColor[,lineThickness]]
|
// top,left,bottom,right[,lineColor[,lineThickness[,arc]]]
|
||||||
List<String> parts = splitFunctionParams( value, ',' );
|
List<String> parts = splitFunctionParams( value, ',' );
|
||||||
Insets insets = parseInsets( value );
|
Insets insets = parseInsets( value );
|
||||||
ColorUIResource lineColor = (parts.size() >= 5)
|
ColorUIResource lineColor = (parts.size() >= 5)
|
||||||
? (ColorUIResource) parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver, true )
|
? (ColorUIResource) parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver, true )
|
||||||
: null;
|
: null;
|
||||||
float lineThickness = (parts.size() >= 6) ? parseFloat( parts.get( 5 ), true ) : 1f;
|
float lineThickness = (parts.size() >= 6 && !parts.get( 5 ).isEmpty()) ? parseFloat( parts.get( 5 ), true ) : 1f;
|
||||||
|
int arc = (parts.size() >= 7) ? parseInteger( parts.get( 6 ), true ) : 0;
|
||||||
|
|
||||||
return (LazyValue) t -> {
|
return (LazyValue) t -> {
|
||||||
return (lineColor != null)
|
return (lineColor != null)
|
||||||
? new FlatLineBorder( insets, lineColor, lineThickness )
|
? new FlatLineBorder( insets, lineColor, lineThickness, arc )
|
||||||
: new FlatEmptyBorder( insets );
|
: new FlatEmptyBorder( insets );
|
||||||
};
|
};
|
||||||
} else
|
} else
|
||||||
|
|||||||
@@ -37,15 +37,18 @@ public class FlatLineBorder
|
|||||||
{
|
{
|
||||||
private final Color lineColor;
|
private final Color lineColor;
|
||||||
private final float lineThickness;
|
private final float lineThickness;
|
||||||
|
/** @since 2 */ private final int arc;
|
||||||
|
|
||||||
public FlatLineBorder( Insets insets, Color lineColor ) {
|
public FlatLineBorder( Insets insets, Color lineColor ) {
|
||||||
this( insets, lineColor, 1f );
|
this( insets, lineColor, 1f, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlatLineBorder( Insets insets, Color lineColor, float lineThickness ) {
|
/** @since 2 */
|
||||||
|
public FlatLineBorder( Insets insets, Color lineColor, float lineThickness, int arc ) {
|
||||||
super( insets );
|
super( insets );
|
||||||
this.lineColor = lineColor;
|
this.lineColor = lineColor;
|
||||||
this.lineThickness = lineThickness;
|
this.lineThickness = lineThickness;
|
||||||
|
this.arc = arc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Color getLineColor() {
|
public Color getLineColor() {
|
||||||
@@ -56,13 +59,18 @@ public class FlatLineBorder
|
|||||||
return lineThickness;
|
return lineThickness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2 */
|
||||||
|
public int getArc() {
|
||||||
|
return arc;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||||
Graphics2D g2 = (Graphics2D) g.create();
|
Graphics2D g2 = (Graphics2D) g.create();
|
||||||
try {
|
try {
|
||||||
FlatUIUtils.setRenderingHints( g2 );
|
FlatUIUtils.setRenderingHints( g2 );
|
||||||
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
||||||
0, 0, 0, scale( getLineThickness() ), 0, null, getLineColor(), null );
|
0, 0, 0, scale( getLineThickness() ), scale( getArc() ), null, getLineColor(), null );
|
||||||
} finally {
|
} finally {
|
||||||
g2.dispose();
|
g2.dispose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,18 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf.ui;
|
package com.formdev.flatlaf.ui;
|
||||||
|
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.basic.BasicPanelUI;
|
import javax.swing.plaf.basic.BasicPanelUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JPanel}.
|
* Provides the Flat LaF UI delegate for {@link javax.swing.JPanel}.
|
||||||
@@ -32,7 +36,7 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
*
|
*
|
||||||
* @uiDefault Panel.font Font unused
|
* @uiDefault Panel.font Font unused
|
||||||
* @uiDefault Panel.background Color only used if opaque
|
* @uiDefault Panel.background Color only used if opaque
|
||||||
* @uiDefault Panel.foreground Color
|
* @uiDefault Panel.foreground Color unused
|
||||||
* @uiDefault Panel.border Border
|
* @uiDefault Panel.border Border
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
@@ -41,6 +45,9 @@ public class FlatPanelUI
|
|||||||
extends BasicPanelUI
|
extends BasicPanelUI
|
||||||
implements StyleableUI
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
|
// only used via styling (not in UI defaults)
|
||||||
|
/** @since 2 */ @Styleable protected int arc = -1;
|
||||||
|
|
||||||
private final boolean shared;
|
private final boolean shared;
|
||||||
private PropertyChangeListener propertyChangeListener;
|
private PropertyChangeListener propertyChangeListener;
|
||||||
private Map<String, Object> oldStyleValues;
|
private Map<String, Object> oldStyleValues;
|
||||||
@@ -113,4 +120,34 @@ public class FlatPanelUI
|
|||||||
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update( Graphics g, JComponent c ) {
|
||||||
|
// fill background
|
||||||
|
if( c.isOpaque() ) {
|
||||||
|
int width = c.getWidth();
|
||||||
|
int height = c.getHeight();
|
||||||
|
int arc = (this.arc >= 0)
|
||||||
|
? this.arc
|
||||||
|
: ((c.getBorder() instanceof FlatLineBorder)
|
||||||
|
? ((FlatLineBorder)c.getBorder()).getArc()
|
||||||
|
: 0);
|
||||||
|
|
||||||
|
// fill background with parent color to avoid garbage in rounded corners
|
||||||
|
if( arc > 0 )
|
||||||
|
FlatUIUtils.paintParentBackground( g, c );
|
||||||
|
|
||||||
|
g.setColor( c.getBackground() );
|
||||||
|
if( arc > 0 ) {
|
||||||
|
// fill rounded rectangle if having rounded corners
|
||||||
|
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
||||||
|
FlatUIUtils.paintComponentBackground( (Graphics2D) g, 0, 0, width, height,
|
||||||
|
0, UIScale.scale( arc ) );
|
||||||
|
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
||||||
|
} else
|
||||||
|
g.fillRect( 0, 0, width, height );
|
||||||
|
}
|
||||||
|
|
||||||
|
paint( g, c );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,12 @@ import java.awt.Dimension;
|
|||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.border.Border;
|
||||||
import javax.swing.UIDefaults.ActiveValue;
|
import javax.swing.UIDefaults.ActiveValue;
|
||||||
|
import javax.swing.UIDefaults.LazyValue;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import com.formdev.flatlaf.ui.FlatEmptyBorder;
|
||||||
|
import com.formdev.flatlaf.ui.FlatLineBorder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
@@ -46,8 +50,8 @@ public class TestUIDefaultsLoader
|
|||||||
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummy", "1.23", null ) );
|
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummy", "1.23", null ) );
|
||||||
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummyWidth", "1.23", null ) );
|
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummyWidth", "1.23", null ) );
|
||||||
|
|
||||||
assertEquals( new Insets( 2,2,2,2 ), UIDefaultsLoader.parseValue( "dummyInsets", "2,2,2,2", null ) );
|
assertEquals( new Insets( 1,2,3,4 ), UIDefaultsLoader.parseValue( "dummyInsets", "1,2,3,4", null ) );
|
||||||
assertEquals( new Dimension( 2,2 ), UIDefaultsLoader.parseValue( "dummySize", "2,2", null ) );
|
assertEquals( new Dimension( 1,2 ), UIDefaultsLoader.parseValue( "dummySize", "1,2", null ) );
|
||||||
assertEquals( new Color( 0xff0000 ), UIDefaultsLoader.parseValue( "dummy", "#f00", null ) );
|
assertEquals( new Color( 0xff0000 ), UIDefaultsLoader.parseValue( "dummy", "#f00", null ) );
|
||||||
assertEquals( new Color( 0xff0000 ), UIDefaultsLoader.parseValue( "dummyColor", "#f00", null ) );
|
assertEquals( new Color( 0xff0000 ), UIDefaultsLoader.parseValue( "dummyColor", "#f00", null ) );
|
||||||
}
|
}
|
||||||
@@ -70,11 +74,35 @@ public class TestUIDefaultsLoader
|
|||||||
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummy", "1.23", float.class ) );
|
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummy", "1.23", float.class ) );
|
||||||
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummy", "1.23", Float.class ) );
|
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummy", "1.23", Float.class ) );
|
||||||
|
|
||||||
assertEquals( new Insets( 2,2,2,2 ), UIDefaultsLoader.parseValue( "dummy", "2,2,2,2", Insets.class ) );
|
assertEquals( new Insets( 1,2,3,4 ), UIDefaultsLoader.parseValue( "dummy", "1,2,3,4", Insets.class ) );
|
||||||
assertEquals( new Dimension( 2,2 ), UIDefaultsLoader.parseValue( "dummy", "2,2", Dimension.class ) );
|
assertEquals( new Dimension( 1,2 ), UIDefaultsLoader.parseValue( "dummy", "1,2", Dimension.class ) );
|
||||||
assertEquals( new Color( 0xff0000 ), UIDefaultsLoader.parseValue( "dummy", "#f00", Color.class ) );
|
assertEquals( new Color( 0xff0000 ), UIDefaultsLoader.parseValue( "dummy", "#f00", Color.class ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void parseBorders() {
|
||||||
|
Insets insets = new Insets( 1,2,3,4 );
|
||||||
|
assertBorderEquals( new FlatEmptyBorder( insets ), "1,2,3,4" );
|
||||||
|
assertBorderEquals( new FlatLineBorder( insets, Color.red ), "1,2,3,4,#f00" );
|
||||||
|
assertBorderEquals( new FlatLineBorder( insets, Color.red, 2.5f, 0 ), "1,2,3,4,#f00,2.5" );
|
||||||
|
assertBorderEquals( new FlatLineBorder( insets, Color.red, 2.5f, 6 ), "1,2,3,4,#f00,2.5,6" );
|
||||||
|
assertBorderEquals( new FlatLineBorder( insets, Color.red, 1, 6 ), "1,2,3,4,#f00,,6" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertBorderEquals( Border expected, String actualStyle ) {
|
||||||
|
Border actual = (Border) ((LazyValue)UIDefaultsLoader.parseValue( "dummyBorder", actualStyle, null )).createValue( null );
|
||||||
|
assertEquals( expected.getClass(), actual.getClass() );
|
||||||
|
if( expected instanceof FlatEmptyBorder )
|
||||||
|
assertEquals( ((FlatEmptyBorder)actual).getBorderInsets(), ((FlatEmptyBorder)expected).getBorderInsets() );
|
||||||
|
if( expected instanceof FlatLineBorder ) {
|
||||||
|
FlatLineBorder a = (FlatLineBorder) actual;
|
||||||
|
FlatLineBorder e = (FlatLineBorder) expected;
|
||||||
|
assertEquals( a.getLineColor(), e.getLineColor() );
|
||||||
|
assertEquals( a.getLineThickness(), e.getLineThickness() );
|
||||||
|
assertEquals( a.getArc(), e.getArc() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void parseFonts() {
|
void parseFonts() {
|
||||||
// style
|
// style
|
||||||
|
|||||||
@@ -386,6 +386,7 @@ public class TestFlatStyleableInfo
|
|||||||
FlatPanelUI ui = (FlatPanelUI) c.getUI();
|
FlatPanelUI ui = (FlatPanelUI) c.getUI();
|
||||||
|
|
||||||
Map<String, Class<?>> expected = expectedMap(
|
Map<String, Class<?>> expected = expectedMap(
|
||||||
|
"arc", int.class
|
||||||
);
|
);
|
||||||
|
|
||||||
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
||||||
|
|||||||
@@ -529,6 +529,8 @@ public class TestFlatStyling
|
|||||||
JPanel c = new JPanel();
|
JPanel c = new JPanel();
|
||||||
FlatPanelUI ui = (FlatPanelUI) c.getUI();
|
FlatPanelUI ui = (FlatPanelUI) c.getUI();
|
||||||
|
|
||||||
|
ui.applyStyle( c, "arc: 8" );
|
||||||
|
|
||||||
// JComponent properties
|
// JComponent properties
|
||||||
ui.applyStyle( c, "background: #fff" );
|
ui.applyStyle( c, "background: #fff" );
|
||||||
ui.applyStyle( c, "foreground: #fff" );
|
ui.applyStyle( c, "foreground: #fff" );
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ class FlatColorPipette
|
|||||||
|
|
||||||
zoom = UIScale.scale( 16 );
|
zoom = UIScale.scale( 16 );
|
||||||
|
|
||||||
getRootPane().setBorder( new FlatLineBorder( new Insets( 2, 2, 2, 2 ), Color.red, 2 ) );
|
getRootPane().setBorder( new FlatLineBorder( new Insets( 2, 2, 2, 2 ), Color.red, 2, 0 ) );
|
||||||
|
|
||||||
view = new MagnifierView();
|
view = new MagnifierView();
|
||||||
view.setPreferredSize( new Dimension( pixels * zoom, pixels * zoom ) );
|
view.setPreferredSize( new Dimension( pixels * zoom, pixels * zoom ) );
|
||||||
|
|||||||
Reference in New Issue
Block a user