1 /* 2 * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.swing.plaf.metal; 27 28 import javax.swing.*; 29 import javax.swing.border.*; 30 import javax.swing.plaf.*; 31 import javax.swing.plaf.basic.BasicBorders; 32 import javax.swing.text.JTextComponent; 33 34 import java.awt.Component; 35 import java.awt.Insets; 36 import java.awt.Color; 37 import java.awt.Dialog; 38 import java.awt.Frame; 39 import java.awt.Graphics; 40 import java.awt.Window; 41 42 import sun.swing.StringUIClientPropertyKey; 43 import sun.swing.SwingUtilities2; 44 45 46 /** 47 * Factory object that can vend Borders appropriate for the metal L & F. 48 * @author Steve Wilson 49 */ 50 51 public class MetalBorders { 52 53 /** 54 * Client property indicating the button shouldn't provide a rollover 55 * indicator. Only used with the Ocean theme. 56 */ 57 static Object NO_BUTTON_ROLLOVER = 58 new StringUIClientPropertyKey("NoButtonRollover"); 59 60 /** 61 * Constructs a {@code MetalBorders}. 62 */ MetalBorders()63 public MetalBorders() {} 64 65 /** 66 * The class represents the 3D border. 67 */ 68 @SuppressWarnings("serial") // Superclass is not serializable across versions 69 public static class Flush3DBorder extends AbstractBorder implements UIResource{ 70 /** 71 * Constructs a {@code Flush3DBorder}. 72 */ Flush3DBorder()73 public Flush3DBorder() {} 74 paintBorder(Component c, Graphics g, int x, int y, int w, int h)75 public void paintBorder(Component c, Graphics g, int x, int y, 76 int w, int h) { 77 if (c.isEnabled()) { 78 MetalUtils.drawFlush3DBorder(g, x, y, w, h); 79 } else { 80 MetalUtils.drawDisabledBorder(g, x, y, w, h); 81 } 82 } 83 getBorderInsets(Component c, Insets newInsets)84 public Insets getBorderInsets(Component c, Insets newInsets) { 85 newInsets.set(2, 2, 2, 2); 86 return newInsets; 87 } 88 } 89 90 /** 91 * The class represents the border of a {@code JButton}. 92 */ 93 @SuppressWarnings("serial") // Superclass is not serializable across versions 94 public static class ButtonBorder extends AbstractBorder implements UIResource { 95 96 /** 97 * The border insets. 98 */ 99 protected static Insets borderInsets = new Insets( 3, 3, 3, 3 ); 100 101 /** 102 * Constructs a {@code ButtonBorder}. 103 */ ButtonBorder()104 public ButtonBorder() {} 105 paintBorder(Component c, Graphics g, int x, int y, int w, int h)106 public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { 107 if (!(c instanceof AbstractButton)) { 108 return; 109 } 110 if (MetalLookAndFeel.usingOcean()) { 111 paintOceanBorder(c, g, x, y, w, h); 112 return; 113 } 114 AbstractButton button = (AbstractButton)c; 115 ButtonModel model = button.getModel(); 116 117 if ( model.isEnabled() ) { 118 boolean isPressed = model.isPressed() && model.isArmed(); 119 boolean isDefault = (button instanceof JButton && ((JButton)button).isDefaultButton()); 120 121 if (isPressed && isDefault) { 122 MetalUtils.drawDefaultButtonPressedBorder(g, x, y, w, h); 123 } else if (isPressed) { 124 MetalUtils.drawPressed3DBorder( g, x, y, w, h ); 125 } else if (isDefault) { 126 MetalUtils.drawDefaultButtonBorder( g, x, y, w, h, false); 127 } else { 128 MetalUtils.drawButtonBorder( g, x, y, w, h, false); 129 } 130 } else { // disabled state 131 MetalUtils.drawDisabledBorder( g, x, y, w-1, h-1 ); 132 } 133 } 134 paintOceanBorder(Component c, Graphics g, int x, int y, int w, int h)135 private void paintOceanBorder(Component c, Graphics g, int x, int y, 136 int w, int h) { 137 AbstractButton button = (AbstractButton)c; 138 ButtonModel model = ((AbstractButton)c).getModel(); 139 140 g.translate(x, y); 141 if (MetalUtils.isToolBarButton(button)) { 142 if (model.isEnabled()) { 143 if (model.isPressed()) { 144 g.setColor(MetalLookAndFeel.getWhite()); 145 g.fillRect(1, h - 1, w - 1, 1); 146 g.fillRect(w - 1, 1, 1, h - 1); 147 g.setColor(MetalLookAndFeel.getControlDarkShadow()); 148 g.drawRect(0, 0, w - 2, h - 2); 149 g.fillRect(1, 1, w - 3, 1); 150 } 151 else if (model.isSelected() || model.isRollover()) { 152 g.setColor(MetalLookAndFeel.getWhite()); 153 g.fillRect(1, h - 1, w - 1, 1); 154 g.fillRect(w - 1, 1, 1, h - 1); 155 g.setColor(MetalLookAndFeel.getControlDarkShadow()); 156 g.drawRect(0, 0, w - 2, h - 2); 157 } 158 else { 159 g.setColor(MetalLookAndFeel.getWhite()); 160 g.drawRect(1, 1, w - 2, h - 2); 161 g.setColor(UIManager.getColor( 162 "Button.toolBarBorderBackground")); 163 g.drawRect(0, 0, w - 2, h - 2); 164 } 165 } 166 else { 167 g.setColor(UIManager.getColor( 168 "Button.disabledToolBarBorderBackground")); 169 g.drawRect(0, 0, w - 2, h - 2); 170 } 171 } 172 else if (model.isEnabled()) { 173 boolean pressed = model.isPressed(); 174 boolean armed = model.isArmed(); 175 176 if ((c instanceof JButton) && ((JButton)c).isDefaultButton()) { 177 g.setColor(MetalLookAndFeel.getControlDarkShadow()); 178 g.drawRect(0, 0, w - 1, h - 1); 179 g.drawRect(1, 1, w - 3, h - 3); 180 } 181 else if (pressed) { 182 g.setColor(MetalLookAndFeel.getControlDarkShadow()); 183 g.fillRect(0, 0, w, 2); 184 g.fillRect(0, 2, 2, h - 2); 185 g.fillRect(w - 1, 1, 1, h - 1); 186 g.fillRect(1, h - 1, w - 2, 1); 187 } 188 else if (model.isRollover() && button.getClientProperty( 189 NO_BUTTON_ROLLOVER) == null) { 190 g.setColor(MetalLookAndFeel.getPrimaryControl()); 191 g.drawRect(0, 0, w - 1, h - 1); 192 g.drawRect(2, 2, w - 5, h - 5); 193 g.setColor(MetalLookAndFeel.getControlDarkShadow()); 194 g.drawRect(1, 1, w - 3, h - 3); 195 } 196 else { 197 g.setColor(MetalLookAndFeel.getControlDarkShadow()); 198 g.drawRect(0, 0, w - 1, h - 1); 199 } 200 } 201 else { 202 g.setColor(MetalLookAndFeel.getInactiveControlTextColor()); 203 g.drawRect(0, 0, w - 1, h - 1); 204 if ((c instanceof JButton) && ((JButton)c).isDefaultButton()) { 205 g.drawRect(1, 1, w - 3, h - 3); 206 } 207 } 208 } 209 getBorderInsets(Component c, Insets newInsets)210 public Insets getBorderInsets(Component c, Insets newInsets) { 211 newInsets.set(3, 3, 3, 3); 212 return newInsets; 213 } 214 } 215 216 /** 217 * The class represents the border of a {@code JInternalFrame}. 218 */ 219 @SuppressWarnings("serial") // Superclass is not serializable across versions 220 public static class InternalFrameBorder extends AbstractBorder implements UIResource { 221 private static final int corner = 14; 222 223 /** 224 * Constructs a {@code InternalFrameBorder}. 225 */ InternalFrameBorder()226 public InternalFrameBorder() {} 227 paintBorder(Component c, Graphics g, int x, int y, int w, int h)228 public void paintBorder(Component c, Graphics g, int x, int y, 229 int w, int h) { 230 231 Color background; 232 Color highlight; 233 Color shadow; 234 235 if (c instanceof JInternalFrame && ((JInternalFrame)c).isSelected()) { 236 background = MetalLookAndFeel.getPrimaryControlDarkShadow(); 237 highlight = MetalLookAndFeel.getPrimaryControlShadow(); 238 shadow = MetalLookAndFeel.getPrimaryControlInfo(); 239 } else { 240 background = MetalLookAndFeel.getControlDarkShadow(); 241 highlight = MetalLookAndFeel.getControlShadow(); 242 shadow = MetalLookAndFeel.getControlInfo(); 243 } 244 245 g.setColor(background); 246 // Draw outermost lines 247 g.drawLine( 1, 0, w-2, 0); 248 g.drawLine( 0, 1, 0, h-2); 249 g.drawLine( w-1, 1, w-1, h-2); 250 g.drawLine( 1, h-1, w-2, h-1); 251 252 // Draw the bulk of the border 253 for (int i = 1; i < 5; i++) { 254 g.drawRect(x+i,y+i,w-(i*2)-1, h-(i*2)-1); 255 } 256 257 if (c instanceof JInternalFrame && 258 ((JInternalFrame)c).isResizable()) { 259 g.setColor(highlight); 260 // Draw the Long highlight lines 261 g.drawLine( corner+1, 3, w-corner, 3); 262 g.drawLine( 3, corner+1, 3, h-corner); 263 g.drawLine( w-2, corner+1, w-2, h-corner); 264 g.drawLine( corner+1, h-2, w-corner, h-2); 265 266 g.setColor(shadow); 267 // Draw the Long shadow lines 268 g.drawLine( corner, 2, w-corner-1, 2); 269 g.drawLine( 2, corner, 2, h-corner-1); 270 g.drawLine( w-3, corner, w-3, h-corner-1); 271 g.drawLine( corner, h-3, w-corner-1, h-3); 272 } 273 274 } 275 getBorderInsets(Component c, Insets newInsets)276 public Insets getBorderInsets(Component c, Insets newInsets) { 277 newInsets.set(5, 5, 5, 5); 278 return newInsets; 279 } 280 } 281 282 /** 283 * Border for a Frame. 284 * @since 1.4 285 */ 286 @SuppressWarnings("serial") // Superclass is not serializable across versions 287 static class FrameBorder extends AbstractBorder implements UIResource { 288 private static final int corner = 14; 289 paintBorder(Component c, Graphics g, int x, int y, int w, int h)290 public void paintBorder(Component c, Graphics g, int x, int y, 291 int w, int h) { 292 293 Color background; 294 Color highlight; 295 Color shadow; 296 297 Window window = SwingUtilities.getWindowAncestor(c); 298 if (window != null && window.isActive()) { 299 background = MetalLookAndFeel.getPrimaryControlDarkShadow(); 300 highlight = MetalLookAndFeel.getPrimaryControlShadow(); 301 shadow = MetalLookAndFeel.getPrimaryControlInfo(); 302 } else { 303 background = MetalLookAndFeel.getControlDarkShadow(); 304 highlight = MetalLookAndFeel.getControlShadow(); 305 shadow = MetalLookAndFeel.getControlInfo(); 306 } 307 308 g.setColor(background); 309 // Draw outermost lines 310 g.drawLine( x+1, y+0, x+w-2, y+0); 311 g.drawLine( x+0, y+1, x+0, y +h-2); 312 g.drawLine( x+w-1, y+1, x+w-1, y+h-2); 313 g.drawLine( x+1, y+h-1, x+w-2, y+h-1); 314 315 // Draw the bulk of the border 316 for (int i = 1; i < 5; i++) { 317 g.drawRect(x+i,y+i,w-(i*2)-1, h-(i*2)-1); 318 } 319 320 if ((window instanceof Frame) && ((Frame) window).isResizable()) { 321 g.setColor(highlight); 322 // Draw the Long highlight lines 323 g.drawLine( corner+1, 3, w-corner, 3); 324 g.drawLine( 3, corner+1, 3, h-corner); 325 g.drawLine( w-2, corner+1, w-2, h-corner); 326 g.drawLine( corner+1, h-2, w-corner, h-2); 327 328 g.setColor(shadow); 329 // Draw the Long shadow lines 330 g.drawLine( corner, 2, w-corner-1, 2); 331 g.drawLine( 2, corner, 2, h-corner-1); 332 g.drawLine( w-3, corner, w-3, h-corner-1); 333 g.drawLine( corner, h-3, w-corner-1, h-3); 334 } 335 336 } 337 getBorderInsets(Component c, Insets newInsets)338 public Insets getBorderInsets(Component c, Insets newInsets) 339 { 340 newInsets.set(5, 5, 5, 5); 341 return newInsets; 342 } 343 } 344 345 /** 346 * Border for a Frame. 347 * @since 1.4 348 */ 349 @SuppressWarnings("serial") // Superclass is not serializable across versions 350 static class DialogBorder extends AbstractBorder implements UIResource 351 { 352 private static final int corner = 14; 353 getActiveBackground()354 protected Color getActiveBackground() 355 { 356 return MetalLookAndFeel.getPrimaryControlDarkShadow(); 357 } 358 getActiveHighlight()359 protected Color getActiveHighlight() 360 { 361 return MetalLookAndFeel.getPrimaryControlShadow(); 362 } 363 getActiveShadow()364 protected Color getActiveShadow() 365 { 366 return MetalLookAndFeel.getPrimaryControlInfo(); 367 } 368 getInactiveBackground()369 protected Color getInactiveBackground() 370 { 371 return MetalLookAndFeel.getControlDarkShadow(); 372 } 373 getInactiveHighlight()374 protected Color getInactiveHighlight() 375 { 376 return MetalLookAndFeel.getControlShadow(); 377 } 378 getInactiveShadow()379 protected Color getInactiveShadow() 380 { 381 return MetalLookAndFeel.getControlInfo(); 382 } 383 paintBorder(Component c, Graphics g, int x, int y, int w, int h)384 public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) 385 { 386 Color background; 387 Color highlight; 388 Color shadow; 389 390 Window window = SwingUtilities.getWindowAncestor(c); 391 if (window != null && window.isActive()) { 392 background = getActiveBackground(); 393 highlight = getActiveHighlight(); 394 shadow = getActiveShadow(); 395 } else { 396 background = getInactiveBackground(); 397 highlight = getInactiveHighlight(); 398 shadow = getInactiveShadow(); 399 } 400 401 g.setColor(background); 402 // Draw outermost lines 403 g.drawLine( x + 1, y + 0, x + w-2, y + 0); 404 g.drawLine( x + 0, y + 1, x + 0, y + h - 2); 405 g.drawLine( x + w - 1, y + 1, x + w - 1, y + h - 2); 406 g.drawLine( x + 1, y + h - 1, x + w - 2, y + h - 1); 407 408 // Draw the bulk of the border 409 for (int i = 1; i < 5; i++) { 410 g.drawRect(x+i,y+i,w-(i*2)-1, h-(i*2)-1); 411 } 412 413 414 if ((window instanceof Dialog) && ((Dialog) window).isResizable()) { 415 g.setColor(highlight); 416 // Draw the Long highlight lines 417 g.drawLine( corner+1, 3, w-corner, 3); 418 g.drawLine( 3, corner+1, 3, h-corner); 419 g.drawLine( w-2, corner+1, w-2, h-corner); 420 g.drawLine( corner+1, h-2, w-corner, h-2); 421 422 g.setColor(shadow); 423 // Draw the Long shadow lines 424 g.drawLine( corner, 2, w-corner-1, 2); 425 g.drawLine( 2, corner, 2, h-corner-1); 426 g.drawLine( w-3, corner, w-3, h-corner-1); 427 g.drawLine( corner, h-3, w-corner-1, h-3); 428 } 429 430 } 431 getBorderInsets(Component c, Insets newInsets)432 public Insets getBorderInsets(Component c, Insets newInsets) 433 { 434 newInsets.set(5, 5, 5, 5); 435 return newInsets; 436 } 437 } 438 439 /** 440 * Border for an Error Dialog. 441 * @since 1.4 442 */ 443 @SuppressWarnings("serial") // Superclass is not serializable across versions 444 static class ErrorDialogBorder extends DialogBorder implements UIResource 445 { getActiveBackground()446 protected Color getActiveBackground() { 447 return UIManager.getColor("OptionPane.errorDialog.border.background"); 448 } 449 } 450 451 452 /** 453 * Border for a QuestionDialog. Also used for a JFileChooser and a 454 * JColorChooser.. 455 * @since 1.4 456 */ 457 @SuppressWarnings("serial") // Superclass is not serializable across versions 458 static class QuestionDialogBorder extends DialogBorder implements UIResource 459 { getActiveBackground()460 protected Color getActiveBackground() { 461 return UIManager.getColor("OptionPane.questionDialog.border.background"); 462 } 463 } 464 465 466 /** 467 * Border for a Warning Dialog. 468 * @since 1.4 469 */ 470 @SuppressWarnings("serial") // Superclass is not serializable across versions 471 static class WarningDialogBorder extends DialogBorder implements UIResource 472 { getActiveBackground()473 protected Color getActiveBackground() { 474 return UIManager.getColor("OptionPane.warningDialog.border.background"); 475 } 476 } 477 478 479 /** 480 * Border for a Palette. 481 * @since 1.3 482 */ 483 @SuppressWarnings("serial") // Superclass is not serializable across versions 484 public static class PaletteBorder extends AbstractBorder implements UIResource { 485 int titleHeight = 0; 486 487 /** 488 * Constructs a {@code PaletteBorder}. 489 */ PaletteBorder()490 public PaletteBorder() {} 491 paintBorder( Component c, Graphics g, int x, int y, int w, int h )492 public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) { 493 494 g.translate(x,y); 495 g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); 496 g.drawLine(0, 1, 0, h-2); 497 g.drawLine(1, h-1, w-2, h-1); 498 g.drawLine(w-1, 1, w-1, h-2); 499 g.drawLine( 1, 0, w-2, 0); 500 g.drawRect(1,1, w-3, h-3); 501 g.translate(-x,-y); 502 503 } 504 getBorderInsets(Component c, Insets newInsets)505 public Insets getBorderInsets(Component c, Insets newInsets) { 506 newInsets.set(1, 1, 1, 1); 507 return newInsets; 508 } 509 } 510 511 /** 512 * The class represents the border of an option dialog. 513 */ 514 @SuppressWarnings("serial") // Superclass is not serializable across versions 515 public static class OptionDialogBorder extends AbstractBorder implements UIResource { 516 int titleHeight = 0; 517 518 /** 519 * Constructs a {@code OptionDialogBorder}. 520 */ OptionDialogBorder()521 public OptionDialogBorder() {} 522 paintBorder( Component c, Graphics g, int x, int y, int w, int h )523 public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) { 524 525 g.translate(x,y); 526 527 int messageType = JOptionPane.PLAIN_MESSAGE; 528 if (c instanceof JInternalFrame) { 529 Object obj = ((JInternalFrame) c).getClientProperty( 530 "JInternalFrame.messageType"); 531 if (obj instanceof Integer) { 532 messageType = (Integer) obj; 533 } 534 } 535 536 Color borderColor; 537 538 switch (messageType) { 539 case(JOptionPane.ERROR_MESSAGE): 540 borderColor = UIManager.getColor( 541 "OptionPane.errorDialog.border.background"); 542 break; 543 case(JOptionPane.QUESTION_MESSAGE): 544 borderColor = UIManager.getColor( 545 "OptionPane.questionDialog.border.background"); 546 break; 547 case(JOptionPane.WARNING_MESSAGE): 548 borderColor = UIManager.getColor( 549 "OptionPane.warningDialog.border.background"); 550 break; 551 case(JOptionPane.INFORMATION_MESSAGE): 552 case(JOptionPane.PLAIN_MESSAGE): 553 default: 554 borderColor = MetalLookAndFeel.getPrimaryControlDarkShadow(); 555 break; 556 } 557 558 g.setColor(borderColor); 559 560 // Draw outermost lines 561 g.drawLine( 1, 0, w-2, 0); 562 g.drawLine( 0, 1, 0, h-2); 563 g.drawLine( w-1, 1, w-1, h-2); 564 g.drawLine( 1, h-1, w-2, h-1); 565 566 // Draw the bulk of the border 567 for (int i = 1; i < 3; i++) { 568 g.drawRect(i, i, w-(i*2)-1, h-(i*2)-1); 569 } 570 571 g.translate(-x,-y); 572 573 } 574 getBorderInsets(Component c, Insets newInsets)575 public Insets getBorderInsets(Component c, Insets newInsets) { 576 newInsets.set(3, 3, 3, 3); 577 return newInsets; 578 } 579 } 580 581 /** 582 * The class represents the border of a {@code JMenuBar}. 583 */ 584 @SuppressWarnings("serial") // Superclass is not serializable across versions 585 public static class MenuBarBorder extends AbstractBorder implements UIResource { 586 587 /** 588 * The border insets. 589 */ 590 protected static Insets borderInsets = new Insets( 1, 0, 1, 0 ); 591 592 /** 593 * Constructs a {@code MenuBarBorder}. 594 */ MenuBarBorder()595 public MenuBarBorder() {} 596 paintBorder( Component c, Graphics g, int x, int y, int w, int h )597 public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) { 598 g.translate(x, y); 599 600 if (MetalLookAndFeel.usingOcean()) { 601 // Only paint a border if we're not next to a horizontal toolbar 602 if (c instanceof JMenuBar 603 && !MetalToolBarUI.doesMenuBarBorderToolBar((JMenuBar)c)) { 604 g.setColor(MetalLookAndFeel.getControl()); 605 SwingUtilities2.drawHLine(g, 0, w - 1, h - 2); 606 g.setColor(UIManager.getColor("MenuBar.borderColor")); 607 SwingUtilities2.drawHLine(g, 0, w - 1, h - 1); 608 } 609 } else { 610 g.setColor(MetalLookAndFeel.getControlShadow()); 611 SwingUtilities2.drawHLine(g, 0, w - 1, h - 1); 612 } 613 g.translate(-x, -y); 614 } 615 getBorderInsets(Component c, Insets newInsets)616 public Insets getBorderInsets(Component c, Insets newInsets) { 617 if (MetalLookAndFeel.usingOcean()) { 618 newInsets.set(0, 0, 2, 0); 619 } 620 else { 621 newInsets.set(1, 0, 1, 0); 622 } 623 return newInsets; 624 } 625 } 626 627 /** 628 * The class represents the border of a {@code JMenuItem}. 629 */ 630 @SuppressWarnings("serial") // Superclass is not serializable across versions 631 public static class MenuItemBorder extends AbstractBorder implements UIResource { 632 633 /** 634 * The border insets. 635 */ 636 protected static Insets borderInsets = new Insets( 2, 2, 2, 2 ); 637 638 /** 639 * Constructs a {@code MenuItemBorder}. 640 */ MenuItemBorder()641 public MenuItemBorder() {} 642 paintBorder( Component c, Graphics g, int x, int y, int w, int h )643 public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) { 644 if (!(c instanceof JMenuItem)) { 645 return; 646 } 647 JMenuItem b = (JMenuItem) c; 648 ButtonModel model = b.getModel(); 649 650 g.translate( x, y ); 651 652 if ( c.getParent() instanceof JMenuBar ) { 653 if ( model.isArmed() || model.isSelected() ) { 654 g.setColor( MetalLookAndFeel.getControlDarkShadow() ); 655 g.drawLine( 0, 0, w - 2, 0 ); 656 g.drawLine( 0, 0, 0, h - 1 ); 657 g.drawLine( w - 2, 2, w - 2, h - 1 ); 658 659 g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() ); 660 g.drawLine( w - 1, 1, w - 1, h - 1 ); 661 662 g.setColor( MetalLookAndFeel.getMenuBackground() ); 663 g.drawLine( w - 1, 0, w - 1, 0 ); 664 } 665 } else { 666 if ( model.isArmed() || ( c instanceof JMenu && model.isSelected() ) ) { 667 g.setColor( MetalLookAndFeel.getPrimaryControlDarkShadow() ); 668 g.drawLine( 0, 0, w - 1, 0 ); 669 670 g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() ); 671 g.drawLine( 0, h - 1, w - 1, h - 1 ); 672 } else { 673 g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() ); 674 g.drawLine( 0, 0, 0, h - 1 ); 675 } 676 } 677 678 g.translate( -x, -y ); 679 } 680 getBorderInsets(Component c, Insets newInsets)681 public Insets getBorderInsets(Component c, Insets newInsets) { 682 newInsets.set(2, 2, 2, 2); 683 return newInsets; 684 } 685 } 686 687 /** 688 * The class represents the border of a {@code JPopupMenu}. 689 */ 690 @SuppressWarnings("serial") // Superclass is not serializable across versions 691 public static class PopupMenuBorder extends AbstractBorder implements UIResource { 692 693 /** 694 * The border insets. 695 */ 696 protected static Insets borderInsets = new Insets( 3, 1, 2, 1 ); 697 698 /** 699 * Constructs a {@code PopupMenuBorder}. 700 */ PopupMenuBorder()701 public PopupMenuBorder() {} 702 paintBorder( Component c, Graphics g, int x, int y, int w, int h )703 public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) { 704 g.translate( x, y ); 705 706 g.setColor( MetalLookAndFeel.getPrimaryControlDarkShadow() ); 707 g.drawRect( 0, 0, w - 1, h - 1 ); 708 709 g.setColor( MetalLookAndFeel.getPrimaryControlHighlight() ); 710 g.drawLine( 1, 1, w - 2, 1 ); 711 g.drawLine( 1, 2, 1, 2 ); 712 g.drawLine( 1, h - 2, 1, h - 2 ); 713 714 g.translate( -x, -y ); 715 716 } 717 getBorderInsets(Component c, Insets newInsets)718 public Insets getBorderInsets(Component c, Insets newInsets) { 719 newInsets.set(3, 1, 2, 1); 720 return newInsets; 721 } 722 } 723 724 /** 725 * The class represents the border of a rollover {@code Button}. 726 */ 727 @SuppressWarnings("serial") // Superclass is not serializable across versions 728 public static class RolloverButtonBorder extends ButtonBorder { 729 730 /** 731 * Constructs a {@code RolloverButtonBorder}. 732 */ RolloverButtonBorder()733 public RolloverButtonBorder() {} 734 paintBorder( Component c, Graphics g, int x, int y, int w, int h )735 public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) { 736 AbstractButton b = (AbstractButton) c; 737 ButtonModel model = b.getModel(); 738 739 if ( model.isRollover() && !( model.isPressed() && !model.isArmed() ) ) { 740 super.paintBorder( c, g, x, y, w, h ); 741 } 742 } 743 744 } 745 746 /** 747 * A border which is like a Margin border but it will only honor the margin 748 * if the margin has been explicitly set by the developer. 749 * 750 * Note: This is identical to the package private class 751 * BasicBorders.RolloverMarginBorder and should probably be consolidated. 752 */ 753 @SuppressWarnings("serial") // Superclass is not serializable across versions 754 static class RolloverMarginBorder extends EmptyBorder { 755 RolloverMarginBorder()756 public RolloverMarginBorder() { 757 super(3,3,3,3); // hardcoded margin for JLF requirements. 758 } 759 getBorderInsets(Component c, Insets insets)760 public Insets getBorderInsets(Component c, Insets insets) { 761 Insets margin = null; 762 763 if (c instanceof AbstractButton) { 764 margin = ((AbstractButton)c).getMargin(); 765 } 766 if (margin == null || margin instanceof UIResource) { 767 // default margin so replace 768 insets.left = left; 769 insets.top = top; 770 insets.right = right; 771 insets.bottom = bottom; 772 } else { 773 // Margin which has been explicitly set by the user. 774 insets.left = margin.left; 775 insets.top = margin.top; 776 insets.right = margin.right; 777 insets.bottom = margin.bottom; 778 } 779 return insets; 780 } 781 } 782 783 /** 784 * The class represents the border of a {@code JToolBar}. 785 */ 786 @SuppressWarnings("serial") // Superclass is not serializable across versions 787 public static class ToolBarBorder extends AbstractBorder implements UIResource, SwingConstants 788 { 789 /** 790 * The instance of {@code MetalBumps}. 791 */ 792 private MetalBumps bumps = new MetalBumps( 10, 10, 793 MetalLookAndFeel.getControlHighlight(), 794 MetalLookAndFeel.getControlDarkShadow(), 795 UIManager.getColor("ToolBar.background")); 796 797 /** 798 * Constructs a {@code ToolBarBorder}. 799 */ ToolBarBorder()800 public ToolBarBorder() {} 801 paintBorder( Component c, Graphics g, int x, int y, int w, int h )802 public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) 803 { 804 if (!(c instanceof JToolBar)) { 805 return; 806 } 807 g.translate( x, y ); 808 809 if ( ((JToolBar) c).isFloatable() ) 810 { 811 if ( ((JToolBar) c).getOrientation() == HORIZONTAL ) 812 { 813 int shift = MetalLookAndFeel.usingOcean() ? -1 : 0; 814 bumps.setBumpArea( 10, h - 4 ); 815 if( MetalUtils.isLeftToRight(c) ) { 816 bumps.paintIcon( c, g, 2, 2 + shift ); 817 } else { 818 bumps.paintIcon( c, g, w-12, 819 2 + shift ); 820 } 821 } 822 else // vertical 823 { 824 bumps.setBumpArea( w - 4, 10 ); 825 bumps.paintIcon( c, g, 2, 2 ); 826 } 827 828 } 829 830 if (((JToolBar) c).getOrientation() == HORIZONTAL && 831 MetalLookAndFeel.usingOcean()) { 832 g.setColor(MetalLookAndFeel.getControl()); 833 g.drawLine(0, h - 2, w, h - 2); 834 g.setColor(UIManager.getColor("ToolBar.borderColor")); 835 g.drawLine(0, h - 1, w, h - 1); 836 } 837 838 g.translate( -x, -y ); 839 } 840 getBorderInsets(Component c, Insets newInsets)841 public Insets getBorderInsets(Component c, Insets newInsets) { 842 if (MetalLookAndFeel.usingOcean()) { 843 newInsets.set(1, 2, 3, 2); 844 } 845 else { 846 newInsets.top = newInsets.left = newInsets.bottom = newInsets.right = 2; 847 } 848 849 if (!(c instanceof JToolBar)) { 850 return newInsets; 851 } 852 if ( ((JToolBar) c).isFloatable() ) { 853 if ( ((JToolBar) c).getOrientation() == HORIZONTAL ) { 854 if (c.getComponentOrientation().isLeftToRight()) { 855 newInsets.left = 16; 856 } else { 857 newInsets.right = 16; 858 } 859 } else {// vertical 860 newInsets.top = 16; 861 } 862 } 863 864 Insets margin = ((JToolBar) c).getMargin(); 865 866 if ( margin != null ) { 867 newInsets.left += margin.left; 868 newInsets.top += margin.top; 869 newInsets.right += margin.right; 870 newInsets.bottom += margin.bottom; 871 } 872 873 return newInsets; 874 } 875 } 876 877 private static Border buttonBorder; 878 879 /** 880 * Returns a border instance for a {@code JButton}. 881 * 882 * @return a border instance for a {@code JButton} 883 * @since 1.3 884 */ getButtonBorder()885 public static Border getButtonBorder() { 886 if (buttonBorder == null) { 887 buttonBorder = new BorderUIResource.CompoundBorderUIResource( 888 new MetalBorders.ButtonBorder(), 889 new BasicBorders.MarginBorder()); 890 } 891 return buttonBorder; 892 } 893 894 private static Border textBorder; 895 896 /** 897 * Returns a border instance for a text component. 898 * 899 * @return a border instance for a text component 900 * @since 1.3 901 */ getTextBorder()902 public static Border getTextBorder() { 903 if (textBorder == null) { 904 textBorder = new BorderUIResource.CompoundBorderUIResource( 905 new MetalBorders.Flush3DBorder(), 906 new BasicBorders.MarginBorder()); 907 } 908 return textBorder; 909 } 910 911 private static Border textFieldBorder; 912 913 /** 914 * Returns a border instance for a {@code JTextField}. 915 * 916 * @return a border instance for a {@code JTextField} 917 * @since 1.3 918 */ getTextFieldBorder()919 public static Border getTextFieldBorder() { 920 if (textFieldBorder == null) { 921 textFieldBorder = new BorderUIResource.CompoundBorderUIResource( 922 new MetalBorders.TextFieldBorder(), 923 new BasicBorders.MarginBorder()); 924 } 925 return textFieldBorder; 926 } 927 928 /** 929 * The class represents the border of a {@code JTestField}. 930 */ 931 @SuppressWarnings("serial") // Superclass is not serializable across versions 932 public static class TextFieldBorder extends Flush3DBorder { 933 934 /** 935 * Constructs a {@code TextFieldBorder}. 936 */ TextFieldBorder()937 public TextFieldBorder() {} 938 paintBorder(Component c, Graphics g, int x, int y, int w, int h)939 public void paintBorder(Component c, Graphics g, int x, int y, 940 int w, int h) { 941 942 if (!(c instanceof JTextComponent)) { 943 // special case for non-text components (bug ID 4144840) 944 if (c.isEnabled()) { 945 MetalUtils.drawFlush3DBorder(g, x, y, w, h); 946 } else { 947 MetalUtils.drawDisabledBorder(g, x, y, w, h); 948 } 949 return; 950 } 951 952 if (c.isEnabled() && ((JTextComponent)c).isEditable()) { 953 MetalUtils.drawFlush3DBorder(g, x, y, w, h); 954 } else { 955 MetalUtils.drawDisabledBorder(g, x, y, w, h); 956 } 957 958 } 959 } 960 961 /** 962 * The class represents the border of a {@code JScrollPane}. 963 */ 964 @SuppressWarnings("serial") // Superclass is not serializable across versions 965 public static class ScrollPaneBorder extends AbstractBorder implements UIResource { 966 /** 967 * Constructs a {@code ScrollPaneBorder}. 968 */ ScrollPaneBorder()969 public ScrollPaneBorder() {} 970 paintBorder(Component c, Graphics g, int x, int y, int w, int h)971 public void paintBorder(Component c, Graphics g, int x, int y, 972 int w, int h) { 973 974 if (!(c instanceof JScrollPane)) { 975 return; 976 } 977 JScrollPane scroll = (JScrollPane)c; 978 JComponent colHeader = scroll.getColumnHeader(); 979 int colHeaderHeight = 0; 980 if (colHeader != null) 981 colHeaderHeight = colHeader.getHeight(); 982 983 JComponent rowHeader = scroll.getRowHeader(); 984 int rowHeaderWidth = 0; 985 if (rowHeader != null) 986 rowHeaderWidth = rowHeader.getWidth(); 987 988 989 g.translate( x, y); 990 991 g.setColor( MetalLookAndFeel.getControlDarkShadow() ); 992 g.drawRect( 0, 0, w-2, h-2 ); 993 g.setColor( MetalLookAndFeel.getControlHighlight() ); 994 995 g.drawLine( w-1, 1, w-1, h-1); 996 g.drawLine( 1, h-1, w-1, h-1); 997 998 g.setColor( MetalLookAndFeel.getControl() ); 999 g.drawLine( w-2, 2+colHeaderHeight, w-2, 2+colHeaderHeight ); 1000 g.drawLine( 1+rowHeaderWidth, h-2, 1+rowHeaderWidth, h-2 ); 1001 1002 g.translate( -x, -y); 1003 1004 } 1005 getBorderInsets(Component c, Insets insets)1006 public Insets getBorderInsets(Component c, Insets insets) { 1007 insets.set(1, 1, 2, 2); 1008 return insets; 1009 } 1010 } 1011 1012 private static Border toggleButtonBorder; 1013 1014 /** 1015 * Returns a border instance for a {@code JToggleButton}. 1016 * 1017 * @return a border instance for a {@code JToggleButton} 1018 * @since 1.3 1019 */ getToggleButtonBorder()1020 public static Border getToggleButtonBorder() { 1021 if (toggleButtonBorder == null) { 1022 toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource( 1023 new MetalBorders.ToggleButtonBorder(), 1024 new BasicBorders.MarginBorder()); 1025 } 1026 return toggleButtonBorder; 1027 } 1028 1029 /** 1030 * @since 1.3 1031 */ 1032 @SuppressWarnings("serial") // Superclass is not serializable across versions 1033 public static class ToggleButtonBorder extends ButtonBorder { 1034 /** 1035 * Constructs a {@code ToggleButtonBorder}. 1036 */ ToggleButtonBorder()1037 public ToggleButtonBorder() {} 1038 paintBorder(Component c, Graphics g, int x, int y, int w, int h)1039 public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { 1040 AbstractButton button = (AbstractButton)c; 1041 ButtonModel model = button.getModel(); 1042 if (MetalLookAndFeel.usingOcean()) { 1043 if(model.isArmed() || !button.isEnabled()) { 1044 super.paintBorder(c, g, x, y, w, h); 1045 } 1046 else { 1047 g.setColor(MetalLookAndFeel.getControlDarkShadow()); 1048 g.drawRect(0, 0, w - 1, h - 1); 1049 } 1050 return; 1051 } 1052 if (! c.isEnabled() ) { 1053 MetalUtils.drawDisabledBorder( g, x, y, w-1, h-1 ); 1054 } else { 1055 if ( model.isPressed() && model.isArmed() ) { 1056 MetalUtils.drawPressed3DBorder( g, x, y, w, h ); 1057 } else if ( model.isSelected() ) { 1058 MetalUtils.drawDark3DBorder( g, x, y, w, h ); 1059 } else { 1060 MetalUtils.drawFlush3DBorder( g, x, y, w, h ); 1061 } 1062 } 1063 } 1064 } 1065 1066 /** 1067 * Border for a Table Header 1068 * @since 1.3 1069 */ 1070 @SuppressWarnings("serial") // Superclass is not serializable across versions 1071 public static class TableHeaderBorder extends javax.swing.border.AbstractBorder { 1072 1073 /** 1074 * Constructs a {@code TableHeaderBorder}. 1075 */ TableHeaderBorder()1076 public TableHeaderBorder() {} 1077 1078 /** 1079 * The border insets. 1080 */ 1081 protected Insets editorBorderInsets = new Insets( 2, 2, 2, 0 ); 1082 paintBorder(Component c, Graphics g, int x, int y, int w, int h)1083 public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { 1084 g.translate( x, y ); 1085 1086 g.setColor( MetalLookAndFeel.getControlDarkShadow() ); 1087 g.drawLine( w-1, 0, w-1, h-1 ); 1088 g.drawLine( 1, h-1, w-1, h-1 ); 1089 g.setColor( MetalLookAndFeel.getControlHighlight() ); 1090 g.drawLine( 0, 0, w-2, 0 ); 1091 g.drawLine( 0, 0, 0, h-2 ); 1092 1093 g.translate( -x, -y ); 1094 } 1095 getBorderInsets(Component c, Insets insets)1096 public Insets getBorderInsets(Component c, Insets insets) { 1097 insets.set(2, 2, 2, 0); 1098 return insets; 1099 } 1100 } 1101 1102 /** 1103 * Returns a border instance for a Desktop Icon. 1104 * 1105 * @return a border instance for a Desktop Icon 1106 * @since 1.3 1107 */ getDesktopIconBorder()1108 public static Border getDesktopIconBorder() { 1109 return new BorderUIResource.CompoundBorderUIResource( 1110 new LineBorder(MetalLookAndFeel.getControlDarkShadow(), 1), 1111 new MatteBorder (2,2,1,2, MetalLookAndFeel.getControl())); 1112 } 1113 getToolBarRolloverBorder()1114 static Border getToolBarRolloverBorder() { 1115 if (MetalLookAndFeel.usingOcean()) { 1116 return new CompoundBorder( 1117 new MetalBorders.ButtonBorder(), 1118 new MetalBorders.RolloverMarginBorder()); 1119 } 1120 return new CompoundBorder(new MetalBorders.RolloverButtonBorder(), 1121 new MetalBorders.RolloverMarginBorder()); 1122 } 1123 getToolBarNonrolloverBorder()1124 static Border getToolBarNonrolloverBorder() { 1125 if (MetalLookAndFeel.usingOcean()) { 1126 new CompoundBorder( 1127 new MetalBorders.ButtonBorder(), 1128 new MetalBorders.RolloverMarginBorder()); 1129 } 1130 return new CompoundBorder(new MetalBorders.ButtonBorder(), 1131 new MetalBorders.RolloverMarginBorder()); 1132 } 1133 } 1134