Styling: Menu: support top-level underline selection

This commit is contained in:
Karl Tauber
2021-09-08 14:55:41 +02:00
parent 08ca2aa266
commit e0dddfceba
5 changed files with 69 additions and 24 deletions

View File

@@ -18,6 +18,7 @@ package com.formdev.flatlaf.ui;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
@@ -40,6 +41,7 @@ import javax.swing.plaf.UIResource;
import javax.swing.plaf.basic.BasicMenuBarUI; import javax.swing.plaf.basic.BasicMenuBarUI;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.FlatLaf;
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.SystemInfo; import com.formdev.flatlaf.util.SystemInfo;
@@ -63,6 +65,15 @@ public class FlatMenuBarUI
extends BasicMenuBarUI extends BasicMenuBarUI
implements StyleableUI 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 PropertyChangeListener propertyChangeListener;
private Map<String, Object> oldStyleValues; private Map<String, Object> oldStyleValues;
private AtomicBoolean borderShared; private AtomicBoolean borderShared;

View File

@@ -18,9 +18,11 @@ package com.formdev.flatlaf.ui;
import static com.formdev.flatlaf.util.UIScale.scale; import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Component; import java.awt.Component;
import java.awt.Container;
import java.awt.Insets; import java.awt.Insets;
import javax.swing.JMenuBar; import javax.swing.JMenuBar;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.plaf.MenuBarUI;
/** /**
* Border for {@link javax.swing.JMenu}, {@link javax.swing.JMenuItem}, * Border for {@link javax.swing.JMenu}, {@link javax.swing.JMenuItem},
@@ -33,15 +35,22 @@ import javax.swing.UIManager;
public class FlatMenuItemBorder public class FlatMenuItemBorder
extends FlatMarginBorder extends FlatMarginBorder
{ {
// only used if parent menubar is not a instance of FlatMenuBarUI
private final Insets menuBarItemMargins = UIManager.getInsets( "MenuBar.itemMargins" ); private final Insets menuBarItemMargins = UIManager.getInsets( "MenuBar.itemMargins" );
@Override @Override
public Insets getBorderInsets( Component c, Insets insets ) { public Insets getBorderInsets( Component c, Insets insets ) {
if( c.getParent() instanceof JMenuBar ) { Container parent = c.getParent();
insets.top = scale( menuBarItemMargins.top ); if( parent instanceof JMenuBar ) {
insets.left = scale( menuBarItemMargins.left ); // get margins from FlatMenuBarUI to allow styling
insets.bottom = scale( menuBarItemMargins.bottom ); MenuBarUI ui = ((JMenuBar)parent).getUI();
insets.right = scale( menuBarItemMargins.right ); 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; return insets;
} else } else
return super.getBorderInsets( c, insets ); return super.getBorderInsets( c, insets );

View File

@@ -23,15 +23,18 @@ import java.awt.Graphics;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.Map; import java.util.Map;
import java.util.function.Function;
import javax.swing.ButtonModel; import javax.swing.ButtonModel;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JMenu; import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.LookAndFeel; import javax.swing.LookAndFeel;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.event.MouseInputListener; import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.MenuBarUI;
import javax.swing.plaf.basic.BasicMenuUI; import javax.swing.plaf.basic.BasicMenuUI;
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException; import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
@@ -64,10 +67,10 @@ import com.formdev.flatlaf.ui.FlatStylingSupport.UnknownStyleException;
* <!-- FlatMenuUI --> * <!-- FlatMenuUI -->
* *
* @uiDefault MenuItem.iconTextGap int * @uiDefault MenuItem.iconTextGap int
* @uiDefault MenuBar.hoverBackground Color
* *
* <!-- FlatMenuRenderer --> * <!-- FlatMenuRenderer -->
* *
* @uiDefault MenuBar.hoverBackground Color
* @uiDefault MenuBar.underlineSelectionBackground Color * @uiDefault MenuBar.underlineSelectionBackground Color
* @uiDefault MenuBar.underlineSelectionColor Color * @uiDefault MenuBar.underlineSelectionColor Color
* @uiDefault MenuBar.underlineSelectionHeight int * @uiDefault MenuBar.underlineSelectionHeight int
@@ -78,7 +81,6 @@ public class FlatMenuUI
extends BasicMenuUI extends BasicMenuUI
implements StyleableUI implements StyleableUI
{ {
private Color hoverBackground;
private FlatMenuItemRenderer renderer; private FlatMenuItemRenderer renderer;
private Map<String, Object> oldStyleValues; private Map<String, Object> oldStyleValues;
@@ -101,7 +103,6 @@ public class FlatMenuUI
menuItem.setRolloverEnabled( true ); menuItem.setRolloverEnabled( true );
hoverBackground = UIManager.getColor( "MenuBar.hoverBackground" );
renderer = createRenderer(); renderer = createRenderer();
} }
@@ -109,7 +110,6 @@ public class FlatMenuUI
protected void uninstallDefaults() { protected void uninstallDefaults() {
super.uninstallDefaults(); super.uninstallDefaults();
hoverBackground = null;
renderer = null; renderer = null;
oldStyleValues = null; oldStyleValues = null;
} }
@@ -200,9 +200,10 @@ public class FlatMenuUI
protected class FlatMenuRenderer protected class FlatMenuRenderer
extends FlatMenuItemRenderer extends FlatMenuItemRenderer
{ {
protected final Color menuBarUnderlineSelectionBackground = FlatUIUtils.getUIColor( "MenuBar.underlineSelectionBackground", underlineSelectionBackground ); protected Color hoverBackground = UIManager.getColor( "MenuBar.hoverBackground" );
protected final Color menuBarUnderlineSelectionColor = FlatUIUtils.getUIColor( "MenuBar.underlineSelectionColor", underlineSelectionColor ); protected Color menuBarUnderlineSelectionBackground = FlatUIUtils.getUIColor( "MenuBar.underlineSelectionBackground", underlineSelectionBackground );
protected final int menuBarUnderlineSelectionHeight = FlatUIUtils.getUIInt( "MenuBar.underlineSelectionHeight", underlineSelectionHeight ); protected Color menuBarUnderlineSelectionColor = FlatUIUtils.getUIColor( "MenuBar.underlineSelectionColor", underlineSelectionColor );
protected int menuBarUnderlineSelectionHeight = FlatUIUtils.getUIInt( "MenuBar.underlineSelectionHeight", underlineSelectionHeight );
protected FlatMenuRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon, protected FlatMenuRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon,
Font acceleratorFont, String acceleratorDelimiter ) Font acceleratorFont, String acceleratorDelimiter )
@@ -212,27 +213,39 @@ public class FlatMenuUI
@Override @Override
protected void paintBackground( Graphics g, Color selectionBackground ) { protected void paintBackground( Graphics g, Color selectionBackground ) {
if( isUnderlineSelection() && ((JMenu)menuItem).isTopLevelMenu() ) if( ((JMenu)menuItem).isTopLevelMenu() ) {
selectionBackground = menuBarUnderlineSelectionBackground; if( isUnderlineSelection() )
selectionBackground = getStyleFromMenuBarUI( ui -> ui.underlineSelectionBackground, menuBarUnderlineSelectionBackground );
ButtonModel model = menuItem.getModel(); ButtonModel model = menuItem.getModel();
if( model.isRollover() && !model.isArmed() && !model.isSelected() && if( model.isRollover() && !model.isArmed() && !model.isSelected() && model.isEnabled() ) {
model.isEnabled() && ((JMenu)menuItem).isTopLevelMenu() ) g.setColor( deriveBackground( getStyleFromMenuBarUI( ui -> ui.hoverBackground, hoverBackground ) ) );
{ g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
g.setColor( deriveBackground( hoverBackground ) ); return;
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() ); }
} else }
super.paintBackground( g, selectionBackground );
super.paintBackground( g, selectionBackground );
} }
@Override @Override
protected void paintUnderlineSelection( Graphics g, Color underlineSelectionColor, int underlineSelectionHeight ) { protected void paintUnderlineSelection( Graphics g, Color underlineSelectionColor, int underlineSelectionHeight ) {
if( ((JMenu)menuItem).isTopLevelMenu() ) { if( ((JMenu)menuItem).isTopLevelMenu() ) {
underlineSelectionColor = menuBarUnderlineSelectionColor; underlineSelectionColor = getStyleFromMenuBarUI( ui -> ui.underlineSelectionColor, menuBarUnderlineSelectionColor );
underlineSelectionHeight = menuBarUnderlineSelectionHeight; underlineSelectionHeight = getStyleFromMenuBarUI( ui -> (ui.underlineSelectionHeight != -1)
? ui.underlineSelectionHeight : null, menuBarUnderlineSelectionHeight );
} }
super.paintUnderlineSelection( g, underlineSelectionColor, underlineSelectionHeight ); super.paintUnderlineSelection( g, underlineSelectionColor, underlineSelectionHeight );
} }
private <T> T getStyleFromMenuBarUI( Function<FlatMenuBarUI, T> 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;
}
} }
} }

View File

@@ -264,6 +264,12 @@ public class TestFlatStyleableInfo
FlatMenuBarUI ui = (FlatMenuBarUI) c.getUI(); FlatMenuBarUI ui = (FlatMenuBarUI) c.getUI();
Map<String, Class<?>> expected = expectedMap( Map<String, Class<?>> expected = expectedMap(
"itemMargins", Insets.class,
"hoverBackground", Color.class,
"underlineSelectionBackground", Color.class,
"underlineSelectionColor", Color.class,
"underlineSelectionHeight", int.class,
// FlatMenuBarBorder // FlatMenuBarBorder
"borderColor", Color.class "borderColor", Color.class
); );

View File

@@ -362,6 +362,12 @@ public class TestFlatStyling
JMenuBar c = new JMenuBar(); JMenuBar c = new JMenuBar();
FlatMenuBarUI ui = (FlatMenuBarUI) c.getUI(); 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 // FlatMenuBarBorder
ui.applyStyle( "borderColor: #fff" ); ui.applyStyle( "borderColor: #fff" );