1 /*
   2  * Copyright (c) 1998, 2014, 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.metal;
  27 
  28 import java.awt.Dimension;
  29 import java.awt.Graphics;
  30 import java.awt.Color;
  31 import java.awt.Polygon;
  32 
  33 import javax.swing.*;
  34 
  35 import javax.swing.plaf.basic.BasicArrowButton;
  36 
  37 
  38 /**
  39  * JButton object for Metal scrollbar arrows.
  40  * <p>
  41  * <strong>Warning:</strong>
  42  * Serialized objects of this class will not be compatible with
  43  * future Swing releases. The current serialization support is
  44  * appropriate for short term storage or RMI between applications running
  45  * the same version of Swing.  As of 1.4, support for long term storage
  46  * of all JavaBeans&trade;
  47  * has been added to the <code>java.beans</code> package.
  48  * Please see {@link java.beans.XMLEncoder}.
  49  *
  50  * @author Tom Santos
  51  * @author Steve Wilson
  52  */
  53 @SuppressWarnings("serial") // Same-version serialization only
  54 public class MetalScrollButton extends BasicArrowButton
  55 {
  56   private static Color shadowColor;
  57   private static Color highlightColor;
  58   private boolean isFreeStanding = false;
  59 
  60   private int buttonWidth;
  61 
  62         /**
  63          * Constructs an instance of {@code MetalScrollButton}.
  64          *
  65          * @param direction the direction
  66          * @param width the width
  67          * @param freeStanding the free standing value
  68          */
  69         public MetalScrollButton( int direction, int width, boolean freeStanding )
  70         {
  71             super( direction );
  72 
  73             shadowColor = UIManager.getColor("ScrollBar.darkShadow");
  74             highlightColor = UIManager.getColor("ScrollBar.highlight");
  75 
  76             buttonWidth = width;
  77             isFreeStanding = freeStanding;
  78         }
  79 
  80         /**
  81          * Sets the free standing value.
  82          *
  83          * @param freeStanding the free standing value
  84          */
  85         public void setFreeStanding( boolean freeStanding )
  86         {
  87             isFreeStanding = freeStanding;
  88         }
  89 
  90         public void paint( Graphics g )
  91         {
  92             boolean leftToRight = MetalUtils.isLeftToRight(this);
  93             boolean isEnabled = getParent().isEnabled();
  94 
  95             Color arrowColor = isEnabled ? MetalLookAndFeel.getControlInfo() : MetalLookAndFeel.getControlDisabled();
  96             boolean isPressed = getModel().isPressed();
  97             int width = getWidth();
  98             int height = getHeight();
  99             int w = width;
 100             int h = height;
 101             int arrowHeight = (height+1) / 4;
 102             int arrowWidth = (height+1) / 2;
 103 
 104             if ( isPressed )
 105             {
 106                 g.setColor( MetalLookAndFeel.getControlShadow() );
 107             }
 108             else
 109             {
 110                 g.setColor( getBackground() );
 111             }
 112 
 113             g.fillRect( 0, 0, width, height );
 114 
 115             if ( getDirection() == NORTH )
 116             {
 117                 if ( !isFreeStanding ) {
 118                     height +=1;
 119                     g.translate( 0, -1 );
 120                     width += 2;
 121                     if ( !leftToRight ) {
 122                         g.translate( -1, 0 );
 123                     }
 124                 }
 125 
 126                 // Draw the arrow
 127                 g.setColor( arrowColor );
 128                 int startY = ((h+1) - arrowHeight) / 2;
 129                 int startX = (w / 2);
 130 
 131                 for (int line = 0; line < arrowHeight; line++) {
 132                     g.drawLine( startX-line, startY+line, startX +line+1, startY+line);
 133                 }
 134 
 135                 if (isEnabled) {
 136                     g.setColor( highlightColor );
 137 
 138                     if ( !isPressed )
 139                     {
 140                         g.drawLine( 1, 1, width - 3, 1 );
 141                         g.drawLine( 1, 1, 1, height - 1 );
 142                     }
 143 
 144                     g.drawLine( width - 1, 1, width - 1, height - 1 );
 145 
 146                     g.setColor( shadowColor );
 147                     g.drawLine( 0, 0, width - 2, 0 );
 148                     g.drawLine( 0, 0, 0, height - 1 );
 149                     g.drawLine( width - 2, 2, width - 2, height - 1 );
 150                 } else {
 151                     MetalUtils.drawDisabledBorder(g, 0, 0, width, height+1);
 152                 }
 153                 if ( !isFreeStanding ) {
 154                     height -= 1;
 155                     g.translate( 0, 1 );
 156                     width -= 2;
 157                     if ( !leftToRight ) {
 158                         g.translate( 1, 0 );
 159                     }
 160                 }
 161             }
 162             else if ( getDirection() == SOUTH )
 163             {
 164                 if ( !isFreeStanding ) {
 165                     height += 1;
 166                     width += 2;
 167                     if ( !leftToRight ) {
 168                         g.translate( -1, 0 );
 169                     }
 170                 }
 171 
 172                 // Draw the arrow
 173                 g.setColor( arrowColor );
 174 
 175                 int startY = (((h+1) - arrowHeight) / 2)+ arrowHeight-1;
 176                 int startX = (w / 2);
 177 
 178                 for (int line = 0; line < arrowHeight; line++) {
 179                     g.drawLine( startX-line, startY-line, startX +line+1, startY-line);
 180                 }
 181 
 182                 if (isEnabled) {
 183                     g.setColor( highlightColor );
 184 
 185                     if ( !isPressed )
 186                     {
 187                         g.drawLine( 1, 0, width - 3, 0 );
 188                         g.drawLine( 1, 0, 1, height - 3 );
 189                     }
 190 
 191                     g.drawLine( 1, height - 1, width - 1, height - 1 );
 192                     g.drawLine( width - 1, 0, width - 1, height - 1 );
 193 
 194                     g.setColor( shadowColor );
 195                     g.drawLine( 0, 0, 0, height - 2 );
 196                     g.drawLine( width - 2, 0, width - 2, height - 2 );
 197                     g.drawLine( 2, height - 2, width - 2, height - 2 );
 198                 } else {
 199                     MetalUtils.drawDisabledBorder(g, 0,-1, width, height+1);
 200                 }
 201 
 202                 if ( !isFreeStanding ) {
 203                     height -= 1;
 204                     width -= 2;
 205                     if ( !leftToRight ) {
 206                         g.translate( 1, 0 );
 207                     }
 208                 }
 209             }
 210             else if ( getDirection() == EAST )
 211             {
 212                 if ( !isFreeStanding ) {
 213                     height += 2;
 214                     width += 1;
 215                 }
 216 
 217                 // Draw the arrow
 218                 g.setColor( arrowColor );
 219 
 220                 int startX = (((w+1) - arrowHeight) / 2) + arrowHeight-1;
 221                 int startY = (h / 2);
 222 
 223                 for (int line = 0; line < arrowHeight; line++) {
 224                     g.drawLine( startX-line, startY-line, startX -line, startY+line+1);
 225                 }
 226 
 227                 if (isEnabled) {
 228                     g.setColor( highlightColor );
 229 
 230                     if ( !isPressed )
 231                     {
 232                         g.drawLine( 0, 1, width - 3, 1 );
 233                         g.drawLine( 0, 1, 0, height - 3 );
 234                     }
 235 
 236                     g.drawLine( width - 1, 1, width - 1, height - 1 );
 237                     g.drawLine( 0, height - 1, width - 1, height - 1 );
 238 
 239                     g.setColor( shadowColor );
 240                     g.drawLine( 0, 0,width - 2, 0 );
 241                     g.drawLine( width - 2, 2, width - 2, height - 2 );
 242                     g.drawLine( 0, height - 2, width - 2, height - 2 );
 243                 } else {
 244                     MetalUtils.drawDisabledBorder(g,-1,0, width+1, height);
 245                 }
 246                 if ( !isFreeStanding ) {
 247                     height -= 2;
 248                     width -= 1;
 249                 }
 250             }
 251             else if ( getDirection() == WEST )
 252             {
 253                 if ( !isFreeStanding ) {
 254                     height += 2;
 255                     width += 1;
 256                     g.translate( -1, 0 );
 257                 }
 258 
 259                 // Draw the arrow
 260                 g.setColor( arrowColor );
 261 
 262                 int startX = (((w+1) - arrowHeight) / 2);
 263                 int startY = (h / 2);
 264 
 265 
 266                 for (int line = 0; line < arrowHeight; line++) {
 267                     g.drawLine( startX+line, startY-line, startX +line, startY+line+1);
 268                 }
 269 
 270                 if (isEnabled) {
 271                     g.setColor( highlightColor );
 272 
 273 
 274                     if ( !isPressed )
 275                     {
 276                         g.drawLine( 1, 1, width - 1, 1 );
 277                         g.drawLine( 1, 1, 1, height - 3 );
 278                     }
 279 
 280                     g.drawLine( 1, height - 1, width - 1, height - 1 );
 281 
 282                     g.setColor( shadowColor );
 283                     g.drawLine( 0, 0, width - 1, 0 );
 284                     g.drawLine( 0, 0, 0, height - 2 );
 285                     g.drawLine( 2, height - 2, width - 1, height - 2 );
 286                 } else {
 287                     MetalUtils.drawDisabledBorder(g,0,0, width+1, height);
 288                 }
 289 
 290                 if ( !isFreeStanding ) {
 291                     height -= 2;
 292                     width -= 1;
 293                     g.translate( 1, 0 );
 294                 }
 295             }
 296         }
 297 
 298         public Dimension getPreferredSize()
 299         {
 300             if ( getDirection() == NORTH )
 301             {
 302                 return new Dimension( buttonWidth, buttonWidth - 2 );
 303             }
 304             else if ( getDirection() == SOUTH )
 305             {
 306                 return new Dimension( buttonWidth, buttonWidth - (isFreeStanding ? 1 : 2) );
 307             }
 308             else if ( getDirection() == EAST )
 309             {
 310                 return new Dimension( buttonWidth - (isFreeStanding ? 1 : 2), buttonWidth );
 311             }
 312             else if ( getDirection() == WEST )
 313             {
 314                 return new Dimension( buttonWidth - 2, buttonWidth );
 315             }
 316             else
 317             {
 318                 return new Dimension( 0, 0 );
 319             }
 320         }
 321 
 322         public Dimension getMinimumSize()
 323         {
 324             return getPreferredSize();
 325         }
 326 
 327         public Dimension getMaximumSize()
 328         {
 329             return new Dimension( Integer.MAX_VALUE, Integer.MAX_VALUE );
 330         }
 331 
 332         /**
 333          * Returns the width of the button.
 334          *
 335          * @return the width of the button
 336          */
 337         public int getButtonWidth() {
 338             return buttonWidth;
 339         }
 340 }