Source for javax.swing.plaf.metal.MetalToolTipUI

   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.event.InputEvent;
  47: import java.awt.event.KeyEvent;
  48: 
  49: import javax.swing.AbstractButton;
  50: import javax.swing.JComponent;
  51: import javax.swing.JMenuItem;
  52: import javax.swing.JToolTip;
  53: import javax.swing.KeyStroke;
  54: import javax.swing.UIManager;
  55: import javax.swing.border.Border;
  56: import javax.swing.plaf.ComponentUI;
  57: import javax.swing.plaf.UIResource;
  58: import javax.swing.plaf.basic.BasicToolTipUI;
  59: 
  60: /**
  61:  * A UI delegate for the {@link JToolTip} component.
  62:  */
  63: public class MetalToolTipUI
  64:   extends BasicToolTipUI
  65: {
  66:   /** 
  67:    * The amount of space between the tool tip text and the accelerator 
  68:    * description (if visible). 
  69:    */
  70:   public static final int padSpaceBetweenStrings = 12;
  71: 
  72:   /** The shared UI instance. */
  73:   private static MetalToolTipUI instance;
  74:   
  75:   /** A flag controlling the visibility of the accelerator (if there is one). */
  76:   private boolean isAcceleratorHidden;
  77:   
  78:   /** A string representing the accelerator key for the component. */
  79:   private String acceleratorString;
  80:   
  81:   /** 
  82:    * The delimiter for the accelerator string.
  83:    */
  84:   private String acceleratorDelimiter;
  85:   
  86:   /** The font for the accelerator string. */
  87:   private Font acceleratorFont;
  88:   
  89:   /** The color for the accelerator string. */
  90:   private Color acceleratorForeground;
  91:   
  92:   /** The active border. */
  93:   private Border activeBorder;
  94:   
  95:   /** The inactive border. */
  96:   private Border inactiveBorder;
  97:   
  98:   /**
  99:    * 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: }