Menus: support "underline" menu selection type (suggested in issue #49)

This commit is contained in:
Karl Tauber
2020-04-29 00:26:25 +02:00
parent bd2f5dd6fe
commit e8c8bece3f
14 changed files with 129 additions and 11 deletions

View File

@@ -30,7 +30,8 @@ import javax.swing.UIManager;
*
* @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
*/
@@ -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 );
@@ -67,9 +68,14 @@ public class FlatCheckBoxMenuItemIcon
}
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" ) );
}
}

View File

@@ -32,6 +32,7 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
* @uiDefault Menu.icon.arrowColor Color
* @uiDefault Menu.icon.disabledArrowColor Color
* @uiDefault Menu.selectionForeground Color
* @uiDefault MenuItem.selectionType String
*
* @author Karl Tauber
*/
@@ -65,9 +66,14 @@ public class FlatMenuArrowIcon
}
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" ) );
}
}

View File

@@ -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 )
{
@@ -226,8 +231,30 @@ debug*/
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 );
}
}
}
}
@@ -252,16 +279,17 @@ debug*/
}
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 ) {
@@ -311,6 +339,10 @@ debug*/
return menuItem instanceof JMenu && ((JMenu)menuItem).isTopLevelMenu();
}
private boolean isUnderlineSelection() {
return "underline".equals( selectionType );
}
private Icon getIconForPainting() {
Icon icon = menuItem.getIcon();

View File

@@ -29,6 +29,7 @@
@disabledText=#777777
@textComponentBackground=#45494A
@menuBackground=darken(@background,5%)
@menuHoverBackground=lighten(@menuBackground,10%)
@menuCheckBackground=lighten(@menuBackground,15%)
@cellFocusColor=#000000
@icon=#adadad
@@ -171,7 +172,7 @@ Menu.icon.disabledArrowColor=#606060
#---- MenuBar ----
MenuBar.borderColor=#515151
MenuBar.hoverBackground=lighten($MenuBar.background,10%)
MenuBar.hoverBackground=@menuHoverBackground
#---- MenuItemCheckBox ----

View File

@@ -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 ----

View File

@@ -29,6 +29,7 @@
@disabledText=#8C8C8C
@textComponentBackground=#ffffff
@menuBackground=#fff
@menuHoverBackground=darken(@menuBackground,10%)
@menuCheckBackground=darken(@menuBackground,15%)
@cellFocusColor=#000000
@icon=#afafaf
@@ -178,7 +179,7 @@ Menu.icon.disabledArrowColor=#ABABAB
#---- MenuBar ----
MenuBar.borderColor=#cdcdcd
MenuBar.hoverBackground=darken($MenuBar.background,10%)
MenuBar.hoverBackground=@menuHoverBackground
#---- MenuItemCheckBox ----

View File

@@ -59,6 +59,11 @@ class DemoFrame
} );
}
private void underlineMenuSelection() {
UIManager.put( "MenuItem.selectionType", underlineMenuSelectionMenuItem.isSelected() ? "underline" : null );
FlatLaf.updateUI();
}
private void fontFamilyChanged( ActionEvent e ) {
String fontFamily = e.getActionCommand();
@@ -132,6 +137,8 @@ class DemoFrame
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();
@@ -355,6 +362,17 @@ class DemoFrame
}
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");
@@ -481,6 +499,7 @@ class DemoFrame
// 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

View File

@@ -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"

View File

@@ -23,6 +23,7 @@ import java.awt.Graphics;
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.*;
@@ -61,6 +62,11 @@ public class FlatMenusTest
}
}
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();
@@ -193,6 +199,7 @@ public class FlatMenusTest
JLabel popupMenuLabel = new JLabel();
JButton showPopupMenuButton = new JButton();
armedCheckBox = new JCheckBox();
underlineCheckBox = new JCheckBox();
//======== this ========
setLayout(new MigLayout(
@@ -207,6 +214,7 @@ public class FlatMenusTest
"[]" +
"[top]" +
"[]" +
"[]" +
"[]"));
//---- menuBarLabel ----
@@ -691,6 +699,11 @@ public class FlatMenusTest
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);
@@ -708,6 +721,7 @@ public class FlatMenusTest
private JCheckBox largerCheckBox;
private JCheckBox accelCheckBox;
private JCheckBox armedCheckBox;
private JCheckBox underlineCheckBox;
// JFormDesigner - End of variables declaration //GEN-END:variables
//---- class PopupMenu ----------------------------------------------------

View File

@@ -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" ) {
@@ -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 )

View File

@@ -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 ----

View File

@@ -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 ----

View File

@@ -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 ----

View File

@@ -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 ----