OSDN Git Service

d1040347fc61ac3455c925ba2f7babf40b4ae3ac
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / swing / plaf / metal / MetalToolTipUI.java
1 /* MetalToolTipUI.java
2    Copyright (C) 2005 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package javax.swing.plaf.metal;
40
41 import java.awt.Color;
42 import java.awt.Dimension;
43 import java.awt.Font;
44 import java.awt.FontMetrics;
45 import java.awt.Graphics;
46 import java.awt.Insets;
47 import java.awt.Rectangle;
48 import java.awt.Toolkit;
49 import java.awt.event.InputEvent;
50 import java.awt.event.KeyEvent;
51
52 import javax.swing.AbstractButton;
53 import javax.swing.JComponent;
54 import javax.swing.JMenuItem;
55 import javax.swing.JToolTip;
56 import javax.swing.KeyStroke;
57 import javax.swing.SwingConstants;
58 import javax.swing.SwingUtilities;
59 import javax.swing.UIManager;
60 import javax.swing.border.Border;
61 import javax.swing.plaf.ComponentUI;
62 import javax.swing.plaf.UIResource;
63 import javax.swing.plaf.basic.BasicToolTipUI;
64
65 /**
66  * A UI delegate for the {@link JToolTip} component.
67  */
68 public class MetalToolTipUI
69   extends BasicToolTipUI
70 {
71   /** 
72    * The amount of space between the tool tip text and the accelerator 
73    * description (if visible). 
74    */
75   public static final int padSpaceBetweenStrings = 12;
76
77   /** The shared UI instance. */
78   private static MetalToolTipUI instance;
79   
80   /** A flag controlling the visibility of the accelerator (if there is one). */
81   private boolean isAcceleratorHidden;
82   
83   /** A string representing the accelerator key for the component. */
84   private String acceleratorString;
85   
86   /** 
87    * The delimiter for the accelerator string.
88    */
89   private String acceleratorDelimiter;
90   
91   /** The font for the accelerator string. */
92   private Font acceleratorFont;
93   
94   /** The color for the accelerator string. */
95   private Color acceleratorForeground;
96   
97   /** The active border. */
98   private Border activeBorder;
99   
100   /** The inactive border. */
101   private Border inactiveBorder;
102   
103   /**
104    * Constructs a new instance of <code>MetalToolTipUI</code>.
105    */
106   public MetalToolTipUI()
107   {
108     super();
109     activeBorder = UIManager.getBorder("ToolTip.border");
110     inactiveBorder = UIManager.getBorder("ToolTip.borderInactive");
111     isAcceleratorHidden = UIManager.getBoolean("ToolTip.hideAccelerator");
112     acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont");
113     acceleratorForeground = UIManager.getColor("MenuItem.acceleratorForeground");
114     acceleratorDelimiter = UIManager.getString("MenuItem.acceleratorDelimiter");
115   }
116
117   /**
118    * Returns a shared instance of the <code>MetalToolTipUI</code> class.
119    * Although this UI delegate does maintain state information, there is never
120    * more than one tool tip visible, so it is OK to use a shared instance.
121    *
122    * @param component  the component (a {@link JToolTip}).
123    *
124    * @return A shared instance of the <code>MetalToolTipUI</code> class.
125    */
126   public static ComponentUI createUI(JComponent component)
127   {
128     if (instance == null)
129       instance = new MetalToolTipUI();
130     return instance;
131   }
132   
133   /**
134    * Returns a string representing the accelerator key (if there is one) for 
135    * the component that the tool tip belongs to.
136    * 
137    * @return A string representing the accelerator key.
138    */
139   public String getAcceleratorString()
140   {
141     return acceleratorString;   
142   }
143   
144   /**
145    * Installs the UI for the specified component (a {@link JToolTip}).
146    * 
147    * @param c  the {@link JToolTip} component.
148    */
149   public void installUI(JComponent c)
150   {
151     super.installUI(c);
152     Border existingBorder = c.getBorder();
153     if (existingBorder == null || existingBorder instanceof UIResource)
154       {
155         if (c.isEnabled())
156           c.setBorder(activeBorder);
157         else
158           c.setBorder(inactiveBorder);
159       }   
160   }
161   
162   /**
163    * Clears the defaults set in {@link #installUI(JComponent)}.
164    * 
165    * @param c  the component.
166    */
167   public void uninstallUI(JComponent c)
168   {
169     super.uninstallUI(c);
170     if (c.getBorder() instanceof UIResource)
171       c.setBorder(null);
172   }
173   
174   /**
175    * Returns <code>true</code> if the accelerator string is hidden, and
176    * <code>false</code> otherwise.  This setting is controlled by the
177    * <code>ToolTip.hideAccelerator</code> entry in the UI defaults table.
178    *
179    * @return A boolean.
180    */
181   protected boolean isAcceleratorHidden()
182   {
183     return isAcceleratorHidden;
184   }
185   
186   /**
187    * Returns the preferred size for the {@link JToolTip} component.
188    * 
189    * @param c  the component (a {@link JToolTip}).
190    * 
191    * @return The preferred size.
192    */
193   public Dimension getPreferredSize(JComponent c)
194   {
195     if (isAcceleratorHidden())
196       return super.getPreferredSize(c);
197     else
198       {
199         Insets insets = c.getInsets();
200         JToolTip tt = (JToolTip) c;
201         String tipText = tt.getTipText();
202         if (tipText != null)
203           {
204             FontMetrics fm = c.getFontMetrics(c.getFont());
205             int prefH = fm.getHeight() + insets.top + insets.bottom;
206             int prefW = fm.stringWidth(tipText) + insets.left + insets.right;
207
208             // this seems to be the first opportunity we have to get the 
209             // accelerator string from the component (if it has one)
210             acceleratorString = fetchAcceleratorString(c);
211             if (acceleratorString != null)
212               {
213                 prefW += padSpaceBetweenStrings;
214                 fm = c.getFontMetrics(acceleratorFont);
215                 prefW += fm.stringWidth(acceleratorString);                
216               }
217             return new Dimension(prefW, prefH);  
218           }
219         else return new Dimension(0, 0);
220       }
221   }
222   
223   /**
224    * Paints the tool tip.
225    * 
226    * @param g  the graphics context.
227    * @param c  the {@link JToolTip} component.
228    */
229   public void paint(Graphics g, JComponent c)
230   {
231     JToolTip tip = (JToolTip) c;
232
233     String text = tip.getTipText();
234     Toolkit t = tip.getToolkit();
235     if (text == null)
236       return;
237
238     Rectangle vr = new Rectangle();
239     vr = SwingUtilities.calculateInnerArea(tip, vr);
240     Rectangle ir = new Rectangle();
241     Rectangle tr = new Rectangle();
242     FontMetrics fm = t.getFontMetrics(tip.getFont());
243     int ascent = fm.getAscent();
244     SwingUtilities.layoutCompoundLabel(tip, fm, text, null, 
245             SwingConstants.CENTER, SwingConstants.LEFT,
246             SwingConstants.CENTER, SwingConstants.CENTER, vr, ir, tr, 0);
247     Color saved = g.getColor();
248     g.setColor(Color.BLACK);
249
250     g.drawString(text, vr.x, vr.y + ascent); 
251     
252     // paint accelerator
253     if (acceleratorString != null)
254       {
255         g.setFont(acceleratorFont);
256         g.setColor(acceleratorForeground);
257         fm = t.getFontMetrics(acceleratorFont);
258         int width = fm.stringWidth(acceleratorString);
259         g.drawString(acceleratorString, vr.x + vr.width - width 
260             - padSpaceBetweenStrings / 2, vr.y + vr.height - fm.getDescent());
261       }
262
263     g.setColor(saved);   
264   }
265   
266   /**
267    * Returns a string representing the accelerator for the component, or 
268    * <code>null</code> if the component has no accelerator.
269    * 
270    * @param c  the component.
271    * 
272    * @return A string representing the accelerator (possibly 
273    *         <code>null</code>).
274    */
275   private String fetchAcceleratorString(JComponent c)
276   {
277     String result = null;
278     if (c instanceof JToolTip)
279       {
280         JToolTip toolTip = (JToolTip) c;
281         JComponent component = toolTip.getComponent();
282         KeyStroke ks = null;
283         int mne = 0;
284         if (component instanceof JMenuItem)
285           {
286             JMenuItem item = (JMenuItem) component;
287             ks = item.getAccelerator();
288             if (ks == null)
289                 mne = item.getMnemonic();
290           }
291         else if (component instanceof AbstractButton)
292           {
293             AbstractButton button = (AbstractButton) component;
294             mne = button.getMnemonic();
295           }
296         if (mne > 0)
297           ks = KeyStroke.getKeyStroke(Character.toUpperCase((char) mne), 
298                 InputEvent.ALT_MASK, false);
299         if (ks != null)
300           result = acceleratorToString(ks);
301       }
302     return result;
303   }
304   
305   /**
306    * Returns a string representing an accelerator.
307    * 
308    * @param accelerator  the accelerator (<code>null</code> not permitted).
309    * 
310    * @return A string representing an accelerator.
311    */
312   private String acceleratorToString(KeyStroke accelerator)
313   {
314     // convert keystroke into string format
315     String modifiersText = "";
316     int modifiers = accelerator.getModifiers();
317     char keyChar = accelerator.getKeyChar();
318     int keyCode = accelerator.getKeyCode();
319     
320     if (modifiers != 0)
321       modifiersText = KeyEvent.getKeyModifiersText(modifiers) 
322           + acceleratorDelimiter;
323
324     if (keyCode == KeyEvent.VK_UNDEFINED)
325       return modifiersText + keyChar;
326     else
327       return modifiersText + KeyEvent.getKeyText(keyCode);
328   }
329
330 }