001    /* BasicToolTipUI.java --
002       Copyright (C) 2004, 2005 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package javax.swing.plaf.basic;
040    
041    import java.awt.Color;
042    import java.awt.Dimension;
043    import java.awt.Font;
044    import java.awt.FontMetrics;
045    import java.awt.Graphics;
046    import java.awt.Insets;
047    import java.awt.Rectangle;
048    import java.beans.PropertyChangeEvent;
049    import java.beans.PropertyChangeListener;
050    
051    import javax.swing.JComponent;
052    import javax.swing.JToolTip;
053    import javax.swing.LookAndFeel;
054    import javax.swing.plaf.ComponentUI;
055    import javax.swing.plaf.ToolTipUI;
056    import javax.swing.text.View;
057    
058    /**
059     * This is the Basic Look and Feel UI class for JToolTip.
060     */
061    public class BasicToolTipUI extends ToolTipUI
062    {
063    
064      /**
065       * Receives notification when a property of the JToolTip changes.
066       * This updates the HTML renderer if appropriate.
067       */
068      private class PropertyChangeHandler
069        implements PropertyChangeListener
070      {
071    
072        public void propertyChange(PropertyChangeEvent e)
073        {
074          String prop = e.getPropertyName();
075          if (prop.equals("tiptext") || prop.equals("font")
076              || prop.equals("foreground"))
077            {
078              JToolTip tip = (JToolTip) e.getSource();
079              String text = tip.getTipText();
080              BasicHTML.updateRenderer(tip, text);
081            }
082        }
083    
084      }
085    
086      /** The shared instance of BasicToolTipUI used for all ToolTips. */
087      private static BasicToolTipUI shared;
088    
089      /** The tooltip's text */
090      private String text;
091    
092      /**
093       * Handles property changes.
094       */
095      private PropertyChangeListener propertyChangeHandler;
096    
097      /**
098       * Creates a new BasicToolTipUI object.
099       */
100      public BasicToolTipUI()
101      {
102        super();
103      }
104    
105      /**
106       * This method creates a new BasicToolTip UI for the given
107       * JComponent.
108       *
109       * @param c The JComponent to create a UI for.
110       *
111       * @return A BasicToolTipUI that can be used by the given JComponent.
112       */
113      public static ComponentUI createUI(JComponent c)
114      {
115        if (shared == null)
116          shared = new BasicToolTipUI();
117        return shared;
118      }
119    
120      /**
121       * This method returns the msximum size of the given JComponent.
122       *
123       * @param c The JComponent to find a maximum size for.
124       *
125       * @return The maximum size.
126       */
127      public Dimension getMaximumSize(JComponent c)
128      {
129        Dimension d = getPreferredSize(c);
130        View view = (View) c.getClientProperty(BasicHTML.propertyKey);
131        if (view != null)
132          d.width += view.getMaximumSpan(View.X_AXIS)
133                     - view.getPreferredSpan(View.X_AXIS);
134        return d;
135      }
136    
137      /**
138       * This method returns the minimum size of the given JComponent.
139       *
140       * @param c The JComponent to find a minimum size for.
141       *
142       * @return The minimum size.
143       */
144      public Dimension getMinimumSize(JComponent c)
145      {
146        Dimension d = getPreferredSize(c);
147        View view = (View) c.getClientProperty(BasicHTML.propertyKey);
148        if (view != null)
149          d.width -= view.getPreferredSpan(View.X_AXIS)
150                     - view.getMinimumSpan(View.X_AXIS);
151        return d;
152      }
153    
154      /**
155       * This method returns the preferred size of the given JComponent.
156       *
157       * @param c The JComponent to find a preferred size for.
158       *
159       * @return The preferred size.
160       */
161      public Dimension getPreferredSize(JComponent c)
162      {
163        JToolTip tip = (JToolTip) c;
164        String str = tip.getTipText();
165        FontMetrics fm = c.getFontMetrics(c.getFont());
166        Insets i = c.getInsets();
167        Dimension d = new Dimension(i.left + i.right, i.top + i.bottom);
168        if (str != null && ! str.equals(""))
169          {
170            View view = (View) c.getClientProperty(BasicHTML.propertyKey);
171            if (view != null)
172              {
173                d.width += (int) view.getPreferredSpan(View.X_AXIS);
174                d.height += (int) view.getPreferredSpan(View.Y_AXIS);
175              }
176            else
177              {
178                d.width += fm.stringWidth(str) + 6;
179                d.height += fm.getHeight();
180              }
181          }
182        return d;
183      }
184    
185      /**
186       * This method installs the defaults for the given JComponent.
187       *
188       * @param c The JComponent to install defaults for.
189       */
190      protected void installDefaults(JComponent c)
191      {
192        LookAndFeel.installColorsAndFont(c, "ToolTip.background",
193                                         "ToolTip.foreground", "ToolTip.font");
194        LookAndFeel.installBorder(c, "ToolTip.border");
195      }
196    
197      /**
198       * This method installs the listeners for the given JComponent.
199       *
200       * @param c The JComponent to install listeners for.
201       */
202      protected void installListeners(JComponent c)
203      {
204        propertyChangeHandler = new PropertyChangeHandler();
205        c.addPropertyChangeListener(propertyChangeHandler);
206      }
207    
208      /**
209       * This method installs the UI for the given JComponent.
210       *
211       * @param c The JComponent to install the UI for.
212       */
213      public void installUI(JComponent c)
214      {
215        c.setOpaque(true);
216        installDefaults(c);
217        BasicHTML.updateRenderer(c, ((JToolTip) c).getTipText());
218        installListeners(c);
219      }
220    
221      /**
222       * This method paints the given JComponent with the given Graphics object.
223       *
224       * @param g The Graphics object to paint with.
225       * @param c The JComponent to paint.
226       */
227      public void paint(Graphics g, JComponent c)
228      {
229        JToolTip tip = (JToolTip) c;
230    
231        String text = tip.getTipText();
232        Font font = c.getFont();
233        FontMetrics fm = c.getFontMetrics(font);
234        int ascent = fm.getAscent();
235        Insets i = c.getInsets();
236        Dimension size = c.getSize();
237        Rectangle paintR = new Rectangle(i.left, i.top,
238                                         size.width - i.left - i.right,
239                                         size.height - i.top - i.bottom);
240        Color saved = g.getColor();
241        Font oldFont = g.getFont();
242        g.setColor(Color.BLACK);
243    
244        View view = (View) c.getClientProperty(BasicHTML.propertyKey);
245        if (view != null)
246          view.paint(g, paintR);
247        else
248          g.drawString(text, paintR.x + 3, paintR.y + ascent);
249    
250        g.setFont(oldFont);
251        g.setColor(saved);
252      }
253    
254      /**
255       * This method uninstalls the defaults for the given JComponent.
256       *
257       * @param c The JComponent to uninstall defaults for.
258       */
259      protected void uninstallDefaults(JComponent c)
260      {
261        c.setForeground(null);
262        c.setBackground(null);
263        c.setFont(null);
264        c.setBorder(null);
265      }
266    
267      /**
268       * This method uninstalls listeners for the given JComponent.
269       *
270       * @param c The JComponent to uninstall listeners for.
271       */
272      protected void uninstallListeners(JComponent c)
273      {
274        if (propertyChangeHandler != null)
275          {
276            c.removePropertyChangeListener(propertyChangeHandler);
277            propertyChangeHandler = null;
278          }
279      }
280    
281      /**
282       * This method uninstalls the UI for the given JComponent.
283       *
284       * @param c The JComponent to uninstall.
285       */
286      public void uninstallUI(JComponent c)
287      {
288        uninstallDefaults(c);
289        BasicHTML.updateRenderer(c, "");
290        uninstallListeners(c);
291      }
292    }