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.Dimension;
042 import java.awt.Graphics;
043 import java.awt.Rectangle;
044
045 import javax.swing.SwingUtilities;
046 import javax.swing.plaf.basic.BasicArrowButton;
047
048 /**
049 * A button used by the {@link MetalScrollBarUI}. The button appearance
050 * varies according to the button direction, whether or not it is part of a
051 * "free standing" scroll bar, and the current state of the button.
052 */
053 public class MetalScrollButton extends BasicArrowButton
054 {
055
056 /**
057 * The maximum size for buttons.
058 * @see #getMaximumSize()
059 */
060 private static Dimension maximumSize;
061
062 /** The width of the button. */
063 private int buttonWidth;
064
065 /**
066 * A flag that indicates whether the button is part of a free standing
067 * scroll bar. This affects how the border is drawn.
068 */
069 private boolean freeStanding;
070
071 /**
072 * Creates a new button.
073 *
074 * @param direction the direction (this should be one of {@link #NORTH},
075 * {@link #SOUTH}, {@link #EAST} and {@link #WEST}, but
076 * this is not enforced).
077 * @param width the button width.
078 * @param freeStanding a flag indicating whether the scroll button is free
079 * standing or not.
080 */
081 public MetalScrollButton(int direction, int width, boolean freeStanding)
082 {
083 super(direction);
084 buttonWidth = width;
085 this.freeStanding = freeStanding;
086 setFocusable(false);
087 }
088
089 /**
090 * Returns the button width.
091 *
092 * @return The button width.
093 */
094 public int getButtonWidth()
095 {
096 return buttonWidth;
097 }
098
099 /**
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 */
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 */
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
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 }