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
26package javax.swing.plaf.metal;
27
28import java.awt.Dimension;
29import java.awt.Graphics;
30import java.awt.Color;
31import java.awt.Polygon;
32
33import javax.swing.*;
34
35import 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
54public 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}
343