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
  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                 g.translate(startX, startY);
 132                 g.fillPolygon(new int[]{0, 1, arrowHeight + 1, -arrowHeight},
 133                               new int[]{0, 0, arrowHeight, arrowHeight}, 4);
 134                 g.translate(-startX, -startY);
 135 
 136                 if (isEnabled) {
 137                     g.setColor( highlightColor );
 138 
 139                     if ( !isPressed )
 140                     {
 141                         g.drawLine( 1, 1, width - 3, 1 );
 142                         g.drawLine( 1, 1, 1, height - 1 );
 143                     }
 144 
 145                     g.drawLine( width - 1, 1, width - 1, height - 1 );
 146 
 147                     g.setColor( shadowColor );
 148                     g.drawLine( 0, 0, width - 2, 0 );
 149                     g.drawLine( 0, 0, 0, height - 1 );
 150                     g.drawLine( width - 2, 2, width - 2, height - 1 );
 151                 } else {
 152                     MetalUtils.drawDisabledBorder(g, 0, 0, width, height+1);
 153                 }
 154                 if ( !isFreeStanding ) {
 155                     height -= 1;
 156                     g.translate( 0, 1 );
 157                     width -= 2;
 158                     if ( !leftToRight ) {
 159                         g.translate( 1, 0 );
 160                     }
 161                 }
 162             }
 163             else if ( getDirection() == SOUTH )
 164             {
 165                 if ( !isFreeStanding ) {
 166                     height += 1;
 167                     width += 2;
 168                     if ( !leftToRight ) {
 169                         g.translate( -1, 0 );
 170                     }
 171                 }
 172 
 173                 // Draw the arrow
 174                 g.setColor( arrowColor );
 175 
 176                 int startY = (((h+1) - arrowHeight) / 2)+ arrowHeight-1;
 177                 int startX = (w / 2);
 178                 g.translate(startX, startY);
 179                 g.fillPolygon(new int[]{0, 1, arrowHeight + 1, -arrowHeight},
 180                               new int[]{0, 0, -arrowHeight, -arrowHeight}, 4);
 181                 g.translate(-startX, -startY);
 182 
 183                 if (isEnabled) {
 184                     g.setColor( highlightColor );
 185 
 186                     if ( !isPressed )
 187                     {
 188                         g.drawLine( 1, 0, width - 3, 0 );
 189                         g.drawLine( 1, 0, 1, height - 3 );
 190                     }
 191 
 192                     g.drawLine( 1, height - 1, width - 1, height - 1 );
 193                     g.drawLine( width - 1, 0, width - 1, height - 1 );
 194 
 195                     g.setColor( shadowColor );
 196                     g.drawLine( 0, 0, 0, height - 2 );
 197                     g.drawLine( width - 2, 0, width - 2, height - 2 );
 198                     g.drawLine( 2, height - 2, width - 2, height - 2 );
 199                 } else {
 200                     MetalUtils.drawDisabledBorder(g, 0,-1, width, height+1);
 201                 }
 202 
 203                 if ( !isFreeStanding ) {
 204                     height -= 1;
 205                     width -= 2;
 206                     if ( !leftToRight ) {
 207                         g.translate( 1, 0 );
 208                     }
 209                 }
 210             }
 211             else if ( getDirection() == EAST )
 212             {
 213                 if ( !isFreeStanding ) {
 214                     height += 2;
 215                     width += 1;
 216                 }
 217 
 218                 // Draw the arrow
 219                 g.setColor( arrowColor );
 220 
 221                 int startX = (((w+1) - arrowHeight) / 2) + arrowHeight-1;
 222                 int startY = (h / 2);
 223 
 224                 g.translate(startX, startY);
 225                 g.fillPolygon(new int[]{0, 0, -arrowHeight, -arrowHeight},
 226                               new int[]{0, 1, arrowHeight + 1, -arrowHeight}, 4);
 227                 g.translate(-startX, -startY);
 228 
 229                 if (isEnabled) {
 230                     g.setColor( highlightColor );
 231 
 232                     if ( !isPressed )
 233                     {
 234                         g.drawLine( 0, 1, width - 3, 1 );
 235                         g.drawLine( 0, 1, 0, height - 3 );
 236                     }
 237 
 238                     g.drawLine( width - 1, 1, width - 1, height - 1 );
 239                     g.drawLine( 0, height - 1, width - 1, height - 1 );
 240 
 241                     g.setColor( shadowColor );
 242                     g.drawLine( 0, 0,width - 2, 0 );
 243                     g.drawLine( width - 2, 2, width - 2, height - 2 );
 244                     g.drawLine( 0, height - 2, width - 2, height - 2 );
 245                 } else {
 246                     MetalUtils.drawDisabledBorder(g,-1,0, width+1, height);
 247                 }
 248                 if ( !isFreeStanding ) {
 249                     height -= 2;
 250                     width -= 1;
 251                 }
 252             }
 253             else if ( getDirection() == WEST )
 254             {
 255                 if ( !isFreeStanding ) {
 256                     height += 2;
 257                     width += 1;
 258                     g.translate( -1, 0 );
 259                 }
 260 
 261                 // Draw the arrow
 262                 g.setColor( arrowColor );
 263 
 264                 int startX = (((w+1) - arrowHeight) / 2);
 265                 int startY = (h / 2);
 266 
 267                 g.translate(startX, startY);
 268                 g.fillPolygon(new int[]{0, 0, arrowHeight, arrowHeight},
 269                               new int[]{0, 1, arrowHeight + 1, -arrowHeight}, 4);
 270                 g.translate(-startX, -startY);
 271 
 272                 if (isEnabled) {
 273                     g.setColor( highlightColor );
 274 
 275 
 276                     if ( !isPressed )
 277                     {
 278                         g.drawLine( 1, 1, width - 1, 1 );
 279                         g.drawLine( 1, 1, 1, height - 3 );
 280                     }
 281 
 282                     g.drawLine( 1, height - 1, width - 1, height - 1 );
 283 
 284                     g.setColor( shadowColor );
 285                     g.drawLine( 0, 0, width - 1, 0 );
 286                     g.drawLine( 0, 0, 0, height - 2 );
 287                     g.drawLine( 2, height - 2, width - 1, height - 2 );
 288                 } else {
 289                     MetalUtils.drawDisabledBorder(g,0,0, width+1, height);
 290                 }
 291 
 292                 if ( !isFreeStanding ) {
 293                     height -= 2;
 294                     width -= 1;
 295                     g.translate( 1, 0 );
 296                 }
 297             }
 298         }
 299 
 300         public Dimension getPreferredSize()
 301         {
 302             if ( getDirection() == NORTH )
 303             {
 304                 return new Dimension( buttonWidth, buttonWidth - 2 );
 305             }
 306             else if ( getDirection() == SOUTH )
 307             {
 308                 return new Dimension( buttonWidth, buttonWidth - (isFreeStanding ? 1 : 2) );
 309             }
 310             else if ( getDirection() == EAST )
 311             {
 312                 return new Dimension( buttonWidth - (isFreeStanding ? 1 : 2), buttonWidth );
 313             }
 314             else if ( getDirection() == WEST )
 315             {
 316                 return new Dimension( buttonWidth - 2, buttonWidth );
 317             }
 318             else
 319             {
 320                 return new Dimension( 0, 0 );
 321             }
 322         }
 323 
 324         public Dimension getMinimumSize()
 325         {
 326             return getPreferredSize();
 327         }
 328 
 329         public Dimension getMaximumSize()
 330         {
 331             return new Dimension( Integer.MAX_VALUE, Integer.MAX_VALUE );
 332         }
 333 
 334         /**
 335          * Returns the width of the button.
 336          *
 337          * @return the width of the button
 338          */
 339         public int getButtonWidth() {
 340             return buttonWidth;
 341         }
 342 }