Skip to content

Commit

Permalink
Menu: hide mnemonics by default and show them only when Alt key is pr…
Browse files Browse the repository at this point in the history
…essed (issue #43)
  • Loading branch information
DevCharly committed Jan 14, 2020
1 parent 2459a36 commit 5c3638a
Show file tree
Hide file tree
Showing 10 changed files with 276 additions and 12 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ FlatLaf Change Log

## Unreleased

- Hide menu mnemonics by default and show them only when <kbd>Alt</kbd> key is
pressed. (issue #43)
- TabbedPane: In scroll-tab-layout, the cropped line is now hidden. (issue #40)
- Tree: UI default value `Tree.textBackground` now has a valid color and is no
longer `null`.
Expand Down
32 changes: 22 additions & 10 deletions flatlaf-core/src/main/java/com/formdev/flatlaf/FlatLaf.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.function.Consumer;
import java.util.logging.Level;
Expand Down Expand Up @@ -66,6 +67,7 @@ public abstract class FlatLaf

private KeyEventPostProcessor mnemonicListener;
private static boolean showMnemonics;
private static WeakReference<Window> lastShowMnemonicWindow;

private Consumer<UIDefaults> postInitialization;

Expand Down Expand Up @@ -391,18 +393,28 @@ private static void showMnemonics( boolean show ) {
if( !UIManager.getBoolean( "Component.hideMnemonics" ) )
return;

// get focus owner
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if( focusOwner == null )
return;
if( show ) {
// get focus owner
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if( focusOwner == null )
return;

// get focused window
Window window = SwingUtilities.windowForComponent( focusOwner );
if( window == null )
return;
// get focused window
Window window = SwingUtilities.windowForComponent( focusOwner );
if( window == null )
return;

// repaint components with mnemonics in focused window
repaintMnemonics( window );

// repaint components with mnemonics in focused window
repaintMnemonics( window );
lastShowMnemonicWindow = new WeakReference<>( window );
} else if( lastShowMnemonicWindow != null ) {
Window window = lastShowMnemonicWindow.get();
if( window != null )
repaintMnemonics( window );

lastShowMnemonicWindow = null;
}
}

private static void repaintMnemonics( Container container ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
package com.formdev.flatlaf.ui;

import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicCheckBoxMenuItemUI;

Expand Down Expand Up @@ -74,4 +77,9 @@ protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
defaultTextIconGap = scale( defaultTextIconGap );
};
}

@Override
protected void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect, String text ) {
FlatMenuItemUI.paintText( g, menuItem, textRect, text, disabledForeground, selectionForeground );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,18 @@
package com.formdev.flatlaf.ui;

import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.beans.PropertyChangeListener;
import javax.swing.ButtonModel;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicMenuItemUI;
import com.formdev.flatlaf.FlatLaf;

/**
* Provides the Flat LaF UI delegate for {@link javax.swing.JMenuItem}.
Expand Down Expand Up @@ -74,4 +82,26 @@ protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
defaultTextIconGap = scale( defaultTextIconGap );
};
}

@Override
protected void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect, String text ) {
paintText( g, menuItem, textRect, text, disabledForeground, selectionForeground );
}

public static void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect,
String text, Color disabledForeground, Color selectionForeground )
{
FontMetrics fm = menuItem.getFontMetrics( menuItem.getFont() );
int mnemonicIndex = FlatLaf.isShowMnemonics() ? menuItem.getDisplayedMnemonicIndex() : -1;

ButtonModel model = menuItem.getModel();
g.setColor( !model.isEnabled()
? disabledForeground
: (model.isArmed() || (menuItem instanceof JMenu && model.isSelected())
? selectionForeground
: menuItem.getForeground()) );

FlatUIUtils.drawStringUnderlineCharAt( menuItem, g, text, mnemonicIndex,
textRect.x, textRect.y + fm.getAscent() );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
package com.formdev.flatlaf.ui;

import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicMenuUI;

Expand Down Expand Up @@ -77,4 +80,9 @@ protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
defaultTextIconGap = scale( defaultTextIconGap );
};
}

@Override
protected void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect, String text ) {
FlatMenuItemUI.paintText( g, menuItem, textRect, text, disabledForeground, selectionForeground );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
package com.formdev.flatlaf.ui;

import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JMenuItem;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicRadioButtonMenuItemUI;

Expand Down Expand Up @@ -74,4 +77,9 @@ protected PropertyChangeListener createPropertyChangeListener( JComponent c ) {
defaultTextIconGap = scale( defaultTextIconGap );
};
}

@Override
protected void paintText( Graphics g, JMenuItem menuItem, Rectangle textRect, String text ) {
FlatMenuItemUI.paintText( g, menuItem, textRect, text, disabledForeground, selectionForeground );
}
}
97 changes: 97 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 @@ -51,6 +51,12 @@ private void selectedTabChanged() {
DemoPrefs.getState().putInt( FlatLafDemo.KEY_TAB, tabbedPane.getSelectedIndex() );
}

private void menuItemActionPerformed(ActionEvent e) {
SwingUtilities.invokeLater( () -> {
JOptionPane.showMessageDialog( this, e.getActionCommand(), "Menu Item", JOptionPane.PLAIN_MESSAGE );
} );
}

private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
JMenuBar menuBar1 = new JMenuBar();
Expand All @@ -68,6 +74,14 @@ private void initComponents() {
JMenuItem deleteMenuItem = new JMenuItem();
JMenu viewMenu = new JMenu();
JCheckBoxMenuItem checkBoxMenuItem1 = new JCheckBoxMenuItem();
JMenu menu1 = new JMenu();
JMenu subViewsMenu = new JMenu();
JMenu subSubViewsMenu = new JMenu();
JMenuItem errorLogViewMenuItem = new JMenuItem();
JMenuItem searchViewMenuItem = new JMenuItem();
JMenuItem projectViewMenuItem = new JMenuItem();
JMenuItem structureViewMenuItem = new JMenuItem();
JMenuItem propertiesViewMenuItem = new JMenuItem();
JRadioButtonMenuItem radioButtonMenuItem1 = new JRadioButtonMenuItem();
JRadioButtonMenuItem radioButtonMenuItem2 = new JRadioButtonMenuItem();
JRadioButtonMenuItem radioButtonMenuItem3 = new JRadioButtonMenuItem();
Expand Down Expand Up @@ -103,27 +117,35 @@ private void initComponents() {
//======== fileMenu ========
{
fileMenu.setText("File");
fileMenu.setMnemonic('F');

//---- newMenuItem ----
newMenuItem.setText("New");
newMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
newMenuItem.setMnemonic('N');
newMenuItem.addActionListener(e -> menuItemActionPerformed(e));
fileMenu.add(newMenuItem);

//---- openMenuItem ----
openMenuItem.setText("Open");
openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
openMenuItem.setMnemonic('O');
openMenuItem.addActionListener(e -> menuItemActionPerformed(e));
fileMenu.add(openMenuItem);
fileMenu.addSeparator();

//---- closeMenuItem ----
closeMenuItem.setText("Close");
closeMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
closeMenuItem.setMnemonic('C');
closeMenuItem.addActionListener(e -> menuItemActionPerformed(e));
fileMenu.add(closeMenuItem);
fileMenu.addSeparator();

//---- exitMenuItem ----
exitMenuItem.setText("Exit");
exitMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
exitMenuItem.setMnemonic('X');
exitMenuItem.addActionListener(e -> exitActionPerformed());
fileMenu.add(exitMenuItem);
}
Expand All @@ -132,72 +154,147 @@ private void initComponents() {
//======== editMenu ========
{
editMenu.setText("Edit");
editMenu.setMnemonic('E');

//---- undoMenuItem ----
undoMenuItem.setText("Undo");
undoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
undoMenuItem.setMnemonic('U');
undoMenuItem.addActionListener(e -> menuItemActionPerformed(e));
editMenu.add(undoMenuItem);

//---- redoMenuItem ----
redoMenuItem.setText("Redo");
redoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
redoMenuItem.setMnemonic('R');
redoMenuItem.addActionListener(e -> menuItemActionPerformed(e));
editMenu.add(redoMenuItem);
editMenu.addSeparator();

//---- cutMenuItem ----
cutMenuItem.setText("Cut");
cutMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
cutMenuItem.setMnemonic('C');
cutMenuItem.addActionListener(e -> menuItemActionPerformed(e));
editMenu.add(cutMenuItem);

//---- copyMenuItem ----
copyMenuItem.setText("Copy");
copyMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
copyMenuItem.setMnemonic('O');
copyMenuItem.addActionListener(e -> menuItemActionPerformed(e));
editMenu.add(copyMenuItem);

//---- pasteMenuItem ----
pasteMenuItem.setText("Paste");
pasteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
pasteMenuItem.setMnemonic('P');
pasteMenuItem.addActionListener(e -> menuItemActionPerformed(e));
editMenu.add(pasteMenuItem);
editMenu.addSeparator();

//---- deleteMenuItem ----
deleteMenuItem.setText("Delete");
deleteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
deleteMenuItem.setMnemonic('D');
deleteMenuItem.addActionListener(e -> menuItemActionPerformed(e));
editMenu.add(deleteMenuItem);
}
menuBar1.add(editMenu);

//======== viewMenu ========
{
viewMenu.setText("View");
viewMenu.setMnemonic('V');

//---- checkBoxMenuItem1 ----
checkBoxMenuItem1.setText("Show Toolbar");
checkBoxMenuItem1.setSelected(true);
checkBoxMenuItem1.setMnemonic('T');
checkBoxMenuItem1.addActionListener(e -> menuItemActionPerformed(e));
viewMenu.add(checkBoxMenuItem1);

//======== menu1 ========
{
menu1.setText("Show View");
menu1.setMnemonic('V');

//======== subViewsMenu ========
{
subViewsMenu.setText("Sub Views");
subViewsMenu.setMnemonic('S');

//======== subSubViewsMenu ========
{
subSubViewsMenu.setText("Sub sub Views");
subSubViewsMenu.setMnemonic('U');

//---- errorLogViewMenuItem ----
errorLogViewMenuItem.setText("Error Log");
errorLogViewMenuItem.setMnemonic('E');
errorLogViewMenuItem.addActionListener(e -> menuItemActionPerformed(e));
subSubViewsMenu.add(errorLogViewMenuItem);
}
subViewsMenu.add(subSubViewsMenu);

//---- searchViewMenuItem ----
searchViewMenuItem.setText("Search");
searchViewMenuItem.setMnemonic('S');
searchViewMenuItem.addActionListener(e -> menuItemActionPerformed(e));
subViewsMenu.add(searchViewMenuItem);
}
menu1.add(subViewsMenu);

//---- projectViewMenuItem ----
projectViewMenuItem.setText("Project");
projectViewMenuItem.setMnemonic('P');
projectViewMenuItem.addActionListener(e -> menuItemActionPerformed(e));
menu1.add(projectViewMenuItem);

//---- structureViewMenuItem ----
structureViewMenuItem.setText("Structure");
structureViewMenuItem.setMnemonic('T');
structureViewMenuItem.addActionListener(e -> menuItemActionPerformed(e));
menu1.add(structureViewMenuItem);

//---- propertiesViewMenuItem ----
propertiesViewMenuItem.setText("Properties");
propertiesViewMenuItem.setMnemonic('O');
propertiesViewMenuItem.addActionListener(e -> menuItemActionPerformed(e));
menu1.add(propertiesViewMenuItem);
}
viewMenu.add(menu1);
viewMenu.addSeparator();

//---- radioButtonMenuItem1 ----
radioButtonMenuItem1.setText("Details");
radioButtonMenuItem1.setSelected(true);
radioButtonMenuItem1.setMnemonic('D');
radioButtonMenuItem1.addActionListener(e -> menuItemActionPerformed(e));
viewMenu.add(radioButtonMenuItem1);

//---- radioButtonMenuItem2 ----
radioButtonMenuItem2.setText("Small Icons");
radioButtonMenuItem2.setMnemonic('S');
radioButtonMenuItem2.addActionListener(e -> menuItemActionPerformed(e));
viewMenu.add(radioButtonMenuItem2);

//---- radioButtonMenuItem3 ----
radioButtonMenuItem3.setText("Large Icons");
radioButtonMenuItem3.setMnemonic('L');
radioButtonMenuItem3.addActionListener(e -> menuItemActionPerformed(e));
viewMenu.add(radioButtonMenuItem3);
}
menuBar1.add(viewMenu);

//======== helpMenu ========
{
helpMenu.setText("Help");
helpMenu.setMnemonic('H');

//---- aboutMenuItem ----
aboutMenuItem.setText("About");
aboutMenuItem.setMnemonic('A');
aboutMenuItem.addActionListener(e -> aboutActionPerformed());
helpMenu.add(aboutMenuItem);
}
Expand Down
Loading

0 comments on commit 5c3638a

Please sign in to comment.