Skip to content

Commit

Permalink
MenuBar: support different underline menu selection style UI defaults…
Browse files Browse the repository at this point in the history
… for `MenuBar` and `MenuItem`. (PR #217; issue #216)
  • Loading branch information
DevCharly committed Dec 5, 2020
1 parent f149d2b commit 14df490
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 35 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ FlatLaf Change Log
- Added "Gradianto Nature Green" theme.
- Updated "Arc Dark", "Cyan", "Dark purple", "Gradianto", "Gray", "Gruvbox"
and "One Dark" themes.
- MenuBar: Support different underline menu selection style UI defaults for
`MenuBar` and `MenuItem`. (PR #217; issue #216)


#### Fixed bugs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.View;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.util.DerivedColor;
import com.formdev.flatlaf.util.Graphics2DProxy;
import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.SystemInfo;
Expand All @@ -55,7 +56,7 @@
* @uiDefault MenuItem.underlineSelectionBackground Color
* @uiDefault MenuItem.underlineSelectionCheckBackground Color
* @uiDefault MenuItem.underlineSelectionColor Color
* @uiDefault MenuItem.underlineSelectionHeight Color
* @uiDefault MenuItem.underlineSelectionHeight int
*
* @author Karl Tauber
*/
Expand Down Expand Up @@ -246,60 +247,63 @@ protected void paintMenuItem( Graphics g, Color selectionBackground, Color selec
g.setColor( Color.orange ); g.drawRect( arrowRect.x, arrowRect.y, arrowRect.width - 1, arrowRect.height - 1 );
debug*/

paintBackground( g, selectionBackground, underlineSelectionColor );
paintIcon( g, iconRect, getIconForPainting() );
boolean underlineSelection = isUnderlineSelection();
paintBackground( g, underlineSelection ? underlineSelectionBackground : selectionBackground );
if( underlineSelection && isArmedOrSelected( menuItem ) )
paintUnderlineSelection( g, underlineSelectionColor, underlineSelectionHeight );
paintIcon( g, iconRect, getIconForPainting(), underlineSelection ? underlineSelectionCheckBackground : checkBackground );
paintText( g, textRect, menuItem.getText(), selectionForeground, disabledForeground );
paintAccelerator( g, accelRect, getAcceleratorText(), acceleratorForeground, acceleratorSelectionForeground, disabledForeground );
if( !isTopLevelMenu( menuItem ) )
paintArrowIcon( g, arrowRect, arrowIcon );
}

protected void paintBackground( Graphics g, Color selectionBackground, Color underlineSelectionColor ) {
protected void paintBackground( Graphics g, Color selectionBackground ) {
boolean armedOrSelected = isArmedOrSelected( menuItem );
if( menuItem.isOpaque() || armedOrSelected ) {
int width = menuItem.getWidth();
int height = menuItem.getHeight();

// paint background
g.setColor( armedOrSelected
? (isUnderlineSelection()
? deriveBackground( underlineSelectionBackground )
: selectionBackground)
? deriveBackground( selectionBackground )
: menuItem.getBackground() );
g.fillRect( 0, 0, width, height );

// paint underline
if( armedOrSelected && isUnderlineSelection() ) {
int underlineHeight = scale( underlineSelectionHeight );
g.setColor( underlineSelectionColor );
if( isTopLevelMenu( menuItem ) ) {
// paint underline at bottom
g.fillRect( 0, height - underlineHeight, width, underlineHeight );
} else if( menuItem.getComponentOrientation().isLeftToRight() ) {
// paint underline at left side
g.fillRect( 0, 0, underlineHeight, height );
} else {
// paint underline at right side
g.fillRect( width - underlineHeight, 0, underlineHeight, height );
}
}
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
}
}

protected void paintUnderlineSelection( Graphics g, Color underlineSelectionColor, int underlineSelectionHeight ) {
int width = menuItem.getWidth();
int height = menuItem.getHeight();

int underlineHeight = scale( underlineSelectionHeight );
g.setColor( underlineSelectionColor );
if( isTopLevelMenu( menuItem ) ) {
// paint underline at bottom
g.fillRect( 0, height - underlineHeight, width, underlineHeight );
} else if( menuItem.getComponentOrientation().isLeftToRight() ) {
// paint underline at left side
g.fillRect( 0, 0, underlineHeight, height );
} else {
// paint underline at right side
g.fillRect( width - underlineHeight, 0, underlineHeight, height );
}
}

protected Color deriveBackground( Color background ) {
if( !(background instanceof DerivedColor) )
return background;

Color baseColor = menuItem.isOpaque()
? menuItem.getBackground()
: FlatUIUtils.getParentBackground( menuItem );

return FlatUIUtils.deriveColor( background, baseColor );
}

protected void paintIcon( Graphics g, Rectangle iconRect, Icon icon ) {
protected void paintIcon( Graphics g, Rectangle iconRect, Icon icon, Color checkBackground ) {
// if checkbox/radiobutton menu item is selected and also has a custom icon,
// then use filled icon background to indicate selection (instead of using checkIcon)
if( menuItem.isSelected() && checkIcon != null && icon != checkIcon ) {
Rectangle r = FlatUIUtils.addInsets( iconRect, scale( checkMargins ) );
g.setColor( deriveBackground( isUnderlineSelection() ? underlineSelectionCheckBackground : checkBackground ) );
g.setColor( deriveBackground( checkBackground ) );
g.fillRect( r.x, r.y, r.width, r.height );
}

Expand Down
30 changes: 25 additions & 5 deletions flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatMenuUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,19 @@
* <!-- FlatMenuUI -->
*
* @uiDefault MenuItem.iconTextGap int
* @uiDefault MenuBar.hoverBackground
* @uiDefault MenuBar.hoverBackground Color
*
* <!-- FlatMenuRenderer -->
*
* @uiDefault MenuBar.underlineSelectionBackground Color
* @uiDefault MenuBar.underlineSelectionColor Color
* @uiDefault MenuBar.underlineSelectionHeight int
*
* @author Karl Tauber
*/
public class FlatMenuUI
extends BasicMenuUI
{
protected final Color menuBarUnderlineSelectionColor = UIManager.getColor( "MenuBar.underlineSelectionColor" );

private Color hoverBackground;
private FlatMenuItemRenderer renderer;

Expand Down Expand Up @@ -150,22 +153,39 @@ public void paint( Graphics g, JComponent c ) {
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 FlatMenuRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon,
Font acceleratorFont, String acceleratorDelimiter )
{
super( menuItem, checkIcon, arrowIcon, acceleratorFont, acceleratorDelimiter );
}

@Override
protected void paintBackground( Graphics g, Color selectionBackground, Color menuItemUnderlineSelectionColor ) {
protected void paintBackground( Graphics g, Color selectionBackground ) {
if( isUnderlineSelection() && ((JMenu)menuItem).isTopLevelMenu() )
selectionBackground = 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, ((JMenu)menuItem).isTopLevelMenu() ? menuBarUnderlineSelectionColor : menuItemUnderlineSelectionColor );
super.paintBackground( g, selectionBackground );
}

@Override
protected void paintUnderlineSelection( Graphics g, Color underlineSelectionColor, int underlineSelectionHeight ) {
if( ((JMenu)menuItem).isTopLevelMenu() ) {
underlineSelectionColor = menuBarUnderlineSelectionColor;
underlineSelectionHeight = menuBarUnderlineSelectionHeight;
}

super.paintUnderlineSelection( g, underlineSelectionColor, underlineSelectionHeight );
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@ MenuBar.border=com.formdev.flatlaf.ui.FlatMenuBarBorder
MenuBar.background=@menuBackground
MenuBar.hoverBackground=@menuHoverBackground
MenuBar.itemMargins=3,8,3,8
MenuBar.underlineSelectionColor=$TabbedPane.underlineColor


#---- MenuItem ----
Expand Down
3 changes: 3 additions & 0 deletions flatlaf-testing/dumps/uidefaults/FlatTestLaf_1.8.0_202.txt
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,9 @@ MenuBar.highlight #ffffff javax.swing.plaf.ColorUIResource [UI]
MenuBar.hoverBackground #ffdddd javax.swing.plaf.ColorUIResource [UI]
MenuBar.itemMargins 3,8,3,8 javax.swing.plaf.InsetsUIResource [UI]
MenuBar.shadow #a0a0a0 javax.swing.plaf.ColorUIResource [UI]
MenuBar.underlineSelectionBackground #00ff00 javax.swing.plaf.ColorUIResource [UI]
MenuBar.underlineSelectionColor #ff0000 javax.swing.plaf.ColorUIResource [UI]
MenuBar.underlineSelectionHeight 5
MenuBar.windowBindings length=2 [Ljava.lang.Object;
[0] F10
[1] takeFocus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ Menu.icon.disabledArrowColor=#ABABAB
MenuBar.borderColor=#44f
MenuBar.hoverBackground=#fdd

MenuBar.underlineSelectionBackground=#0f0
MenuBar.underlineSelectionColor=#f00
MenuBar.underlineSelectionHeight=5

#---- MenuItemCheckBox ----

Expand Down

0 comments on commit 14df490

Please sign in to comment.