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 }