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          */
MetalScrollButton( int direction, int width, boolean freeStanding )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          */
setFreeStanding( boolean freeStanding )85         public void setFreeStanding( boolean freeStanding )
86         {
87             isFreeStanding = freeStanding;
88         }
89 
paint( Graphics g )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 
getPreferredSize()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 
getMinimumSize()324         public Dimension getMinimumSize()
325         {
326             return getPreferredSize();
327         }
328 
getMaximumSize()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          */
getButtonWidth()339         public int getButtonWidth() {
340             return buttonWidth;
341         }
342 }
343