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 }