Source for javax.swing.plaf.basic.BasicLabelUI

   1: /* BasicLabelUI.java
   2:  Copyright (C) 2002, 2004 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: package javax.swing.plaf.basic;
  39: 
  40: import java.awt.Color;
  41: import java.awt.Dimension;
  42: import java.awt.Font;
  43: import java.awt.FontMetrics;
  44: import java.awt.Graphics;
  45: import java.awt.Insets;
  46: import java.awt.Rectangle;
  47: import java.beans.PropertyChangeEvent;
  48: import java.beans.PropertyChangeListener;
  49: 
  50: import javax.swing.Icon;
  51: import javax.swing.JComponent;
  52: import javax.swing.JLabel;
  53: import javax.swing.SwingUtilities;
  54: import javax.swing.UIDefaults;
  55: import javax.swing.UIManager;
  56: import javax.swing.plaf.ComponentUI;
  57: import javax.swing.plaf.LabelUI;
  58: 
  59: /**
  60:  * This is the Basic Look and Feel class for the JLabel.  One BasicLabelUI
  61:  * object is used to paint all JLabels that utilize the Basic Look and Feel.
  62:  */
  63: public class BasicLabelUI
  64:     extends LabelUI
  65:     implements PropertyChangeListener
  66: {
  67:   /** The labelUI that is shared by all labels. */
  68:   protected static BasicLabelUI labelUI;
  69: 
  70:   /**
  71:    * Creates a new BasicLabelUI object.
  72:    */
  73:   public BasicLabelUI()
  74:   {
  75:     super();
  76:   }
  77: 
  78:   /**
  79:    * Creates and returns a UI for the label. Since one UI is shared by  all
  80:    * labels, this means creating only if necessary and returning the  shared
  81:    * UI.
  82:    *
  83:    * @param c The {@link JComponent} that a UI is being created for.
  84:    *
  85:    * @return A label UI for the Basic Look and Feel.
  86:    */
  87:   public static ComponentUI createUI(JComponent c)
  88:   {
  89:     if (labelUI == null)
  90:       labelUI = new BasicLabelUI();
  91:     return labelUI;
  92:   }
  93: 
  94:   /**
  95:    * Returns the preferred size of this component as calculated by the
  96:    * {@link #layoutCL(JLabel, FontMetrics, String, Icon, Rectangle, Rectangle, 
  97:    * Rectangle)} method.
  98:    *
  99:    * @param c This {@link JComponent} to get a preferred size for.
 100:    *
 101:    * @return The preferred size.
 102:    */
 103:   public Dimension getPreferredSize(JComponent c)
 104:   {
 105:     JLabel lab = (JLabel) c;
 106:     Rectangle vr = new Rectangle();
 107:     Rectangle ir = new Rectangle();
 108:     Rectangle tr = new Rectangle();
 109:     Insets insets = lab.getInsets();
 110:     FontMetrics fm = lab.getToolkit().getFontMetrics(lab.getFont());
 111:     layoutCL(lab, fm, lab.getText(), lab.getIcon(), vr, ir, tr);
 112:     Rectangle cr = tr.union(ir);
 113:     return new Dimension(insets.left + cr.width + insets.right, insets.top
 114:         + cr.height + insets.bottom);
 115: 
 116:   }
 117: 
 118:   /**
 119:    * This method returns the minimum size of the {@link JComponent} given. If
 120:    * this method returns null, then it is up to the Layout Manager to give
 121:    * this component a minimum size.
 122:    *
 123:    * @param c The {@link JComponent} to get a minimum size for.
 124:    *
 125:    * @return The minimum size.
 126:    */
 127:   public Dimension getMinimumSize(JComponent c)
 128:   {
 129:     return getPreferredSize(c);
 130:   }
 131: 
 132:   /**
 133:    * This method returns the maximum size of the {@link JComponent} given. If
 134:    * this method returns null, then it is up to the Layout Manager to give
 135:    * this component a maximum size.
 136:    *
 137:    * @param c The {@link JComponent} to get a maximum size for.
 138:    *
 139:    * @return The maximum size.
 140:    */
 141:   public Dimension getMaximumSize(JComponent c)
 142:   {
 143:     return getPreferredSize(c);
 144:   }
 145: 
 146:   /**
 147:    * The method that paints the label according to its current state.
 148:    * 
 149:    * @param g The {@link Graphics} object to paint with.
 150:    * @param c The {@link JComponent} to paint.
 151:    */
 152:   public void paint(Graphics g, JComponent c)
 153:   {
 154:     JLabel b = (JLabel) c;
 155: 
 156:     Font saved_font = g.getFont();
 157: 
 158:     Rectangle tr = new Rectangle();
 159:     Rectangle ir = new Rectangle();
 160:     Rectangle vr = new Rectangle();
 161: 
 162:     Font f = c.getFont();
 163: 
 164:     g.setFont(f);
 165:     FontMetrics fm = g.getFontMetrics(f);
 166: 
 167:     vr = SwingUtilities.calculateInnerArea(c, vr);
 168: 
 169:     if (vr.width < 0)
 170:       vr.width = 0;
 171:     if (vr.height < 0)
 172:       vr.height = 0;
 173: 
 174:     Icon icon = (b.isEnabled()) ? b.getIcon() : b.getDisabledIcon();
 175: 
 176:     String text = layoutCL(b, fm, b.getText(), icon, vr, ir, tr);
 177: 
 178:     if (icon != null)
 179:       icon.paintIcon(b, g, ir.x, ir.y);        
 180: 
 181:     if (text != null && !text.equals(""))
 182:     {
 183:       if (b.isEnabled())
 184:         paintEnabledText(b, g, text, tr.x, tr.y + fm.getAscent());
 185:       else
 186:         paintDisabledText(b, g, text, tr.x, tr.y + fm.getAscent());
 187:     }
 188: 
 189:     g.setFont(saved_font);
 190:   }
 191: 
 192:   /**
 193:    * This method is simply calls SwingUtilities's layoutCompoundLabel.
 194:    * 
 195:    * @param label The label to lay out.
 196:    * @param fontMetrics The FontMetrics for the font used.
 197:    * @param text The text to paint.
 198:    * @param icon The icon to draw.
 199:    * @param viewR The entire viewable rectangle.
 200:    * @param iconR The icon bounds rectangle.
 201:    * @param textR The text bounds rectangle.
 202:    * 
 203:    * @return A possibly clipped version of the text.
 204:    */
 205:   protected String layoutCL(JLabel label, FontMetrics fontMetrics, String text,
 206:       Icon icon, Rectangle viewR, Rectangle iconR, Rectangle textR)
 207:   {
 208:     return SwingUtilities.layoutCompoundLabel(label, fontMetrics, text, icon,
 209:         label.getVerticalAlignment(), label.getHorizontalAlignment(), label
 210:             .getVerticalTextPosition(), label.getHorizontalTextPosition(),
 211:         viewR, iconR, textR, label.getIconTextGap());
 212:   }
 213: 
 214:   /**
 215:    * Paints the text if the label is disabled. By default, this paints the
 216:    * clipped text returned by layoutCompoundLabel using the
 217:    * background.brighter() color. It also paints the same text using the
 218:    * background.darker() color one pixel to the right and one pixel down.
 219:    *
 220:    * @param l The {@link JLabel} being painted.
 221:    * @param g The {@link Graphics} object to paint with.
 222:    * @param s The String to paint.
 223:    * @param textX The x coordinate of the start of the baseline.
 224:    * @param textY The y coordinate of the start of the baseline.
 225:    */
 226:   protected void paintDisabledText(JLabel l, Graphics g, String s, int textX,
 227:       int textY)
 228:   {
 229:     Color saved_color = g.getColor();
 230: 
 231:     g.setColor(l.getBackground().brighter());
 232: 
 233:     int mnemIndex = l.getDisplayedMnemonicIndex();
 234: 
 235:     if (mnemIndex != -1)
 236:       BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX,
 237:           textY);
 238:     else
 239:       g.drawString(s, textX, textY);
 240: 
 241:     g.setColor(l.getBackground().darker());
 242:     if (mnemIndex != -1)
 243:       BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX + 1,
 244:           textY + 1);
 245:     else
 246:       g.drawString(s, textX + 1, textY + 1);
 247: 
 248:     g.setColor(saved_color);
 249:   }
 250: 
 251:   /**
 252:    * Paints the text if the label is enabled. The text is painted using the
 253:    * foreground color.
 254:    *
 255:    * @param l The {@link JLabel} being painted.
 256:    * @param g The {@link Graphics} object to paint with.
 257:    * @param s The String to paint.
 258:    * @param textX The x coordinate of the start of the baseline.
 259:    * @param textY The y coordinate of the start of the baseline.
 260:    */
 261:   protected void paintEnabledText(JLabel l, Graphics g, String s, int textX,
 262:       int textY)
 263:   {
 264:     Color saved_color = g.getColor();
 265:     g.setColor(l.getForeground());
 266: 
 267:     int mnemIndex = l.getDisplayedMnemonicIndex();
 268: 
 269:     if (mnemIndex != -1)
 270:       BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX,
 271:           textY);
 272:     else
 273:       g.drawString(s, textX, textY);
 274: 
 275:     g.setColor(saved_color);
 276:   }
 277: 
 278:   /**
 279:    * This method installs the UI for the given {@link JComponent}.  This
 280:    * method will install the component, defaults, listeners,  and keyboard
 281:    * actions.
 282:    *
 283:    * @param c The {@link JComponent} that this UI is being installed on.
 284:    */
 285:   public void installUI(JComponent c)
 286:   {
 287:     super.installUI(c);
 288:     if (c instanceof JLabel)
 289:     {
 290:       JLabel l = (JLabel) c;
 291: 
 292:       installComponents(l);
 293:       installDefaults(l);
 294:       installListeners(l);
 295:       installKeyboardActions(l);
 296:     }
 297:   }
 298: 
 299:   /**
 300:    * This method uninstalls the UI for the given {@link JComponent}. This
 301:    * method will uninstall the component, defaults, listeners,  and keyboard
 302:    * actions.
 303:    *
 304:    * @param c The {@link JComponent} that this UI is being installed on.
 305:    */
 306:   public void uninstallUI(JComponent c)
 307:   {
 308:     super.uninstallUI(c);
 309:     if (c instanceof JLabel)
 310:     {
 311:       JLabel l = (JLabel) c;
 312: 
 313:       uninstallKeyboardActions(l);
 314:       uninstallListeners(l);
 315:       uninstallDefaults(l);
 316:       uninstallComponents(l);
 317:     }
 318:   }
 319: 
 320:   /**
 321:    * This method installs the components for this {@link JLabel}.
 322:    *
 323:    * @param c The {@link JLabel} to install components for.
 324:    */
 325:   protected void installComponents(JLabel c)
 326:   {
 327:     //FIXME: fix javadoc + implement.
 328:   }
 329: 
 330:   /**
 331:    * This method uninstalls the components for this {@link JLabel}.
 332:    *
 333:    * @param c The {@link JLabel} to uninstall components for.
 334:    */
 335:   protected void uninstallComponents(JLabel c)
 336:   {
 337:     //FIXME: fix javadoc + implement.
 338:   }
 339: 
 340:   /**
 341:    * This method installs the defaults that are defined in  the Basic look and
 342:    * feel for this {@link JLabel}.
 343:    *
 344:    * @param c The {@link JLabel} to install defaults for.
 345:    */
 346:   protected void installDefaults(JLabel c)
 347:   {
 348:     UIDefaults defaults = UIManager.getLookAndFeelDefaults();
 349: 
 350:     c.setForeground(defaults.getColor("Label.foreground"));
 351:     c.setBackground(defaults.getColor("Label.background"));
 352:     c.setFont(defaults.getFont("Label.font"));
 353:     //XXX: There are properties we don't use called disabledForeground
 354:     //and disabledShadow.
 355:   }
 356: 
 357:   /**
 358:    * This method uninstalls the defaults that are defined in the Basic look
 359:    * and feel for this {@link JLabel}.
 360:    *
 361:    * @param c The {@link JLabel} to uninstall defaults for.
 362:    */
 363:   protected void uninstallDefaults(JLabel c)
 364:   {
 365:     c.setForeground(null);
 366:     c.setBackground(null);
 367:     c.setFont(null);
 368:   }
 369: 
 370:   /**
 371:    * This method installs the keyboard actions for the given {@link JLabel}.
 372:    *
 373:    * @param l The {@link JLabel} to install keyboard actions for.
 374:    */
 375:   protected void installKeyboardActions(JLabel l)
 376:   {
 377:     //FIXME: implement.
 378:   }
 379: 
 380:   /**
 381:    * This method uninstalls the keyboard actions for the given {@link JLabel}.
 382:    *
 383:    * @param l The {@link JLabel} to uninstall keyboard actions for.
 384:    */
 385:   protected void uninstallKeyboardActions(JLabel l)
 386:   {
 387:     //FIXME: implement.
 388:   }
 389: 
 390:   /**
 391:    * This method installs the listeners for the  given {@link JLabel}. The UI
 392:    * delegate only listens to  the label.
 393:    *
 394:    * @param c The {@link JLabel} to install listeners for.
 395:    */
 396:   protected void installListeners(JLabel c)
 397:   {
 398:     c.addPropertyChangeListener(this);
 399:   }
 400: 
 401:   /**
 402:    * This method uninstalls the listeners for the given {@link JLabel}. The UI
 403:    * delegate only listens to the label.
 404:    *
 405:    * @param c The {@link JLabel} to uninstall listeners for.
 406:    */
 407:   protected void uninstallListeners(JLabel c)
 408:   {
 409:     c.removePropertyChangeListener(this);
 410:   }
 411: 
 412:   /**
 413:    * This method is called whenever any JLabel's that use this UI has one of
 414:    * their properties change.
 415:    *
 416:    * @param e The {@link PropertyChangeEvent} that describes the change.
 417:    */
 418:   public void propertyChange(PropertyChangeEvent e)
 419:   {
 420:     JLabel c = (JLabel) e.getSource();
 421:     c.revalidate();
 422:     c.repaint();
 423:   }
 424: }