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