| /* |
| * Copyright (c) 1999, 2016, 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 javax.swing.plaf.basic; |
| |
| import java.awt.event.ActionEvent; |
| import java.awt.KeyboardFocusManager; |
| import java.awt.Component; |
| import java.awt.Point; |
| import java.awt.Rectangle; |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| import javax.swing.*; |
| import javax.swing.plaf.*; |
| import sun.swing.DefaultLookup; |
| import sun.swing.UIAction; |
| |
| /** |
| * Basic implementation of RootPaneUI, there is one shared between all |
| * JRootPane instances. |
| * |
| * @author Scott Violet |
| * @since 1.3 |
| */ |
| public class BasicRootPaneUI extends RootPaneUI implements |
| PropertyChangeListener { |
| private static RootPaneUI rootPaneUI = new BasicRootPaneUI(); |
| |
| /** |
| * Returns a new instance of {@code BasicRootPaneUI}. |
| * |
| * @param c a component |
| * @return a new instance of {@code BasicRootPaneUI} |
| */ |
| public static ComponentUI createUI(JComponent c) { |
| return rootPaneUI; |
| } |
| |
| public void installUI(JComponent c) { |
| installDefaults((JRootPane)c); |
| installComponents((JRootPane)c); |
| installListeners((JRootPane)c); |
| installKeyboardActions((JRootPane)c); |
| } |
| |
| |
| public void uninstallUI(JComponent c) { |
| uninstallDefaults((JRootPane)c); |
| uninstallComponents((JRootPane)c); |
| uninstallListeners((JRootPane)c); |
| uninstallKeyboardActions((JRootPane)c); |
| } |
| |
| /** |
| * Installs default properties. |
| * |
| * @param c an instance of {@code JRootPane} |
| */ |
| protected void installDefaults(JRootPane c){ |
| LookAndFeel.installProperty(c, "opaque", Boolean.FALSE); |
| } |
| |
| /** |
| * Installs components. |
| * |
| * @param root an instance of {@code JRootPane} |
| */ |
| protected void installComponents(JRootPane root) { |
| } |
| |
| /** |
| * Registers listeners. |
| * |
| * @param root an instance of {@code JRootPane} |
| */ |
| protected void installListeners(JRootPane root) { |
| root.addPropertyChangeListener(this); |
| } |
| |
| /** |
| * Registers keyboard actions. |
| * |
| * @param root an instance of {@code JRootPane} |
| */ |
| protected void installKeyboardActions(JRootPane root) { |
| InputMap km = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, root); |
| SwingUtilities.replaceUIInputMap(root, |
| JComponent.WHEN_IN_FOCUSED_WINDOW, km); |
| km = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, |
| root); |
| SwingUtilities.replaceUIInputMap(root, |
| JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, km); |
| |
| LazyActionMap.installLazyActionMap(root, BasicRootPaneUI.class, |
| "RootPane.actionMap"); |
| updateDefaultButtonBindings(root); |
| } |
| |
| /** |
| * Uninstalls default properties. |
| * |
| * @param root an instance of {@code JRootPane} |
| */ |
| protected void uninstallDefaults(JRootPane root) { |
| } |
| |
| /** |
| * Unregisters components. |
| * |
| * @param root an instance of {@code JRootPane} |
| */ |
| protected void uninstallComponents(JRootPane root) { |
| } |
| |
| /** |
| * Unregisters listeners. |
| * |
| * @param root an instance of {@code JRootPane} |
| */ |
| protected void uninstallListeners(JRootPane root) { |
| root.removePropertyChangeListener(this); |
| } |
| |
| /** |
| * Unregisters keyboard actions. |
| * |
| * @param root an instance of {@code JRootPane} |
| */ |
| protected void uninstallKeyboardActions(JRootPane root) { |
| SwingUtilities.replaceUIInputMap(root, JComponent. |
| WHEN_IN_FOCUSED_WINDOW, null); |
| SwingUtilities.replaceUIActionMap(root, null); |
| } |
| |
| InputMap getInputMap(int condition, JComponent c) { |
| if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) { |
| return (InputMap)DefaultLookup.get(c, this, |
| "RootPane.ancestorInputMap"); |
| } |
| |
| if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) { |
| return createInputMap(condition, c); |
| } |
| return null; |
| } |
| |
| ComponentInputMap createInputMap(int condition, JComponent c) { |
| return new RootPaneInputMap(c); |
| } |
| |
| static void loadActionMap(LazyActionMap map) { |
| map.put(new Actions(Actions.PRESS)); |
| map.put(new Actions(Actions.RELEASE)); |
| map.put(new Actions(Actions.POST_POPUP)); |
| } |
| |
| /** |
| * Invoked when the default button property has changed. This reloads |
| * the bindings from the defaults table with name |
| * <code>RootPane.defaultButtonWindowKeyBindings</code>. |
| */ |
| void updateDefaultButtonBindings(JRootPane root) { |
| InputMap km = SwingUtilities.getUIInputMap(root, JComponent. |
| WHEN_IN_FOCUSED_WINDOW); |
| while (km != null && !(km instanceof RootPaneInputMap)) { |
| km = km.getParent(); |
| } |
| if (km != null) { |
| km.clear(); |
| if (root.getDefaultButton() != null) { |
| Object[] bindings = (Object[])DefaultLookup.get(root, this, |
| "RootPane.defaultButtonWindowKeyBindings"); |
| if (bindings != null) { |
| LookAndFeel.loadKeyBindings(km, bindings); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Invoked when a property changes on the root pane. If the event |
| * indicates the <code>defaultButton</code> has changed, this will |
| * reinstall the keyboard actions. |
| */ |
| public void propertyChange(PropertyChangeEvent e) { |
| if(e.getPropertyName().equals("defaultButton")) { |
| JRootPane rootpane = (JRootPane)e.getSource(); |
| updateDefaultButtonBindings(rootpane); |
| if (rootpane.getClientProperty("temporaryDefaultButton") == null) { |
| rootpane.putClientProperty("initialDefaultButton", e.getNewValue()); |
| } |
| } |
| } |
| |
| |
| static class Actions extends UIAction { |
| public static final String PRESS = "press"; |
| public static final String RELEASE = "release"; |
| public static final String POST_POPUP = "postPopup"; |
| |
| Actions(String name) { |
| super(name); |
| } |
| |
| public void actionPerformed(ActionEvent evt) { |
| JRootPane root = (JRootPane)evt.getSource(); |
| JButton owner = root.getDefaultButton(); |
| String key = getName(); |
| |
| if (key == POST_POPUP) { // Action to post popup |
| Component c = KeyboardFocusManager |
| .getCurrentKeyboardFocusManager() |
| .getFocusOwner(); |
| |
| if(c instanceof JComponent) { |
| JComponent src = (JComponent) c; |
| JPopupMenu jpm = src.getComponentPopupMenu(); |
| if(jpm != null) { |
| Point pt = src.getPopupLocation(null); |
| if(pt == null) { |
| Rectangle vis = src.getVisibleRect(); |
| pt = new Point(vis.x+vis.width/2, |
| vis.y+vis.height/2); |
| } |
| jpm.show(c, pt.x, pt.y); |
| } |
| } |
| } |
| else if (owner != null |
| && SwingUtilities.getRootPane(owner) == root) { |
| if (key == PRESS) { |
| owner.doClick(20); |
| } |
| } |
| } |
| |
| @Override |
| public boolean accept(Object sender) { |
| String key = getName(); |
| if(key == POST_POPUP) { |
| MenuElement[] elems = MenuSelectionManager |
| .defaultManager() |
| .getSelectedPath(); |
| if(elems != null && elems.length != 0) { |
| return false; |
| // We shall not interfere with already opened menu |
| } |
| |
| Component c = KeyboardFocusManager |
| .getCurrentKeyboardFocusManager() |
| .getFocusOwner(); |
| if(c instanceof JComponent) { |
| JComponent src = (JComponent) c; |
| return src.getComponentPopupMenu() != null; |
| } |
| |
| return false; |
| } |
| |
| if (sender instanceof JRootPane) { |
| JButton owner = ((JRootPane)sender).getDefaultButton(); |
| return (owner != null && owner.getModel().isEnabled() && owner.isShowing()); |
| } |
| return true; |
| } |
| } |
| |
| @SuppressWarnings("serial") // JDK-implementation class |
| private static class RootPaneInputMap extends ComponentInputMapUIResource { |
| public RootPaneInputMap(JComponent c) { |
| super(c); |
| } |
| } |
| } |