mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-07 06:20:53 +03:00
Menus: on Windows, releasing Alt key now activates the menu bar (issue #43)
This commit is contained in:
@@ -13,6 +13,8 @@ FlatLaf Change Log
|
|||||||
- Menus: On Windows, pressing <kbd>F10</kbd> now activates the menu bar without
|
- Menus: On Windows, pressing <kbd>F10</kbd> now activates the menu bar without
|
||||||
showing a menu popup (as usual on Windows platform). On other platforms the
|
showing a menu popup (as usual on Windows platform). On other platforms the
|
||||||
first menu popup is shown.
|
first menu popup is shown.
|
||||||
|
- Menus: On Windows, releasing <kbd>Alt</kbd> key now activates the menu bar (as
|
||||||
|
usual on Windows platform). (issue #43)
|
||||||
- Menus: Fixed inconsistent left padding in menu items. (issue #3)
|
- Menus: Fixed inconsistent left padding in menu items. (issue #3)
|
||||||
- Menus: Fixed: Setting `iconTextGap` property on a menu item did increase left
|
- Menus: Fixed: Setting `iconTextGap` property on a menu item did increase left
|
||||||
and right margins. (issue #54)
|
and right margins. (issue #54)
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ import java.awt.event.WindowEvent;
|
|||||||
import java.awt.event.WindowListener;
|
import java.awt.event.WindowListener;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
import javax.swing.JMenuBar;
|
||||||
import javax.swing.JRootPane;
|
import javax.swing.JRootPane;
|
||||||
import javax.swing.JTabbedPane;
|
import javax.swing.JTabbedPane;
|
||||||
import javax.swing.MenuElement;
|
import javax.swing.MenuElement;
|
||||||
@@ -74,6 +77,9 @@ class MnemonicHandler
|
|||||||
showMnemonics( shouldShowMnemonics( e ) && e.isControlDown() && e.isAltDown(), e.getComponent() );
|
showMnemonics( shouldShowMnemonics( e ) && e.isControlDown() && e.isAltDown(), e.getComponent() );
|
||||||
} else {
|
} else {
|
||||||
// Alt key must be pressed on Windows and Linux
|
// Alt key must be pressed on Windows and Linux
|
||||||
|
if( SystemInfo.IS_WINDOWS )
|
||||||
|
return processKeyEventOnWindows( e );
|
||||||
|
|
||||||
if( keyCode == KeyEvent.VK_ALT )
|
if( keyCode == KeyEvent.VK_ALT )
|
||||||
showMnemonics( shouldShowMnemonics( e ), e.getComponent() );
|
showMnemonics( shouldShowMnemonics( e ), e.getComponent() );
|
||||||
}
|
}
|
||||||
@@ -86,10 +92,77 @@ class MnemonicHandler
|
|||||||
MenuSelectionManager.defaultManager().getSelectedPath().length > 0;
|
MenuSelectionManager.defaultManager().getSelectedPath().length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int altPressedEventCount;
|
||||||
|
private boolean selectMenuOnAltReleased;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special Alt key behavior on Windows.
|
||||||
|
*
|
||||||
|
* Press-and-release Alt key selects first menu (if available) and moves focus
|
||||||
|
* temporary to menu bar. If menu bar has focus (some menu is selected),
|
||||||
|
* pressing Alt key unselects menu and moves focus back to permanent focus owner.
|
||||||
|
*/
|
||||||
|
private boolean processKeyEventOnWindows( KeyEvent e ) {
|
||||||
|
if( e.getKeyCode() != KeyEvent.VK_ALT ) {
|
||||||
|
selectMenuOnAltReleased = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( e.getID() == KeyEvent.KEY_PRESSED ) {
|
||||||
|
altPressedEventCount++;
|
||||||
|
|
||||||
|
if( altPressedEventCount == 1 && !e.isConsumed() ) {
|
||||||
|
MenuSelectionManager menuSelectionManager = MenuSelectionManager.defaultManager();
|
||||||
|
selectMenuOnAltReleased = (menuSelectionManager.getSelectedPath().length == 0);
|
||||||
|
|
||||||
|
// if menu is selected when Alt key is pressed then clear menu selection
|
||||||
|
if( !selectMenuOnAltReleased )
|
||||||
|
menuSelectionManager.clearSelectedPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// show mnemonics
|
||||||
|
showMnemonics( shouldShowMnemonics( e ), e.getComponent() );
|
||||||
|
|
||||||
|
// avoid that the system menu of the window gets focus
|
||||||
|
e.consume();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else if( e.getID() == KeyEvent.KEY_RELEASED ) {
|
||||||
|
altPressedEventCount = 0;
|
||||||
|
|
||||||
|
boolean mnemonicsShown = false;
|
||||||
|
if( selectMenuOnAltReleased && !e.isConsumed() ) {
|
||||||
|
MenuSelectionManager menuSelectionManager = MenuSelectionManager.defaultManager();
|
||||||
|
if( menuSelectionManager.getSelectedPath().length == 0 ) {
|
||||||
|
// get menu bar and first menu
|
||||||
|
Component c = e.getComponent();
|
||||||
|
JRootPane rootPane = SwingUtilities.getRootPane( c );
|
||||||
|
Window window = (rootPane != null) ? SwingUtilities.getWindowAncestor( rootPane ) : null;
|
||||||
|
JMenuBar menuBar = (rootPane != null) ? rootPane.getJMenuBar() : null;
|
||||||
|
if( menuBar == null && window instanceof JFrame )
|
||||||
|
menuBar = ((JFrame)window).getJMenuBar();
|
||||||
|
JMenu firstMenu = (menuBar != null) ? menuBar.getMenu( 0 ) : null;
|
||||||
|
|
||||||
|
// select first menu and show mnemonics
|
||||||
|
if( firstMenu != null ) {
|
||||||
|
menuSelectionManager.setSelectedPath( new MenuElement[] { menuBar, firstMenu } );
|
||||||
|
showMnemonics( true, c );
|
||||||
|
mnemonicsShown = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hide mnemonics
|
||||||
|
if( !mnemonicsShown )
|
||||||
|
showMnemonics( shouldShowMnemonics( e ), e.getComponent() );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stateChanged( ChangeEvent e ) {
|
public void stateChanged( ChangeEvent e ) {
|
||||||
MenuElement[] selectedPath = MenuSelectionManager.defaultManager().getSelectedPath();
|
MenuElement[] selectedPath = MenuSelectionManager.defaultManager().getSelectedPath();
|
||||||
if( selectedPath.length == 0 ) {
|
if( selectedPath.length == 0 && altPressedEventCount == 0 ) {
|
||||||
// hide mnemonics when menu selection was canceled
|
// hide mnemonics when menu selection was canceled
|
||||||
showMnemonics( false, null );
|
showMnemonics( false, null );
|
||||||
}
|
}
|
||||||
@@ -126,7 +199,7 @@ class MnemonicHandler
|
|||||||
// use invokeLater() to avoid that the listener is removed
|
// use invokeLater() to avoid that the listener is removed
|
||||||
// while the listener queue is iterated to fire this event
|
// while the listener queue is iterated to fire this event
|
||||||
EventQueue.invokeLater( () -> {
|
EventQueue.invokeLater( () -> {
|
||||||
showMnemonics( false, c );
|
showMnemonics( false, null );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ public class FlatMnemonicsTest
|
|||||||
SwingUtilities.windowForComponent( this ).repaint();
|
SwingUtilities.windowForComponent( this ).repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void openDialog() {
|
||||||
|
JOptionPane.showMessageDialog( this, new FlatMnemonicsTest() );
|
||||||
|
}
|
||||||
|
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||||
JLabel label1 = new JLabel();
|
JLabel label1 = new JLabel();
|
||||||
@@ -77,6 +81,7 @@ public class FlatMnemonicsTest
|
|||||||
JPanel panel3 = new JPanel();
|
JPanel panel3 = new JPanel();
|
||||||
JLabel label5 = new JLabel();
|
JLabel label5 = new JLabel();
|
||||||
alwaysShowMnemonicsCheckBox = new JCheckBox();
|
alwaysShowMnemonicsCheckBox = new JCheckBox();
|
||||||
|
JButton button2 = new JButton();
|
||||||
menuBar = new JMenuBar();
|
menuBar = new JMenuBar();
|
||||||
JMenu fileMenu = new JMenu();
|
JMenu fileMenu = new JMenu();
|
||||||
JMenuItem newMenuItem = new JMenuItem();
|
JMenuItem newMenuItem = new JMenuItem();
|
||||||
@@ -114,7 +119,7 @@ public class FlatMnemonicsTest
|
|||||||
// columns
|
// columns
|
||||||
"[fill]" +
|
"[fill]" +
|
||||||
"[150,fill]para" +
|
"[150,fill]para" +
|
||||||
"[grow,fill]",
|
"[300,grow,fill]",
|
||||||
// rows
|
// rows
|
||||||
"[]" +
|
"[]" +
|
||||||
"[]" +
|
"[]" +
|
||||||
@@ -238,6 +243,11 @@ public class FlatMnemonicsTest
|
|||||||
alwaysShowMnemonicsCheckBox.addActionListener(e -> alwaysShowMnemonicsChanged());
|
alwaysShowMnemonicsCheckBox.addActionListener(e -> alwaysShowMnemonicsChanged());
|
||||||
add(alwaysShowMnemonicsCheckBox, "cell 0 7 2 1,alignx left,growx 0");
|
add(alwaysShowMnemonicsCheckBox, "cell 0 7 2 1,alignx left,growx 0");
|
||||||
|
|
||||||
|
//---- button2 ----
|
||||||
|
button2.setText("Open Dialog");
|
||||||
|
button2.addActionListener(e -> openDialog());
|
||||||
|
add(button2, "cell 2 7,alignx left,growx 0");
|
||||||
|
|
||||||
//======== menuBar ========
|
//======== menuBar ========
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ new FormModel {
|
|||||||
}
|
}
|
||||||
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||||
"$columnConstraints": "[fill][150,fill]para[grow,fill]"
|
"$columnConstraints": "[fill][150,fill]para[300,grow,fill]"
|
||||||
"$rowConstraints": "[][][][][]para[][]para[]"
|
"$rowConstraints": "[][][][][]para[][]para[]"
|
||||||
} ) {
|
} ) {
|
||||||
name: "this"
|
name: "this"
|
||||||
@@ -141,6 +141,13 @@ new FormModel {
|
|||||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
"value": "cell 0 7 2 1,alignx left,growx 0"
|
"value": "cell 0 7 2 1,alignx left,growx 0"
|
||||||
} )
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "button2"
|
||||||
|
"text": "Open Dialog"
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openDialog", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 7,alignx left,growx 0"
|
||||||
|
} )
|
||||||
}, new FormLayoutConstraints( null ) {
|
}, new FormLayoutConstraints( null ) {
|
||||||
"location": new java.awt.Point( 0, 0 )
|
"location": new java.awt.Point( 0, 0 )
|
||||||
"size": new java.awt.Dimension( 790, 380 )
|
"size": new java.awt.Dimension( 790, 380 )
|
||||||
|
|||||||
Reference in New Issue
Block a user