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

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