1. /*
  2. * @(#)MetalToolTipUI.java 1.28 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.metal;
  8. import com.sun.java.swing.SwingUtilities2;
  9. import java.awt.*;
  10. import java.awt.event.*;
  11. import javax.swing.*;
  12. import javax.swing.BorderFactory;
  13. import javax.swing.border.Border;
  14. import javax.swing.plaf.*;
  15. import javax.swing.plaf.basic.BasicToolTipUI;
  16. /**
  17. * A Metal L&F extension of BasicToolTipUI.
  18. * <p>
  19. * <strong>Warning:</strong>
  20. * Serialized objects of this class will not be compatible with
  21. * future Swing releases. The current serialization support is
  22. * appropriate for short term storage or RMI between applications running
  23. * the same version of Swing. As of 1.4, support for long term storage
  24. * of all JavaBeans<sup><font size="-2">TM</font></sup>
  25. * has been added to the <code>java.beans</code> package.
  26. * Please see {@link java.beans.XMLEncoder}.
  27. *
  28. * @version 1.28 12/19/03
  29. * @author Steve Wilson
  30. */
  31. public class MetalToolTipUI extends BasicToolTipUI {
  32. static MetalToolTipUI sharedInstance = new MetalToolTipUI();
  33. private Font smallFont;
  34. // Refer to note in getAcceleratorString about this field.
  35. private JToolTip tip;
  36. public static final int padSpaceBetweenStrings = 12;
  37. private String acceleratorDelimiter;
  38. public MetalToolTipUI() {
  39. super();
  40. }
  41. public static ComponentUI createUI(JComponent c) {
  42. return sharedInstance;
  43. }
  44. public void installUI(JComponent c) {
  45. super.installUI(c);
  46. tip = (JToolTip)c;
  47. Font f = c.getFont();
  48. smallFont = new Font( f.getName(), f.getStyle(), f.getSize() - 2 );
  49. acceleratorDelimiter = UIManager.getString( "MenuItem.acceleratorDelimiter" );
  50. if ( acceleratorDelimiter == null ) { acceleratorDelimiter = "-"; }
  51. }
  52. public void uninstallUI(JComponent c) {
  53. super.uninstallUI(c);
  54. tip = null;
  55. }
  56. public void paint(Graphics g, JComponent c) {
  57. JToolTip tip = (JToolTip)c;
  58. super.paint(g, c);
  59. Font font = c.getFont();
  60. FontMetrics metrics = SwingUtilities2.getFontMetrics(c, g, font);
  61. String keyText = getAcceleratorString(tip);
  62. String tipText = tip.getTipText();
  63. if (tipText == null) {
  64. tipText = "";
  65. }
  66. if (! (keyText.equals(""))) { // only draw control key if there is one
  67. g.setFont(smallFont);
  68. g.setColor( MetalLookAndFeel.getPrimaryControlDarkShadow() );
  69. SwingUtilities2.drawString(tip, g, keyText,
  70. SwingUtilities2.stringWidth(
  71. tip, metrics, tipText) + padSpaceBetweenStrings,
  72. 2 + metrics.getAscent());
  73. }
  74. }
  75. public Dimension getPreferredSize(JComponent c) {
  76. Dimension d = super.getPreferredSize(c);
  77. String key = getAcceleratorString((JToolTip)c);
  78. if (! (key.equals(""))) {
  79. FontMetrics fm = c.getFontMetrics(smallFont);
  80. d.width += SwingUtilities2.stringWidth(c, fm, key) +
  81. padSpaceBetweenStrings;
  82. }
  83. return d;
  84. }
  85. protected boolean isAcceleratorHidden() {
  86. Boolean b = (Boolean)UIManager.get("ToolTip.hideAccelerator");
  87. return b != null && b.booleanValue();
  88. }
  89. private String getAcceleratorString(JToolTip tip) {
  90. this.tip = tip;
  91. String retValue = getAcceleratorString();
  92. this.tip = null;
  93. return retValue;
  94. }
  95. // NOTE: This requires the tip field to be set before this is invoked.
  96. // As MetalToolTipUI is shared between all JToolTips the tip field is
  97. // set appropriately before this is invoked. Unfortunately this means
  98. // that subclasses that randomly invoke this method will see varying
  99. // results. If this becomes an issue, MetalToolTipUI should no longer be
  100. // shared.
  101. public String getAcceleratorString() {
  102. if (tip == null || isAcceleratorHidden()) {
  103. return "";
  104. }
  105. JComponent comp = tip.getComponent();
  106. if (comp == null) {
  107. return "";
  108. }
  109. KeyStroke[] keys;
  110. if (comp instanceof JTabbedPane) {
  111. TabbedPaneUI ui = ( (JTabbedPane)(comp) ).getUI();
  112. if (ui instanceof MetalTabbedPaneUI) {
  113. // if comp is instance of JTabbedPane and have 'metal' look-and-feel
  114. // detect tab the mouse is over now
  115. int rolloverTabIndex = ( (MetalTabbedPaneUI)ui ).getRolloverTabIndex();
  116. if (rolloverTabIndex == -1)
  117. keys = new KeyStroke[0];
  118. else {
  119. // detect mnemonic for this tab
  120. int mnemonic = ((JTabbedPane)comp).getMnemonicAt(rolloverTabIndex);
  121. if (mnemonic == -1)
  122. keys = new KeyStroke[0];
  123. else {
  124. // and store it as mnemonic for the component
  125. KeyStroke keyStroke = KeyStroke.getKeyStroke(mnemonic, Event.ALT_MASK);
  126. keys = new KeyStroke[1];
  127. keys[0] = keyStroke;
  128. }
  129. }
  130. }
  131. else
  132. keys = comp.getRegisteredKeyStrokes();
  133. }
  134. else
  135. keys = comp.getRegisteredKeyStrokes();
  136. String controlKeyStr = "";
  137. for (int i = 0; i < keys.length; i++) {
  138. int mod = keys[i].getModifiers();
  139. int condition = comp.getConditionForKeyStroke(keys[i]);
  140. if ( condition == JComponent.WHEN_IN_FOCUSED_WINDOW )
  141. {
  142. controlKeyStr = KeyEvent.getKeyModifiersText(mod) +
  143. acceleratorDelimiter +
  144. KeyEvent.getKeyText(keys[i].getKeyCode());
  145. break;
  146. }
  147. }
  148. /* Special case for menu item since they do not register a
  149. keyboard action for their mnemonics and they always use Alt */
  150. if ( controlKeyStr.equals("") && comp instanceof JMenuItem )
  151. {
  152. int mnemonic = ((JMenuItem) comp).getMnemonic();
  153. if ( mnemonic != 0 )
  154. {
  155. controlKeyStr =
  156. KeyEvent.getKeyModifiersText(KeyEvent.ALT_MASK) +
  157. acceleratorDelimiter + (char)mnemonic;
  158. }
  159. }
  160. return controlKeyStr;
  161. }
  162. }