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 }