1 /* 2 * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.swing.plaf.basic; 27 28 import java.awt.event.ActionEvent; 29 import java.awt.KeyboardFocusManager; 30 import java.awt.Component; 31 import java.awt.Point; 32 import java.awt.Rectangle; 33 import java.beans.PropertyChangeEvent; 34 import java.beans.PropertyChangeListener; 35 import javax.swing.*; 36 import javax.swing.plaf.*; 37 import sun.swing.DefaultLookup; 38 import sun.swing.UIAction; 39 40 /** 41 * Basic implementation of RootPaneUI, there is one shared between all 42 * JRootPane instances. 43 * 44 * @author Scott Violet 45 * @since 1.3 46 */ 47 public class BasicRootPaneUI extends RootPaneUI implements 48 PropertyChangeListener { 49 private static RootPaneUI rootPaneUI = new BasicRootPaneUI(); 50 51 public static ComponentUI createUI(JComponent c) { 52 return rootPaneUI; 53 } 54 55 public void installUI(JComponent c) { 56 installDefaults((JRootPane)c); 57 installComponents((JRootPane)c); 58 installListeners((JRootPane)c); 59 installKeyboardActions((JRootPane)c); 60 } 61 62 63 public void uninstallUI(JComponent c) { 64 uninstallDefaults((JRootPane)c); 65 uninstallComponents((JRootPane)c); 66 uninstallListeners((JRootPane)c); 67 uninstallKeyboardActions((JRootPane)c); 68 } 69 70 protected void installDefaults(JRootPane c){ 71 LookAndFeel.installProperty(c, "opaque", Boolean.FALSE); 72 } 73 74 protected void installComponents(JRootPane root) { 75 } 76 77 protected void installListeners(JRootPane root) { 78 root.addPropertyChangeListener(this); 79 } 80 81 protected void installKeyboardActions(JRootPane root) { 82 InputMap km = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, root); 83 SwingUtilities.replaceUIInputMap(root, 84 JComponent.WHEN_IN_FOCUSED_WINDOW, km); 85 km = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, 86 root); 87 SwingUtilities.replaceUIInputMap(root, 88 JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, km); 89 90 LazyActionMap.installLazyActionMap(root, BasicRootPaneUI.class, 91 "RootPane.actionMap"); 92 updateDefaultButtonBindings(root); 93 } 94 95 protected void uninstallDefaults(JRootPane root) { 96 } 97 98 protected void uninstallComponents(JRootPane root) { 99 } 100 101 protected void uninstallListeners(JRootPane root) { 102 root.removePropertyChangeListener(this); 103 } 104 105 protected void uninstallKeyboardActions(JRootPane root) { 106 SwingUtilities.replaceUIInputMap(root, JComponent. 107 WHEN_IN_FOCUSED_WINDOW, null); 108 SwingUtilities.replaceUIActionMap(root, null); 109 } 110 111 InputMap getInputMap(int condition, JComponent c) { 112 if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) { 113 return (InputMap)DefaultLookup.get(c, this, 114 "RootPane.ancestorInputMap"); 115 } 116 117 if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) { 118 return createInputMap(condition, c); 119 } 120 return null; 121 } 122 123 ComponentInputMap createInputMap(int condition, JComponent c) { 124 return new RootPaneInputMap(c); 125 } 126 127 static void loadActionMap(LazyActionMap map) { 128 map.put(new Actions(Actions.PRESS)); 129 map.put(new Actions(Actions.RELEASE)); 130 map.put(new Actions(Actions.POST_POPUP)); 131 } 132 133 /** 134 * Invoked when the default button property has changed. This reloads 135 * the bindings from the defaults table with name 136 * <code>RootPane.defaultButtonWindowKeyBindings</code>. 137 */ 138 void updateDefaultButtonBindings(JRootPane root) { 139 InputMap km = SwingUtilities.getUIInputMap(root, JComponent. 140 WHEN_IN_FOCUSED_WINDOW); 141 while (km != null && !(km instanceof RootPaneInputMap)) { 142 km = km.getParent(); 143 } 144 if (km != null) { 145 km.clear(); 146 if (root.getDefaultButton() != null) { 147 Object[] bindings = (Object[])DefaultLookup.get(root, this, 148 "RootPane.defaultButtonWindowKeyBindings"); 149 if (bindings != null) { 150 LookAndFeel.loadKeyBindings(km, bindings); 151 } 152 } 153 } 154 } 155 156 /** 157 * Invoked when a property changes on the root pane. If the event 158 * indicates the <code>defaultButton</code> has changed, this will 159 * reinstall the keyboard actions. 160 */ 161 public void propertyChange(PropertyChangeEvent e) { 162 if(e.getPropertyName().equals("defaultButton")) { 163 JRootPane rootpane = (JRootPane)e.getSource(); 164 updateDefaultButtonBindings(rootpane); 165 if (rootpane.getClientProperty("temporaryDefaultButton") == null) { 166 rootpane.putClientProperty("initialDefaultButton", e.getNewValue()); 167 } 168 } 169 } 170 171 172 static class Actions extends UIAction { 173 public static final String PRESS = "press"; 174 public static final String RELEASE = "release"; 175 public static final String POST_POPUP = "postPopup"; 176 177 Actions(String name) { 178 super(name); 179 } 180 181 public void actionPerformed(ActionEvent evt) { 182 JRootPane root = (JRootPane)evt.getSource(); 183 JButton owner = root.getDefaultButton(); 184 String key = getName(); 185 186 if (key == POST_POPUP) { // Action to post popup 187 Component c = KeyboardFocusManager 188 .getCurrentKeyboardFocusManager() 189 .getFocusOwner(); 190 191 if(c instanceof JComponent) { 192 JComponent src = (JComponent) c; 193 JPopupMenu jpm = src.getComponentPopupMenu(); 194 if(jpm != null) { 195 Point pt = src.getPopupLocation(null); 196 if(pt == null) { 197 Rectangle vis = src.getVisibleRect(); 198 pt = new Point(vis.x+vis.width/2, 199 vis.y+vis.height/2); 200 } 201 jpm.show(c, pt.x, pt.y); 202 } 203 } 204 } 205 else if (owner != null 206 && SwingUtilities.getRootPane(owner) == root) { 207 if (key == PRESS) { 208 owner.doClick(20); 209 } 210 } 211 } 212 213 public boolean isEnabled(Object sender) { 214 String key = getName(); 215 if(key == POST_POPUP) { 216 MenuElement[] elems = MenuSelectionManager 217 .defaultManager() 218 .getSelectedPath(); 219 if(elems != null && elems.length != 0) { 220 return false; 221 // We shall not interfere with already opened menu 222 } 223 224 Component c = KeyboardFocusManager 225 .getCurrentKeyboardFocusManager() 226 .getFocusOwner(); 227 if(c instanceof JComponent) { 228 JComponent src = (JComponent) c; 229 return src.getComponentPopupMenu() != null; 230 } 231 232 return false; 233 } 234 235 if (sender != null && sender instanceof JRootPane) { 236 JButton owner = ((JRootPane)sender).getDefaultButton(); 237 return (owner != null && owner.getModel().isEnabled()); 238 } 239 return true; 240 } 241 } 242 243 private static class RootPaneInputMap extends ComponentInputMapUIResource { 244 public RootPaneInputMap(JComponent c) { 245 super(c); 246 } 247 } 248 }