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