001 /* MetalToolTipUI.java
002 Copyright (C) 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.metal;
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.event.InputEvent;
047 import java.awt.event.KeyEvent;
048
049 import javax.swing.AbstractButton;
050 import javax.swing.JComponent;
051 import javax.swing.JMenuItem;
052 import javax.swing.JToolTip;
053 import javax.swing.KeyStroke;
054 import javax.swing.UIManager;
055 import javax.swing.border.Border;
056 import javax.swing.plaf.ComponentUI;
057 import javax.swing.plaf.UIResource;
058 import javax.swing.plaf.basic.BasicToolTipUI;
059
060 /**
061 * A UI delegate for the {@link JToolTip} component.
062 */
063 public class MetalToolTipUI
064 extends BasicToolTipUI
065 {
066 /**
067 * The amount of space between the tool tip text and the accelerator
068 * description (if visible).
069 */
070 public static final int padSpaceBetweenStrings = 12;
071
072 /** The shared UI instance. */
073 private static MetalToolTipUI instance;
074
075 /** A flag controlling the visibility of the accelerator (if there is one). */
076 private boolean isAcceleratorHidden;
077
078 /** A string representing the accelerator key for the component. */
079 private String acceleratorString;
080
081 /**
082 * The delimiter for the accelerator string.
083 */
084 private String acceleratorDelimiter;
085
086 /** The font for the accelerator string. */
087 private Font acceleratorFont;
088
089 /** The color for the accelerator string. */
090 private Color acceleratorForeground;
091
092 /** The active border. */
093 private Border activeBorder;
094
095 /** The inactive border. */
096 private Border inactiveBorder;
097
098 /**
099 * Constructs a new instance of <code>MetalToolTipUI</code>.
100 */
101 public MetalToolTipUI()
102 {
103 super();
104 activeBorder = UIManager.getBorder("ToolTip.border");
105 inactiveBorder = UIManager.getBorder("ToolTip.borderInactive");
106 isAcceleratorHidden = UIManager.getBoolean("ToolTip.hideAccelerator");
107 acceleratorFont = UIManager.getFont("MenuItem.acceleratorFont");
108 acceleratorForeground = UIManager.getColor("MenuItem.acceleratorForeground");
109 acceleratorDelimiter = UIManager.getString("MenuItem.acceleratorDelimiter");
110 }
111
112 /**
113 * Returns a shared instance of the <code>MetalToolTipUI</code> class.
114 * Although this UI delegate does maintain state information, there is never
115 * more than one tool tip visible, so it is OK to use a shared instance.
116 *
117 * @param component the component (a {@link JToolTip}).
118 *
119 * @return A shared instance of the <code>MetalToolTipUI</code> class.
120 */
121 public static ComponentUI createUI(JComponent component)
122 {
123 if (instance == null)
124 instance = new MetalToolTipUI();
125 return instance;
126 }
127
128 /**
129 * Returns a string representing the accelerator key (if there is one) for
130 * the component that the tool tip belongs to.
131 *
132 * @return A string representing the accelerator key.
133 */
134 public String getAcceleratorString()
135 {
136 return acceleratorString;
137 }
138
139 /**
140 * Installs the UI for the specified component (a {@link JToolTip}).
141 *
142 * @param c the {@link JToolTip} component.
143 */
144 public void installUI(JComponent c)
145 {
146 super.installUI(c);
147 Border existingBorder = c.getBorder();
148 if (existingBorder == null || existingBorder instanceof UIResource)
149 {
150 if (c.isEnabled())
151 c.setBorder(activeBorder);
152 else
153 c.setBorder(inactiveBorder);
154 }
155 }
156
157 /**
158 * Clears the defaults set in {@link #installUI(JComponent)}.
159 *
160 * @param c the component.
161 */
162 public void uninstallUI(JComponent c)
163 {
164 super.uninstallUI(c);
165 if (c.getBorder() instanceof UIResource)
166 c.setBorder(null);
167 }
168
169 /**
170 * Returns <code>true</code> if the accelerator string is hidden, and
171 * <code>false</code> otherwise. This setting is controlled by the
172 * <code>ToolTip.hideAccelerator</code> entry in the UI defaults table.
173 *
174 * @return A boolean.
175 */
176 protected boolean isAcceleratorHidden()
177 {
178 return isAcceleratorHidden;
179 }
180
181 /**
182 * Returns the preferred size for the {@link JToolTip} component.
183 *
184 * @param c the component (a {@link JToolTip}).
185 *
186 * @return The preferred size.
187 */
188 public Dimension getPreferredSize(JComponent c)
189 {
190 Dimension d = super.getPreferredSize(c);
191 String acc = getAcceleratorString();
192 if (acc != null && ! acc.equals(""))
193 {
194 FontMetrics fm = c.getFontMetrics(c.getFont());
195 d.width += fm.stringWidth(acc);
196 }
197 return d;
198 }
199
200 /**
201 * Paints the tool tip.
202 *
203 * @param g the graphics context.
204 * @param c the {@link JToolTip} component.
205 */
206 public void paint(Graphics g, JComponent c)
207 {
208 super.paint(g, c);
209 // Somehow paint accelerator. Keep care for possible HTML rendering.
210 }
211
212 /**
213 * Returns a string representing the accelerator for the component, or
214 * <code>null</code> if the component has no accelerator.
215 *
216 * @param c the component.
217 *
218 * @return A string representing the accelerator (possibly
219 * <code>null</code>).
220 */
221 private String fetchAcceleratorString(JComponent c)
222 {
223 String result = null;
224 if (c instanceof JToolTip)
225 {
226 JToolTip toolTip = (JToolTip) c;
227 JComponent component = toolTip.getComponent();
228 KeyStroke ks = null;
229 int mne = 0;
230 if (component instanceof JMenuItem)
231 {
232 JMenuItem item = (JMenuItem) component;
233 ks = item.getAccelerator();
234 if (ks == null)
235 mne = item.getMnemonic();
236 }
237 else if (component instanceof AbstractButton)
238 {
239 AbstractButton button = (AbstractButton) component;
240 mne = button.getMnemonic();
241 }
242 if (mne > 0)
243 ks = KeyStroke.getKeyStroke(Character.toUpperCase((char) mne),
244 InputEvent.ALT_MASK, false);
245 if (ks != null)
246 result = acceleratorToString(ks);
247 }
248 return result;
249 }
250
251 /**
252 * Returns a string representing an accelerator.
253 *
254 * @param accelerator the accelerator (<code>null</code> not permitted).
255 *
256 * @return A string representing an accelerator.
257 */
258 private String acceleratorToString(KeyStroke accelerator)
259 {
260 // convert keystroke into string format
261 String modifiersText = "";
262 int modifiers = accelerator.getModifiers();
263 char keyChar = accelerator.getKeyChar();
264 int keyCode = accelerator.getKeyCode();
265
266 if (modifiers != 0)
267 modifiersText = KeyEvent.getKeyModifiersText(modifiers)
268 + acceleratorDelimiter;
269
270 if (keyCode == KeyEvent.VK_UNDEFINED)
271 return modifiersText + keyChar;
272 else
273 return modifiersText + KeyEvent.getKeyText(keyCode);
274 }
275
276 }