void (Component c, Graphics g, int x, int y, int width, int height) { Point textLoc = new Point(); Border border = getBorder(); if (getTitle() == null || getTitle().length() == 0) { if (border != null) { border.paintBorder(c, g, x, y, width, height); } return; } Rectangle grooveRect = new Rectangle(x + EDGE_SPACING, y + EDGE_SPACING, width - (EDGE_SPACING * 2), height - (EDGE_SPACING * 2)); Font font = g.getFont(); Color color = g.getColor(); g.setFont(getFont(c)); FontMetrics fm = g.getFontMetrics(); int fontHeight = fm.getHeight(); int descent = fm.getDescent(); int ascent = fm.getAscent(); int diff; int stringWidth = fm.stringWidth(getTitle()); Insets insets; if (border != null) { insets = border.getBorderInsets(c); } else { insets = new Insets(0, 0, 0, 0); } int titlePos = getTitlePosition(); switch (titlePos) { case ABOVE_TOP -> { diff = ascent + descent + (Math.max(EDGE_SPACING, TEXT_SPACING * 2) - EDGE_SPACING); grooveRect.y += diff; grooveRect.height -= diff; textLoc.y = grooveRect.y - (descent + TEXT_SPACING); } case TOP, DEFAULT_POSITION -> { diff = Math.max(0, ((ascent / 2) + TEXT_SPACING) - EDGE_SPACING); grooveRect.y += diff; grooveRect.height -= diff; textLoc.y = (grooveRect.y - descent) + (insets.top + ascent + descent) / 2; } case BELOW_TOP -> textLoc.y = grooveRect.y + insets.top + ascent + TEXT_SPACING; case ABOVE_BOTTOM -> textLoc.y = (grooveRect.y + grooveRect.height) - (insets.bottom + descent + TEXT_SPACING); case BOTTOM -> { grooveRect.height -= fontHeight / 2; textLoc.y = ((grooveRect.y + grooveRect.height) - descent) + ((ascent + descent) - insets.bottom) / 2; } case BELOW_BOTTOM -> { grooveRect.height -= fontHeight; textLoc.y = grooveRect.y + grooveRect.height + ascent + TEXT_SPACING; } } int justification = getTitleJustification(); if(c.getComponentOrientation().isLeftToRight()) { if(justification==LEADING || justification==DEFAULT_JUSTIFICATION) { justification = LEFT; } else if(justification==TRAILING) { justification = RIGHT; } } else { if(justification==LEADING || justification==DEFAULT_JUSTIFICATION) { justification = RIGHT; } else if(justification==TRAILING) { justification = LEFT; } } switch (justification) { case LEFT -> textLoc.x = grooveRect.x + TEXT_INSET_H + insets.left; case RIGHT -> textLoc.x = (grooveRect.x + grooveRect.width) - (stringWidth + TEXT_INSET_H + insets.right); case CENTER -> textLoc.x = grooveRect.x + ((grooveRect.width - stringWidth) / 2); } // If title is positioned in middle of border AND its fontsize // is greater than the border's thickness, we'll need to paint // the border in sections to leave space for the component's background // to show through the title. // if (border != null) { if (((titlePos == TOP || titlePos == DEFAULT_POSITION) && (grooveRect.y > textLoc.y - ascent)) || (titlePos == BOTTOM && (grooveRect.y + grooveRect.height < textLoc.y + descent))) { Rectangle clipRect = new Rectangle(); // save original clip Rectangle saveClip = g.getClipBounds(); // paint strip left of text clipRect.setBounds(saveClip); if (computeIntersection2(clipRect, x, y, textLoc.x-1-x, height)) { g.setClip(clipRect); border.paintBorder(c, g, grooveRect.x, grooveRect.y, grooveRect.width, grooveRect.height); } // paint strip right of text clipRect.setBounds(saveClip); if (computeIntersection2(clipRect, textLoc.x+stringWidth+1, y, x+width-(textLoc.x+stringWidth+1), height)) { g.setClip(clipRect); border.paintBorder(c, g, grooveRect.x, grooveRect.y, grooveRect.width, grooveRect.height); } if (titlePos == TOP || titlePos == DEFAULT_POSITION) { // paint strip below text clipRect.setBounds(saveClip); if (computeIntersection2(clipRect, textLoc.x-1, textLoc.y+descent, stringWidth+2, y+height-textLoc.y-descent)) { g.setClip(clipRect); border.paintBorder(c, g, grooveRect.x, grooveRect.y, grooveRect.width, grooveRect.height); } } else { // titlePos == BOTTOM // paint strip above text clipRect.setBounds(saveClip); if (computeIntersection2(clipRect, textLoc.x-1, y, stringWidth+2, textLoc.y - ascent - y)) { g.setClip(clipRect); border.paintBorder(c, g, grooveRect.x, grooveRect.y, grooveRect.width, grooveRect.height); } } // restore clip g.setClip(saveClip); } else { border.paintBorder(c, g, grooveRect.x, grooveRect.y, grooveRect.width, grooveRect.height); } } g.setColor(getTitleColor()); g.drawString(getTitle(), textLoc.x, textLoc.y); final int index = myOriginalTitle.indexOf('&'); if (index != -1 && index != myOriginalTitle.length() - 1 && index == myOriginalTitle.lastIndexOf('&') && g instanceof Graphics2D) { int x0 = fm.stringWidth(getTitle().substring(0, index)); int x1 = fm.stringWidth(getTitle().substring(0, index+1)); ((Graphics2D)g).setPaint(getTitleColor()); g.drawLine(textLoc.x + x0 - 1, textLoc.y + 1, textLoc.x + x1 - 1, textLoc.y + 1); ((Graphics2D)g).setPaint(color); } g.setFont(font); g.setColor(color); }