Skip to content

Commit

Permalink
Menus: support "underline" menu selection type (suggested in issue #49)
Browse files Browse the repository at this point in the history
  • Loading branch information
DevCharly committed Apr 28, 2020
1 parent bd2f5dd commit e8c8bec
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
*
* @uiDefault MenuItemCheckBox.icon.checkmarkColor Color
* @uiDefault MenuItemCheckBox.icon.disabledCheckmarkColor Color
* @uiDefault Menu.selectionForeground Color
* @uiDefault MenuItem.selectionForeground Color
* @uiDefault MenuItem.selectionType String
*
* @author Karl Tauber
*/
Expand All @@ -39,7 +40,7 @@ public class FlatCheckBoxMenuItemIcon
{
protected final Color checkmarkColor = UIManager.getColor( "MenuItemCheckBox.icon.checkmarkColor" );
protected final Color disabledCheckmarkColor = UIManager.getColor( "MenuItemCheckBox.icon.disabledCheckmarkColor" );
protected final Color selectionForeground = UIManager.getColor( "Menu.selectionForeground" );
protected final Color selectionForeground = UIManager.getColor( "MenuItem.selectionForeground" );

public FlatCheckBoxMenuItemIcon() {
super( 15, 15, null );
Expand Down Expand Up @@ -67,9 +68,14 @@ protected void paintCheckmark( Graphics2D g2 ) {
}

private Color getCheckmarkColor( Component c ) {
if( c instanceof JMenuItem && ((JMenuItem)c).isArmed() )
if( c instanceof JMenuItem && ((JMenuItem)c).isArmed() && !isUnderlineSelection() )
return selectionForeground;

return c.isEnabled() ? checkmarkColor : disabledCheckmarkColor;
}

private boolean isUnderlineSelection() {
// not storing value of "MenuItem.selectionType" in class to allow changing at runtime
return "underline".equals( UIManager.getString( "MenuItem.selectionType" ) );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
* @uiDefault Menu.icon.arrowColor Color
* @uiDefault Menu.icon.disabledArrowColor Color
* @uiDefault Menu.selectionForeground Color
* @uiDefault MenuItem.selectionType String
*
* @author Karl Tauber
*/
Expand Down Expand Up @@ -65,9 +66,14 @@ protected void paintIcon( Component c, Graphics2D g ) {
}

private Color getArrowColor( Component c ) {
if( c instanceof JMenu && ((JMenu)c).isSelected() )
if( c instanceof JMenu && ((JMenu)c).isSelected() && !isUnderlineSelection() )
return selectionForeground;

return c.isEnabled() ? arrowColor : disabledArrowColor;
}

private boolean isUnderlineSelection() {
// not storing value of "MenuItem.selectionType" in class to allow changing at runtime
return "underline".equals( UIManager.getString( "MenuItem.selectionType" ) );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ public class FlatMenuItemRenderer
protected final int textAcceleratorGap;
protected final int textArrowGap;

protected final String selectionType = UIManager.getString( "MenuItem.selectionType" );
protected final Color underlineSelectionBackground = UIManager.getColor( "MenuItem.underlineSelectionBackground" );
protected final Color underlineSelectionColor = UIManager.getColor( "MenuItem.underlineSelectionColor" );
protected final int underlineSelectionHeight = UIManager.getInt( "MenuItem.underlineSelectionHeight" );

protected FlatMenuItemRenderer( JMenuItem menuItem, Icon checkIcon, Icon arrowIcon,
Font acceleratorFont, String acceleratorDelimiter )
{
Expand Down Expand Up @@ -226,8 +231,30 @@ protected void paintMenuItem( Graphics g, Color selectionBackground, Color selec
protected void paintBackground( Graphics g, Color selectionBackground ) {
boolean armedOrSelected = isArmedOrSelected( menuItem );
if( menuItem.isOpaque() || armedOrSelected ) {
g.setColor( armedOrSelected ? selectionBackground : menuItem.getBackground() );
g.fillRect( 0, 0, menuItem.getWidth(), menuItem.getHeight() );
int width = menuItem.getWidth();
int height = menuItem.getHeight();

// paint background
g.setColor( armedOrSelected
? (isUnderlineSelection() ? underlineSelectionBackground : 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 );
}
}
}
}

Expand All @@ -252,16 +279,17 @@ protected void paintText( Graphics g, Rectangle textRect, String text, Color sel
}

int mnemonicIndex = FlatLaf.isShowMnemonics() ? menuItem.getDisplayedMnemonicIndex() : -1;
Color foreground = menuItem.getForeground();

paintText( g, menuItem, textRect, text, mnemonicIndex, menuItem.getFont(),
menuItem.getForeground(), selectionForeground, disabledForeground );
foreground, isUnderlineSelection() ? foreground : selectionForeground, disabledForeground );
}

protected void paintAccelerator( Graphics g, Rectangle accelRect, String accelText,
Color foreground, Color selectionForeground, Color disabledForeground )
{
paintText( g, menuItem, accelRect, accelText, -1, acceleratorFont,
foreground, selectionForeground, disabledForeground );
foreground, isUnderlineSelection() ? foreground : selectionForeground, disabledForeground );
}

protected void paintArrowIcon( Graphics g, Rectangle arrowRect, Icon arrowIcon ) {
Expand Down Expand Up @@ -311,6 +339,10 @@ protected static boolean isTopLevelMenu( JMenuItem menuItem ) {
return menuItem instanceof JMenu && ((JMenu)menuItem).isTopLevelMenu();
}

private boolean isUnderlineSelection() {
return "underline".equals( selectionType );
}

private Icon getIconForPainting() {
Icon icon = menuItem.getIcon();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
@disabledText=#777777
@textComponentBackground=#45494A
@menuBackground=darken(@background,5%)
@menuHoverBackground=lighten(@menuBackground,10%)
@menuCheckBackground=lighten(@menuBackground,15%)
@cellFocusColor=#000000
@icon=#adadad
Expand Down Expand Up @@ -171,7 +172,7 @@ Menu.icon.disabledArrowColor=#606060
#---- MenuBar ----

MenuBar.borderColor=#515151
MenuBar.hoverBackground=lighten($MenuBar.background,10%)
MenuBar.hoverBackground=@menuHoverBackground


#---- MenuItemCheckBox ----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,11 @@ MenuItem.textArrowGap=8
MenuItem.acceleratorDelimiter=-
[mac]MenuItem.acceleratorDelimiter=

# for MenuItem.selectionType=underline
MenuItem.underlineSelectionBackground=@menuHoverBackground
MenuItem.underlineSelectionColor=$TabbedPane.underlineColor
MenuItem.underlineSelectionHeight=3


#---- OptionPane ----

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
@disabledText=#8C8C8C
@textComponentBackground=#ffffff
@menuBackground=#fff
@menuHoverBackground=darken(@menuBackground,10%)
@menuCheckBackground=darken(@menuBackground,15%)
@cellFocusColor=#000000
@icon=#afafaf
Expand Down Expand Up @@ -178,7 +179,7 @@ Menu.icon.disabledArrowColor=#ABABAB
#---- MenuBar ----

MenuBar.borderColor=#cdcdcd
MenuBar.hoverBackground=darken($MenuBar.background,10%)
MenuBar.hoverBackground=@menuHoverBackground


#---- MenuItemCheckBox ----
Expand Down
19 changes: 19 additions & 0 deletions flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ private void menuItemActionPerformed( ActionEvent e ) {
} );
}

private void underlineMenuSelection() {
UIManager.put( "MenuItem.selectionType", underlineMenuSelectionMenuItem.isSelected() ? "underline" : null );
FlatLaf.updateUI();
}

private void fontFamilyChanged( ActionEvent e ) {
String fontFamily = e.getActionCommand();

Expand Down Expand Up @@ -132,6 +137,8 @@ private void initComponents() {
JMenuItem restoreFontMenuItem = new JMenuItem();
JMenuItem incrFontMenuItem = new JMenuItem();
JMenuItem decrFontMenuItem = new JMenuItem();
JMenu optionsMenu = new JMenu();
underlineMenuSelectionMenuItem = new JCheckBoxMenuItem();
JMenu helpMenu = new JMenu();
JMenuItem aboutMenuItem = new JMenuItem();
JToolBar toolBar1 = new JToolBar();
Expand Down Expand Up @@ -355,6 +362,17 @@ private void initComponents() {
}
menuBar1.add(fontMenu);

//======== optionsMenu ========
{
optionsMenu.setText("Options");

//---- underlineMenuSelectionMenuItem ----
underlineMenuSelectionMenuItem.setText("Use underline menu selection");
underlineMenuSelectionMenuItem.addActionListener(e -> underlineMenuSelection());
optionsMenu.add(underlineMenuSelectionMenuItem);
}
menuBar1.add(optionsMenu);

//======== helpMenu ========
{
helpMenu.setText("Help");
Expand Down Expand Up @@ -481,6 +499,7 @@ private void initComponents() {

// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
private JMenu fontMenu;
private JCheckBoxMenuItem underlineMenuSelectionMenuItem;
private JTabbedPane tabbedPane;
private ControlBar controlBar;
// JFormDesigner - End of variables declaration //GEN-END:variables
Expand Down
12 changes: 12 additions & 0 deletions flatlaf-demo/src/main/java/com/formdev/flatlaf/demo/DemoFrame.jfd
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,18 @@ new FormModel {
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "decrFont", false ) )
} )
} )
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
name: "optionsMenu"
"text": "Options"
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
name: "underlineMenuSelectionMenuItem"
"text": "Use underline menu selection"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "underlineMenuSelection", false ) )
} )
} )
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
name: "helpMenu"
"text": "Help"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.awt.event.*;
import java.util.function.Supplier;
import javax.swing.*;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.util.UIScale;
import net.miginfocom.swing.*;

