diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuBorder.java index ce1b314e..593dd2f1 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuBorder.java @@ -16,11 +16,16 @@ package com.formdev.flatlaf.ui; +import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Insets; +import java.util.LinkedHashMap; +import java.util.Map; import javax.swing.JScrollPane; import javax.swing.UIManager; +import com.formdev.flatlaf.ui.FlatStyleSupport.StyleableBorder; +import com.formdev.flatlaf.ui.FlatStyleSupport.UnknownStyleException; import com.formdev.flatlaf.util.UIScale; /** @@ -33,12 +38,44 @@ import com.formdev.flatlaf.util.UIScale; */ public class FlatPopupMenuBorder extends FlatLineBorder + implements StyleableBorder { + private Color borderColor; + public FlatPopupMenuBorder() { super( UIManager.getInsets( "PopupMenu.borderInsets" ), UIManager.getColor( "PopupMenu.borderColor" ) ); } + /** + * @since TODO + */ + @Override + public Object applyStyleProperty( String key, Object value ) { + Object oldValue; + switch( key ) { + case "borderInsets": return applyStyleProperty( (Insets) value ); + case "borderColor": oldValue = getLineColor(); borderColor = (Color) value; return oldValue; + } + throw new UnknownStyleException( key ); + } + + /** + * @since TODO + */ + @Override + public Map> getStyleableInfos() { + Map> infos = new LinkedHashMap<>(); + infos.put( "borderInsets", Insets.class ); + infos.put( "borderColor", Color.class ); + return infos; + } + + @Override + public Color getLineColor() { + return (borderColor != null) ? borderColor : super.getLineColor(); + } + @Override public Insets getBorderInsets( Component c, Insets insets ) { if( c instanceof Container && diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuUI.java index 480b0222..27435846 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatPopupMenuUI.java @@ -16,9 +16,14 @@ package com.formdev.flatlaf.ui; +import java.beans.PropertyChangeListener; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.JComponent; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicPopupMenuUI; +import com.formdev.flatlaf.FlatClientProperties; +import com.formdev.flatlaf.ui.FlatStyleSupport.StyleableUI; /** * Provides the Flat LaF UI delegate for {@link javax.swing.JPopupMenu}. @@ -34,8 +39,68 @@ import javax.swing.plaf.basic.BasicPopupMenuUI; */ public class FlatPopupMenuUI extends BasicPopupMenuUI + implements StyleableUI { + private PropertyChangeListener propertyChangeListener; + private Map oldStyleValues; + private AtomicBoolean borderShared; + public static ComponentUI createUI( JComponent c ) { return new FlatPopupMenuUI(); } + + @Override + public void installUI( JComponent c ) { + super.installUI( c ); + + applyStyle( FlatStyleSupport.getStyle( c ) ); + } + + @Override + public void uninstallUI( JComponent c ) { + super.uninstallUI( c ); + + oldStyleValues = null; + borderShared = null; + } + + @Override + protected void installListeners() { + super.installListeners(); + + propertyChangeListener = FlatStyleSupport.createPropertyChangeListener( popupMenu, this::applyStyle, null ); + popupMenu.addPropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + } + + @Override + protected void uninstallListeners() { + super.uninstallListeners(); + + popupMenu.removePropertyChangeListener( FlatClientProperties.STYLE, propertyChangeListener ); + propertyChangeListener = null; + } + + /** + * @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, popupMenu, borderShared ); + } + + /** + * @since TODO + */ + @Override + public Map> getStyleableInfos( JComponent c ) { + return FlatStyleSupport.getAnnotatedStyleableInfos( this, popupMenu.getBorder() ); + } } diff --git a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java index 70caf329..46da6a99 100644 --- a/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java +++ b/flatlaf-core/src/test/java/com/formdev/flatlaf/ui/TestFlatStyleableInfo.java @@ -392,6 +392,19 @@ public class TestFlatStyleableInfo assertMapEquals( expected, ui.getStyleableInfos( c ) ); } + @Test + void popupMenu() { + JPopupMenu c = new JPopupMenu(); + FlatPopupMenuUI ui = (FlatPopupMenuUI) c.getUI(); + + Map> expected = expectedMap( + "borderInsets", Insets.class, + "borderColor", Color.class + ); + + assertMapEquals( expected, ui.getStyleableInfos( c ) ); + } + @Test void popupMenuSeparator() { JPopupMenu.Separator c = new JPopupMenu.Separator(); 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 75d82e41..4333d836 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 @@ -347,6 +347,15 @@ public class TestFlatStyling flatTextBorder( style -> ui.applyStyle( style ) ); } + @Test + void popupMenu() { + JPopupMenu c = new JPopupMenu(); + FlatPopupMenuUI ui = (FlatPopupMenuUI) c.getUI(); + + ui.applyStyle( "borderInsets: 1,2,3,4" ); + ui.applyStyle( "borderColor: #fff" ); + } + @Test void popupMenuSeparator() { JPopupMenu.Separator c = new JPopupMenu.Separator();