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