diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatDropShadowBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatDropShadowBorder.java index 505b9276..977c97cb 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatDropShadowBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatDropShadowBorder.java @@ -24,6 +24,8 @@ import java.awt.Image; import java.awt.Insets; import java.awt.RadialGradientPaint; import java.awt.image.BufferedImage; +import com.formdev.flatlaf.ui.FlatStyleSupport.Styleable; +import com.formdev.flatlaf.ui.FlatStyleSupport.StyleableBorder; import com.formdev.flatlaf.util.HiDPIUtils; import com.formdev.flatlaf.util.UIScale; @@ -40,14 +42,17 @@ import com.formdev.flatlaf.util.UIScale; */ public class FlatDropShadowBorder extends FlatEmptyBorder + implements StyleableBorder { - private final Color shadowColor; - private final Insets shadowInsets; - private final float shadowOpacity; + @Styleable protected Color shadowColor; + @Styleable protected Insets shadowInsets; + @Styleable protected float shadowOpacity; - private final int shadowSize; + private int shadowSize; private Image shadowImage; private Color lastShadowColor; + private float lastShadowOpacity; + private int lastShadowSize; private double lastSystemScaleFactor; private float lastUserScaleFactor; @@ -64,17 +69,36 @@ public class FlatDropShadowBorder } public FlatDropShadowBorder( Color shadowColor, Insets shadowInsets, float shadowOpacity ) { - super( Math.max( shadowInsets.top, 0 ), Math.max( shadowInsets.left, 0 ), - Math.max( shadowInsets.bottom, 0 ), Math.max( shadowInsets.right, 0 ) ); + super( nonNegativeInsets( shadowInsets ) ); + this.shadowColor = shadowColor; this.shadowInsets = shadowInsets; this.shadowOpacity = shadowOpacity; - shadowSize = Math.max( + shadowSize = maxInset( shadowInsets ); + } + + private static Insets nonNegativeInsets( Insets shadowInsets ) { + return new Insets( Math.max( shadowInsets.top, 0 ), Math.max( shadowInsets.left, 0 ), + Math.max( shadowInsets.bottom, 0 ), Math.max( shadowInsets.right, 0 ) ); + } + + private int maxInset( Insets shadowInsets ) { + return Math.max( Math.max( shadowInsets.left, shadowInsets.right ), Math.max( shadowInsets.top, shadowInsets.bottom ) ); } + @Override + public Object applyStyleProperty( String key, Object value ) { + Object oldValue = FlatStyleSupport.applyToAnnotatedObject( this, key, value ); + if( key.equals( "shadowInsets" ) ) { + applyStyleProperty( nonNegativeInsets( shadowInsets ) ); + shadowSize = maxInset( shadowInsets ); + } + return oldValue; + } + @Override public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) { if( shadowSize <= 0 ) @@ -91,12 +115,16 @@ public class FlatDropShadowBorder float userScaleFactor = UIScale.getUserScaleFactor(); if( shadowImage == null || !shadowColor.equals( lastShadowColor ) || + lastShadowOpacity != shadowOpacity || + lastShadowSize != shadowSize || lastSystemScaleFactor != scaleFactor || lastUserScaleFactor != userScaleFactor ) { shadowImage = createShadowImage( shadowColor, shadowSize, shadowOpacity, (float) (scaleFactor * userScaleFactor) ); lastShadowColor = shadowColor; + lastShadowOpacity = shadowOpacity; + lastShadowSize = shadowSize; lastSystemScaleFactor = scaleFactor; lastUserScaleFactor = userScaleFactor; } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatEmptyBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatEmptyBorder.java index 455d7445..34e5fb04 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatEmptyBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatEmptyBorder.java @@ -67,4 +67,13 @@ public class FlatEmptyBorder public Insets getUnscaledBorderInsets() { return super.getBorderInsets(); } + + public Object applyStyleProperty( Insets insets ) { + Insets oldInsets = getUnscaledBorderInsets(); + top = insets.top; + left = insets.left; + bottom = insets.bottom; + right = insets.right; + return oldInsets; + } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatInternalFrameUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatInternalFrameUI.java index efc3bfaf..5a1d9020 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatInternalFrameUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatInternalFrameUI.java @@ -22,12 +22,17 @@ import java.awt.Component; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; +import java.beans.PropertyChangeListener; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.JComponent; import javax.swing.JInternalFrame; import javax.swing.LookAndFeel; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicInternalFrameUI; +import com.formdev.flatlaf.ui.FlatStyleSupport.Styleable; +import com.formdev.flatlaf.ui.FlatStyleSupport.StyleableBorder; /** * Provides the Flat LaF UI delegate for {@link javax.swing.JInternalFrame}. @@ -86,6 +91,9 @@ public class FlatInternalFrameUI { protected FlatWindowResizer windowResizer; + private Map oldStyleValues; + private AtomicBoolean borderShared; + public static ComponentUI createUI( JComponent c ) { return new FlatInternalFrameUI( (JInternalFrame) c ); } @@ -101,6 +109,8 @@ public class FlatInternalFrameUI LookAndFeel.installProperty( frame, "opaque", false ); windowResizer = createWindowResizer(); + + applyStyle( FlatStyleSupport.getStyle( c ) ); } @Override @@ -111,6 +121,9 @@ public class FlatInternalFrameUI windowResizer.uninstall(); windowResizer = null; } + + oldStyleValues = null; + borderShared = null; } @Override @@ -122,15 +135,38 @@ public class FlatInternalFrameUI return new FlatWindowResizer.InternalFrameResizer( frame, this::getDesktopManager ); } + @Override + protected PropertyChangeListener createPropertyChangeListener() { + return FlatStyleSupport.createPropertyChangeListener( frame, this::applyStyle, + super.createPropertyChangeListener() ); + } + + /** + * @since TODO + */ + protected void applyStyle( Object style ) { + oldStyleValues = FlatStyleSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty ); + } + + /** + * @since TODO + */ + protected Object applyStyleProperty( String key, Object value ) { + if( borderShared == null ) + borderShared = new AtomicBoolean( true ); + return FlatStyleSupport.applyToAnnotatedObjectOrBorder( this, key, value, frame, borderShared ); + } + //---- class FlatInternalFrameBorder -------------------------------------- public static class FlatInternalFrameBorder extends FlatEmptyBorder + implements StyleableBorder { - private final Color activeBorderColor = UIManager.getColor( "InternalFrame.activeBorderColor" ); - private final Color inactiveBorderColor = UIManager.getColor( "InternalFrame.inactiveBorderColor" ); - private final int borderLineWidth = FlatUIUtils.getUIInt( "InternalFrame.borderLineWidth", 1 ); - private final boolean dropShadowPainted = UIManager.getBoolean( "InternalFrame.dropShadowPainted" ); + @Styleable protected Color activeBorderColor = UIManager.getColor( "InternalFrame.activeBorderColor" ); + @Styleable protected Color inactiveBorderColor = UIManager.getColor( "InternalFrame.inactiveBorderColor" ); + @Styleable protected int borderLineWidth = FlatUIUtils.getUIInt( "InternalFrame.borderLineWidth", 1 ); + @Styleable protected boolean dropShadowPainted = UIManager.getBoolean( "InternalFrame.dropShadowPainted" ); private final FlatDropShadowBorder activeDropShadowBorder = new FlatDropShadowBorder( UIManager.getColor( "InternalFrame.activeDropShadowColor" ), @@ -145,6 +181,22 @@ public class FlatInternalFrameUI super( UIManager.getInsets( "InternalFrame.borderMargins" ) ); } + @Override + public Object applyStyleProperty( String key, Object value ) { + switch( key ) { + case "borderMargins": return applyStyleProperty( (Insets) value ); + + case "activeDropShadowColor": return activeDropShadowBorder.applyStyleProperty( "shadowColor", value ); + case "activeDropShadowInsets": return activeDropShadowBorder.applyStyleProperty( "shadowInsets", value ); + case "activeDropShadowOpacity": return activeDropShadowBorder.applyStyleProperty( "shadowOpacity", value ); + case "inactiveDropShadowColor": return inactiveDropShadowBorder.applyStyleProperty( "shadowColor", value ); + case "inactiveDropShadowInsets": return inactiveDropShadowBorder.applyStyleProperty( "shadowInsets", value ); + case "inactiveDropShadowOpacity": return inactiveDropShadowBorder.applyStyleProperty( "shadowOpacity", value ); + } + + return FlatStyleSupport.applyToAnnotatedObject( this, key, value ); + } + @Override public Insets getBorderInsets( Component c, Insets insets ) { if( c instanceof JInternalFrame && ((JInternalFrame)c).isMaximum() ) { diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java index 09db1f2b..47747e1a 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyling.java @@ -197,6 +197,25 @@ public class TestFlatStyling textField( ui ); } + @Test + void internalFrame() { + JInternalFrame c = new JInternalFrame(); + FlatInternalFrameUI ui = (FlatInternalFrameUI) c.getUI(); + + ui.applyStyle( "activeBorderColor: #fff" ); + ui.applyStyle( "inactiveBorderColor: #fff" ); + ui.applyStyle( "borderLineWidth: 123" ); + ui.applyStyle( "dropShadowPainted: false" ); + ui.applyStyle( "borderMargins: 1,2,3,4" ); + + ui.applyStyle( "activeDropShadowColor: #fff" ); + ui.applyStyle( "activeDropShadowInsets: 1,2,3,4" ); + ui.applyStyle( "activeDropShadowOpacity: 0.5" ); + ui.applyStyle( "inactiveDropShadowColor: #fff" ); + ui.applyStyle( "inactiveDropShadowInsets: 1,2,3,4" ); + ui.applyStyle( "inactiveDropShadowOpacity: 0.5" ); + } + @Test void label() { JLabel c = new JLabel();