1 /* 2 * Copyright (c) 1997, 2014, 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 com.sun.java.swing.plaf.motif; 27 28 import sun.swing.SwingUtilities2; 29 import javax.swing.*; 30 import javax.swing.border.*; 31 import javax.swing.plaf.*; 32 33 import java.awt.Color; 34 import java.awt.Component; 35 import java.awt.Dimension; 36 import java.awt.Font; 37 import java.awt.FontMetrics; 38 import java.awt.Graphics; 39 import java.awt.Insets; 40 import java.awt.Point; 41 import java.awt.Rectangle; 42 43 /** 44 * Factory object that can vend Icons appropriate for the basic {@literal L & F}. 45 * <p> 46 * <strong>Warning:</strong> 47 * Serialized objects of this class will not be compatible with 48 * future Swing releases. The current serialization support is appropriate 49 * for short term storage or RMI between applications running the same 50 * version of Swing. A future release of Swing will provide support for 51 * long term persistence. 52 * 53 * @author Amy Fowler 54 */ 55 public class MotifBorders { 56 57 @SuppressWarnings("serial") // Superclass is not serializable across versions 58 public static class BevelBorder extends AbstractBorder implements UIResource { 59 private Color darkShadow = UIManager.getColor("controlShadow"); 60 private Color lightShadow = UIManager.getColor("controlLtHighlight"); 61 private boolean isRaised; 62 BevelBorder(boolean isRaised, Color darkShadow, Color lightShadow)63 public BevelBorder(boolean isRaised, Color darkShadow, Color lightShadow) { 64 this.isRaised = isRaised; 65 this.darkShadow = darkShadow; 66 this.lightShadow = lightShadow; 67 } 68 paintBorder(Component c, Graphics g, int x, int y, int w, int h)69 public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { 70 g.setColor((isRaised) ? lightShadow : darkShadow); 71 g.drawLine(x, y, x+w-1, y); // top 72 g.drawLine(x, y+h-1, x, y+1); // left 73 74 g.setColor((isRaised) ? darkShadow : lightShadow); 75 g.drawLine(x+1, y+h-1, x+w-1, y+h-1); // bottom 76 g.drawLine(x+w-1, y+h-1, x+w-1, y+1); // right 77 } 78 getBorderInsets(Component c, Insets insets)79 public Insets getBorderInsets(Component c, Insets insets) { 80 insets.set(1, 1, 1, 1); 81 return insets; 82 } 83 isOpaque(Component c)84 public boolean isOpaque(Component c) { 85 return true; 86 } 87 88 } 89 90 91 @SuppressWarnings("serial") // Superclass is not serializable across versions 92 public static class FocusBorder extends AbstractBorder implements UIResource { 93 private Color focus; 94 private Color control; 95 FocusBorder(Color control, Color focus)96 public FocusBorder(Color control, Color focus) { 97 this.control = control; 98 this.focus = focus; 99 } 100 paintBorder(Component c, Graphics g, int x, int y, int w, int h)101 public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { 102 if (c.hasFocus()) { 103 g.setColor(focus); 104 g.drawRect(x, y, w-1, h-1); 105 } else { 106 g.setColor(control); 107 g.drawRect(x, y, w-1, h-1); 108 } 109 } 110 getBorderInsets(Component c, Insets insets)111 public Insets getBorderInsets(Component c, Insets insets) { 112 insets.set(1, 1, 1, 1); 113 return insets; 114 } 115 } 116 117 118 @SuppressWarnings("serial") // Superclass is not serializable across versions 119 public static class ButtonBorder extends AbstractBorder implements UIResource { 120 protected Color focus = UIManager.getColor("activeCaptionBorder"); 121 protected Color shadow = UIManager.getColor("Button.shadow"); 122 protected Color highlight = UIManager.getColor("Button.light"); 123 protected Color darkShadow; 124 ButtonBorder(Color shadow, Color highlight, Color darkShadow, Color focus)125 public ButtonBorder(Color shadow, Color highlight, Color darkShadow, Color focus) { 126 this.shadow = shadow; 127 this.highlight = highlight; 128 this.darkShadow = darkShadow; 129 this.focus = focus; 130 } 131 paintBorder(Component c, Graphics g, int x, int y, int w, int h)132 public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { 133 boolean isPressed = false; 134 boolean hasFocus = false; 135 boolean canBeDefault = false; 136 boolean isDefault = false; 137 138 if (c instanceof AbstractButton) { 139 AbstractButton b = (AbstractButton)c; 140 ButtonModel model = b.getModel(); 141 142 isPressed = (model.isArmed() && model.isPressed()); 143 hasFocus = (model.isArmed() && isPressed) || 144 (b.isFocusPainted() && b.hasFocus()); 145 if (b instanceof JButton) { 146 canBeDefault = ((JButton)b).isDefaultCapable(); 147 isDefault = ((JButton)b).isDefaultButton(); 148 } 149 } 150 int bx1 = x+1; 151 int by1 = y+1; 152 int bx2 = x+w-2; 153 int by2 = y+h-2; 154 155 if (canBeDefault) { 156 if (isDefault) { 157 g.setColor(shadow); 158 g.drawLine(x+3, y+3, x+3, y+h-4); 159 g.drawLine(x+3, y+3, x+w-4, y+3); 160 161 g.setColor(highlight); 162 g.drawLine(x+4, y+h-4, x+w-4, y+h-4); 163 g.drawLine(x+w-4, y+3, x+w-4, y+h-4); 164 } 165 bx1 +=6; 166 by1 += 6; 167 bx2 -= 6; 168 by2 -= 6; 169 } 170 171 if (hasFocus) { 172 g.setColor(focus); 173 if (isDefault) { 174 g.drawRect(x, y, w-1, h-1); 175 } else { 176 g.drawRect(bx1-1, by1-1, bx2-bx1+2, by2-by1+2); 177 } 178 } 179 180 g.setColor(isPressed? shadow : highlight); 181 g.drawLine(bx1, by1, bx2, by1); 182 g.drawLine(bx1, by1, bx1, by2); 183 184 g.setColor(isPressed? highlight : shadow); 185 g.drawLine(bx2, by1+1, bx2, by2); 186 g.drawLine(bx1+1, by2, bx2, by2); 187 } 188 getBorderInsets(Component c, Insets insets)189 public Insets getBorderInsets(Component c, Insets insets) { 190 int thickness = (c instanceof JButton && ((JButton)c).isDefaultCapable())? 8 : 2; 191 insets.set(thickness, thickness, thickness, thickness); 192 return insets; 193 } 194 195 } 196 197 @SuppressWarnings("serial") // Superclass is not serializable across versions 198 public static class ToggleButtonBorder extends ButtonBorder { 199 ToggleButtonBorder(Color shadow, Color highlight, Color darkShadow, Color focus)200 public ToggleButtonBorder(Color shadow, Color highlight, Color darkShadow, Color focus) { 201 super(shadow, highlight, darkShadow, focus); 202 } 203 paintBorder(Component c, Graphics g, int x, int y, int width, int height)204 public void paintBorder(Component c, Graphics g, int x, int y, 205 int width, int height) { 206 if (c instanceof AbstractButton) { 207 AbstractButton b = (AbstractButton)c; 208 ButtonModel model = b.getModel(); 209 210 if (model.isArmed() && model.isPressed() || model.isSelected()) { 211 drawBezel(g, x, y, width, height, 212 (model.isPressed() || model.isSelected()), 213 b.isFocusPainted() && b.hasFocus(), shadow, highlight, darkShadow, focus); 214 } else { 215 drawBezel(g, x, y, width, height, 216 false, b.isFocusPainted() && b.hasFocus(), 217 shadow, highlight, darkShadow, focus); 218 } 219 } else { 220 drawBezel(g, x, y, width, height, false, false, 221 shadow, highlight, darkShadow, focus); 222 } 223 } 224 getBorderInsets(Component c, Insets insets)225 public Insets getBorderInsets(Component c, Insets insets) { 226 insets.set(2, 2, 3, 3); 227 return insets; 228 } 229 } 230 231 @SuppressWarnings("serial") // Superclass is not serializable across versions 232 public static class MenuBarBorder extends ButtonBorder { 233 MenuBarBorder(Color shadow, Color highlight, Color darkShadow, Color focus)234 public MenuBarBorder(Color shadow, Color highlight, Color darkShadow, Color focus) { 235 super(shadow, highlight, darkShadow, focus); 236 } 237 paintBorder(Component c, Graphics g, int x, int y, int width, int height)238 public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { 239 if (!(c instanceof JMenuBar)) { 240 return; 241 } 242 JMenuBar menuBar = (JMenuBar)c; 243 if (menuBar.isBorderPainted() == true) { 244 // this draws the MenuBar border 245 Dimension size = menuBar.getSize(); 246 drawBezel(g,x,y,size.width,size.height,false,false, 247 shadow, highlight, darkShadow, focus); 248 } 249 } 250 getBorderInsets(Component c, Insets insets)251 public Insets getBorderInsets(Component c, Insets insets) { 252 insets.set(6, 6, 6, 6); 253 return insets; 254 } 255 } 256 257 @SuppressWarnings("serial") // Superclass is not serializable across versions 258 public static class FrameBorder extends AbstractBorder implements UIResource { 259 260 JComponent jcomp; 261 Color frameHighlight; 262 Color frameColor; 263 Color frameShadow; 264 265 // The width of the border 266 public static final int BORDER_SIZE = 5; 267 268 /** Constructs an FrameBorder for the JComponent <b>comp</b>. 269 */ FrameBorder(JComponent comp)270 public FrameBorder(JComponent comp) { 271 jcomp = comp; 272 } 273 274 /** Sets the FrameBorder's JComponent. 275 */ setComponent(JComponent comp)276 public void setComponent(JComponent comp) { 277 jcomp = comp; 278 } 279 280 /** Returns the FrameBorder's JComponent. 281 * @see #setComponent 282 */ component()283 public JComponent component() { 284 return jcomp; 285 } 286 getFrameHighlight()287 protected Color getFrameHighlight() { 288 return frameHighlight; 289 } 290 getFrameColor()291 protected Color getFrameColor() { 292 return frameColor; 293 } 294 getFrameShadow()295 protected Color getFrameShadow() { 296 return frameShadow; 297 } 298 getBorderInsets(Component c, Insets newInsets)299 public Insets getBorderInsets(Component c, Insets newInsets) { 300 newInsets.set(BORDER_SIZE, BORDER_SIZE, BORDER_SIZE, BORDER_SIZE); 301 return newInsets; 302 } 303 304 /** Draws the FrameBorder's top border. 305 */ drawTopBorder(Component c, Graphics g, int x, int y, int width, int height)306 protected boolean drawTopBorder(Component c, Graphics g, 307 int x, int y, int width, int height) { 308 Rectangle titleBarRect = new Rectangle(x, y, width, BORDER_SIZE); 309 if (!g.getClipBounds().intersects(titleBarRect)) { 310 return false; 311 } 312 313 int maxX = width - 1; 314 int maxY = BORDER_SIZE - 1; 315 316 // Draw frame 317 g.setColor(frameColor); 318 g.drawLine(x, y + 2, maxX - 2, y + 2); 319 g.drawLine(x, y + 3, maxX - 2, y + 3); 320 g.drawLine(x, y + 4, maxX - 2, y + 4); 321 322 // Draw highlights 323 g.setColor(frameHighlight); 324 g.drawLine(x, y, maxX, y); 325 g.drawLine(x, y + 1, maxX, y + 1); 326 g.drawLine(x, y + 2, x, y + 4); 327 g.drawLine(x + 1, y + 2, x + 1, y + 4); 328 329 // Draw shadows 330 g.setColor(frameShadow); 331 g.drawLine(x + 4, y + 4, maxX - 4, y + 4); 332 g.drawLine(maxX, y + 1, maxX, maxY); 333 g.drawLine(maxX - 1, y + 2, maxX - 1, maxY); 334 335 return true; 336 } 337 338 /** Draws the FrameBorder's left border. 339 */ drawLeftBorder(Component c, Graphics g, int x, int y, int width, int height)340 protected boolean drawLeftBorder(Component c, Graphics g, int x, int y, 341 int width, int height) { 342 Rectangle borderRect = 343 new Rectangle(0, 0, getBorderInsets(c).left, height); 344 if (!g.getClipBounds().intersects(borderRect)) { 345 return false; 346 } 347 348 int startY = BORDER_SIZE; 349 350 g.setColor(frameHighlight); 351 g.drawLine(x, startY, x, height - 1); 352 g.drawLine(x + 1, startY, x + 1, height - 2); 353 354 g.setColor(frameColor); 355 g.fillRect(x + 2, startY, x + 2, height - 3); 356 357 g.setColor(frameShadow); 358 g.drawLine(x + 4, startY, x + 4, height - 5); 359 360 return true; 361 } 362 363 /** Draws the FrameBorder's right border. 364 */ drawRightBorder(Component c, Graphics g, int x, int y, int width, int height)365 protected boolean drawRightBorder(Component c, Graphics g, int x, int y, 366 int width, int height) { 367 Rectangle borderRect = new Rectangle( 368 width - getBorderInsets(c).right, 0, 369 getBorderInsets(c).right, height); 370 if (!g.getClipBounds().intersects(borderRect)) { 371 return false; 372 } 373 374 int startX = width - getBorderInsets(c).right; 375 int startY = BORDER_SIZE; 376 377 g.setColor(frameColor); 378 g.fillRect(startX + 1, startY, 2, height - 1); 379 380 g.setColor(frameShadow); 381 g.fillRect(startX + 3, startY, 2, height - 1); 382 383 g.setColor(frameHighlight); 384 g.drawLine(startX, startY, startX, height - 1); 385 386 return true; 387 } 388 389 /** Draws the FrameBorder's bottom border. 390 */ drawBottomBorder(Component c, Graphics g, int x, int y, int width, int height)391 protected boolean drawBottomBorder(Component c, Graphics g, int x, int y, 392 int width, int height) { 393 Rectangle borderRect; 394 int marginHeight, startY; 395 396 borderRect = new Rectangle(0, height - getBorderInsets(c).bottom, 397 width, getBorderInsets(c).bottom); 398 if (!g.getClipBounds().intersects(borderRect)) { 399 return false; 400 } 401 402 startY = height - getBorderInsets(c).bottom; 403 404 g.setColor(frameShadow); 405 g.drawLine(x + 1, height - 1, width - 1, height - 1); 406 g.drawLine(x + 2, height - 2, width - 2, height - 2); 407 408 g.setColor(frameColor); 409 g.fillRect(x + 2, startY + 1, width - 4, 2); 410 411 g.setColor(frameHighlight); 412 g.drawLine(x + 5, startY, width - 5, startY); 413 414 return true; 415 } 416 417 // Returns true if the associated component has focus. isActiveFrame()418 protected boolean isActiveFrame() { 419 return jcomp.hasFocus(); 420 } 421 422 /** Draws the FrameBorder in the given Rect. Calls 423 * <b>drawTitleBar</b>, <b>drawLeftBorder</b>, <b>drawRightBorder</b> and 424 * <b>drawBottomBorder</b>. 425 */ paintBorder(Component c, Graphics g, int x, int y, int width, int height)426 public void paintBorder(Component c, Graphics g, 427 int x, int y, int width, int height) { 428 if (isActiveFrame()) { 429 frameColor = UIManager.getColor("activeCaptionBorder"); 430 } else { 431 frameColor = UIManager.getColor("inactiveCaptionBorder"); 432 } 433 frameHighlight = frameColor.brighter(); 434 frameShadow = frameColor.darker().darker(); 435 436 drawTopBorder(c, g, x, y, width, height); 437 drawLeftBorder(c, g, x, y, width, height); 438 drawRightBorder(c, g, x, y, width, height); 439 drawBottomBorder(c, g, x, y, width, height); 440 } 441 } 442 443 @SuppressWarnings("serial") // Superclass is not serializable across versions 444 public static class InternalFrameBorder extends FrameBorder { 445 446 JInternalFrame frame; 447 448 // The size of the bounding box for Motif frame corners. 449 public static final int CORNER_SIZE = 24; 450 451 /** Constructs an InternalFrameBorder for the InternalFrame 452 * <b>aFrame</b>. 453 */ InternalFrameBorder(JInternalFrame aFrame)454 public InternalFrameBorder(JInternalFrame aFrame) { 455 super(aFrame); 456 frame = aFrame; 457 } 458 459 /** Sets the InternalFrameBorder's InternalFrame. 460 */ setFrame(JInternalFrame aFrame)461 public void setFrame(JInternalFrame aFrame) { 462 frame = aFrame; 463 } 464 465 /** Returns the InternalFrameBorder's InternalFrame. 466 * @see #setFrame 467 */ frame()468 public JInternalFrame frame() { 469 return frame; 470 } 471 472 /** Returns the width of the InternalFrameBorder's resize controls, 473 * appearing along the InternalFrameBorder's bottom border. Clicking 474 * and dragging within these controls lets the user change both the 475 * InternalFrame's width and height, while dragging between the controls 476 * constrains resizing to just the vertical dimension. Override this 477 * method if you implement your own bottom border painting and use a 478 * resize control with a different size. 479 */ resizePartWidth()480 public int resizePartWidth() { 481 if (!frame.isResizable()) { 482 return 0; 483 } 484 return FrameBorder.BORDER_SIZE; 485 } 486 487 /** Draws the InternalFrameBorder's top border. 488 */ drawTopBorder(Component c, Graphics g, int x, int y, int width, int height)489 protected boolean drawTopBorder(Component c, Graphics g, 490 int x, int y, int width, int height) { 491 if (super.drawTopBorder(c, g, x, y, width, height) && 492 frame.isResizable()) { 493 g.setColor(getFrameShadow()); 494 g.drawLine(CORNER_SIZE - 1, y + 1, CORNER_SIZE - 1, y + 4); 495 g.drawLine(width - CORNER_SIZE - 1, y + 1, 496 width - CORNER_SIZE - 1, y + 4); 497 498 g.setColor(getFrameHighlight()); 499 g.drawLine(CORNER_SIZE, y, CORNER_SIZE, y + 4); 500 g.drawLine(width - CORNER_SIZE, y, width - CORNER_SIZE, y + 4); 501 return true; 502 } 503 return false; 504 } 505 506 /** Draws the InternalFrameBorder's left border. 507 */ drawLeftBorder(Component c, Graphics g, int x, int y, int width, int height)508 protected boolean drawLeftBorder(Component c, Graphics g, int x, int y, 509 int width, int height) { 510 if (super.drawLeftBorder(c, g, x, y, width, height) && 511 frame.isResizable()) { 512 g.setColor(getFrameHighlight()); 513 int topY = y + CORNER_SIZE; 514 g.drawLine(x, topY, x + 4, topY); 515 int bottomY = height - CORNER_SIZE; 516 g.drawLine(x + 1, bottomY, x + 5, bottomY); 517 g.setColor(getFrameShadow()); 518 g.drawLine(x + 1, topY - 1, x + 5, topY - 1); 519 g.drawLine(x + 1, bottomY - 1, x + 5, bottomY - 1); 520 return true; 521 } 522 return false; 523 } 524 525 /** Draws the InternalFrameBorder's right border. 526 */ drawRightBorder(Component c, Graphics g, int x, int y, int width, int height)527 protected boolean drawRightBorder(Component c, Graphics g, int x, int y, 528 int width, int height) { 529 if (super.drawRightBorder(c, g, x, y, width, height) && 530 frame.isResizable()) { 531 int startX = width - getBorderInsets(c).right; 532 g.setColor(getFrameHighlight()); 533 int topY = y + CORNER_SIZE; 534 g.drawLine(startX, topY, width - 2, topY); 535 int bottomY = height - CORNER_SIZE; 536 g.drawLine(startX + 1, bottomY, startX + 3, bottomY); 537 g.setColor(getFrameShadow()); 538 g.drawLine(startX + 1, topY - 1, width - 2, topY - 1); 539 g.drawLine(startX + 1, bottomY - 1, startX + 3, bottomY - 1); 540 return true; 541 } 542 return false; 543 } 544 545 /** Draws the InternalFrameBorder's bottom border. 546 */ drawBottomBorder(Component c, Graphics g, int x, int y, int width, int height)547 protected boolean drawBottomBorder(Component c, Graphics g, int x, int y, 548 int width, int height) { 549 if (super.drawBottomBorder(c, g, x, y, width, height) && 550 frame.isResizable()) { 551 int startY = height - getBorderInsets(c).bottom; 552 553 g.setColor(getFrameShadow()); 554 g.drawLine(CORNER_SIZE - 1, startY + 1, 555 CORNER_SIZE - 1, height - 1); 556 g.drawLine(width - CORNER_SIZE, startY + 1, 557 width - CORNER_SIZE, height - 1); 558 559 g.setColor(getFrameHighlight()); 560 g.drawLine(CORNER_SIZE, startY, CORNER_SIZE, height - 2); 561 g.drawLine(width - CORNER_SIZE + 1, startY, 562 width - CORNER_SIZE + 1, height - 2); 563 return true; 564 } 565 return false; 566 } 567 568 // Returns true if the associated internal frame has focus. isActiveFrame()569 protected boolean isActiveFrame() { 570 return frame.isSelected(); 571 } 572 } 573 drawBezel(Graphics g, int x, int y, int w, int h, boolean isPressed, boolean hasFocus, Color shadow, Color highlight, Color darkShadow, Color focus)574 public static void drawBezel(Graphics g, int x, int y, int w, int h, 575 boolean isPressed, boolean hasFocus, 576 Color shadow, Color highlight, 577 Color darkShadow, Color focus) { 578 579 Color oldColor = g.getColor(); 580 g.translate(x, y); 581 582 if (isPressed) { 583 if (hasFocus){ 584 g.setColor(focus); 585 g.drawRect(0, 0, w-1, h-1); 586 } 587 g.setColor(shadow); // inner border 588 g.drawRect(1, 1, w-3, h-3); 589 590 g.setColor(highlight); // inner 3D border 591 g.drawLine(2, h-3, w-3, h-3); 592 g.drawLine(w-3, 2, w-3, h-4); 593 594 } else { 595 if (hasFocus) { 596 g.setColor(focus); 597 g.drawRect(0, 0, w-1, h-1); 598 599 g.setColor(highlight); // inner 3D border 600 g.drawLine(1, 1, 1, h-3); 601 g.drawLine(2, 1, w-4, 1); 602 603 g.setColor(shadow); 604 g.drawLine(2, h-3, w-3, h-3); 605 g.drawLine(w-3, 1, w-3, h-4); 606 607 g.setColor(darkShadow); // black drop shadow __| 608 g.drawLine(1, h-2, w-2, h-2); 609 g.drawLine(w-2, h-2, w-2, 1); 610 } else { 611 g.setColor(highlight); // inner 3D border 612 g.drawLine(1,1,1,h-3); 613 g.drawLine(2,1,w-4,1); 614 g.setColor(shadow); 615 g.drawLine(2,h-3,w-3,h-3); 616 g.drawLine(w-3,1,w-3,h-4); 617 618 g.setColor(darkShadow); // black drop shadow __| 619 g.drawLine(1,h-2,w-2,h-2); 620 g.drawLine(w-2,h-2,w-2,0); 621 622 } 623 g.translate(-x, -y); 624 } 625 g.setColor(oldColor); 626 } 627 628 @SuppressWarnings("serial") // Superclass is not serializable across versions 629 public static class MotifPopupMenuBorder extends AbstractBorder implements UIResource { 630 protected Font font; 631 protected Color background; 632 protected Color foreground; 633 protected Color shadowColor; 634 protected Color highlightColor; 635 636 // Space between the border and text 637 protected static final int TEXT_SPACING = 2; 638 639 // Space for the separator under the title 640 protected static final int GROOVE_HEIGHT = 2; 641 642 /** 643 * Creates a MotifPopupMenuBorder instance 644 * 645 */ MotifPopupMenuBorder( Font titleFont, Color bgColor, Color fgColor, Color shadow, Color highlight)646 public MotifPopupMenuBorder( 647 Font titleFont, 648 Color bgColor, 649 Color fgColor, 650 Color shadow, 651 Color highlight) { 652 this.font = titleFont; 653 this.background = bgColor; 654 this.foreground = fgColor; 655 this.shadowColor = shadow; 656 this.highlightColor = highlight; 657 } 658 659 /** 660 * Paints the border for the specified component with the 661 * specified position and size. 662 * @param c the component for which this border is being painted 663 * @param g the paint graphics 664 * @param x the x position of the painted border 665 * @param y the y position of the painted border 666 * @param width the width of the painted border 667 * @param height the height of the painted border 668 */ paintBorder(Component c, Graphics g, int x, int y, int width, int height)669 public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { 670 if (!(c instanceof JPopupMenu)) { 671 return; 672 } 673 674 Font origFont = g.getFont(); 675 Color origColor = g.getColor(); 676 JPopupMenu popup = (JPopupMenu)c; 677 678 String title = popup.getLabel(); 679 if (title == null) { 680 return; 681 } 682 683 g.setFont(font); 684 685 FontMetrics fm = SwingUtilities2.getFontMetrics(popup, g, font); 686 int fontHeight = fm.getHeight(); 687 int descent = fm.getDescent(); 688 int ascent = fm.getAscent(); 689 Point textLoc = new Point(); 690 int stringWidth = SwingUtilities2.stringWidth(popup, fm, 691 title); 692 693 textLoc.y = y + ascent + TEXT_SPACING; 694 textLoc.x = x + ((width - stringWidth) / 2); 695 696 g.setColor(background); 697 g.fillRect(textLoc.x - TEXT_SPACING, textLoc.y - (fontHeight-descent), 698 stringWidth + (2 * TEXT_SPACING), fontHeight - descent); 699 g.setColor(foreground); 700 SwingUtilities2.drawString(popup, g, title, textLoc.x, textLoc.y); 701 702 MotifGraphicsUtils.drawGroove(g, x, textLoc.y + TEXT_SPACING, 703 width, GROOVE_HEIGHT, 704 shadowColor, highlightColor); 705 706 g.setFont(origFont); 707 g.setColor(origColor); 708 } 709 710 /** 711 * Reinitialize the insets parameter with this Border's current Insets. 712 * @param c the component for which this border insets value applies 713 * @param insets the object to be reinitialized 714 */ getBorderInsets(Component c, Insets insets)715 public Insets getBorderInsets(Component c, Insets insets) { 716 if (!(c instanceof JPopupMenu)) { 717 return insets; 718 } 719 FontMetrics fm; 720 int descent = 0; 721 int ascent = 16; 722 723 String title = ((JPopupMenu)c).getLabel(); 724 if (title == null) { 725 insets.left = insets.top = insets.right = insets.bottom = 0; 726 return insets; 727 } 728 729 fm = c.getFontMetrics(font); 730 731 if(fm != null) { 732 descent = fm.getDescent(); 733 ascent = fm.getAscent(); 734 } 735 736 insets.top += ascent + descent + TEXT_SPACING + GROOVE_HEIGHT; 737 return insets; 738 } 739 740 } 741 742 } 743