1. /*
  2. * @(#)BasicToolTipUI.java 1.37 03/01/23
  3. *
  4. * Copyright 2003 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.*;
  9. import java.beans.PropertyChangeEvent;
  10. import java.beans.PropertyChangeListener;
  11. import javax.swing.*;
  12. import javax.swing.BorderFactory;
  13. import javax.swing.border.Border;
  14. import javax.swing.plaf.ToolTipUI;
  15. import javax.swing.plaf.ComponentUI;
  16. import javax.swing.plaf.UIResource;
  17. import javax.swing.text.View;
  18. /**
  19. * Standard tool tip L&F.
  20. * <p>
  21. *
  22. * @version 1.37 01/23/03
  23. * @author Dave Moore
  24. */
  25. public class BasicToolTipUI extends ToolTipUI
  26. {
  27. static BasicToolTipUI sharedInstance = new BasicToolTipUI();
  28. /**
  29. * Global <code>PropertyChangeListener</code> that
  30. * <code>createPropertyChangeListener</code> returns.
  31. */
  32. private static PropertyChangeListener sharedPropertyChangedListener;
  33. private PropertyChangeListener propertyChangeListener;
  34. public static ComponentUI createUI(JComponent c) {
  35. return sharedInstance;
  36. }
  37. public BasicToolTipUI() {
  38. super();
  39. }
  40. public void installUI(JComponent c) {
  41. installDefaults(c);
  42. installComponents(c);
  43. installListeners(c);
  44. }
  45. public void uninstallUI(JComponent c) {
  46. // REMIND: this is NOT getting called
  47. uninstallDefaults(c);
  48. uninstallComponents(c);
  49. uninstallListeners(c);
  50. }
  51. protected void installDefaults(JComponent c){
  52. LookAndFeel.installColorsAndFont(c, "ToolTip.background",
  53. "ToolTip.foreground",
  54. "ToolTip.font");
  55. componentChanged(c);
  56. }
  57. protected void uninstallDefaults(JComponent c){
  58. LookAndFeel.uninstallBorder(c);
  59. }
  60. /* Unfortunately this has to remain private until we can make API additions.
  61. */
  62. private void installComponents(JComponent c){
  63. BasicHTML.updateRenderer(c, ((JToolTip)c).getTipText());
  64. }
  65. /* Unfortunately this has to remain private until we can make API additions.
  66. */
  67. private void uninstallComponents(JComponent c){
  68. BasicHTML.updateRenderer(c, "");
  69. }
  70. protected void installListeners(JComponent c) {
  71. propertyChangeListener = createPropertyChangeListener(c);
  72. c.addPropertyChangeListener(propertyChangeListener);
  73. }
  74. protected void uninstallListeners(JComponent c) {
  75. c.removePropertyChangeListener(propertyChangeListener);
  76. propertyChangeListener = null;
  77. }
  78. /* Unfortunately this has to remain private until we can make API additions.
  79. */
  80. private PropertyChangeListener createPropertyChangeListener(JComponent c) {
  81. if (sharedPropertyChangedListener == null) {
  82. sharedPropertyChangedListener = new PropertyChangeHandler();
  83. }
  84. return sharedPropertyChangedListener;
  85. }
  86. public void paint(Graphics g, JComponent c) {
  87. Font font = c.getFont();
  88. FontMetrics metrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
  89. Dimension size = c.getSize();
  90. if (c.isOpaque()) {
  91. g.setColor(c.getBackground());
  92. g.fillRect(0, 0, size.width, size.height);
  93. }
  94. g.setColor(c.getForeground());
  95. g.setFont(font);
  96. // fix for bug 4153892
  97. String tipText = ((JToolTip)c).getTipText();
  98. if (tipText == null) {
  99. tipText = "";
  100. }
  101. Insets insets = c.getInsets();
  102. Rectangle paintTextR = new Rectangle(
  103. insets.left,
  104. insets.top,
  105. size.width - (insets.left + insets.right),
  106. size.height - (insets.top + insets.bottom));
  107. View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  108. if (v != null) {
  109. v.paint(g, paintTextR);
  110. } else {
  111. g.drawString(tipText, paintTextR.x + 3,
  112. paintTextR.y + metrics.getAscent());
  113. }
  114. }
  115. public Dimension getPreferredSize(JComponent c) {
  116. Font font = c.getFont();
  117. FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
  118. Insets insets = c.getInsets();
  119. Dimension prefSize = new Dimension(insets.left+insets.right,
  120. insets.top+insets.bottom);
  121. String text = ((JToolTip)c).getTipText();
  122. if ((text == null) || text.equals("")) {
  123. text = "";
  124. }
  125. else {
  126. View v = (c != null) ? (View) c.getClientProperty("html") : null;
  127. if (v != null) {
  128. prefSize.width += (int) v.getPreferredSpan(View.X_AXIS);
  129. prefSize.height += (int) v.getPreferredSpan(View.Y_AXIS);
  130. } else {
  131. prefSize.width += SwingUtilities.computeStringWidth(fm,text) + 6;
  132. prefSize.height += fm.getHeight();
  133. }
  134. }
  135. return prefSize;
  136. }
  137. public Dimension getMinimumSize(JComponent c) {
  138. Dimension d = getPreferredSize(c);
  139. View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  140. if (v != null) {
  141. d.width -= v.getPreferredSpan(View.X_AXIS) - v.getMinimumSpan(View.X_AXIS);
  142. }
  143. return d;
  144. }
  145. public Dimension getMaximumSize(JComponent c) {
  146. Dimension d = getPreferredSize(c);
  147. View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  148. if (v != null) {
  149. d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS);
  150. }
  151. return d;
  152. }
  153. /**
  154. * Invoked when the <code>JCompoment</code> associated with the
  155. * <code>JToolTip</code> has changed, or at initialization time. This
  156. * should update any state dependant upon the <code>JComponent</code>.
  157. *
  158. * @param c the JToolTip the JComponent has changed on.
  159. */
  160. private void componentChanged(JComponent c) {
  161. JComponent comp = ((JToolTip)c).getComponent();
  162. if (comp != null && !(comp.isEnabled())) {
  163. // For better backward compatability, only install inactive
  164. // properties if they are defined.
  165. if (UIManager.getBorder("ToolTip.borderInactive") != null) {
  166. LookAndFeel.installBorder(c, "ToolTip.borderInactive");
  167. }
  168. else {
  169. LookAndFeel.installBorder(c, "ToolTip.border");
  170. }
  171. if (UIManager.getColor("ToolTip.backgroundInactive") != null) {
  172. LookAndFeel.installColors(c,"ToolTip.backgroundInactive",
  173. "ToolTip.foregroundInactive");
  174. }
  175. else {
  176. LookAndFeel.installColors(c,"ToolTip.background",
  177. "ToolTip.foreground");
  178. }
  179. } else {
  180. LookAndFeel.installBorder(c, "ToolTip.border");
  181. LookAndFeel.installColors(c, "ToolTip.background",
  182. "ToolTip.foreground");
  183. }
  184. }
  185. private static class PropertyChangeHandler implements
  186. PropertyChangeListener {
  187. public void propertyChange(PropertyChangeEvent e) {
  188. String name = e.getPropertyName();
  189. if (name.equals("tiptext") || "font".equals(name) ||
  190. "foreground".equals(name)) {
  191. // remove the old html view client property if one
  192. // existed, and install a new one if the text installed
  193. // into the JLabel is html source.
  194. JToolTip tip = ((JToolTip) e.getSource());
  195. String text = tip.getTipText();
  196. BasicHTML.updateRenderer(tip, text);
  197. }
  198. else if ("component".equals(name)) {
  199. JToolTip tip = ((JToolTip) e.getSource());
  200. if (tip.getUI() instanceof BasicToolTipUI) {
  201. ((BasicToolTipUI)tip.getUI()).componentChanged(tip);
  202. }
  203. }
  204. }
  205. }
  206. }