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.awt.AppContext;
   30   
   31   import java.awt;
   32   import java.awt.event;
   33   import java.io.Serializable;
   34   import javax.swing;
   35   import javax.swing.border;
   36   import java.awt;
   37   import java.awt.event;
   38   import javax.swing.plaf.ButtonUI;
   39   import javax.swing.plaf.UIResource;
   40   import javax.swing.plaf.ComponentUI;
   41   import javax.swing.text.View;
   42   
   43   /**
   44    * BasicButton implementation
   45    *
   46    * @author Jeff Dinkins
   47    */
   48   public class BasicButtonUI extends ButtonUI{
   49       // Visual constants
   50       // NOTE: This is not used or set any where. Were we allowed to remove
   51       // fields, this would be removed.
   52       protected int defaultTextIconGap;
   53   
   54       // Amount to offset text, the value of this comes from
   55       // defaultTextShiftOffset once setTextShiftOffset has been invoked.
   56       private int shiftOffset = 0;
   57       // Value that is set in shiftOffset once setTextShiftOffset has been
   58       // invoked. The value of this comes from the defaults table.
   59       protected int defaultTextShiftOffset;
   60   
   61       private final static String propertyPrefix = "Button" + ".";
   62   
   63       private static final Object BASIC_BUTTON_UI_KEY = new Object();
   64   
   65       // ********************************
   66       //          Create PLAF
   67       // ********************************
   68       public static ComponentUI createUI(JComponent c) {
   69           AppContext appContext = AppContext.getAppContext();
   70           BasicButtonUI buttonUI =
   71                   (BasicButtonUI) appContext.get(BASIC_BUTTON_UI_KEY);
   72           if (buttonUI == null) {
   73               buttonUI = new BasicButtonUI();
   74               appContext.put(BASIC_BUTTON_UI_KEY, buttonUI);
   75           }
   76           return buttonUI;
   77       }
   78   
   79       protected String getPropertyPrefix() {
   80           return propertyPrefix;
   81       }
   82   
   83   
   84       // ********************************
   85       //          Install PLAF
   86       // ********************************
   87       public void installUI(JComponent c) {
   88           installDefaults((AbstractButton) c);
   89           installListeners((AbstractButton) c);
   90           installKeyboardActions((AbstractButton) c);
   91           BasicHTML.updateRenderer(c, ((AbstractButton) c).getText());
   92       }
   93   
   94       protected void installDefaults(AbstractButton b) {
   95           // load shared instance defaults
   96           String pp = getPropertyPrefix();
   97   
   98           defaultTextShiftOffset = UIManager.getInt(pp + "textShiftOffset");
   99   
  100           // set the following defaults on the button
  101           if (b.isContentAreaFilled()) {
  102               LookAndFeel.installProperty(b, "opaque", Boolean.TRUE);
  103           } else {
  104               LookAndFeel.installProperty(b, "opaque", Boolean.FALSE);
  105           }
  106   
  107           if(b.getMargin() == null || (b.getMargin() instanceof UIResource)) {
  108               b.setMargin(UIManager.getInsets(pp + "margin"));
  109           }
  110   
  111           LookAndFeel.installColorsAndFont(b, pp + "background",
  112                                            pp + "foreground", pp + "font");
  113           LookAndFeel.installBorder(b, pp + "border");
  114   
  115           Object rollover = UIManager.get(pp + "rollover");
  116           if (rollover != null) {
  117               LookAndFeel.installProperty(b, "rolloverEnabled", rollover);
  118           }
  119   
  120           LookAndFeel.installProperty(b, "iconTextGap", Integer.valueOf(4));
  121       }
  122   
  123       protected void installListeners(AbstractButton b) {
  124           BasicButtonListener listener = createButtonListener(b);
  125           if(listener != null) {
  126               b.addMouseListener(listener);
  127               b.addMouseMotionListener(listener);
  128               b.addFocusListener(listener);
  129               b.addPropertyChangeListener(listener);
  130               b.addChangeListener(listener);
  131           }
  132       }
  133   
  134       protected void installKeyboardActions(AbstractButton b){
  135           BasicButtonListener listener = getButtonListener(b);
  136   
  137           if(listener != null) {
  138               listener.installKeyboardActions(b);
  139           }
  140       }
  141   
  142   
  143       // ********************************
  144       //         Uninstall PLAF
  145       // ********************************
  146       public void uninstallUI(JComponent c) {
  147           uninstallKeyboardActions((AbstractButton) c);
  148           uninstallListeners((AbstractButton) c);
  149           uninstallDefaults((AbstractButton) c);
  150           BasicHTML.updateRenderer(c, "");
  151       }
  152   
  153       protected void uninstallKeyboardActions(AbstractButton b) {
  154           BasicButtonListener listener = getButtonListener(b);
  155           if(listener != null) {
  156               listener.uninstallKeyboardActions(b);
  157           }
  158       }
  159   
  160       protected void uninstallListeners(AbstractButton b) {
  161           BasicButtonListener listener = getButtonListener(b);
  162           if(listener != null) {
  163               b.removeMouseListener(listener);
  164               b.removeMouseMotionListener(listener);
  165               b.removeFocusListener(listener);
  166               b.removeChangeListener(listener);
  167               b.removePropertyChangeListener(listener);
  168           }
  169       }
  170   
  171       protected void uninstallDefaults(AbstractButton b) {
  172           LookAndFeel.uninstallBorder(b);
  173       }
  174   
  175       // ********************************
  176       //        Create Listeners
  177       // ********************************
  178       protected BasicButtonListener createButtonListener(AbstractButton b) {
  179           return new BasicButtonListener(b);
  180       }
  181   
  182       public int getDefaultTextIconGap(AbstractButton b) {
  183           return defaultTextIconGap;
  184       }
  185   
  186       /* These rectangles/insets are allocated once for all
  187        * ButtonUI.paint() calls.  Re-using rectangles rather than
  188        * allocating them in each paint call substantially reduced the time
  189        * it took paint to run.  Obviously, this method can't be re-entered.
  190        */
  191       private static Rectangle viewRect = new Rectangle();
  192       private static Rectangle textRect = new Rectangle();
  193       private static Rectangle iconRect = new Rectangle();
  194   
  195       // ********************************
  196       //          Paint Methods
  197       // ********************************
  198   
  199       public void paint(Graphics g, JComponent c)
  200       {
  201           AbstractButton b = (AbstractButton) c;
  202           ButtonModel model = b.getModel();
  203   
  204           String text = layout(b, SwingUtilities2.getFontMetrics(b, g),
  205                  b.getWidth(), b.getHeight());
  206   
  207           clearTextShiftOffset();
  208   
  209           // perform UI specific press action, e.g. Windows L&F shifts text
  210           if (model.isArmed() && model.isPressed()) {
  211               paintButtonPressed(g,b);
  212           }
  213   
  214           // Paint the Icon
  215           if(b.getIcon() != null) {
  216               paintIcon(g,c,iconRect);
  217           }
  218   
  219           if (text != null && !text.equals("")){
  220               View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  221               if (v != null) {
  222                   v.paint(g, textRect);
  223               } else {
  224                   paintText(g, b, textRect, text);
  225               }
  226           }
  227   
  228           if (b.isFocusPainted() && b.hasFocus()) {
  229               // paint UI specific focus
  230               paintFocus(g,b,viewRect,textRect,iconRect);
  231           }
  232       }
  233   
  234       protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect){
  235               AbstractButton b = (AbstractButton) c;
  236               ButtonModel model = b.getModel();
  237               Icon icon = b.getIcon();
  238               Icon tmpIcon = null;
  239   
  240               if(icon == null) {
  241                  return;
  242               }
  243   
  244               Icon selectedIcon = null;
  245   
  246               /* the fallback icon should be based on the selected state */
  247               if (model.isSelected()) {
  248                   selectedIcon = b.getSelectedIcon();
  249                   if (selectedIcon != null) {
  250                       icon = selectedIcon;
  251                   }
  252               }
  253   
  254               if(!model.isEnabled()) {
  255                   if(model.isSelected()) {
  256                      tmpIcon = b.getDisabledSelectedIcon();
  257                      if (tmpIcon == null) {
  258                          tmpIcon = selectedIcon;
  259                      }
  260                   }
  261   
  262                   if (tmpIcon == null) {
  263                       tmpIcon = b.getDisabledIcon();
  264                   }
  265               } else if(model.isPressed() && model.isArmed()) {
  266                   tmpIcon = b.getPressedIcon();
  267                   if(tmpIcon != null) {
  268                       // revert back to 0 offset
  269                       clearTextShiftOffset();
  270                   }
  271               } else if(b.isRolloverEnabled() && model.isRollover()) {
  272                   if(model.isSelected()) {
  273                      tmpIcon = b.getRolloverSelectedIcon();
  274                      if (tmpIcon == null) {
  275                          tmpIcon = selectedIcon;
  276                      }
  277                   }
  278   
  279                   if (tmpIcon == null) {
  280                       tmpIcon = b.getRolloverIcon();
  281                   }
  282               }
  283   
  284               if(tmpIcon != null) {
  285                   icon = tmpIcon;
  286               }
  287   
  288               if(model.isPressed() && model.isArmed()) {
  289                   icon.paintIcon(c, g, iconRect.x + getTextShiftOffset(),
  290                           iconRect.y + getTextShiftOffset());
  291               } else {
  292                   icon.paintIcon(c, g, iconRect.x, iconRect.y);
  293               }
  294   
  295       }
  296   
  297       /**
  298        * As of Java 2 platform v 1.4 this method should not be used or overriden.
  299        * Use the paintText method which takes the AbstractButton argument.
  300        */
  301       protected void paintText(Graphics g, JComponent c, Rectangle textRect, String text) {
  302           AbstractButton b = (AbstractButton) c;
  303           ButtonModel model = b.getModel();
  304           FontMetrics fm = SwingUtilities2.getFontMetrics(c, g);
  305           int mnemonicIndex = b.getDisplayedMnemonicIndex();
  306   
  307           /* Draw the Text */
  308           if(model.isEnabled()) {
  309               /*** paint the text normally */
  310               g.setColor(b.getForeground());
  311               SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex,
  312                                             textRect.x + getTextShiftOffset(),
  313                                             textRect.y + fm.getAscent() + getTextShiftOffset());
  314           }
  315           else {
  316               /*** paint the text disabled ***/
  317               g.setColor(b.getBackground().brighter());
  318               SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex,
  319                                             textRect.x, textRect.y + fm.getAscent());
  320               g.setColor(b.getBackground().darker());
  321               SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex,
  322                                             textRect.x - 1, textRect.y + fm.getAscent() - 1);
  323           }
  324       }
  325   
  326       /**
  327        * Method which renders the text of the current button.
  328        * <p>
  329        * @param g Graphics context
  330        * @param b Current button to render
  331        * @param textRect Bounding rectangle to render the text.
  332        * @param text String to render
  333        * @since 1.4
  334        */
  335       protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, String text) {
  336           paintText(g, (JComponent)b, textRect, text);
  337       }
  338   
  339       // Method signature defined here overriden in subclasses.
  340       // Perhaps this class should be abstract?
  341       protected void paintFocus(Graphics g, AbstractButton b,
  342                                 Rectangle viewRect, Rectangle textRect, Rectangle iconRect){
  343       }
  344   
  345   
  346   
  347       protected void paintButtonPressed(Graphics g, AbstractButton b){
  348       }
  349   
  350       protected void clearTextShiftOffset(){
  351           this.shiftOffset = 0;
  352       }
  353   
  354       protected void setTextShiftOffset(){
  355           this.shiftOffset = defaultTextShiftOffset;
  356       }
  357   
  358       protected int getTextShiftOffset() {
  359           return shiftOffset;
  360       }
  361   
  362       // ********************************
  363       //          Layout Methods
  364       // ********************************
  365       public Dimension getMinimumSize(JComponent c) {
  366           Dimension d = getPreferredSize(c);
  367           View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  368           if (v != null) {
  369               d.width -= v.getPreferredSpan(View.X_AXIS) - v.getMinimumSpan(View.X_AXIS);
  370           }
  371           return d;
  372       }
  373   
  374       public Dimension getPreferredSize(JComponent c) {
  375           AbstractButton b = (AbstractButton)c;
  376           return BasicGraphicsUtils.getPreferredButtonSize(b, b.getIconTextGap());
  377       }
  378   
  379       public Dimension getMaximumSize(JComponent c) {
  380           Dimension d = getPreferredSize(c);
  381           View v = (View) c.getClientProperty(BasicHTML.propertyKey);
  382           if (v != null) {
  383               d.width += v.getMaximumSpan(View.X_AXIS) - v.getPreferredSpan(View.X_AXIS);
  384           }
  385           return d;
  386       }
  387   
  388       /**
  389        * Returns the baseline.
  390        *
  391        * @throws NullPointerException {@inheritDoc}
  392        * @throws IllegalArgumentException {@inheritDoc}
  393        * @see javax.swing.JComponent#getBaseline(int, int)
  394        * @since 1.6
  395        */
  396       public int getBaseline(JComponent c, int width, int height) {
  397           super.getBaseline(c, width, height);
  398           AbstractButton b = (AbstractButton)c;
  399           String text = b.getText();
  400           if (text == null || "".equals(text)) {
  401               return -1;
  402           }
  403           FontMetrics fm = b.getFontMetrics(b.getFont());
  404           layout(b, fm, width, height);
  405           return BasicHTML.getBaseline(b, textRect.y, fm.getAscent(),
  406                                        textRect.width, textRect.height);
  407       }
  408   
  409       /**
  410        * Returns an enum indicating how the baseline of the component
  411        * changes as the size changes.
  412        *
  413        * @throws NullPointerException {@inheritDoc}
  414        * @see javax.swing.JComponent#getBaseline(int, int)
  415        * @since 1.6
  416        */
  417       public Component.BaselineResizeBehavior getBaselineResizeBehavior(
  418               JComponent c) {
  419           super.getBaselineResizeBehavior(c);
  420           if (c.getClientProperty(BasicHTML.propertyKey) != null) {
  421               return Component.BaselineResizeBehavior.OTHER;
  422           }
  423           switch(((AbstractButton)c).getVerticalAlignment()) {
  424           case AbstractButton.TOP:
  425               return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
  426           case AbstractButton.BOTTOM:
  427               return Component.BaselineResizeBehavior.CONSTANT_DESCENT;
  428           case AbstractButton.CENTER:
  429               return Component.BaselineResizeBehavior.CENTER_OFFSET;
  430           }
  431           return Component.BaselineResizeBehavior.OTHER;
  432       }
  433   
  434       private String layout(AbstractButton b, FontMetrics fm,
  435                             int width, int height) {
  436           Insets i = b.getInsets();
  437           viewRect.x = i.left;
  438           viewRect.y = i.top;
  439           viewRect.width = width - (i.right + viewRect.x);
  440           viewRect.height = height - (i.bottom + viewRect.y);
  441   
  442           textRect.x = textRect.y = textRect.width = textRect.height = 0;
  443           iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
  444   
  445           // layout the text and icon
  446           return SwingUtilities.layoutCompoundLabel(
  447               b, fm, b.getText(), b.getIcon(),
  448               b.getVerticalAlignment(), b.getHorizontalAlignment(),
  449               b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
  450               viewRect, iconRect, textRect,
  451               b.getText() == null ? 0 : b.getIconTextGap());
  452       }
  453   
  454       /**
  455        * Returns the ButtonListener for the passed in Button, or null if one
  456        * could not be found.
  457        */
  458       private BasicButtonListener getButtonListener(AbstractButton b) {
  459           MouseMotionListener[] listeners = b.getMouseMotionListeners();
  460   
  461           if (listeners != null) {
  462               for (MouseMotionListener listener : listeners) {
  463                   if (listener instanceof BasicButtonListener) {
  464                       return (BasicButtonListener) listener;
  465                   }
  466               }
  467           }
  468           return null;
  469       }
  470   
  471   }

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