1. /*
  2. * @(#)BasicMenuBarUI.java 1.74 00/02/02
  3. *
  4. * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package javax.swing.plaf.basic;
  11. import javax.swing.*;
  12. import javax.swing.event.*;
  13. import java.awt.Color;
  14. import java.awt.Component;
  15. import java.awt.Container;
  16. import java.awt.Dimension;
  17. import java.awt.Graphics;
  18. import java.awt.Insets;
  19. import java.awt.Point;
  20. import java.awt.Rectangle;
  21. import java.awt.FlowLayout;
  22. import java.awt.event.*;
  23. import java.beans.PropertyChangeEvent;
  24. import java.beans.PropertyChangeListener;
  25. import javax.swing.border.*;
  26. import javax.swing.plaf.*;
  27. /**
  28. * A default L&F implementation of MenuBarUI. This implementation
  29. * is a "combined" view/controller.
  30. *
  31. * @version 1.74 02/02/00
  32. * @author Georges Saab
  33. * @author David Karlton
  34. * @author Arnaud Weber
  35. */
  36. public class BasicMenuBarUI extends MenuBarUI {
  37. protected JMenuBar menuBar = null;
  38. protected ContainerListener containerListener;
  39. protected ChangeListener changeListener;
  40. private PropertyChangeListener propertyChangeListener;
  41. public static ComponentUI createUI(JComponent x) {
  42. return new BasicMenuBarUI();
  43. }
  44. public void installUI(JComponent c) {
  45. menuBar = (JMenuBar) c;
  46. installDefaults();
  47. installListeners();
  48. installKeyboardActions();
  49. }
  50. protected void installDefaults() {
  51. if (menuBar.getLayout() == null ||
  52. menuBar.getLayout() instanceof UIResource) {
  53. if( BasicGraphicsUtils.isLeftToRight(menuBar) ) {
  54. menuBar.setLayout(new DefaultMenuLayout(menuBar,BoxLayout.X_AXIS));
  55. } else {
  56. menuBar.setLayout(new RightToLeftMenuLayout());
  57. }
  58. }
  59. menuBar.setOpaque(true);
  60. LookAndFeel.installBorder(menuBar,"MenuBar.border");
  61. LookAndFeel.installColorsAndFont(menuBar,
  62. "MenuBar.background",
  63. "MenuBar.foreground",
  64. "MenuBar.font");
  65. }
  66. protected void installListeners() {
  67. containerListener = createContainerListener();
  68. changeListener = createChangeListener();
  69. propertyChangeListener = createPropertyChangeListener();
  70. for (int i = 0; i < menuBar.getMenuCount(); i++) {
  71. JMenu menu = menuBar.getMenu(i);
  72. if (menu!=null)
  73. menu.getModel().addChangeListener(changeListener);
  74. }
  75. menuBar.addContainerListener(containerListener);
  76. menuBar.addPropertyChangeListener(propertyChangeListener);
  77. }
  78. protected void installKeyboardActions() {
  79. InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
  80. SwingUtilities.replaceUIInputMap(menuBar,
  81. JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap);
  82. ActionMap actionMap = getActionMap();
  83. SwingUtilities.replaceUIActionMap(menuBar, actionMap);
  84. }
  85. InputMap getInputMap(int condition) {
  86. if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
  87. Object[] bindings = (Object[])UIManager.get
  88. ("MenuBar.windowBindings");
  89. if (bindings != null) {
  90. return LookAndFeel.makeComponentInputMap(menuBar, bindings);
  91. }
  92. }
  93. return null;
  94. }
  95. ActionMap getActionMap() {
  96. ActionMap map = (ActionMap)UIManager.get("MenuBar.actionMap");
  97. if (map == null) {
  98. map = createActionMap();
  99. if (map != null) {
  100. UIManager.put("MenuBar.actionMap", map);
  101. }
  102. }
  103. return map;
  104. }
  105. ActionMap createActionMap() {
  106. ActionMap map = new ActionMapUIResource();
  107. map.put("takeFocus", new TakeFocus());
  108. return map;
  109. }
  110. public void uninstallUI(JComponent c) {
  111. uninstallDefaults();
  112. uninstallListeners();
  113. uninstallKeyboardActions();
  114. menuBar = null;
  115. }
  116. protected void uninstallDefaults() {
  117. if (menuBar!=null) {
  118. LookAndFeel.uninstallBorder(menuBar);
  119. }
  120. }
  121. protected void uninstallListeners() {
  122. menuBar.removeContainerListener(containerListener);
  123. menuBar.removePropertyChangeListener(propertyChangeListener);
  124. for (int i = 0; i < menuBar.getMenuCount(); i++) {
  125. JMenu menu = menuBar.getMenu(i);
  126. if (menu !=null)
  127. menu.getModel().removeChangeListener(changeListener);
  128. }
  129. containerListener = null;
  130. changeListener = null;
  131. propertyChangeListener = null;
  132. }
  133. protected void uninstallKeyboardActions() {
  134. SwingUtilities.replaceUIInputMap(menuBar, JComponent.
  135. WHEN_IN_FOCUSED_WINDOW, null);
  136. SwingUtilities.replaceUIActionMap(menuBar, null);
  137. }
  138. protected ContainerListener createContainerListener() {
  139. return new ContainerHandler();
  140. }
  141. protected ChangeListener createChangeListener() {
  142. return new ChangeHandler();
  143. }
  144. private PropertyChangeListener createPropertyChangeListener() {
  145. return new PropertyChangeHandler();
  146. }
  147. private class ChangeHandler implements ChangeListener {
  148. public void stateChanged(ChangeEvent e) {
  149. int i,c;
  150. for(i=0,c = menuBar.getMenuCount() ; i < c ; i++) {
  151. JMenu menu = menuBar.getMenu(i);
  152. if(menu !=null && menu.isSelected()) {
  153. menuBar.getSelectionModel().setSelectedIndex(i);
  154. break;
  155. }
  156. }
  157. }
  158. }
  159. /*
  160. * This PropertyChangeListener is used to adjust the default layout
  161. * manger when the menuBar is given a right-to-left ComponentOrientation.
  162. * This is a hack to work around the fact that the DefaultMenuLayout
  163. * (BoxLayout) isn't aware of ComponentOrientation. When BoxLayout is
  164. * made aware of ComponentOrientation, this listener will no longer be
  165. * necessary.
  166. */
  167. private class PropertyChangeHandler implements PropertyChangeListener {
  168. public void propertyChange(PropertyChangeEvent e) {
  169. String name = e.getPropertyName();
  170. if( name.equals("componentOrientation")
  171. && (menuBar.getLayout() instanceof UIResource) )
  172. {
  173. if( BasicGraphicsUtils.isLeftToRight(menuBar) ) {
  174. menuBar.setLayout(new DefaultMenuLayout(menuBar,BoxLayout.X_AXIS));
  175. } else {
  176. menuBar.setLayout(new RightToLeftMenuLayout());
  177. }
  178. }
  179. }
  180. }
  181. public Dimension getPreferredSize(JComponent c) {
  182. return null;
  183. }
  184. public Dimension getMinimumSize(JComponent c) {
  185. return null;
  186. }
  187. public Dimension getMaximumSize(JComponent c) {
  188. return null;
  189. }
  190. private class ContainerHandler implements ContainerListener {
  191. public void componentAdded(ContainerEvent e) {
  192. Component c = e.getChild();
  193. if (c instanceof JMenu)
  194. ((JMenu)c).getModel().addChangeListener(changeListener);
  195. }
  196. public void componentRemoved(ContainerEvent e) {
  197. Component c = e.getChild();
  198. if (c instanceof JMenu)
  199. ((JMenu)c).getModel().removeChangeListener(changeListener);
  200. }
  201. }
  202. private static class TakeFocus extends AbstractAction {
  203. TakeFocus() {
  204. }
  205. public void actionPerformed(ActionEvent e) {
  206. JMenuBar menuBar = (JMenuBar)e.getSource();
  207. MenuSelectionManager defaultManager = MenuSelectionManager.defaultManager();
  208. MenuElement me[];
  209. MenuElement subElements[];
  210. JMenu menu = menuBar.getMenu(0);
  211. if (menu!=null) {
  212. me = new MenuElement[3];
  213. me[0] = (MenuElement) menuBar;
  214. me[1] = (MenuElement) menu;
  215. me[2] = (MenuElement) menu.getPopupMenu();
  216. defaultManager.setSelectedPath(me);
  217. }
  218. }
  219. }
  220. private static class RightToLeftMenuLayout
  221. extends FlowLayout implements UIResource
  222. {
  223. private RightToLeftMenuLayout() {
  224. super(3/*FlowLayout.LEADING*/,0,0);
  225. }
  226. }
  227. }