1 /* MetalScrollButton.java
2    Copyright (C) 2005 Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package javax.swing.plaf.metal;
40 
41 import java.awt.Dimension;
42 import java.awt.Graphics;
43 import java.awt.Rectangle;
44 
45 import javax.swing.SwingUtilities;
46 import javax.swing.plaf.basic.BasicArrowButton;
47 
48 /**
49  * A button used by the {@link MetalScrollBarUI}.  The button appearance
50  * varies according to the button direction, whether or not it is part of a
51  * "free standing" scroll bar, and the current state of the button.
52  */
53 public class MetalScrollButton extends BasicArrowButton
54 {
55 
56   /**
57    * The maximum size for buttons.
58    * @see #getMaximumSize()
59    */
60   private static Dimension maximumSize;
61 
62   /** The width of the button. */
63   private int buttonWidth;
64 
65   /**
66    * A flag that indicates whether the button is part of a free standing
67    * scroll bar.  This affects how the border is drawn.
68    */
69   private boolean freeStanding;
70 
71   /**
72    * Creates a new button.
73    *
74    * @param direction  the direction (this should be one of {@link #NORTH},
75    *                   {@link #SOUTH}, {@link #EAST} and {@link #WEST}, but
76    *                   this is not enforced).
77    * @param width  the button width.
78    * @param freeStanding  a flag indicating whether the scroll button is free
79    *                      standing or not.
80    */
MetalScrollButton(int direction, int width, boolean freeStanding)81   public MetalScrollButton(int direction, int width, boolean freeStanding)
82   {
83     super(direction);
84     buttonWidth = width;
85     this.freeStanding = freeStanding;
86     setFocusable(false);
87   }
88 
89   /**
90    * Returns the button width.
91    *
92    * @return The button width.
93    */
getButtonWidth()94   public int getButtonWidth()
95   {
96     return buttonWidth;
97   }
98 
99   /**
100    * Sets the free standing flag.  This controls how the button border is
101    * drawn.
102    *
103    * @param freeStanding  the new value of the flag.
104    */
setFreeStanding(boolean freeStanding)105   public void setFreeStanding(boolean freeStanding)
106   {
107     this.freeStanding = freeStanding;
108   }
109 
110   /**
111    * Paints the button.
112    *
113    * @param g  the graphics device.
114    */
paint(Graphics g)115   public void paint(Graphics g)
116   {
117     Rectangle bounds = SwingUtilities.getLocalBounds(this);
118 
119     // fill the background
120     if (getModel().isPressed())
121       g.setColor(MetalLookAndFeel.getControlShadow());
122     else
123       g.setColor(MetalLookAndFeel.getControl());
124     g.fillRect(0, 0, bounds.width, bounds.height);
125 
126     paintArrow(g, bounds.width, bounds.height);
127 
128     // paint a border manually - I tried using a real (custom) Border
129     // but couldn't get it to stay set for the button, something was
130     // overwriting it...
131     if (freeStanding)
132       {
133         if (direction == WEST)
134           paintWestBorderFreeStanding(g, bounds.width, bounds.height);
135         else if (direction == EAST)
136           paintEastBorderFreeStanding(g, bounds.width, bounds.height);
137         else if (direction == SOUTH)
138           paintSouthBorderFreeStanding(g, bounds.width, bounds.height);
139         else // asume NORTH
140           paintNorthBorderFreeStanding(g, bounds.width, bounds.height);
141       }
142     else
143       {
144         if (direction == WEST)
145           paintWestBorder(g, bounds.width, bounds.height);
146         else if (direction == EAST)
147           paintEastBorder(g, bounds.width, bounds.height);
148         else if (direction == SOUTH)
149           paintSouthBorder(g, bounds.width, bounds.height);
150         else // asume NORTH
151           paintNorthBorder(g, bounds.width, bounds.height);
152       }
153   }
154 
paintArrow(Graphics g, int w, int h)155   private void paintArrow(Graphics g, int w, int h)
156   {
157     if (isEnabled())
158       g.setColor(MetalLookAndFeel.getBlack());
159     else
160       g.setColor(MetalLookAndFeel.getControlDisabled());
161 
162     if (direction == SOUTH)
163       {
164         int x = w / 2;
165         int y = h / 2 + 2;
166         for (int i = 1; i < 5; i++)
167           g.drawLine(x - i, y - i, x + i - 1, y - i);
168       }
169     else if (direction == EAST)
170       {
171         int x = w / 2 + 2;
172         int y = h / 2;
173         for (int i = 1; i < 5; i++)
174           g.drawLine(x - i, y - i, x - i, y + i - 1);
175       }
176     else if (direction == WEST)
177       {
178         int x = w / 2 - 3;
179         int y = h / 2;
180         for (int i = 1; i < 5; i++)
181           g.drawLine(x + i, y - i, x + i, y + i - 1);
182       }
183     else // assume NORTH
184       {
185         int x = w / 2;
186         int y = h / 2 - 3;
187         for (int i = 1; i < 5; i++)
188           g.drawLine(x - i, y + i, x + i - 1, y + i);
189       }
190   }
191   /**
192    * Paints the border for a button with a {@link #NORTH} direction that
193    * belongs to a free standing scroll bar.
194    *
195    * @param g  the graphics device.
196    * @param w  the button width.
197    * @param h  the button height.
198    */
paintNorthBorderFreeStanding(Graphics g, int w, int h)199   private void paintNorthBorderFreeStanding(Graphics g, int w, int h)
200   {
201     if (isEnabled())
202       {
203         g.setColor(MetalLookAndFeel.getControlDarkShadow());
204         g.drawLine(0, 0, w - 2, 0);
205         g.drawLine(0, 0, 0, h - 1);
206         g.drawLine(2, h - 1, w - 2, h - 1);
207         g.drawLine(w - 2, 2, w - 2, h - 1);
208 
209         g.setColor(MetalLookAndFeel.getControlHighlight());
210         g.drawLine(1, 1, 1, h - 2);
211         g.drawLine(1, 1, w - 3, 1);
212         g.drawLine(w - 1, 1, w - 1, h - 1);
213 
214         g.setColor(MetalLookAndFeel.getControl());
215         g.drawLine(1, h - 1, 1, h - 1);
216         g.drawLine(w - 2, 1, w - 2, 1);
217       }
218     else
219       {
220         g.setColor(MetalLookAndFeel.getControlDisabled());
221         g.drawLine(0, 0, w - 1, 0);
222         g.drawLine(w - 1, 0, w - 1, h - 1);
223         g.drawLine(0, 0, 0, h - 1);
224       }
225   }
226 
227   /**
228    * Paints the border for a button with a {@link #SOUTH} direction that
229    * belongs to a free standing scroll bar.
230    *
231    * @param g  the graphics device.
232    * @param w  the button width.
233    * @param h  the button height.
234    */
paintSouthBorderFreeStanding(Graphics g, int w, int h)235   private void paintSouthBorderFreeStanding(Graphics g, int w, int h)
236   {
237     if (isEnabled())
238       {
239         g.setColor(MetalLookAndFeel.getControlDarkShadow());
240         g.drawLine(0, 0, w - 2, 0);
241         g.drawLine(0, 0, 0, h - 1);
242         g.drawLine(2, h - 1, w - 2, h - 1);
243         g.drawLine(w - 2, 2, w - 2, h - 1);
244 
245         g.setColor(MetalLookAndFeel.getControlHighlight());
246         g.drawLine(1, 1, 1, h - 1);
247         g.drawLine(1, 1, w - 1, 1);
248         g.drawLine(w - 1, 1, w - 1, h - 1);
249 
250         g.setColor(MetalLookAndFeel.getControl());
251         g.drawLine(1, h - 1, 1, h - 1);
252         g.drawLine(w - 1, 1, w - 1, 1);
253       }
254     else
255       {
256         g.setColor(MetalLookAndFeel.getControlDisabled());
257         g.drawLine(0, h - 1, w - 1, h - 1);
258         g.drawLine(w - 1, 0, w - 1, h - 1);
259         g.drawLine(0, 0, 0, h - 1);
260       }
261   }
262 
263   /**
264    * Paints the border for a button with an {@link #EAST} direction that
265    * belongs to a free standing scroll bar.
266    *
267    * @param g  the graphics device.
268    * @param w  the button width.
269    * @param h  the button height.
270    */
paintEastBorderFreeStanding(Graphics g, int w, int h)271   private void paintEastBorderFreeStanding(Graphics g, int w, int h)
272   {
273     if (isEnabled())
274       {
275         g.setColor(MetalLookAndFeel.getControlDarkShadow());
276         g.drawLine(0, 0, w - 2, 0);
277         g.drawLine(w - 2, 0, w - 2, h - 2);
278         g.drawLine(0, h - 2, w - 2, h - 2);
279 
280         g.setColor(MetalLookAndFeel.getControlHighlight());
281         g.drawLine(0, 1, w - 1, 1);
282         g.drawLine(w - 1, 1, w - 1, h - 1);
283         g.drawLine(0, h - 1, w - 1, h - 1);
284 
285         g.setColor(MetalLookAndFeel.getControl());
286         g.drawLine(w - 2, 1, w - 2, 1);
287       }
288     else
289       {
290         g.setColor(MetalLookAndFeel.getControlDisabled());
291         g.drawLine(0, 0, w - 1, 0);
292         g.drawLine(w - 1, 0, w - 1, h - 1);
293         g.drawLine(0, h - 1, w - 1, h - 1);
294       }
295   }
296 
297   /**
298    * Paints the border for a button with a {@link #WEST} direction that
299    * belongs to a free standing scroll bar.
300    *
301    * @param g  the graphics device.
302    * @param w  the button width.
303    * @param h  the button height.
304    */
paintWestBorderFreeStanding(Graphics g, int w, int h)305   private void paintWestBorderFreeStanding(Graphics g, int w, int h)
306   {
307     if (isEnabled())
308       {
309         g.setColor(MetalLookAndFeel.getControlDarkShadow());
310         g.drawLine(0, 0, w - 1, 0);
311         g.drawLine(0, 0, 0, h - 2);
312         g.drawLine(0, h - 2, w - 1, h - 2);
313 
314         g.setColor(MetalLookAndFeel.getControlHighlight());
315         g.drawLine(1, 1, w - 1, 1);
316         g.drawLine(1, 1, 1, h - 1);
317         g.drawLine(1, h - 1, w - 1, h - 1);
318 
319         g.setColor(MetalLookAndFeel.getControl());
320         g.drawLine(1, h - 2, 1, h - 2);
321       }
322     else
323       {
324         g.setColor(MetalLookAndFeel.getControlDisabled());
325         g.drawLine(0, 0, w - 1, 0);
326         g.drawLine(0, 0, 0, h - 1);
327         g.drawLine(0, h - 1, w - 1, h - 1);
328       }
329   }
330 
331   /**
332    * Paints the border for a button with a {@link #NORTH} direction that
333    * belongs to a scroll bar that is not free standing.
334    *
335    * @param g  the graphics device.
336    * @param w  the button width.
337    * @param h  the button height.
338    */
paintNorthBorder(Graphics g, int w, int h)339   private void paintNorthBorder(Graphics g, int w, int h)
340   {
341     if (isEnabled())
342       {
343         g.setColor(MetalLookAndFeel.getControlDarkShadow());
344         g.drawLine(0, 0, 0, h - 1);
345 
346         g.setColor(MetalLookAndFeel.getControlHighlight());
347         g.drawLine(1, 0, 1, h - 1);
348         g.drawLine(1, 0, w - 1, 0);
349       }
350     else
351       {
352         g.setColor(MetalLookAndFeel.getControlDisabled());
353         g.drawLine(0, 0, 0, h - 1);
354       }
355   }
356 
357   /**
358    * Paints the border for a button with a {@link #SOUTH} direction that
359    * belongs to a scroll bar that is not free standing.
360    *
361    * @param g  the graphics device.
362    * @param w  the button width.
363    * @param h  the button height.
364    */
paintSouthBorder(Graphics g, int w, int h)365   private void paintSouthBorder(Graphics g, int w, int h)
366   {
367     if (isEnabled())
368       {
369         g.setColor(MetalLookAndFeel.getControlDarkShadow());
370         g.drawLine(0, 0, 0, h - 1);
371         g.drawLine(0, h - 1, w - 1, h - 1);
372 
373         g.setColor(MetalLookAndFeel.getControlHighlight());
374         g.drawLine(1, 0, 1, h - 1);
375         g.drawLine(1, 0, w - 1, 0);
376 
377         g.setColor(MetalLookAndFeel.getControl());
378         g.drawLine(1, h - 1, 1, h - 1);
379       }
380     else
381       {
382         g.setColor(MetalLookAndFeel.getControlDisabled());
383         g.drawLine(0, 0, 0, h - 1);
384       }
385   }
386 
387   /**
388    * Paints the border for a button with an {@link #EAST} direction that
389    * belongs to a scroll bar that is not free standing.
390    *
391    * @param g  the graphics device.
392    * @param w  the button width.
393    * @param h  the button height.
394    */
paintEastBorder(Graphics g, int w, int h)395   private void paintEastBorder(Graphics g, int w, int h)
396   {
397     if (isEnabled())
398       {
399         g.setColor(MetalLookAndFeel.getControlDarkShadow());
400         g.drawLine(0, 0, w - 1, 0);
401         g.drawLine(w - 1, 2, w - 1, h - 1);
402         g.setColor(MetalLookAndFeel.getControlHighlight());
403         g.drawLine(0, 1, w - 2, 1);
404         g.drawLine(0, 1, 0, h - 1);
405       }
406     else
407       {
408         g.setColor(MetalLookAndFeel.getControlDisabled());
409         g.drawLine(0, 0, w - 1, 0);
410       }
411   }
412 
413   /**
414    * Paints the border for a button with a {@link #WEST} direction that
415    * belongs to a scroll bar that is not free standing.
416    *
417    * @param g  the graphics device.
418    * @param w  the button width.
419    * @param h  the button height.
420    */
paintWestBorder(Graphics g, int w, int h)421   private void paintWestBorder(Graphics g, int w, int h)
422   {
423     Rectangle bounds = SwingUtilities.getLocalBounds(this);
424     if (isEnabled())
425       {
426         g.setColor(MetalLookAndFeel.getControlDarkShadow());
427         g.drawLine(0, 0, bounds.width - 1, 0);
428         g.setColor(MetalLookAndFeel.getControlHighlight());
429         g.drawLine(0, 1, bounds.width - 1, 1);
430         g.drawLine(0, 1, 0, bounds.height - 1);
431       }
432     else
433       {
434         g.setColor(MetalLookAndFeel.getControlDisabled());
435         g.drawLine(0, 0, bounds.width - 1, 0);
436       }
437   }
438 
439   /**
440    * Returns the preferred size for the button, which varies depending on
441    * the direction of the button and whether or not it is free standing.
442    *
443    * @return The preferred size.
444    */
getPreferredSize()445   public Dimension getPreferredSize()
446   {
447     int adj = 1;
448     if (!freeStanding)
449       adj = 2;
450 
451     if (direction == EAST)
452       return new Dimension(buttonWidth - adj, buttonWidth);
453     else if (direction == WEST)
454       return new Dimension(buttonWidth - 2, buttonWidth);
455     else if (direction == SOUTH)
456       return new Dimension(buttonWidth, buttonWidth - adj);
457     else // assume NORTH
458       return new Dimension(buttonWidth, buttonWidth - 2);
459   }
460 
461   /**
462    * Returns the minimum size for the button.
463    *
464    * @return The minimum size for the button.
465    */
getMinimumSize()466   public Dimension getMinimumSize()
467   {
468     return getPreferredSize();
469   }
470 
471   /**
472    * Returns the maximum size for the button.
473    *
474    * @return <code>Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)</code>.
475    */
getMaximumSize()476   public Dimension getMaximumSize()
477   {
478     if (maximumSize == null)
479       maximumSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
480     return maximumSize;
481   }
482 
483 }
484