Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/flexstor/common/awt/ToolTip.java


1   /*
2    * ToolTip.java
3    *
4    * Copyright $Date: 2003/08/11 02:22:32 $ FLEXSTOR.net Inc.
5    *
6    * This work is licensed for use and distribution under license terms found at
7    * http://www.flexstor.org/license.html
8    *
9    */
10  
11  package com.flexstor.common.awt;
12  
13  import java.awt.Color;
14  import java.awt.Font;
15  import java.awt.FontMetrics;
16  import java.awt.Frame;
17  import java.awt.Graphics;
18  import java.util.Vector;
19  
20  /**
21   * This class is used for displaying tool tips.
22   * It is a window without title bar nor border.
23   * The paint method draws directly on the graphic context.
24   */
25  public class ToolTip
26     extends java.awt.Window
27     //implements FocusListener
28  {
29     static final protected int   MAX_WIDTH = 300;
30     static final protected int   INSETS_X  = 2;
31     static final protected Color TIP_COLOR = new Color(16447424);
32     static       protected int   CURSOR_OFFSET = -2;   // default
33     
34     String        sText         = null;
35     FontMetrics   fm            = null;
36     Vector        vTextLines    = new Vector();
37     
38     public ToolTip(Frame f)
39     {
40        super(f);
41        setLayout(null);
42        setBackground(TIP_COLOR);  
43        //addFocusListener(this);
44        //setEnabled(false);
45     }
46  /*
47     public void requestFocus()
48     {
49     }
50  */   
51     /**
52      * Gets the default font and reduces it by 1 (one).
53      * Gets the font metrics for the tool tip font.
54      * Analyzes text and enforces location before first show.
55      */
56     public void addNotify()
57     {
58        Font tipFont;
59        
60        super.addNotify();
61        
62        //System.out.println("Original font: " + getFont());
63        int nFontSize = Math.max(9, getFont().getSize() - 1);
64        //System.out.println("New FontSize: " + nFontSize);
65        tipFont = new Font(getFont().getName(), getFont().getStyle(), nFontSize);
66        setFont(tipFont);
67        //System.out.println("Set font: " + tipFont);
68        fm = getFontMetrics(tipFont);
69        CURSOR_OFFSET = fm.getHeight() / -2;
70        vTextLines = analyze(sText);
71        // call this.setLocation to enforce on-screen display for first show
72        setLocation(getLocation().x, getLocation().y - CURSOR_OFFSET);
73     }
74  
75     // Must be true to set focus to the tool tip
76     /*
77     public boolean isFocusTraversable()
78     {
79        return false;
80     }
81     */
82     
83     /**
84      * To work properly, the instance MUST get focus when
85      * set to visible.
86      */
87      /*
88     public void focusLost(FocusEvent e)
89     {
90        //System.out.println(this + " focusLost");
91        setVisible(false);
92     }
93     */
94  
95     /**
96      * Implements FocusListener
97      */
98      /*
99     public void focusGained(FocusEvent e)
100    {
101       //System.out.println(this + " focusGained");
102    }
103    */
104 
105    /**
106     */
107    public void paint(Graphics g)
108    {
109       int i;
110       int nSize = vTextLines.size();
111 
112       int y = fm.getMaxAscent();
113 
114       for (i = 0; i < nSize; i++)
115       {
116          g.drawString((String)vTextLines.elementAt(i), INSETS_X, y);
117          y += fm.getHeight();
118       }
119       //super.paint(g); // not needed, just paints children which this class does not have
120       g.drawRect(0, 0, getSize().width - 1, getSize().height - 1);
121    }
122    
123    /**
124     * This methods is modified from Symantec's WrappingLabel.
125     * It splits up the string into lines based on the font's metrics
126     * which are set in addNotify.
127     * The constant MAX_WIDTH specifies the maximum width in pixels for this window.
128     * @param SText the string to analyze
129     * @return a vector with each element representing a line of text
130     */
131    protected Vector analyze(String sText)
132    {
133       Vector vText = new Vector();
134       
135       //if (fm == null)
136       //   System.out.println("fm == null");
137       
138       if (sText != null && fm != null)
139       {
140          int y;   // keeps track of height
141          int fromIndex = 0;
142          int pos = 0;
143          int bestpos;
144          String largestString;
145          String s;
146 
147          y = fm.getMaxAscent();
148 
149          // set max width
150          int nWidth = fm.stringWidth(sText) + 4; // sum of individual characters != stringWidth
151          if (nWidth > MAX_WIDTH)
152          {
153             nWidth = MAX_WIDTH;
154          }
155          
156          // While we haven't passed the bottom of the label and we
157          // haven't run past the end of the string...
158          while (fromIndex != -1)
159          {
160             // Automatically skip any spaces at the beginning of the line
161             while (fromIndex < sText.length() && sText.charAt(fromIndex) == ' ')
162             {
163                ++fromIndex;
164                // If we hit the end of line while skipping spaces, we're done.
165                if (fromIndex >= sText.length()) break;
166             }
167 
168             // fromIndex represents the beginning of the line
169             pos = fromIndex;
170             bestpos = -1;
171             largestString = null;
172 
173             while (pos >= fromIndex)
174             {
175                pos = sText.indexOf(' ', pos+1);
176 
177                // Couldn't find another space?
178                if (pos == -1)
179                {
180                   s = sText.substring(fromIndex);
181                }
182                else
183                {
184                   s = sText.substring(fromIndex, pos);
185                }
186 
187                // If the string fits, keep track of it.
188                if (fm.stringWidth(s) < nWidth)
189                {
190                   largestString = s;
191                   bestpos = pos;
192 
193                   // If we've hit the end of the string, use it.
194                   if (pos == -1) break;
195                }
196                else
197                {
198                    break;
199                }
200 
201                ++pos;
202             }
203 
204             if (largestString == null)
205             {
206                // Couldn't wrap at a space, so find the largest line
207                // that fits and print that.  Note that this will be
208                // slightly off -- the width of a string will not necessarily
209                // be the sum of the width of its characters, due to kerning.
210                int totalWidth = 0;
211                int oneCharWidth = 0;
212 
213                pos = fromIndex;
214 
215                while (pos < sText.length())
216                {
217                   oneCharWidth = fm.charWidth(sText.charAt(pos));
218                   if ((totalWidth + oneCharWidth) >= nWidth) break;
219                   totalWidth += oneCharWidth;
220                   ++pos;
221                }
222 
223                //g.drawString(sText.substring(fromIndex, pos), x, y);
224                
225                vText.addElement(sText.substring(fromIndex, pos));
226                
227                fromIndex = pos;
228             }
229             else
230             {
231                //g.drawString(largestString, x, y);
232 
233                vText.addElement(largestString);
234 
235                fromIndex = bestpos;
236             }
237             y += fm.getHeight();
238          }
239          
240          // correct y for last line
241          y -= fm.getHeight();
242 
243          setSize(nWidth + 2 * INSETS_X, y + fm.getMaxDescent() + 1);
244       }
245       
246       return vText;
247    }
248 
249    /**
250     * Sets the text of the tool tip
251     * @param sTip the new tip text
252     */
253    public void setText(String sTip)
254    {
255       if (sTip.equals(sText))
256          return;
257          
258       sText = sTip;
259       if (fm != null)
260       {
261          vTextLines = analyze(sText);
262          /*
263          for (int i = 0; i < vTextLines.size(); i++)
264          {
265             System.out.println("[" + i + "]" + vTextLines.elementAt(i));
266          }
267          */
268       }
269    }
270    
271    public void setVisible(boolean bShow)
272    {
273       //setLocation(0, -500);
274       super.setVisible(bShow);
275       if (bShow)
276       {
277          toFront();
278          //requestFocus(); // this call prevents it from working in Win95
279                            // evidently something is screwed up!
280       }
281    }
282    
283    /**
284     * This method ensures that the tooltip is completely on screen by
285     * modifying the x,y coordinates before calling super.setLocation.
286     */
287    public void setLocation(int x, int y)
288    {
289       
290       y += CURSOR_OFFSET;
291       
292       // ensure that tooltip is always on screen
293       int dx = x + getSize().width  - getToolkit().getScreenSize().width;
294       int dy = y + getSize().height - getToolkit().getScreenSize().height;
295       if (dx > 0)
296       {
297          x -= dx;
298       }
299       if (dy > 0)
300       {
301          y -= (2 * CURSOR_OFFSET + getSize().height);
302       }
303 
304       super.setLocation(x, y);
305    }
306 }