Expand Down Expand Up @@ -61,6 +62,11 @@ private void arm( Container container, boolean armed ) {
}
}

private void underlineChanged() {
UIManager.put( "MenuItem.selectionType", underlineCheckBox.isSelected() ? "underline" : null );
FlatLaf.updateUI();
}

private void showPopupMenuButtonActionPerformed(ActionEvent e) {
Component invoker = (Component) e.getSource();
PopupMenu popupMenu = new PopupMenu();
Expand Down Expand Up @@ -193,6 +199,7 @@ private void initComponents() {
JLabel popupMenuLabel = new JLabel();
JButton showPopupMenuButton = new JButton();
armedCheckBox = new JCheckBox();
underlineCheckBox = new JCheckBox();

//======== this ========
setLayout(new MigLayout(
Expand All @@ -207,6 +214,7 @@ private void initComponents() {
"[]" +
"[top]" +
"[]" +
"[]" +
"[]"));

//---- menuBarLabel ----
Expand Down Expand Up @@ -691,6 +699,11 @@ private void initComponents() {
armedCheckBox.addActionListener(e -> armedChanged());
add(armedCheckBox, "cell 0 3");

//---- underlineCheckBox ----
underlineCheckBox.setText("underline menu selection");
underlineCheckBox.addActionListener(e -> underlineChanged());
add(underlineCheckBox, "cell 0 4 2 1");

//---- buttonGroup1 ----
ButtonGroup buttonGroup1 = new ButtonGroup();
buttonGroup1.add(radioButtonMenuItem5);
Expand All @@ -708,6 +721,7 @@ private void initComponents() {
private JCheckBox largerCheckBox;
private JCheckBox accelCheckBox;
private JCheckBox armedCheckBox;
private JCheckBox underlineCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables

//---- class PopupMenu ----------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ new FormModel {
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
"$columnConstraints": "[125][][][][]"
"$rowConstraints": "[][top][][]"
"$rowConstraints": "[][top][][][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
Expand Down Expand Up @@ -528,6 +528,16 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 3"
} )
add( new FormComponent( "javax.swing.JCheckBox" ) {
name: "underlineCheckBox"
"text": "underline menu selection"
auxiliary() {
"JavaCodeGenerator.variableLocal": false
}
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "underlineChanged", false ) )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 4 2 1"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 790, 380 )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,9 @@ MenuItem.selectionBackground #4b6eaf javax.swing.plaf.ColorUIResource [UI]
MenuItem.selectionForeground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
MenuItem.textAcceleratorGap 24
MenuItem.textArrowGap 8
MenuItem.underlineSelectionBackground #484c4f javax.swing.plaf.ColorUIResource [UI]
MenuItem.underlineSelectionColor #4a88c7 javax.swing.plaf.ColorUIResource [UI]
MenuItem.underlineSelectionHeight 3


#---- MenuItemCheckBox ----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,9 @@ MenuItem.selectionBackground #4b6eaf javax.swing.plaf.ColorUIResource [UI]
MenuItem.selectionForeground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
MenuItem.textAcceleratorGap 24
MenuItem.textArrowGap 8
MenuItem.underlineSelectionBackground #484c4f javax.swing.plaf.ColorUIResource [UI]
MenuItem.underlineSelectionColor #4a88c7 javax.swing.plaf.ColorUIResource [UI]
MenuItem.underlineSelectionHeight 3


#---- MenuItemCheckBox ----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,9 @@ MenuItem.selectionBackground #2675bf javax.swing.plaf.ColorUIResource [UI]
MenuItem.selectionForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
MenuItem.textAcceleratorGap 24
MenuItem.textArrowGap 8
MenuItem.underlineSelectionBackground #e6e6e6 javax.swing.plaf.ColorUIResource [UI]
MenuItem.underlineSelectionColor #4083c9 javax.swing.plaf.ColorUIResource [UI]
MenuItem.underlineSelectionHeight 3


#---- MenuItemCheckBox ----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,9 @@ MenuItem.selectionBackground #2675bf javax.swing.plaf.ColorUIResource [UI]
MenuItem.selectionForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
MenuItem.textAcceleratorGap 24
MenuItem.textArrowGap 8
MenuItem.underlineSelectionBackground #e6e6e6 javax.swing.plaf.ColorUIResource [UI]
MenuItem.underlineSelectionColor #4083c9 javax.swing.plaf.ColorUIResource [UI]
MenuItem.underlineSelectionHeight 3


#---- MenuItemCheckBox ----
Expand Down

0 comments on commit e8c8bec

Please sign in to comment.