diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java index eb04751f..39fb218b 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuBarUI.java @@ -18,6 +18,7 @@ package com.formdev.flatlaf.ui; import java.awt.Color; import java.awt.Graphics; +import java.awt.Insets; import java.awt.Window; import java.awt.event.ActionEvent; import java.beans.PropertyChangeListener; @@ -40,6 +41,7 @@ import javax.swing.plaf.UIResource; import javax.swing.plaf.basic.BasicMenuBarUI; import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatLaf; +import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; import com.formdev.flatlaf.util.SystemInfo; @@ -63,6 +65,15 @@ public class FlatMenuBarUI extends BasicMenuBarUI implements StyleableUI { + // used in FlatMenuItemBorder + /** @since 2 */ @Styleable protected Insets itemMargins; + + // used in FlatMenuUI + /** @since 2 */ @Styleable protected Color hoverBackground; + /** @since 2 */ @Styleable protected Color underlineSelectionBackground; + /** @since 2 */ @Styleable protected Color underlineSelectionColor; + /** @since 2 */ @Styleable protected int underlineSelectionHeight = -1; + private PropertyChangeListener propertyChangeListener; private Map oldStyleValues; private AtomicBoolean borderShared; diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemBorder.java index aa8079a6..108371ec 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuItemBorder.java @@ -18,9 +18,11 @@ package com.formdev.flatlaf.ui; import static com.formdev.flatlaf.util.UIScale.scale; import java.awt.Component; +import java.awt.Container; import java.awt.Insets; import javax.swing.JMenuBar; import javax.swing.UIManager; +import javax.swing.plaf.MenuBarUI; /** * Border for {@link javax.swing.JMenu}, {@link javax.swing.JMenuItem}, @@ -33,15 +35,22 @@ import javax.swing.UIManager; public class FlatMenuItemBorder extends FlatMarginBorder { + // only used if parent menubar is not a instance of FlatMenuBarUI private final Insets menuBarItemMargins = UIManager.getInsets( "MenuBar.itemMargins" ); @Override public Insets getBorderInsets( Component c, Insets insets ) { - if( c.getParent() instanceof JMenuBar ) { - insets.top = scale( menuBarItemMargins.top ); - insets.left = scale( menuBarItemMargins.left ); - insets.bottom = scale( menuBarItemMargins.bottom ); - insets.right = scale( menuBarItemMargins.right ); + Container parent = c.getParent(); + if( parent instanceof JMenuBar ) { + // get margins from FlatMenuBarUI to allow styling + MenuBarUI ui = ((JMenuBar)parent).getUI(); + Insets margins = (ui instanceof FlatMenuBarUI && ((FlatMenuBarUI)ui).itemMargins != null) + ? ((FlatMenuBarUI)ui).itemMargins + : this.menuBarItemMargins; + insets.top = scale( margins.top ); + insets.left = scale( margins.left ); + insets.bottom = scale( margins.bottom ); + insets.right = scale( margins.right ); return insets; } else return super.getBorderInsets( c, insets ); diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuUI.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuUI.java index 0767e7d8..edf94112 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuUI.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuUI.java @@ -23,15 +23,18 @@ import java.awt.Graphics; import java.awt.event.MouseEvent; import java.beans.PropertyChangeListener; import java.util.Map; +import java.util.function.Function; import javax.swing.ButtonModel; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JMenu; +import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.LookAndFeel; import javax.swing.UIManager; import javax.swing.event.MouseInputListener; import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.MenuBarUI; import javax.swing.plaf.basic.BasicMenuUI; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException; @@ -64,10 +67,10 @@ import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException; * * * @uiDefault MenuItem.iconTextGap int - * @uiDefault MenuBar.hoverBackground Color * * * + * @uiDefault MenuBar.hoverBackground Color * @uiDefault MenuBar.underlineSelectionBackground Color * @uiDefault MenuBar.underlineSelectionColor Color * @uiDefault MenuBar.underlineSelectionHeight int @@ -78,7 +81,6 @@ public class FlatMenuUI extends BasicMenuUI implements StyleableUI { - private Color hoverBackground; private FlatMenuItemRenderer renderer; private Map oldStyleValues; @@ -101,7 +103,6 @@ public class FlatMenuUI menuItem.setRolloverEnabled( true ); - hoverBackground = UIManager.getColor( "MenuBar.hoverBackground" ); renderer = createRenderer(); } @@ -109,7 +110,6 @@ public class FlatMenuUI protected void uninstallDefaults() { super.uninstallDefaults(); - hoverBackground = null; renderer = null; oldStyleValues = null; } @@ -200,9 +200,10 @@ public class FlatMenuUI protected class FlatMenuRenderer extends FlatMenuItemRenderer { - protected final Color menuBarUnderlineSelectionBackground = FlatUIUtils.getUIColor( "MenuBar.underlineSelectionBackground", underlineSelectionBackground ); - protected final Color menuBarUnderlineSelectionColor = FlatUIUtils.getUIColor( "MenuBar.underlineSelectionColor", underlineSelectionColor ); - protected final int menuBarUnderlineSelectionHeight = FlatUIUtils.getUIInt( "MenuBar.underlineSelectionHeight", underlineSelectionHeight ); + protected Color hoverBackground = UIManager.getColor( "MenuBar.hoverBackground" ); + protected Color menuBarUnderlineSelectionBackground = FlatUIUtils.getUIColor( "MenuBar.underlineSelectionBackground", underlineSelectionBackground ); + protected Color menuBarUnderlineSelectionColor = FlatUIUtils.getUIColor( "MenuBar.underlineSelectionColor", underlineSelectionColor ); + protected int menuBarUnderlineSelectionHeight = FlatUIUtils.getUIInt( "MenuBar.underlineSelectionHeight", underlineSelectionHeight ); protected FlatMenuRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon, Font acceleratorFont, String acceleratorDelimiter ) @@ -212,27 +213,39 @@ public class FlatMenuUI @Override protected void paintBackground( Graphics g, Color selectionBackground ) { - if( isUnderlineSelection() && ((JMenu)menuItem).isTopLevelMenu() ) - selectionBackground = menuBarUnderlineSelectionBackground; + if( ((JMenu)menuItem).isTopLevelMenu() ) { + if( isUnderlineSelection() ) + selectionBackground = getStyleFromMenuBarUI( ui -> ui.underlineSelectionBackground, menuBarUnderlineSelectionBackground ); - ButtonModel model = menuItem.getModel(); - if( model.isRollover() && !model.isArmed() && !model.isSelected() && - model.isEnabled() && ((JMenu)menuItem).isTopLevelMenu() ) - { - g.setColor( deriveBackground( hoverBackground ) ); - g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() ); - } else - super.paintBackground( g, selectionBackground ); + ButtonModel model = menuItem.getModel(); + if( model.isRollover() && !model.isArmed() && !model.isSelected() && model.isEnabled() ) { + g.setColor( deriveBackground( getStyleFromMenuBarUI( ui -> ui.hoverBackground, hoverBackground ) ) ); + g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() ); + return; + } + } + + super.paintBackground( g, selectionBackground ); } @Override protected void paintUnderlineSelection( Graphics g, Color underlineSelectionColor, int underlineSelectionHeight ) { if( ((JMenu)menuItem).isTopLevelMenu() ) { - underlineSelectionColor = menuBarUnderlineSelectionColor; - underlineSelectionHeight = menuBarUnderlineSelectionHeight; + underlineSelectionColor = getStyleFromMenuBarUI( ui -> ui.underlineSelectionColor, menuBarUnderlineSelectionColor ); + underlineSelectionHeight = getStyleFromMenuBarUI( ui -> (ui.underlineSelectionHeight != -1) + ? ui.underlineSelectionHeight : null, menuBarUnderlineSelectionHeight ); } super.paintUnderlineSelection( g, underlineSelectionColor, underlineSelectionHeight ); } + + private T getStyleFromMenuBarUI( Function f, T defaultValue ) { + MenuBarUI ui = ((JMenuBar)menuItem.getParent()).getUI(); + if( !(ui instanceof FlatMenuBarUI) ) + return defaultValue; + + T value = f.apply( (FlatMenuBarUI) ui ); + return (value != null) ? value : defaultValue; + } } } 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 46da6a99..55ec6d4d 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 @@ -264,6 +264,12 @@ public class TestFlatStyleableInfo FlatMenuBarUI ui = (FlatMenuBarUI) c.getUI(); Map> expected = expectedMap( + "itemMargins", Insets.class, + "hoverBackground", Color.class, + "underlineSelectionBackground", Color.class, + "underlineSelectionColor", Color.class, + "underlineSelectionHeight", int.class, + // FlatMenuBarBorder "borderColor", Color.class ); 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 5f3b99cd..6b819dec 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 @@ -362,6 +362,12 @@ public class TestFlatStyling JMenuBar c = new JMenuBar(); FlatMenuBarUI ui = (FlatMenuBarUI) c.getUI(); + ui.applyStyle( "itemMargins: 1,2,3,4" ); + ui.applyStyle( "hoverBackground: #fff" ); + ui.applyStyle( "underlineSelectionBackground: #fff" ); + ui.applyStyle( "underlineSelectionColor: #fff" ); + ui.applyStyle( "underlineSelectionHeight: 3" ); + // FlatMenuBarBorder ui.applyStyle( "borderColor: #fff" );