Home » openjdk-7 » javax » swing » plaf » basic » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package javax.swing.plaf.basic;
   27   
   28   import sun.swing.SwingUtilities2;
   29   import sun.swing.DefaultLookup;
   30   import sun.swing.UIAction;
   31   import sun.awt.AppContext;
   32   
   33   import javax.swing;
   34   import javax.swing.plaf;
   35   import javax.swing.text.View;
   36   
   37   import java.awt.event.ActionEvent;
   38   import java.awt.event.ActionListener;
   39   import java.awt.event.KeyEvent;
   40   import java.awt.Component;
   41   import java.awt.Container;
   42   import java.awt.Dimension;
   43   import java.awt.Rectangle;
   44   import java.awt.Insets;
   45   import java.awt.Color;
   46   import java.awt.Graphics;
   47   import java.awt.Font;
   48   import java.awt.FontMetrics;
   49   import java.beans.PropertyChangeEvent;
   50   import java.beans.PropertyChangeListener;
   51   
   52   /**
   53    * A Windows L&F implementation of LabelUI.  This implementation
   54    * is completely static, i.e. there's only one UIView implementation
   55    * that's shared by all JLabel objects.
   56    *
   57    * @author Hans Muller
   58    */
   59   public class BasicLabelUI extends LabelUI implements  PropertyChangeListener
   60   {
   61      /**
   62       * The default <code>BasicLabelUI</code> instance. This field might
   63       * not be used. To change the default instance use a subclass which
   64       * overrides the <code>createUI</code> method, and place that class
   65       * name in defaults table under the key "LabelUI".
   66       */
   67       protected static BasicLabelUI labelUI = new BasicLabelUI();
   68       private static final Object BASIC_LABEL_UI_KEY = new Object();
   69   
   70       private Rectangle paintIconR = new Rectangle();
   71       private Rectangle paintTextR = new Rectangle();
   72   
   73       static void loadActionMap(LazyActionMap map) {
   74           map.put(new Actions(Actions.PRESS));
   75           map.put(new Actions(Actions.RELEASE));
   76       }
   77   
   78       /**
   79        * Forwards the call to SwingUtilities.layoutCompoundLabel().
   80        * This method is here so that a subclass could do Label specific
   81        * layout and to shorten the method name a little.
   82        *
   83        * @see SwingUtilities#layoutCompoundLabel
   84        */
   85       protected String layoutCL(
   86           JLabel label,
   87           FontMetrics fontMetrics,
   88           String text,
   89           Icon icon,
   90           Rectangle viewR,
   91           Rectangle iconR,
   92           Rectangle textR)
   93       {
   94           return SwingUtilities.layoutCompoundLabel(
   95               (JComponent) label,
   96               fontMetrics,
   97               text,
   98               icon,
   99               label.getVerticalAlignment(),
  100               label.getHorizontalAlignment(),
  101               label.getVerticalTextPosition(),
  102               label.getHorizontalTextPosition(),
  103               viewR,
  104               iconR,
  105               textR,
  106               label.getIconTextGap());
  107       }
  108   
  109       /**
  110        * Paint clippedText at textX, textY with the labels foreground color.
  111        *
  112        * @see #paint
  113        * @see #paintDisabledText
  114        */
  115       protected void paintEnabledText(JLabel l, Graphics g, String s, int textX, int textY)
  116       {
  117           int mnemIndex = l.getDisplayedMnemonicIndex();
  118           g.setColor(l.getForeground());
  119           SwingUtilities2.drawStringUnderlineCharAt(l, g, s, mnemIndex,
  120                                                        textX, textY);
  121       }
  122   
  123   
  124       /**
  125        * Paint clippedText at textX, textY with background.lighter() and then
  126        * shifted down and to the right by one pixel with background.darker().
  127        *
  128        * @see #paint
  129        * @see #paintEnabledText
  130        */
  131       protected void paintDisabledText(JLabel l, Graphics g, String s, int textX, int textY)
  132       {
  133           int accChar = l.getDisplayedMnemonicIndex();
  134           Color background = l.getBackground();
  135           g.setColor(background.brighter());
  136           SwingUtilities2.drawStringUnderlineCharAt(l, g, s, accChar,
  137                                                      textX + 1, textY + 1);
  138           g.setColor(background.darker());
  139           SwingUtilities2.drawStringUnderlineCharAt(l, g, s, accChar,
  140                                                      textX, textY);
  141       }
  142   
  143       /**
  144        * Paints the label text with the foreground color, if the label is opaque
  145        * then paints the entire background with the background color. The Label
  146        * text is drawn by {@link #paintEnabledText} or {@link #paintDisabledText}.
  147        * The locations of the label parts are computed by {@link #layoutCL}.
  148        *
  149        * @see #paintEnabledText
  150        * @see #paintDisabledText
  151        * @see #layoutCL
  152        */
  153       public void paint(Graphics g, JComponent c)
  154       {
  155           JLabel label = (JLabel)c;
  156           String text = label.getText();
  157           Icon icon = (label.isEnabled()) ? label.getIcon() : label.getDisabledIcon();
  158   
  159           if ((icon == null) && (text == null)) {
  160               return;
  161           }
  162   
  163           FontMetrics fm = SwingUtilities2.getFontMetrics(label, g);
  164           String clippedText = layout(label, fm, c.getWidth(), c.getHeight());
  165   
  166           if (icon != null) {
  167               icon.paintIcon(c, g, paintIconR.x, paintIconR.y);
  168           }
  169   
  170           if (text != null) {
  171               View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  172               if (v != null) {
  173                   v.paint(g, paintTextR);
  174               } else {
  175                   int textX = paintTextR.x;
  176                   int textY = paintTextR.y + fm.getAscent();
  177   
  178                   if (label.isEnabled()) {
  179                       paintEnabledText(label, g, clippedText, textX, textY);
  180                   }
  181                   else {
  182                       paintDisabledText(label, g, clippedText, textX, textY);
  183                   }
  184               }
  185           }
  186       }
  187   
  188       private String layout(JLabel label, FontMetrics fm,
  189                             int width, int height) {
  190           Insets insets = label.getInsets(null);
  191           String text = label.getText();
  192           Icon icon = (label.isEnabled()) ? label.getIcon() :
  193                                             label.getDisabledIcon();
  194           Rectangle paintViewR = new Rectangle();
  195           paintViewR.x = insets.left;
  196           paintViewR.y = insets.top;
  197           paintViewR.width = width - (insets.left + insets.right);
  198           paintViewR.height = height - (insets.top + insets.bottom);
  199           paintIconR.x = paintIconR.y = paintIconR.width = paintIconR.height = 0;
  200           paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 0;
  201           return layoutCL(label, fm, text, icon, paintViewR, paintIconR,
  202                           paintTextR);
  203       }
  204   
  205       public Dimension getPreferredSize(JComponent c)
  206       {
  207           JLabel label = (JLabel)c;
  208           String text = label.getText();
  209           Icon icon = (label.isEnabled()) ? label.getIcon() :
  210                                             label.getDisabledIcon();
  211           Insets insets = label.getInsets(null);
  212           Font font = label.getFont();
  213   
  214           int dx = insets.left + insets.right;
  215           int dy = insets.top + insets.bottom;
  216   
  217           if ((icon == null) &&
  218               ((text == null) ||
  219                ((text != null) && (font == null)))) {
  220               return new Dimension(dx, dy);
  221           }
  222           else if ((text == null) || ((icon != null) && (font == null))) {
  223               return new Dimension(icon.getIconWidth() + dx,
  224                                    icon.getIconHeight() + dy);
  225           }
  226           else {
  227               FontMetrics fm = label.getFontMetrics(font);
  228               Rectangle iconR = new Rectangle();
  229               Rectangle textR = new Rectangle();
  230               Rectangle viewR = new Rectangle();
  231   
  232               iconR.x = iconR.y = iconR.width = iconR.height = 0;
  233               textR.x = textR.y = textR.width = textR.height = 0;
  234               viewR.x = dx;
  235               viewR.y = dy;
  236               viewR.width = viewR.height = Short.MAX_VALUE;
  237   
  238               layoutCL(label, fm, text, icon, viewR, iconR, textR);
  239               int x1 = Math.min(iconR.x, textR.x);
  240               int x2 = Math.max(iconR.x + iconR.width, textR.x + textR.width);
  241               int y1 = Math.min(iconR.y, textR.y);
  242               int y2 = Math.max(iconR.y + iconR.height, textR.y + textR.height);
  243               Dimension rv = new Dimension(x2 - x1, y2 - y1);
  244   
  245               rv.width += dx;
  246               rv.height += dy;
  247               return rv;
  248           }
  249       }
  250   
  251   
  252       /**
  253        * @return getPreferredSize(c)
  254        */
  255       public Dimension getMinimumSize(JComponent c) {
  256           Dimension d = getPreferredSize(c);
  257           View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  258           if (v != null) {
  259               d.width -= v.getPreferredSpan(View.X_AXIS) - v.getMinimumSpan(View.X_AXIS);
  260           }
  261           return d;
  262       }
  263   
  264       /**
  265        * @return getPreferredSize(c)
  266        */
  267       public Dimension getMaximumSize(JComponent c) {
  268           Dimension d = getPreferredSize(c);
  269           View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  270           if (v != null) {
  271               d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS);
  272           }
  273           return d;
  274       }
  275   
  276       /**
  277        * Returns the baseline.
  278        *
  279        * @throws NullPointerException {@inheritDoc}
  280        * @throws IllegalArgumentException {@inheritDoc}
  281        * @see javax.swing.JComponent#getBaseline(int, int)
  282        * @since 1.6
  283        */
  284       public int getBaseline(JComponent c, int width, int height) {
  285           super.getBaseline(c, width, height);
  286           JLabel label = (JLabel)c;
  287           String text = label.getText();
  288           if (text == null || "".equals(text) || label.getFont() == null) {
  289               return -1;
  290           }
  291           FontMetrics fm = label.getFontMetrics(label.getFont());
  292           layout(label, fm, width, height);
  293           return BasicHTML.getBaseline(label, paintTextR.y, fm.getAscent(),
  294                                        paintTextR.width, paintTextR.height);
  295       }
  296   
  297       /**
  298        * Returns an enum indicating how the baseline of the component
  299        * changes as the size changes.
  300        *
  301        * @throws NullPointerException {@inheritDoc}
  302        * @see javax.swing.JComponent#getBaseline(int, int)
  303        * @since 1.6
  304        */
  305       public Component.BaselineResizeBehavior getBaselineResizeBehavior(
  306               JComponent c) {
  307           super.getBaselineResizeBehavior(c);
  308           if (c.getClientProperty(BasicHTML.propertyKey) != null) {
  309               return Component.BaselineResizeBehavior.OTHER;
  310           }
  311           switch(((JLabel)c).getVerticalAlignment()) {
  312           case JLabel.TOP:
  313               return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
  314           case JLabel.BOTTOM:
  315               return Component.BaselineResizeBehavior.CONSTANT_DESCENT;
  316           case JLabel.CENTER:
  317               return Component.BaselineResizeBehavior.CENTER_OFFSET;
  318           }
  319           return Component.BaselineResizeBehavior.OTHER;
  320       }
  321   
  322   
  323       public void installUI(JComponent c) {
  324           installDefaults((JLabel)c);
  325           installComponents((JLabel)c);
  326           installListeners((JLabel)c);
  327           installKeyboardActions((JLabel)c);
  328       }
  329   
  330   
  331       public void uninstallUI(JComponent c) {
  332           uninstallDefaults((JLabel)c);
  333           uninstallComponents((JLabel)c);
  334           uninstallListeners((JLabel)c);
  335           uninstallKeyboardActions((JLabel)c);
  336       }
  337   
  338        protected void installDefaults(JLabel c){
  339            LookAndFeel.installColorsAndFont(c, "Label.background", "Label.foreground", "Label.font");
  340            LookAndFeel.installProperty(c, "opaque", Boolean.FALSE);
  341         }
  342   
  343       protected void installListeners(JLabel c){
  344           c.addPropertyChangeListener(this);
  345       }
  346   
  347       protected void installComponents(JLabel c){
  348           BasicHTML.updateRenderer(c, c.getText());
  349           c.setInheritsPopupMenu(true);
  350       }
  351   
  352       protected void installKeyboardActions(JLabel l) {
  353           int dka = l.getDisplayedMnemonic();
  354           Component lf = l.getLabelFor();
  355           if ((dka != 0) && (lf != null)) {
  356               LazyActionMap.installLazyActionMap(l, BasicLabelUI.class,
  357                                                  "Label.actionMap");
  358               InputMap inputMap = SwingUtilities.getUIInputMap
  359                               (l, JComponent.WHEN_IN_FOCUSED_WINDOW);
  360               if (inputMap == null) {
  361                   inputMap = new ComponentInputMapUIResource(l);
  362                   SwingUtilities.replaceUIInputMap(l,
  363                                   JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap);
  364               }
  365               inputMap.clear();
  366               inputMap.put(KeyStroke.getKeyStroke(dka, ActionEvent.ALT_MASK,
  367                                                 false), "press");
  368           }
  369           else {
  370               InputMap inputMap = SwingUtilities.getUIInputMap
  371                               (l, JComponent.WHEN_IN_FOCUSED_WINDOW);
  372               if (inputMap != null) {
  373                   inputMap.clear();
  374               }
  375           }
  376       }
  377   
  378       protected void uninstallDefaults(JLabel c){
  379       }
  380   
  381       protected void uninstallListeners(JLabel c){
  382           c.removePropertyChangeListener(this);
  383       }
  384   
  385       protected void uninstallComponents(JLabel c){
  386           BasicHTML.updateRenderer(c, "");
  387       }
  388   
  389       protected void uninstallKeyboardActions(JLabel c) {
  390           SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_FOCUSED, null);
  391           SwingUtilities.replaceUIInputMap(c, JComponent.WHEN_IN_FOCUSED_WINDOW,
  392                                          null);
  393           SwingUtilities.replaceUIActionMap(c, null);
  394       }
  395   
  396       public static ComponentUI createUI(JComponent c) {
  397           if (System.getSecurityManager() != null) {
  398               AppContext appContext = AppContext.getAppContext();
  399               BasicLabelUI safeBasicLabelUI =
  400                       (BasicLabelUI) appContext.get(BASIC_LABEL_UI_KEY);
  401               if (safeBasicLabelUI == null) {
  402                   safeBasicLabelUI = new BasicLabelUI();
  403                   appContext.put(BASIC_LABEL_UI_KEY, safeBasicLabelUI);
  404               }
  405               return safeBasicLabelUI;
  406           }
  407           return labelUI;
  408       }
  409   
  410       public void propertyChange(PropertyChangeEvent e) {
  411           String name = e.getPropertyName();
  412           if (name == "text" || "font" == name || "foreground" == name) {
  413               // remove the old html view client property if one
  414               // existed, and install a new one if the text installed
  415               // into the JLabel is html source.
  416               JLabel lbl = ((JLabel) e.getSource());
  417               String text = lbl.getText();
  418               BasicHTML.updateRenderer(lbl, text);
  419           }
  420           else if (name == "labelFor" || name == "displayedMnemonic") {
  421               installKeyboardActions((JLabel) e.getSource());
  422           }
  423       }
  424   
  425       // When the accelerator is pressed, temporarily make the JLabel
  426       // focusTraversable by registering a WHEN_FOCUSED action for the
  427       // release of the accelerator.  Then give it focus so it can
  428       // prevent unwanted keyTyped events from getting to other components.
  429       private static class Actions extends UIAction {
  430           private static final String PRESS = "press";
  431           private static final String RELEASE = "release";
  432   
  433           Actions(String key) {
  434               super(key);
  435           }
  436   
  437           public void actionPerformed(ActionEvent e) {
  438               JLabel label = (JLabel)e.getSource();
  439               String key = getName();
  440               if (key == PRESS) {
  441                   doPress(label);
  442               }
  443               else if (key == RELEASE) {
  444                   doRelease(label);
  445               }
  446           }
  447   
  448           private void doPress(JLabel label) {
  449               Component labelFor = label.getLabelFor();
  450               if (labelFor != null && labelFor.isEnabled()) {
  451                   InputMap inputMap = SwingUtilities.getUIInputMap(label, JComponent.WHEN_FOCUSED);
  452                   if (inputMap == null) {
  453                       inputMap = new InputMapUIResource();
  454                       SwingUtilities.replaceUIInputMap(label, JComponent.WHEN_FOCUSED, inputMap);
  455                   }
  456                   int dka = label.getDisplayedMnemonic();
  457                   inputMap.put(KeyStroke.getKeyStroke(dka, ActionEvent.ALT_MASK, true), RELEASE);
  458                   // Need this when the sticky keys are enabled
  459                   inputMap.put(KeyStroke.getKeyStroke(dka, 0, true), RELEASE);
  460                   // Need this if ALT is released before the accelerator
  461                   inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ALT, 0, true), RELEASE);
  462                   label.requestFocus();
  463               }
  464           }
  465   
  466           private void doRelease(JLabel label) {
  467               Component labelFor = label.getLabelFor();
  468               if (labelFor != null && labelFor.isEnabled()) {
  469                   InputMap inputMap = SwingUtilities.getUIInputMap(label, JComponent.WHEN_FOCUSED);
  470                   if (inputMap != null) {
  471                       // inputMap should never be null.
  472                       int dka = label.getDisplayedMnemonic();
  473                       inputMap.remove(KeyStroke.getKeyStroke(dka, ActionEvent.ALT_MASK, true));
  474                       inputMap.remove(KeyStroke.getKeyStroke(dka, 0, true));
  475                       inputMap.remove(KeyStroke.getKeyStroke(KeyEvent.VK_ALT, 0, true));
  476                   }
  477                   if (labelFor instanceof Container &&
  478                           ((Container) labelFor).isFocusCycleRoot()) {
  479                       labelFor.requestFocus();
  480                   } else {
  481                       SwingUtilities2.compositeRequestFocus(labelFor);
  482                   }
  483               }
  484           }
  485       }
  486   }

Home » openjdk-7 » javax » swing » plaf » basic » [javadoc | source]