1 7 package javax.swing.border; 8 9 import com.sun.java.swing.SwingUtilities2; 10 11 import java.awt.Graphics ; 12 import java.awt.Insets ; 13 import java.awt.Rectangle ; 14 import java.awt.Color ; 15 import java.awt.Font ; 16 import java.awt.FontMetrics ; 17 import java.awt.Point ; 18 import java.awt.Toolkit ; 19 import java.awt.Component ; 20 import java.awt.Dimension ; 21 22 import javax.swing.JComponent ; 23 import javax.swing.UIManager ; 24 25 54 public class TitledBorder extends AbstractBorder 55 { 56 protected String title; 57 protected Border border; 58 protected int titlePosition; 59 protected int titleJustification; 60 protected Font titleFont; 61 protected Color titleColor; 62 63 private Point textLoc = new Point (); 64 65 68 static public final int DEFAULT_POSITION = 0; 69 70 static public final int ABOVE_TOP = 1; 71 72 static public final int TOP = 2; 73 74 static public final int BELOW_TOP = 3; 75 76 static public final int ABOVE_BOTTOM = 4; 77 78 static public final int BOTTOM = 5; 79 80 static public final int BELOW_BOTTOM = 6; 81 82 85 static public final int DEFAULT_JUSTIFICATION = 0; 86 87 static public final int LEFT = 1; 88 89 static public final int CENTER = 2; 90 91 static public final int RIGHT = 3; 92 96 static public final int LEADING = 4; 97 101 static public final int TRAILING = 5; 102 103 static protected final int EDGE_SPACING = 2; 105 106 static protected final int TEXT_SPACING = 2; 108 109 static protected final int TEXT_INSET_H = 5; 111 112 117 public TitledBorder(String title) { 118 this(null, title, LEADING, TOP, null, null); 119 } 120 121 127 public TitledBorder(Border border) { 128 this(border, "", LEADING, TOP, null, null); 129 } 130 131 138 public TitledBorder(Border border, String title) { 139 this(border, title, LEADING, TOP, null, null); 140 } 141 142 151 public TitledBorder(Border border, 152 String title, 153 int titleJustification, 154 int titlePosition) { 155 this(border, title, titleJustification, 156 titlePosition, null, null); 157 } 158 159 169 public TitledBorder(Border border, 170 String title, 171 int titleJustification, 172 int titlePosition, 173 Font titleFont) { 174 this(border, title, titleJustification, 175 titlePosition, titleFont, null); 176 } 177 178 190 public TitledBorder(Border border, 191 String title, 192 int titleJustification, 193 int titlePosition, 194 Font titleFont, 195 Color titleColor) { 196 this.title = title; 197 this.border = border; 198 this.titleFont = titleFont; 199 this.titleColor = titleColor; 200 201 setTitleJustification(titleJustification); 202 setTitlePosition(titlePosition); 203 } 204 205 215 public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { 216 217 Border border = getBorder(); 218 219 if (getTitle() == null || getTitle().equals("")) { 220 if (border != null) { 221 border.paintBorder(c, g, x, y, width, height); 222 } 223 return; 224 } 225 226 Rectangle grooveRect = new Rectangle (x + EDGE_SPACING, y + EDGE_SPACING, 227 width - (EDGE_SPACING * 2), 228 height - (EDGE_SPACING * 2)); 229 Font font = g.getFont(); 230 Color color = g.getColor(); 231 232 g.setFont(getFont(c)); 233 234 JComponent jc = (c instanceof JComponent ) ? (JComponent )c : null; 235 FontMetrics fm = SwingUtilities2.getFontMetrics(jc, g); 236 int fontHeight = fm.getHeight(); 237 int descent = fm.getDescent(); 238 int ascent = fm.getAscent(); 239 int diff; 240 int stringWidth = SwingUtilities2.stringWidth(jc, fm, 241 getTitle()); 242 Insets insets; 243 244 if (border != null) { 245 insets = border.getBorderInsets(c); 246 } else { 247 insets = new Insets (0, 0, 0, 0); 248 } 249 250 int titlePos = getTitlePosition(); 251 switch (titlePos) { 252 case ABOVE_TOP: 253 diff = ascent + descent + (Math.max(EDGE_SPACING, 254 TEXT_SPACING*2) - EDGE_SPACING); 255 grooveRect.y += diff; 256 grooveRect.height -= diff; 257 textLoc.y = grooveRect.y - (descent + TEXT_SPACING); 258 break; 259 case TOP: 260 case DEFAULT_POSITION: 261 diff = Math.max(0, ((ascent/2) + TEXT_SPACING) - EDGE_SPACING); 262 grooveRect.y += diff; 263 grooveRect.height -= diff; 264 textLoc.y = (grooveRect.y - descent) + 265 (insets.top + ascent + descent)/2; 266 break; 267 case BELOW_TOP: 268 textLoc.y = grooveRect.y + insets.top + ascent + TEXT_SPACING; 269 break; 270 case ABOVE_BOTTOM: 271 textLoc.y = (grooveRect.y + grooveRect.height) - 272 (insets.bottom + descent + TEXT_SPACING); 273 break; 274 case BOTTOM: 275 grooveRect.height -= fontHeight/2; 276 textLoc.y = ((grooveRect.y + grooveRect.height) - descent) + 277 ((ascent + descent) - insets.bottom)/2; 278 break; 279 case BELOW_BOTTOM: 280 grooveRect.height -= fontHeight; 281 textLoc.y = grooveRect.y + grooveRect.height + ascent + 282 TEXT_SPACING; 283 break; 284 } 285 286 int justification = getTitleJustification(); 287 if(isLeftToRight(c)) { 288 if(justification==LEADING || 289 justification==DEFAULT_JUSTIFICATION) { 290 justification = LEFT; 291 } 292 else if(justification==TRAILING) { 293 justification = RIGHT; 294 } 295 } 296 else { 297 if(justification==LEADING || 298 justification==DEFAULT_JUSTIFICATION) { 299 justification = RIGHT; 300 } 301 else if(justification==TRAILING) { 302 justification = LEFT; 303 } 304 } 305 306 switch (justification) { 307 case LEFT: 308 textLoc.x = grooveRect.x + TEXT_INSET_H + insets.left; 309 break; 310 case RIGHT: 311 textLoc.x = (grooveRect.x + grooveRect.width) - 312 (stringWidth + TEXT_INSET_H + insets.right); 313 break; 314 case CENTER: 315 textLoc.x = grooveRect.x + 316 ((grooveRect.width - stringWidth) / 2); 317 break; 318 } 319 320 if (border != null) { 326 if (((titlePos == TOP || titlePos == DEFAULT_POSITION) && 327 (grooveRect.y > textLoc.y - ascent)) || 328 (titlePos == BOTTOM && 329 (grooveRect.y + grooveRect.height < textLoc.y + descent))) { 330 331 Rectangle clipRect = new Rectangle (); 332 333 Rectangle saveClip = g.getClipBounds(); 335 336 clipRect.setBounds(saveClip); 338 if (computeIntersection(clipRect, x, y, textLoc.x-1-x, height)) { 339 g.setClip(clipRect); 340 border.paintBorder(c, g, grooveRect.x, grooveRect.y, 341 grooveRect.width, grooveRect.height); 342 } 343 344 clipRect.setBounds(saveClip); 346 if (computeIntersection(clipRect, textLoc.x+stringWidth+1, y, 347 x+width-(textLoc.x+stringWidth+1), height)) { 348 g.setClip(clipRect); 349 border.paintBorder(c, g, grooveRect.x, grooveRect.y, 350 grooveRect.width, grooveRect.height); 351 } 352 353 if (titlePos == TOP || titlePos == DEFAULT_POSITION) { 354 clipRect.setBounds(saveClip); 356 if (computeIntersection(clipRect, textLoc.x-1, textLoc.y+descent, 357 stringWidth+2, y+height-textLoc.y-descent)) { 358 g.setClip(clipRect); 359 border.paintBorder(c, g, grooveRect.x, grooveRect.y, 360 grooveRect.width, grooveRect.height); 361 } 362 363 } else { clipRect.setBounds(saveClip); 366 if (computeIntersection(clipRect, textLoc.x-1, y, 367 stringWidth+2, textLoc.y - ascent - y)) { 368 g.setClip(clipRect); 369 border.paintBorder(c, g, grooveRect.x, grooveRect.y, 370 grooveRect.width, grooveRect.height); 371 } 372 } 373 374 g.setClip(saveClip); 376 377 } else { 378 border.paintBorder(c, g, grooveRect.x, grooveRect.y, 379 grooveRect.width, grooveRect.height); 380 } 381 } 382 383 g.setColor(getTitleColor()); 384 SwingUtilities2.drawString(jc, g, getTitle(), textLoc.x, textLoc.y); 385 386 g.setFont(font); 387 g.setColor(color); 388 } 389 390 394 public Insets getBorderInsets(Component c) { 395 return getBorderInsets(c, new Insets (0, 0, 0, 0)); 396 } 397 398 403 public Insets getBorderInsets(Component c, Insets insets) { 404 FontMetrics fm; 405 int descent = 0; 406 int ascent = 16; 407 int height = 16; 408 409 Border border = getBorder(); 410 if (border != null) { 411 if (border instanceof AbstractBorder ) { 412 ((AbstractBorder )border).getBorderInsets(c, insets); 413 } else { 414 Insets i = border.getBorderInsets(c); 417 insets.top = i.top; 418 insets.right = i.right; 419 insets.bottom = i.bottom; 420 insets.left = i.left; 421 } 422 } else { 423 insets.left = insets.top = insets.right = insets.bottom = 0; 424 } 425 426 insets.left += EDGE_SPACING + TEXT_SPACING; 427 insets.right += EDGE_SPACING + TEXT_SPACING; 428 insets.top += EDGE_SPACING + TEXT_SPACING; 429 insets.bottom += EDGE_SPACING + TEXT_SPACING; 430 431 if(c == null || getTitle() == null || getTitle().equals("")) { 432 return insets; 433 } 434 435 Font font = getFont(c); 436 437 fm = c.getFontMetrics(font); 438 439 if(fm != null) { 440 descent = fm.getDescent(); 441 ascent = fm.getAscent(); 442 height = fm.getHeight(); 443 } 444 445 switch (getTitlePosition()) { 446 case ABOVE_TOP: 447 insets.top += ascent + descent 448 + (Math.max(EDGE_SPACING, TEXT_SPACING*2) 449 - EDGE_SPACING); 450 break; 451 case TOP: 452 case DEFAULT_POSITION: 453 insets.top += ascent + descent; 454 break; 455 case BELOW_TOP: 456 insets.top += ascent + descent + TEXT_SPACING; 457 break; 458 case ABOVE_BOTTOM: 459 insets.bottom += ascent + descent + TEXT_SPACING; 460 break; 461 case BOTTOM: 462 insets.bottom += ascent + descent; 463 break; 464 case BELOW_BOTTOM: 465 insets.bottom += height; 466 break; 467 } 468 return insets; 469 } 470 471 474 public boolean isBorderOpaque() { return false; } 475 476 479 public String getTitle() { return title; } 480 481 484 public Border getBorder() { 485 Border b = border; 486 if (b == null) 487 b = UIManager.getBorder("TitledBorder.border"); 488 return b; 489 } 490 491 494 public int getTitlePosition() { return titlePosition; } 495 496 499 public int getTitleJustification() { return titleJustification; } 500 501 504 public Font getTitleFont() { 505 Font f = titleFont; 506 if (f == null) 507 f = UIManager.getFont("TitledBorder.font"); 508 return f; 509 } 510 511 514 public Color getTitleColor() { 515 Color c = titleColor; 516 if (c == null) 517 c = UIManager.getColor("TitledBorder.titleColor"); 518 return c; 519 } 520 521 522 524 528 public void setTitle(String title) { this.title = title; } 529 530 534 public void setBorder(Border border) { this.border = border; } 535 536 540 public void setTitlePosition(int titlePosition) { 541 switch (titlePosition) { 542 case ABOVE_TOP: 543 case TOP: 544 case BELOW_TOP: 545 case ABOVE_BOTTOM: 546 case BOTTOM: 547 case BELOW_BOTTOM: 548 case DEFAULT_POSITION: 549 this.titlePosition = titlePosition; 550 break; 551 default: 552 throw new IllegalArgumentException (titlePosition + 553 " is not a valid title position."); 554 } 555 } 556 557 561 public void setTitleJustification(int titleJustification) { 562 switch (titleJustification) { 563 case DEFAULT_JUSTIFICATION: 564 case LEFT: 565 case CENTER: 566 case RIGHT: 567 case LEADING: 568 case TRAILING: 569 this.titleJustification = titleJustification; 570 break; 571 default: 572 throw new IllegalArgumentException (titleJustification + 573 " is not a valid title justification."); 574 } 575 } 576 577 581 public void setTitleFont(Font titleFont) { 582 this.titleFont = titleFont; 583 } 584 585 589 public void setTitleColor(Color titleColor) { 590 this.titleColor = titleColor; 591 } 592 593 598 public Dimension getMinimumSize(Component c) { 599 Insets insets = getBorderInsets(c); 600 Dimension minSize = new Dimension (insets.right+insets.left, 601 insets.top+insets.bottom); 602 Font font = getFont(c); 603 FontMetrics fm = c.getFontMetrics(font); 604 JComponent jc = (c instanceof JComponent ) ? (JComponent )c : null; 605 switch (titlePosition) { 606 case ABOVE_TOP: 607 case BELOW_BOTTOM: 608 minSize.width = Math.max(SwingUtilities2.stringWidth(jc, fm, 609 getTitle()), minSize.width); 610 break; 611 case BELOW_TOP: 612 case ABOVE_BOTTOM: 613 case TOP: 614 case BOTTOM: 615 case DEFAULT_POSITION: 616 default: 617 minSize.width += SwingUtilities2.stringWidth(jc, fm, getTitle()); 618 } 619 return minSize; 620 } 621 622 protected Font getFont(Component c) { 623 Font font; 624 if ((font = getTitleFont()) != null) { 625 return font; 626 } else if (c != null && (font = c.getFont()) != null) { 627 return font; 628 } 629 return new Font ("Dialog", Font.PLAIN, 12); 630 } 631 632 private static boolean computeIntersection(Rectangle dest, 633 int rx, int ry, int rw, int rh) { 634 int x1 = Math.max(rx, dest.x); 635 int x2 = Math.min(rx + rw, dest.x + dest.width); 636 int y1 = Math.max(ry, dest.y); 637 int y2 = Math.min(ry + rh, dest.y + dest.height); 638 dest.x = x1; 639 dest.y = y1; 640 dest.width = x2 - x1; 641 dest.height = y2 - y1; 642 643 if (dest.width <= 0 || dest.height <= 0) { 644 return false; 645 } 646 return true; 647 } 648 } 649 | Popular Tags |