1. /*
  2. * @(#)BasicRootPaneUI.java 1.15 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.plaf.basic;
  8. import java.awt.event.ActionEvent;
  9. import java.awt.KeyboardFocusManager;
  10. import java.awt.Component;
  11. import java.awt.Point;
  12. import java.awt.Rectangle;
  13. import java.beans.PropertyChangeEvent;
  14. import java.beans.PropertyChangeListener;
  15. import javax.swing.*;
  16. import javax.swing.plaf.*;
  17. import sun.swing.DefaultLookup;
  18. import sun.swing.UIAction;
  19. /**
  20. * Basic implementation of RootPaneUI, there is one shared between all
  21. * JRootPane instances.
  22. *
  23. * @version 1.15 12/19/03
  24. * @author Scott Violet
  25. */
  26. public class BasicRootPaneUI extends RootPaneUI implements
  27. PropertyChangeListener {
  28. private static RootPaneUI rootPaneUI = new BasicRootPaneUI();
  29. public static ComponentUI createUI(JComponent c) {
  30. return rootPaneUI;
  31. }
  32. public void installUI(JComponent c) {
  33. installDefaults((JRootPane)c);
  34. installComponents((JRootPane)c);
  35. installListeners((JRootPane)c);
  36. installKeyboardActions((JRootPane)c);
  37. }
  38. public void uninstallUI(JComponent c) {
  39. uninstallDefaults((JRootPane)c);
  40. uninstallComponents((JRootPane)c);
  41. uninstallListeners((JRootPane)c);
  42. uninstallKeyboardActions((JRootPane)c);
  43. }
  44. protected void installDefaults(JRootPane c){
  45. LookAndFeel.installProperty(c, "opaque", Boolean.FALSE);
  46. }
  47. protected void installComponents(JRootPane root) {
  48. }
  49. protected void installListeners(JRootPane root) {
  50. root.addPropertyChangeListener(this);
  51. }
  52. protected void installKeyboardActions(JRootPane root) {
  53. InputMap km = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, root);
  54. SwingUtilities.replaceUIInputMap(root,
  55. JComponent.WHEN_IN_FOCUSED_WINDOW, km);
  56. km = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
  57. root);
  58. SwingUtilities.replaceUIInputMap(root,
  59. JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, km);
  60. LazyActionMap.installLazyActionMap(root, BasicRootPaneUI.class,
  61. "RootPane.actionMap");
  62. updateDefaultButtonBindings(root);
  63. }
  64. protected void uninstallDefaults(JRootPane root) {
  65. }
  66. protected void uninstallComponents(JRootPane root) {
  67. }
  68. protected void uninstallListeners(JRootPane root) {
  69. root.removePropertyChangeListener(this);
  70. }
  71. protected void uninstallKeyboardActions(JRootPane root) {
  72. SwingUtilities.replaceUIInputMap(root, JComponent.
  73. WHEN_IN_FOCUSED_WINDOW, null);
  74. SwingUtilities.replaceUIActionMap(root, null);
  75. }
  76. InputMap getInputMap(int condition, JComponent c) {
  77. if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
  78. return (InputMap)DefaultLookup.get(c, this,
  79. "RootPane.ancestorInputMap");
  80. }
  81. if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
  82. return createInputMap(condition, c);
  83. }
  84. return null;
  85. }
  86. ComponentInputMap createInputMap(int condition, JComponent c) {
  87. return new RootPaneInputMap(c);
  88. }
  89. static void loadActionMap(LazyActionMap map) {
  90. map.put(new Actions(Actions.PRESS));
  91. map.put(new Actions(Actions.RELEASE));
  92. map.put(new Actions(Actions.POST_POPUP));
  93. }
  94. /**
  95. * Invoked when the default button property has changed. This reloads
  96. * the bindings from the defaults table with name
  97. * <code>RootPane.defaultButtonWindowKeyBindings</code>.
  98. */
  99. void updateDefaultButtonBindings(JRootPane root) {
  100. InputMap km = SwingUtilities.getUIInputMap(root, JComponent.
  101. WHEN_IN_FOCUSED_WINDOW);
  102. while (km != null && !(km instanceof RootPaneInputMap)) {
  103. km = km.getParent();
  104. }
  105. if (km != null) {
  106. km.clear();
  107. if (root.getDefaultButton() != null) {
  108. Object[] bindings = (Object[])DefaultLookup.get(root, this,
  109. "RootPane.defaultButtonWindowKeyBindings");
  110. if (bindings != null) {
  111. LookAndFeel.loadKeyBindings(km, bindings);
  112. }
  113. }
  114. }
  115. }
  116. /**
  117. * Invoked when a property changes on the root pane. If the event
  118. * indicates the <code>defaultButton</code> has changed, this will
  119. * reinstall the keyboard actions.
  120. */
  121. public void propertyChange(PropertyChangeEvent e) {
  122. if(e.getPropertyName().equals("defaultButton")) {
  123. JRootPane rootpane = (JRootPane)e.getSource();
  124. updateDefaultButtonBindings(rootpane);
  125. if (rootpane.getClientProperty("temporaryDefaultButton") == null) {
  126. rootpane.putClientProperty("initialDefaultButton", e.getNewValue());
  127. }
  128. }
  129. }
  130. static class Actions extends UIAction {
  131. public static final String PRESS = "press";
  132. public static final String RELEASE = "release";
  133. public static final String POST_POPUP = "postPopup";
  134. Actions(String name) {
  135. super(name);
  136. }
  137. public void actionPerformed(ActionEvent evt) {
  138. JRootPane root = (JRootPane)evt.getSource();
  139. JButton owner = root.getDefaultButton();
  140. String key = getName();
  141. if (key == POST_POPUP) { // Action to post popup
  142. Component c = KeyboardFocusManager
  143. .getCurrentKeyboardFocusManager()
  144. .getFocusOwner();
  145. if(c instanceof JComponent) {
  146. JComponent src = (JComponent) c;
  147. JPopupMenu jpm = src.getComponentPopupMenu();
  148. if(jpm != null) {
  149. Point pt = src.getPopupLocation(null);
  150. if(pt == null) {
  151. Rectangle vis = src.getVisibleRect();
  152. pt = new Point(vis.x+vis.width2,
  153. vis.y+vis.height2);
  154. }
  155. jpm.show(c, pt.x, pt.y);
  156. }
  157. }
  158. }
  159. else if (owner != null
  160. && SwingUtilities.getRootPane(owner) == root) {
  161. if (key == PRESS) {
  162. owner.doClick(20);
  163. }
  164. }
  165. }
  166. public boolean isEnabled(Object sender) {
  167. String key = getName();
  168. if(key == POST_POPUP) {
  169. MenuElement[] elems = MenuSelectionManager
  170. .defaultManager()
  171. .getSelectedPath();
  172. if(elems != null && elems.length != 0) {
  173. return false;
  174. // We shall not interfere with already opened menu
  175. }
  176. Component c = KeyboardFocusManager
  177. .getCurrentKeyboardFocusManager()
  178. .getFocusOwner();
  179. if(c instanceof JComponent) {
  180. JComponent src = (JComponent) c;
  181. return src.getComponentPopupMenu() != null;
  182. }
  183. return false;
  184. }
  185. if (sender != null && sender instanceof JRootPane) {
  186. JButton owner = ((JRootPane)sender).getDefaultButton();
  187. return (owner != null && owner.getModel().isEnabled());
  188. }
  189. return true;
  190. }
  191. }
  192. private static class RootPaneInputMap extends ComponentInputMapUIResource {
  193. public RootPaneInputMap(JComponent c) {
  194. super(c);
  195. }
  196. }
  197. }