001 /* MetalScrollButton.java
002 Copyright (C) 2005 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package javax.swing.plaf.metal;
040
041 import java.awt.Color;
042 import java.awt.Dimension;
043 import java.awt.Graphics;
044 import java.awt.Rectangle;
045
046 import javax.swing.SwingUtilities;
047 import javax.swing.plaf.basic.BasicArrowButton;
048
049 /**
050 * A button used by the {@link MetalScrollBarUI}. The button appearance
051 * varies according to the button direction, whether or not it is part of a
052 * "free standing" scroll bar, and the current state of the button.
053 */
054 public class MetalScrollButton extends BasicArrowButton
055 {
056
057 /**
058 * The maximum size for buttons.
059 * @see #getMaximumSize()
060 */
061 private static Dimension maximumSize;
062
063 /** The width of the button. */
064 private int buttonWidth;
065
066 /**
067 * A flag that indicates whether the button is part of a free standing
068 * scroll bar. This affects how the border is drawn.
069 */
070 private boolean freeStanding;
071
072 /**
073 * Creates a new button.
074 *
075 * @param direction the direction (this should be one of {@link #NORTH},
076 * {@link #SOUTH}, {@link #EAST} and {@link #WEST}, but
077 * this is not enforced).
078 * @param width the button width.
079 * @param freeStanding a flag indicating whether the scroll button is free
080 * standing or not.
081 */
082 public MetalScrollButton(int direction, int width, boolean freeStanding)
083 {
084 super(direction);
085 buttonWidth = width;
086 this.freeStanding = freeStanding;
087 setFocusable(false);
088 }
089
090 /**
091 * Returns the button width.
092 *
093 * @return The button width.
094 */
095 public int getButtonWidth()
096 {
097 return buttonWidth;
098 }
099
100 /**
101 * Sets the free standing flag. This controls how the button border is
102 * drawn.
103 *
104 * @param freeStanding the new value of the flag.
105 */
106 public void setFreeStanding(boolean freeStanding)
107 {
108 this.freeStanding = freeStanding;
109 }
110
111 /**
112 * Paints the button.
113 *
114 * @param g the graphics device.
115 */
116 public void paint(Graphics g)
117 {
118 Rectangle bounds = SwingUtilities.getLocalBounds(this);
119
120 // fill the background
121 if (getModel().isPressed())
122 g.setColor(MetalLookAndFeel.getControlShadow());
123 else
124 g.setColor(MetalLookAndFeel.getControl());
125 g.fillRect(0, 0, bounds.width, bounds.height);
126
127 paintArrow(g, bounds.width, bounds.height);
128
129 // paint a border manually - I tried using a real (custom) Border
130 // but couldn't get it to stay set for the button, something was
131 // overwriting it...
132 if (freeStanding)
133 {
134 if (direction == WEST)
135 paintWestBorderFreeStanding(g, bounds.width, bounds.height);
136 else if (direction == EAST)
137 paintEastBorderFreeStanding(g, bounds.width, bounds.height);
138 else if (direction == SOUTH)
139 paintSouthBorderFreeStanding(g, bounds.width, bounds.height);
140 else // asume NORTH
141 paintNorthBorderFreeStanding(g, bounds.width, bounds.height);
142 }
143 else
144 {
145 if (direction == WEST)
146 paintWestBorder(g, bounds.width, bounds.height);
147 else if (direction == EAST)
148 paintEastBorder(g, bounds.width, bounds.height);
149 else if (direction == SOUTH)
150 paintSouthBorder(g, bounds.width, bounds.height);
151 else // asume NORTH
152 paintNorthBorder(g, bounds.width, bounds.height);
153 }
154 }
155
156 private void paintArrow(Graphics g, int w, int h)
157 {
158 if (isEnabled())
159 g.setColor(MetalLookAndFeel.getBlack());
160 else
161 g.setColor(MetalLookAndFeel.getControlDisabled());
162
163 if (direction == SOUTH)
164 {
165 int x = w / 2;
166 int y = h / 2 + 2;
167 for (int i = 1; i < 5; i++)
168 g.drawLine(x - i, y - i, x + i - 1, y - i);
169 }
170 else if (direction == EAST)
171 {
172 int x = w / 2 + 2;
173 int y = h / 2;
174 for (int i = 1; i < 5; i++)
175 g.drawLine(x - i, y - i, x - i, y + i - 1);
176 }
177 else if (direction == WEST)
178 {
179 int x = w / 2 - 3;
180 int y = h / 2;
181 for (int i = 1; i < 5; i++)
182 g.drawLine(x + i, y - i, x + i, y + i - 1);
183 }
184 else // assume NORTH
185 {
186 int x = w / 2;
187 int y = h / 2 - 3;
188 for (int i = 1; i < 5; i++)
189 g.drawLine(x - i, y + i, x + i - 1, y + i);
190 }
191 }
192 /**
193 * Paints the border for a button with a {@link #NORTH} direction that
194 * belongs to a free standing scroll bar.
195 *
196 * @param g the graphics device.
197 * @param w the button width.
198 * @param h the button height.
199 */
200 private void paintNorthBorderFreeStanding(Graphics g, int w, int h)
201 {
202 if (isEnabled())
203 {
204 g.setColor(MetalLookAndFeel.getControlDarkShadow());
205 g.drawLine(0, 0, w - 2, 0);
206 g.drawLine(0, 0, 0, h - 1);
207 g.drawLine(2, h - 1, w - 2, h - 1);
208 g.drawLine(w - 2, 2, w - 2, h - 1);
209
210 g.setColor(MetalLookAndFeel.getControlHighlight());
211 g.drawLine(1, 1, 1, h - 2);
212 g.drawLine(1, 1, w - 3, 1);
213 g.drawLine(w - 1, 1, w - 1, h - 1);
214
215 g.setColor(MetalLookAndFeel.getControl());
216 g.drawLine(1, h - 1, 1, h - 1);
217 g.drawLine(w - 2, 1, w - 2, 1);
218 }
219 else
220 {
221 g.setColor(MetalLookAndFeel.getControlDisabled());
222 g.drawLine(0, 0, w - 1, 0);
223 g.drawLine(w - 1, 0, w - 1, h - 1);
224 g.drawLine(0, 0, 0, h - 1);
225 }
226 }
227
228 /**
229 * Paints the border for a button with a {@link #SOUTH} direction that
230 * belongs to a free standing scroll bar.
231 *
232 * @param g the graphics device.
233 * @param w the button width.
234 * @param h the button height.
235 */
236 private void paintSouthBorderFreeStanding(Graphics g, int w, int h)
237 {
238 if (isEnabled())
239 {
240 g.setColor(MetalLookAndFeel.getControlDarkShadow());
241 g.drawLine(0, 0, w - 2, 0);
242 g.drawLine(0, 0, 0, h - 1);
243 g.drawLine(2, h - 1, w - 2, h - 1);
244 g.drawLine(w - 2, 2, w - 2, h - 1);
245
246 g.setColor(MetalLookAndFeel.getControlHighlight());
247 g.drawLine(1, 1, 1, h - 1);
248 g.drawLine(1, 1, w - 1, 1);
249 g.drawLine(w - 1, 1, w - 1, h - 1);
250
251 g.setColor(MetalLookAndFeel.getControl());
252 g.drawLine(1, h - 1, 1, h - 1);
253 g.drawLine(w - 1, 1, w - 1, 1);
254 }
255 else
256 {
257 g.setColor(MetalLookAndFeel.getControlDisabled());
258 g.drawLine(0, h - 1, w - 1, h - 1);
259 g.drawLine(w - 1, 0, w - 1, h - 1);
260 g.drawLine(0, 0, 0, h - 1);
261 }
262 }
263
264 /**
265 * Paints the border for a button with an {@link #EAST} direction that
266 * belongs to a free standing scroll bar.
267 *
268 * @param g the graphics device.
269 * @param w the button width.
270 * @param h the button height.
271 */
272 private void paintEastBorderFreeStanding(Graphics g, int w, int h)
273 {
274 if (isEnabled())
275 {
276 g.setColor(MetalLookAndFeel.getControlDarkShadow());
277 g.drawLine(0, 0, w - 2, 0);
278 g.drawLine(w - 2, 0, w - 2, h - 2);
279 g.drawLine(0, h - 2, w - 2, h - 2);
280
281 g.setColor(MetalLookAndFeel.getControlHighlight());
282 g.drawLine(0, 1, w - 1, 1);
283 g.drawLine(w - 1, 1, w - 1, h - 1);
284 g.drawLine(0, h - 1, w - 1, h - 1);
285
286 g.setColor(MetalLookAndFeel.getControl());
287 g.drawLine(w - 2, 1, w - 2, 1);
288 }
289 else
290 {
291 g.setColor(MetalLookAndFeel.getControlDisabled());
292 g.drawLine(0, 0, w - 1, 0);
293 g.drawLine(w - 1, 0, w - 1, h - 1);
294 g.drawLine(0, h - 1, w - 1, h - 1);
295 }
296 }
297
298 /**
299 * Paints the border for a button with a {@link #WEST} direction that
300 * belongs to a free standing scroll bar.
301 *
302 * @param g the graphics device.
303 * @param w the button width.
304 * @param h the button height.
305 */
306 private void paintWestBorderFreeStanding(Graphics g, int w, int h)
307 {
308 if (isEnabled())
309 {
310 g.setColor(MetalLookAndFeel.getControlDarkShadow());
311 g.drawLine(0, 0, w - 1, 0);
312 g.drawLine(0, 0, 0, h - 2);
313 g.drawLine(0, h - 2, w - 1, h - 2);
314
315 g.setColor(MetalLookAndFeel.getControlHighlight());
316 g.drawLine(1, 1, w - 1, 1);
317 g.drawLine(1, 1, 1, h - 1);
318 g.drawLine(1, h - 1, w - 1, h - 1);
319
320 g.setColor(MetalLookAndFeel.getControl());
321 g.drawLine(1, h - 2, 1, h - 2);
322 }
323 else
324 {
325 g.setColor(MetalLookAndFeel.getControlDisabled());
326 g.drawLine(0, 0, w - 1, 0);
327 g.drawLine(0, 0, 0, h - 1);
328 g.drawLine(0, h - 1, w - 1, h - 1);
329 }
330 }
331
332 /**
333 * Paints the border for a button with a {@link #NORTH} direction that
334 * belongs to a scroll bar that is not free standing.
335 *
336 * @param g the graphics device.
337 * @param w the button width.
338 * @param h the button height.
339 */
340 private void paintNorthBorder(Graphics g, int w, int h)
341 {
342 if (isEnabled())
343 {
344 g.setColor(MetalLookAndFeel.getControlDarkShadow());
345 g.drawLine(0, 0, 0, h - 1);
346
347 g.setColor(MetalLookAndFeel.getControlHighlight());
348 g.drawLine(1, 0, 1, h - 1);
349 g.drawLine(1, 0, w - 1, 0);
350 }
351 else
352 {
353 g.setColor(MetalLookAndFeel.getControlDisabled());
354 g.drawLine(0, 0, 0, h - 1);
355 }
356 }
357
358 /**
359 * Paints the border for a button with a {@link #SOUTH} direction that
360 * belongs to a scroll bar that is not free standing.
361 *
362 * @param g the graphics device.
363 * @param w the button width.
364 * @param h the button height.
365 */
366 private void paintSouthBorder(Graphics g, int w, int h)
367 {
368 if (isEnabled())
369 {
370 g.setColor(MetalLookAndFeel.getControlDarkShadow());
371 g.drawLine(0, 0, 0, h - 1);
372 g.drawLine(0, h - 1, w - 1, h - 1);
373
374 g.setColor(MetalLookAndFeel.getControlHighlight());
375 g.drawLine(1, 0, 1, h - 1);
376 g.drawLine(1, 0, w - 1, 0);
377
378 g.setColor(MetalLookAndFeel.getControl());
379 g.drawLine(1, h - 1, 1, h - 1);
380 }
381 else
382 {
383 g.setColor(MetalLookAndFeel.getControlDisabled());
384 g.drawLine(0, 0, 0, h - 1);
385 }
386 }
387
388 /**
389 * Paints the border for a button with an {@link #EAST} direction that
390 * belongs to a scroll bar that is not free standing.
391 *
392 * @param g the graphics device.
393 * @param w the button width.
394 * @param h the button height.
395 */
396 private void paintEastBorder(Graphics g, int w, int h)
397 {
398 if (isEnabled())
399 {
400 g.setColor(MetalLookAndFeel.getControlDarkShadow());
401 g.drawLine(0, 0, w - 1, 0);
402 g.drawLine(w - 1, 2, w - 1, h - 1);
403 g.setColor(MetalLookAndFeel.getControlHighlight());
404 g.drawLine(0, 1, w - 2, 1);
405 g.drawLine(0, 1, 0, h - 1);
406 }
407 else
408 {
409 g.setColor(MetalLookAndFeel.getControlDisabled());
410 g.drawLine(0, 0, w - 1, 0);
411 }
412 }
413
414 /**
415 * Paints the border for a button with a {@link #WEST} direction that
416 * belongs to a scroll bar that is not free standing.
417 *
418 * @param g the graphics device.
419 * @param w the button width.
420 * @param h the button height.
421 */
422 private void paintWestBorder(Graphics g, int w, int h)
423 {
424 Rectangle bounds = SwingUtilities.getLocalBounds(this);
425 if (isEnabled())
426 {
427 g.setColor(MetalLookAndFeel.getControlDarkShadow());
428 g.drawLine(0, 0, bounds.width - 1, 0);
429 g.setColor(MetalLookAndFeel.getControlHighlight());
430 g.drawLine(0, 1, bounds.width - 1, 1);
431 g.drawLine(0, 1, 0, bounds.height - 1);
432 }
433 else
434 {
435 g.setColor(MetalLookAndFeel.getControlDisabled());
436 g.drawLine(0, 0, bounds.width - 1, 0);
437 }
438 }
439
440 /**
441 * Returns the preferred size for the button, which varies depending on
442 * the direction of the button and whether or not it is free standing.
443 *
444 * @return The preferred size.
445 */
446 public Dimension getPreferredSize()
447 {
448 int adj = 1;
449 if (!freeStanding)
450 adj = 2;
451
452 if (direction == EAST)
453 return new Dimension(buttonWidth - adj, buttonWidth);
454 else if (direction == WEST)
455 return new Dimension(buttonWidth - 2, buttonWidth);
456 else if (direction == SOUTH)
457 return new Dimension(buttonWidth, buttonWidth - adj);
458 else // assume NORTH
459 return new Dimension(buttonWidth, buttonWidth - 2);
460 }
461
462 /**
463 * Returns the minimum size for the button.
464 *
465 * @return The minimum size for the button.
466 */
467 public Dimension getMinimumSize()
468 {
469 return getPreferredSize();
470 }
471
472 /**
473 * Returns the maximum size for the button.
474 *
475 * @return <code>Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)</code>.
476 */
477 public Dimension getMaximumSize()
478 {
479 if (maximumSize == null)
480 maximumSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
481 return maximumSize;
482 }
483
484 }