1. /*
  2. * @(#)SynthMenuUI.java 1.11 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.synth;
  8. import java.awt.*;
  9. import java.awt.event.*;
  10. import java.beans.*;
  11. import javax.swing.*;
  12. import javax.swing.event.*;
  13. import javax.swing.plaf.*;
  14. import javax.swing.plaf.basic.*;
  15. import javax.swing.border.*;
  16. import java.util.Arrays;
  17. import java.util.ArrayList;
  18. import sun.swing.plaf.synth.SynthUI;
  19. /**
  20. * Synth's MenuUI.
  21. *
  22. * @version 1.11, 12/19/03
  23. * @author Georges Saab
  24. * @author David Karlton
  25. * @author Arnaud Weber
  26. */
  27. class SynthMenuUI extends BasicMenuUI implements PropertyChangeListener,
  28. SynthUI {
  29. private SynthStyle style;
  30. private SynthStyle accStyle;
  31. private String acceleratorDelimiter;
  32. public static ComponentUI createUI(JComponent x) {
  33. return new SynthMenuUI();
  34. }
  35. protected void installDefaults() {
  36. updateStyle(menuItem);
  37. }
  38. protected void installListeners() {
  39. super.installListeners();
  40. menuItem.addPropertyChangeListener(this);
  41. }
  42. private void updateStyle(JMenuItem mi) {
  43. SynthStyle oldStyle = style;
  44. SynthContext context = getContext(mi, ENABLED);
  45. style = SynthLookAndFeel.updateStyle(context, this);
  46. if (oldStyle != style) {
  47. String prefix = getPropertyPrefix();
  48. defaultTextIconGap = style.getInt(
  49. context, prefix + ".textIconGap", 4);
  50. if (menuItem.getMargin() == null ||
  51. (menuItem.getMargin() instanceof UIResource)) {
  52. Insets insets = (Insets)style.get(context, prefix + ".margin");
  53. if (insets == null) {
  54. // Some places assume margins are non-null.
  55. insets = SynthLookAndFeel.EMPTY_UIRESOURCE_INSETS;
  56. }
  57. menuItem.setMargin(insets);
  58. }
  59. acceleratorDelimiter = style.getString(context, prefix +
  60. ".acceleratorDelimiter", "+");
  61. arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
  62. checkIcon = style.getIcon(context, prefix + ".checkIcon");
  63. ((JMenu)menuItem).setDelay(style.getInt(context, prefix +
  64. ".delay", 200));
  65. if (oldStyle != null) {
  66. uninstallKeyboardActions();
  67. installKeyboardActions();
  68. }
  69. }
  70. context.dispose();
  71. SynthContext accContext = getContext(mi, Region.MENU_ITEM_ACCELERATOR,
  72. ENABLED);
  73. accStyle = SynthLookAndFeel.updateStyle(accContext, this);
  74. accContext.dispose();
  75. }
  76. protected void uninstallDefaults() {
  77. SynthContext context = getContext(menuItem, ENABLED);
  78. style.uninstallDefaults(context);
  79. context.dispose();
  80. style = null;
  81. SynthContext accContext = getContext(menuItem,
  82. Region.MENU_ITEM_ACCELERATOR, ENABLED);
  83. accStyle.uninstallDefaults(accContext);
  84. accContext.dispose();
  85. accStyle = null;
  86. super.uninstallDefaults();
  87. }
  88. protected void uninstallListeners() {
  89. super.uninstallListeners();
  90. menuItem.removePropertyChangeListener(this);
  91. }
  92. public SynthContext getContext(JComponent c) {
  93. return getContext(c, getComponentState(c));
  94. }
  95. SynthContext getContext(JComponent c, int state) {
  96. Region region = getRegion(c);
  97. return SynthContext.getContext(SynthContext.class, c, region,
  98. style, state);
  99. }
  100. public SynthContext getContext(JComponent c, Region region) {
  101. return getContext(c, region, getComponentState(c, region));
  102. }
  103. private SynthContext getContext(JComponent c, Region region, int state) {
  104. return SynthContext.getContext(SynthContext.class, c,
  105. region, accStyle, state);
  106. }
  107. private Region getRegion(JComponent c) {
  108. return SynthLookAndFeel.getRegion(c);
  109. }
  110. private int getComponentState(JComponent c) {
  111. int state;
  112. if (!c.isEnabled()) {
  113. return DISABLED;
  114. }
  115. if (menuItem.isArmed()) {
  116. state = MOUSE_OVER;
  117. }
  118. else {
  119. state = SynthLookAndFeel.getComponentState(c);
  120. }
  121. if (menuItem.isSelected()) {
  122. state |= SELECTED;
  123. }
  124. return state;
  125. }
  126. private int getComponentState(JComponent c, Region region) {
  127. return getComponentState(c);
  128. }
  129. protected Dimension getPreferredMenuItemSize(JComponent c,
  130. Icon checkIcon,
  131. Icon arrowIcon,
  132. int defaultTextIconGap) {
  133. SynthContext context = getContext(c);
  134. SynthContext accContext = getContext(c, Region.MENU_ITEM_ACCELERATOR);
  135. Dimension value = SynthMenuItemUI.getPreferredMenuItemSize(
  136. context, accContext, useCheckAndArrow(), c, checkIcon,
  137. arrowIcon, defaultTextIconGap, acceleratorDelimiter);
  138. context.dispose();
  139. accContext.dispose();
  140. return value;
  141. }
  142. public void update(Graphics g, JComponent c) {
  143. SynthContext context = getContext(c);
  144. SynthLookAndFeel.update(context, g);
  145. context.getPainter().paintMenuBackground(context,
  146. g, 0, 0, c.getWidth(), c.getHeight());
  147. paint(context, g);
  148. context.dispose();
  149. }
  150. public void paint(Graphics g, JComponent c) {
  151. SynthContext context = getContext(c);
  152. paint(context, g);
  153. context.dispose();
  154. }
  155. protected void paint(SynthContext context, Graphics g) {
  156. SynthContext accContext = getContext(menuItem,
  157. Region.MENU_ITEM_ACCELERATOR);
  158. SynthMenuItemUI.paint(context, accContext, g, checkIcon, arrowIcon,
  159. useCheckAndArrow(), acceleratorDelimiter,
  160. defaultTextIconGap);
  161. accContext.dispose();
  162. }
  163. public void paintBorder(SynthContext context, Graphics g, int x,
  164. int y, int w, int h) {
  165. context.getPainter().paintMenuBorder(context, g, x, y, w, h);
  166. }
  167. public void propertyChange(PropertyChangeEvent e) {
  168. if (SynthLookAndFeel.shouldUpdateStyle(e)) {
  169. updateStyle((JMenu)e.getSource());
  170. }
  171. }
  172. private boolean useCheckAndArrow() {
  173. return !((JMenu)menuItem).isTopLevelMenu();
  174. }
  175. }