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