/* |
|
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. |
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
* |
|
* This code is free software; you can redistribute it and/or modify it |
|
* under the terms of the GNU General Public License version 2 only, as |
|
* published by the Free Software Foundation. Oracle designates this |
|
* particular file as subject to the "Classpath" exception as provided |
|
* by Oracle in the LICENSE file that accompanied this code. |
|
* |
|
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
* version 2 for more details (a copy is included in the LICENSE file that |
|
* accompanied this code). |
|
* |
|
* You should have received a copy of the GNU General Public License version |
|
* 2 along with this work; if not, write to the Free Software Foundation, |
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
* |
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
* or visit www.oracle.com if you need additional information or have any |
|
* questions. |
|
*/ |
|
package com.sun.java.swing.plaf.windows; |
|
import java.awt.Component; |
|
import java.awt.Container; |
|
import java.awt.Event; |
|
import java.awt.KeyEventPostProcessor; |
|
import java.awt.Window; |
|
import java.awt.Toolkit; |
|
import sun.awt.AWTAccessor; |
|
import sun.awt.SunToolkit; |
|
import java.awt.event.ActionEvent; |
|
import java.awt.event.KeyEvent; |
|
import javax.swing.AbstractAction; |
|
import javax.swing.ActionMap; |
|
import javax.swing.InputMap; |
|
import javax.swing.KeyStroke; |
|
import javax.swing.JComponent; |
|
import javax.swing.JLabel; |
|
import javax.swing.JRootPane; |
|
import javax.swing.SwingUtilities; |
|
import javax.swing.UIManager; |
|
import javax.swing.AbstractButton; |
|
import javax.swing.JFrame; |
|
import javax.swing.JMenu; |
|
import javax.swing.JMenuBar; |
|
import javax.swing.MenuElement; |
|
import javax.swing.MenuSelectionManager; |
|
import javax.swing.plaf.ActionMapUIResource; |
|
import javax.swing.plaf.ComponentUI; |
|
import javax.swing.plaf.InputMapUIResource; |
|
import javax.swing.plaf.basic.BasicRootPaneUI; |
|
import javax.swing.plaf.basic.ComboPopup; |
|
/** |
|
* Windows implementation of RootPaneUI, there is one shared between all |
|
* JRootPane instances. |
|
* |
|
* @author Mark Davidson |
|
* @since 1.4 |
|
*/ |
|
public class WindowsRootPaneUI extends BasicRootPaneUI { |
|
private final static WindowsRootPaneUI windowsRootPaneUI = new WindowsRootPaneUI(); |
|
static final AltProcessor altProcessor = new AltProcessor(); |
|
public static ComponentUI createUI(JComponent c) { |
|
return windowsRootPaneUI; |
|
} |
|
static class AltProcessor implements KeyEventPostProcessor { |
|
static boolean altKeyPressed = false; |
|
static boolean menuCanceledOnPress = false; |
|
static JRootPane root = null; |
|
static Window winAncestor = null; |
|
void altPressed(KeyEvent ev) { |
|
MenuSelectionManager msm = |
|
MenuSelectionManager.defaultManager(); |
|
MenuElement[] path = msm.getSelectedPath(); |
|
if (path.length > 0 && ! (path[0] instanceof ComboPopup)) { |
|
msm.clearSelectedPath(); |
|
menuCanceledOnPress = true; |
|
ev.consume(); |
|
} else if(path.length > 0) { // We are in ComboBox |
|
menuCanceledOnPress = false; |
|
WindowsLookAndFeel.setMnemonicHidden(false); |
|
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor); |
|
ev.consume(); |
|
} else { |
|
menuCanceledOnPress = false; |
|
WindowsLookAndFeel.setMnemonicHidden(false); |
|
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor); |
|
JMenuBar mbar = root != null ? root.getJMenuBar() : null; |
|
if(mbar == null && winAncestor instanceof JFrame) { |
|
mbar = ((JFrame)winAncestor).getJMenuBar(); |
|
} |
|
JMenu menu = mbar != null ? mbar.getMenu(0) : null; |
|
if(menu != null) { |
|
ev.consume(); |
|
} |
|
} |
|
} |
|
void altReleased(KeyEvent ev) { |
|
if (menuCanceledOnPress) { |
|
WindowsLookAndFeel.setMnemonicHidden(true); |
|
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor); |
|
return; |
|
} |
|
MenuSelectionManager msm = |
|
MenuSelectionManager.defaultManager(); |
|
if (msm.getSelectedPath().length == 0) { |
|
// if no menu is active, we try activating the menubar |
|
JMenuBar mbar = root != null ? root.getJMenuBar() : null; |
|
if(mbar == null && winAncestor instanceof JFrame) { |
|
mbar = ((JFrame)winAncestor).getJMenuBar(); |
|
} |
|
JMenu menu = mbar != null ? mbar.getMenu(0) : null; |
|
// It might happen that the altRelease event is processed |
|
// with a reasonable delay since it has been generated. |
|
// Here we check the last deactivation time of the containing |
|
// window. If this time appears to be greater than the altRelease |
|
// event time the event is skipped to avoid unexpected menu |
|
// activation. See 7121442. |
|
// Also we must ensure that original source of key event belongs |
|
// to the same window object as winAncestor. See 8001633. |
|
boolean skip = false; |
|
Toolkit tk = Toolkit.getDefaultToolkit(); |
|
if (tk instanceof SunToolkit) { |
|
Component originalSource = AWTAccessor.getKeyEventAccessor() |
|
.getOriginalSource(ev); |
|
skip = SunToolkit.getContainingWindow(originalSource) != winAncestor || |
|
ev.getWhen() <= ((SunToolkit) tk).getWindowDeactivationTime(winAncestor); |
|
} |
|
if (menu != null && !skip) { |
|
MenuElement[] path = new MenuElement[2]; |
|
path[0] = mbar; |
|
path[1] = menu; |
|
msm.setSelectedPath(path); |
|
} else if(!WindowsLookAndFeel.isMnemonicHidden()) { |
|
WindowsLookAndFeel.setMnemonicHidden(true); |
|
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor); |
|
} |
|
} else { |
|
if((msm.getSelectedPath())[0] instanceof ComboPopup) { |
|
WindowsLookAndFeel.setMnemonicHidden(true); |
|
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor); |
|
} |
|
} |
|
} |
|
public boolean postProcessKeyEvent(KeyEvent ev) { |
|
if(ev.isConsumed() && ev.getKeyCode() != KeyEvent.VK_ALT) { |
|
// mnemonic combination, it's consumed, but we need |
|
// set altKeyPressed to false, otherwise after selection |
|
// component by mnemonic combination a menu will be open |
|
altKeyPressed = false; |
|
return false; |
|
} |
|
if (ev.getKeyCode() == KeyEvent.VK_ALT) { |
|
root = SwingUtilities.getRootPane(ev.getComponent()); |
|
winAncestor = (root == null ? null : |
|
SwingUtilities.getWindowAncestor(root)); |
|
if (ev.getID() == KeyEvent.KEY_PRESSED) { |
|
if (!altKeyPressed) { |
|
altPressed(ev); |
|
} |
|
altKeyPressed = true; |
|
return true; |
|
} else if (ev.getID() == KeyEvent.KEY_RELEASED) { |
|
if (altKeyPressed) { |
|
altReleased(ev); |
|
} else { |
|
MenuSelectionManager msm = |
|
MenuSelectionManager.defaultManager(); |
|
MenuElement[] path = msm.getSelectedPath(); |
|
if (path.length <= 0) { |
|
WindowsLookAndFeel.setMnemonicHidden(true); |
|
WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor); |
|
} |
|
} |
|
altKeyPressed = false; |
|
} |
|
root = null; |
|
winAncestor = null; |
|
} else { |
|
altKeyPressed = false; |
|
} |
|
return false; |
|
} |
|
} |
|
} |