1 /* TitledBorder.java --
2 Copyright (C) 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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., 59 Temple Place, Suite 330, Boston, MA
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
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. */
39 package javax
.swing
.border
;
41 import java
.awt
.Color
;
42 import java
.awt
.Component
;
43 import java
.awt
.Dimension
;
45 import java
.awt
.FontMetrics
;
46 import java
.awt
.Graphics
;
47 import java
.awt
.Insets
;
48 import java
.awt
.Rectangle
;
49 import java
.awt
.Shape
;
50 import javax
.swing
.UIManager
;
54 * A border that paints a title on top of another border.
56 * @author Sascha Brawer (brawer@dandelis.ch)
58 public class TitledBorder
59 extends AbstractBorder
62 * A value for the <code>titlePosition</code> property that vertically
63 * positions the title text at the default vertical position, which
64 * is in the middle of the top line of the border.
66 * @see #getTitlePosition()
67 * @see #setTitlePosition(int)
69 public static final int DEFAULT_POSITION
= 0;
73 * A value for the <code>titlePosition</code> property that vertically
74 * positions the title text above the top line of the border.
76 * @see #getTitlePosition()
77 * @see #setTitlePosition(int)
79 public static final int ABOVE_TOP
= 1;
83 * A value for the <code>titlePosition</code> property that vertically
84 * positions the title text at the middle of the top line
87 * @see #getTitlePosition()
88 * @see #setTitlePosition(int)
90 public static final int TOP
= 2;
94 * A value for the <code>titlePosition</code> property that vertically
95 * positions the title text below the top line of the border.
97 * @see #getTitlePosition()
98 * @see #setTitlePosition(int)
100 public static final int BELOW_TOP
= 3;
104 * A value for the <code>titlePosition</code> property that vertically
105 * positions the title text above the bottom line of the border.
107 * @see #getTitlePosition()
108 * @see #setTitlePosition(int)
110 public static final int ABOVE_BOTTOM
= 4;
114 * A value for the <code>titlePosition</code> property that vertically
115 * positions the title text at the center of the bottom line
118 * @see #getTitlePosition()
119 * @see #setTitlePosition(int)
121 public static final int BOTTOM
= 5;
125 * A value for the <code>titlePosition</code> property that vertically
126 * positions the title text below the bottom line of the border.
128 * @see #getTitlePosition()
129 * @see #setTitlePosition(int)
131 public static final int BELOW_BOTTOM
= 6;
135 * A value for the <code>titleJustification</code> property that
136 * horizontally aligns the title text with either the left or the
137 * right edge of the border, depending on the orientation of the
138 * component nested into the border. If the component orientation
139 * is left-to-right, the title text is aligned with the left edge;
140 * otherwise, it is aligned with the right edge. This is the same
141 * behavior as with {@link #LEADING}.
143 * @see #getTitleJustification()
144 * @see #setTitleJustification(int)
145 * @see java.awt.ComponentOrientation#isLeftToRight()
147 public static final int DEFAULT_JUSTIFICATION
= 0;
151 * A value for the <code>titleJustification</code> property that
152 * horizontally aligns the title text with the left-hand edge of
155 * @see #getTitleJustification()
156 * @see #setTitleJustification(int)
158 public static final int LEFT
= 1;
162 * A value for the <code>titleJustification</code> property that
163 * horizontally aligns the title text with the center of the border.
165 * @see #getTitleJustification()
166 * @see #setTitleJustification(int)
168 public static final int CENTER
= 2;
172 * A value for the <code>titleJustification</code> property that
173 * horizontally aligns the title text with the right-hand edge of
176 * @see #getTitleJustification()
177 * @see #setTitleJustification(int)
179 public static final int RIGHT
= 3;
183 * A value for the <code>titleJustification</code> property that
184 * horizontally aligns the title text with either the left or the
185 * right edge of the border, depending on the orientation of the
186 * component nested into the border. If the component orientation
187 * is left-to-right, the title text is aligned with the left edge;
188 * otherwise, it is aligned with the right edge. This is the same
189 * behavior as with {@link #DEFAULT_JUSTIFICATION}.
191 * @see #getTitleJustification()
192 * @see #setTitleJustification(int)
193 * @see java.awt.ComponentOrientation#isLeftToRight()
195 public static final int LEADING
= 4;
199 * A value for the <code>titleJustification</code> property that
200 * horizontally aligns the title text with either the right or the
201 * left edge of the border, depending on the orientation of the
202 * component nested into the border. If the component orientation
203 * is left-to-right, the title text is aligned with the right edge;
204 * otherwise, it is aligned with the left edge.
206 * @see #getTitleJustification()
207 * @see #setTitleJustification(int)
208 * @see java.awt.ComponentOrientation#isLeftToRight()
210 public static final int TRAILING
= 5;
214 * The number of pixels between the inside of {@link #border}
215 * and the bordered component.
217 protected static final int EDGE_SPACING
= 2;
221 * The number of pixels between the outside of this TitledBorder
222 * and the beginning (if left-aligned) or end (if right-aligned)
225 protected static final int TEXT_INSET_H
= 5;
229 * The number of pixels between the title text and {@link #border}.
230 * This value is only relevant if the title text does not intersect
231 * {@link #border}. No intersection occurs if {@link #titlePosition}
232 * is one of {@link #ABOVE_TOP}, {@link #BELOW_TOP}, {@link #ABOVE_BOTTOM},
233 * or {@link #BELOW_BOTTOM}.
235 protected static final int TEXT_SPACING
= 2;
239 * Determined using the <code>serialver</code> tool of Apple/Sun JDK 1.3.1
242 static final long serialVersionUID
= 8012999415147721601L;
246 * The title, or <code>null</code> to display no title.
248 protected String title
;
252 * The border underneath the title. If this value is
253 * <code>null</code>, the border will be retrieved from the {@link
254 * javax.swing.UIManager}’s defaults table using the key
255 * <code>"TitledBorder.border"</code>.
257 protected Border border
;
261 * The vertical position of the title text relative to the border,
262 * which is one of {@link #ABOVE_TOP}, {@link #TOP}, {@link
263 * #BELOW_TOP}, {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, {@link
264 * #BELOW_BOTTOM}, or {@link #DEFAULT_POSITION}.
266 protected int titlePosition
;
270 * The horizontal alignment of the title text in relation to the
271 * border, which is one of {@link #LEFT}, {@link #CENTER}, {@link
272 * #RIGHT}, {@link #LEADING}, {@link #TRAILING}, or {@link
273 * #DEFAULT_JUSTIFICATION}.
275 protected int titleJustification
;
279 * The font for displaying the title text. If this value is
280 * <code>null</code>, the font will be retrieved from the {@link
281 * javax.swing.UIManager}’s defaults table using the key
282 * <code>"TitledBorder.font"</code>.
284 protected Font titleFont
;
288 * The color for displaying the title text. If this value is
289 * <code>null</code>, the color will be retrieved from the {@link
290 * javax.swing.UIManager}’s defaults table using the key
291 * <code>"TitledBorder.titleColor"</code>.
293 protected Color titleColor
;
297 * Constructs a TitledBorder given the text of its title.
299 * @param title the title text, or <code>null</code> to use no title text.
301 public TitledBorder(String title
)
303 this(/* border */ null,
304 title
, DEFAULT_JUSTIFICATION
, DEFAULT_POSITION
,
305 /* titleFont */ null, /* titleColor */ null);
310 * Constructs an initially untitled TitledBorder given another border.
312 * @param border the border underneath the title, or <code>null</code>
313 * to use a default from the current look and feel.
315 public TitledBorder(Border border
)
317 this(border
, /* title */ "", DEFAULT_JUSTIFICATION
, DEFAULT_POSITION
,
318 /* titleFont */ null, /* titleColor */ null);
323 * Constructs a TitledBorder given its border and title text.
325 * @param border the border underneath the title, or <code>null</code>
326 * to use a default from the current look and feel.
328 * @param title the title text, or <code>null</code> to use no title
331 public TitledBorder(Border border
, String title
)
333 this(border
, title
, DEFAULT_JUSTIFICATION
, DEFAULT_POSITION
,
334 /* titleFont */ null, /* titleColor */ null);
339 * Constructs a TitledBorder given its border, title text, horizontal
340 * alignment, and vertical position.
342 * @param border the border underneath the title, or <code>null</code>
343 * to use a default from the current look and feel.
345 * @param title the title text, or <code>null</code> to use no title
348 * @param titleJustification the horizontal alignment of the title
349 * text in relation to the border. The value must be one of
350 * {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING},
351 * {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}.
353 * @param titlePosition the vertical position of the title text
354 * in relation to the border. The value must be one of
355 * {@link #ABOVE_TOP}, {@link #TOP}, {@link #BELOW_TOP},
356 * {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, {@link #BELOW_BOTTOM},
357 * or {@link #DEFAULT_POSITION}.
359 * @throws IllegalArgumentException if <code>titleJustification</code>
360 * or <code>titlePosition</code> have an unsupported value.
362 public TitledBorder(Border border
, String title
, int titleJustification
,
365 this(border
, title
, titleJustification
, titlePosition
,
366 /* titleFont */ null, /* titleColor */ null);
371 * Constructs a TitledBorder given its border, title text, horizontal
372 * alignment, vertical position, and font.
374 * @param border the border underneath the title, or <code>null</code>
375 * to use a default from the current look and feel.
377 * @param title the title text, or <code>null</code> to use no title
380 * @param titleJustification the horizontal alignment of the title
381 * text in relation to the border. The value must be one of
382 * {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING},
383 * {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}.
385 * @param titlePosition the vertical position of the title text
386 * in relation to the border. The value must be one of
387 * {@link #ABOVE_TOP}, {@link #TOP}, {@link #BELOW_TOP},
388 * {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, {@link #BELOW_BOTTOM},
389 * or {@link #DEFAULT_POSITION}.
391 * @param titleFont the font for the title text, or <code>null</code>
392 * to use a default from the current look and feel.
394 * @throws IllegalArgumentException if <code>titleJustification</code>
395 * or <code>titlePosition</code> have an unsupported value.
397 public TitledBorder(Border border
, String title
, int titleJustification
,
398 int titlePosition
, Font titleFont
)
400 this(border
, title
, titleJustification
, titlePosition
, titleFont
,
401 /* titleColor */ null);
406 * Constructs a TitledBorder given its border, title text, horizontal
407 * alignment, vertical position, font, and color.
409 * @param border the border underneath the title, or <code>null</code>
410 * to use a default from the current look and feel.
412 * @param title the title text, or <code>null</code> to use no title
415 * @param titleJustification the horizontal alignment of the title
416 * text in relation to the border. The value must be one of
417 * {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING},
418 * {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}.
420 * @param titlePosition the vertical position of the title text
421 * in relation to the border. The value must be one of
422 * {@link #ABOVE_TOP}, {@link #TOP}, {@link #BELOW_TOP},
423 * {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, {@link #BELOW_BOTTOM},
424 * or {@link #DEFAULT_POSITION}.
426 * @param titleFont the font for the title text, or <code>null</code>
427 * to use a default from the current look and feel.
429 * @param titleColor the color for the title text, or <code>null</code>
430 * to use a default from the current look and feel.
432 * @throws IllegalArgumentException if <code>titleJustification</code>
433 * or <code>titlePosition</code> have an unsupported value.
435 public TitledBorder(Border border
, String title
, int titleJustification
,
436 int titlePosition
, Font titleFont
, Color titleColor
)
438 this.border
= border
;
441 /* Invoking the setter methods ensures that the newly constructed
442 * TitledBorder has valid property values.
444 setTitleJustification(titleJustification
);
445 setTitlePosition(titlePosition
);
447 this.titleFont
= titleFont
;
448 this.titleColor
= titleColor
;
453 * Paints the border and the title text.
455 * @param c the component whose border is to be painted.
456 * @param g the graphics for painting.
457 * @param x the horizontal position for painting the border.
458 * @param y the vertical position for painting the border.
459 * @param width the width of the available area for painting the border.
460 * @param height the height of the available area for painting the border.
462 public void paintBorder(Component c
, Graphics g
,
463 int x
, int y
, int width
, int height
)
465 Measurements mes
= getMeasurements(c
);
466 Font oldFont
= g
.getFont();
467 Color oldColor
= g
.getColor();
470 * A local helper class for painting the border without changing
471 * any pixels inside the rectangle of the title text.
477 private int x
, y
, width
, height
;
480 * Constructs a BorderPainter.
482 * @param c the component whose border is being painted.
483 * @param b the border object.
484 * @param x the x coordinate of the rectangle delimiting the border.
485 * @param y the y coordinate of the rectangle delimiting the border.
486 * @param width the width of the rectangle delimiting the border.
487 * @param height the width of the rectangle delimiting the border.
489 public BorderPainter(Component c
, Border b
,
490 int x
, int y
, int width
, int height
)
497 this.height
= height
;
502 * Paints the entire border.
504 public void paint(Graphics g
)
507 b
.paintBorder(c
, g
, x
, y
, width
- 1, height
- 1);
512 * Paints the border, clipping the drawing operation to a
513 * given rectangular area.
515 private void paint(Graphics g
,
516 int clipX
, int clipY
, int clipWidth
, int clipHeight
)
518 Shape oldClip
= g
.getClip();
521 g
.clipRect(clipX
, clipY
, clipWidth
, clipHeight
);
532 * Paints the border without affecting a given rectangular area.
533 * This is used for painting the border without drawing anything
534 * underneath the title text.
536 * <p>Since we do not want to introduce unnecessary dependencies
537 * on Java 2D, we perform the clipping without constructive geometry
538 * (provided by java.awt.geom.Area). Instead, the border’s
539 * bounding rectangle is split into smaller parts, which are then
540 * clipped and painted individually.:
543 * +--------------------+ +--------------------+
545 * | +--------+ | +---+--------+-------+
546 * | | hole | | |====> | 2 | hole | 3 |
547 * | +--------+ | |---+--------+-------+
549 * +--------------------+ +--------------------+</pre>
552 public void paintExcept(Graphics g
,
553 int holeX
, int holeY
, int holeWidth
, int holeHeight
)
557 stripeHeight
= holeY
- y
;
558 if (stripeHeight
> 0)
559 paint(g
, x
, y
, width
, stripeHeight
); // patch #1 in the image above
561 stripeHeight
= holeHeight
;
562 if (stripeHeight
> 0)
564 paint(g
, x
, holeY
, holeX
- x
, stripeHeight
); // patches #2 and #3
565 paint(g
, holeX
+ holeWidth
, holeY
, width
- (holeX
+ holeWidth
), stripeHeight
);
568 stripeHeight
= height
- (holeY
- y
+ holeHeight
);
569 if (stripeHeight
> 0)
570 paint(g
, x
, y
+ height
- stripeHeight
, width
, stripeHeight
); // #4
575 int textX
, textY
, borderWidth
, borderHeight
;
577 borderWidth
= width
- (mes
.borderSpacing
.left
+ mes
.borderSpacing
.right
);
578 borderHeight
= height
- (mes
.borderSpacing
.top
+ mes
.borderSpacing
.bottom
);
579 bp
= new BorderPainter(c
, getBorder(),
580 x
+ mes
.borderSpacing
.left
, y
+ mes
.borderSpacing
.top
,
581 borderWidth
, borderHeight
);
583 switch (getRealTitleJustification(c
))
586 textX
= x
+ TEXT_INSET_H
;
590 textX
= x
+ (borderWidth
- mes
.textWidth
) / 2;
594 textX
= x
+ borderWidth
- (mes
.textWidth
+ TEXT_INSET_H
);
598 throw new IllegalStateException();
601 switch (titlePosition
)
608 case DEFAULT_POSITION
:
610 textY
= y
+ mes
.borderSpacing
.top
+ mes
.borderInsets
.top
- mes
.textAscent
;
614 textY
= y
+ mes
.borderSpacing
.top
+ mes
.borderInsets
.top
+ TEXT_SPACING
;
618 textY
= y
+ height
- mes
.borderSpacing
.bottom
- mes
.borderInsets
.bottom
619 - TEXT_SPACING
- (mes
.textAscent
+ mes
.textDescent
);
624 textY
= y
+ height
- (mes
.textAscent
+ mes
.textDescent
);
628 if (mes
.trimmedText
== null)
635 g
.setColor(getTitleColor());
636 g
.drawString(mes
.trimmedText
, textX
, textY
+ mes
.textAscent
);
641 g
.setColor(oldColor
);
643 bp
.paintExcept(g
, textX
- 2, textY
,
644 mes
.textWidth
+ 2, mes
.textAscent
+ mes
.textDescent
);
650 * Measures the width of this border.
652 * @param c the component whose border is to be measured.
654 * @return an Insets object whose <code>left</code>, <code>right</code>,
655 * <code>top</code> and <code>bottom</code> fields indicate the
656 * width of the border at the respective edge.
658 * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
660 public Insets
getBorderInsets(Component c
)
662 return getBorderInsets(c
, new Insets(0, 0, 0, 0));
667 * Measures the width of this border, storing the results into a
668 * pre-existing Insets object.
670 * @param insets an Insets object for holding the result values.
671 * After invoking this method, the <code>left</code>,
672 * <code>right</code>, <code>top</code> and
673 * <code>bottom</code> fields indicate the width of the
674 * border at the respective edge.
676 * @return the same object that was passed for <code>insets</code>.
678 * @see #getBorderInsets()
680 public Insets
getBorderInsets(Component c
, Insets insets
)
682 return getMeasurements(c
).getContentInsets(insets
);
687 * Returns <code>false</code>, indicating that there are pixels inside
688 * the area of this border where the background shines through.
690 * @return <code>false</code>.
692 public boolean isBorderOpaque()
694 /* Note that the AbstractBorder.isBorderOpaque would also return
695 * false, so there is actually no need to override the inherited
696 * implementation. However, GNU Classpath strives for exact
697 * compatibility with the Sun reference implementation, which
698 * overrides isBorderOpaque for unknown reasons.
705 * Returns the text of the title.
707 * @return the title text, or <code>null</code> if no title is
710 public String
getTitle()
717 * Retrieves the border underneath the title. If no border has been
718 * set, or if it has been set to<code>null</code>, the current
719 * {@link javax.swing.LookAndFeel} will be asked for a border
720 * using the key <code>"TitledBorder.border"</code>.
722 * @return a border, or <code>null</code> if the current LookAndFeel
723 * does not provide a border for the key
724 * <code>"TitledBorder.border"</code>.
726 * @see javax.swing.UIManager#getBorder(Object)
728 public Border
getBorder()
733 return UIManager
.getBorder("TitledBorder.border");
738 * Returns the vertical position of the title text in relation
741 * @return one of the values {@link #ABOVE_TOP}, {@link #TOP},
742 * {@link #BELOW_TOP}, {@link #ABOVE_BOTTOM}, {@link #BOTTOM},
743 * {@link #BELOW_BOTTOM}, or {@link #DEFAULT_POSITION}.
745 public int getTitlePosition()
747 return titlePosition
;
752 * Returns the horizontal alignment of the title text in relation to
755 * @return one of the values {@link #LEFT}, {@link #CENTER}, {@link
756 * #RIGHT}, {@link #LEADING}, {@link #TRAILING}, or {@link
757 * #DEFAULT_JUSTIFICATION}.
759 public int getTitleJustification()
761 return titleJustification
;
766 * Retrieves the font for displaying the title text. If no font has
767 * been set, or if it has been set to<code>null</code>, the current
768 * {@link javax.swing.LookAndFeel} will be asked for a font
769 * using the key <code>"TitledBorder.font"</code>.
771 * @return a font, or <code>null</code> if the current LookAndFeel
772 * does not provide a font for the key
773 * <code>"TitledBorder.font"</code>.
775 * @see javax.swing.UIManager#getFont(Object)
777 public Font
getTitleFont()
779 if (titleFont
!= null)
782 return UIManager
.getFont("TitledBorder.font");
787 * Retrieves the color for displaying the title text. If no color has
788 * been set, or if it has been set to<code>null</code>, the current
789 * {@link javax.swing.LookAndFeel} will be asked for a color
790 * using the key <code>"TitledBorder.titleColor"</code>.
792 * @return a color, or <code>null</code> if the current LookAndFeel
793 * does not provide a color for the key
794 * <code>"TitledBorder.titleColor"</code>.
796 * @see javax.swing.UIManager#getColor(Object)
798 public Color
getTitleColor()
800 if (titleColor
!= null)
803 return UIManager
.getColor("TitledBorder.titleColor");
808 * Sets the text of the title.
810 * @param title the new title text, or <code>null</code> for displaying
813 public void setTitle(String title
)
815 // Swing borders are not JavaBeans, thus no need to fire an event.
821 * Sets the border underneath the title.
823 * @param border a border, or <code>null</code> to use the
824 * border that is supplied by the current LookAndFeel.
828 public void setBorder(Border border
)
830 // Swing borders are not JavaBeans, thus no need to fire an event.
831 this.border
= border
;
836 * Sets the vertical position of the title text in relation
839 * @param titlePosition one of the values {@link #ABOVE_TOP},
840 * {@link #TOP}, {@link #BELOW_TOP}, {@link #ABOVE_BOTTOM},
841 * {@link #BOTTOM}, {@link #BELOW_BOTTOM},
842 * or {@link #DEFAULT_POSITION}.
844 * @throws IllegalArgumentException if an unsupported value is passed
845 * for <code>titlePosition</code>.
847 public void setTitlePosition(int titlePosition
)
849 if ((titlePosition
< DEFAULT_POSITION
) || (titlePosition
> BELOW_BOTTOM
))
850 throw new IllegalArgumentException();
852 // Swing borders are not JavaBeans, thus no need to fire an event.
853 this.titlePosition
= titlePosition
;
858 * Sets the horizontal alignment of the title text in relation to the border.
860 * @param titleJustification the new alignment, which must be one of
861 * {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING},
862 * {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}.
864 * @throws IllegalArgumentException if an unsupported value is passed
865 * for <code>titleJustification</code>.
867 public void setTitleJustification(int titleJustification
)
869 if ((titleJustification
< DEFAULT_JUSTIFICATION
)
870 || (titleJustification
> TRAILING
))
871 throw new IllegalArgumentException();
873 // Swing borders are not JavaBeans, thus no need to fire an event.
874 this.titleJustification
= titleJustification
;
879 * Sets the font for displaying the title text.
881 * @param titleFont the font, or <code>null</code> to use the font
882 * provided by the current {@link javax.swing.LookAndFeel}.
884 * @see #getTitleFont()
886 public void setTitleFont(Font titleFont
)
888 // Swing borders are not JavaBeans, thus no need to fire an event.
889 this.titleFont
= titleFont
;
894 * Sets the color for displaying the title text.
896 * @param titleColor the color, or <code>null</code> to use the color
897 * provided by the current {@link javax.swing.LookAndFeel}.
899 * @see #getTitleColor()
901 public void setTitleColor(Color titleColor
)
903 // Swing borders are not JavaBeans, thus no need to fire an event.
904 this.titleColor
= titleColor
;
909 * Calculates the minimum size needed for displaying the border
912 * @param c the Component for which this TitledBorder consitutes
915 public Dimension
getMinimumSize(Component c
)
917 return getMeasurements(c
).getMinimumSize();
922 * Returns the font that is used for displaying the title text for
925 * @param c the Component for which this TitledBorder is the border.
927 * @return The font returned by {@link #getTitleFont()}, or a fallback
928 * if {@link #getTitleFont()} returned <code>null</code>.
930 protected Font
getFont(Component c
)
938 return new Font("Dialog", Font
.PLAIN
, 12);
943 * Returns the horizontal alignment of the title text in relation to
944 * the border, mapping the component-dependent alignment constants
945 * {@link #LEADING}, {@link #TRAILING} and {@link #DEFAULT_JUSTIFICATION}
946 * to the correct value according to the embedded component’s
949 * @param c the Component for which this TitledBorder is the border.
951 * @return one of the values {@link #LEFT}, {@link #CENTER}, or {@link
954 private int getRealTitleJustification(Component c
)
956 switch (titleJustification
)
958 case DEFAULT_JUSTIFICATION
:
960 if ((c
== null) || c
.getComponentOrientation().isLeftToRight())
966 if ((c
== null) || c
.getComponentOrientation().isLeftToRight())
972 return titleJustification
;
978 * Performs various measurements for the current state of this TitledBorder
979 * and the given Component.
981 private Measurements
getMeasurements(Component c
)
983 Measurements m
= new Measurements();
987 fmet
= c
.getFontMetrics(m
.font
);
988 m
.border
= getBorder();
989 if (m
.border
!= null)
990 m
.borderInsets
= m
.border
.getBorderInsets(c
);
992 m
.borderInsets
= new Insets(0, 0, 0, 0);
996 m
.trimmedText
= title
.trim();
997 if (m
.trimmedText
.length() == 0)
998 m
.trimmedText
= null;
1001 m
.textAscent
= fmet
.getAscent();
1002 m
.textDescent
= fmet
.getDescent();
1003 if (m
.trimmedText
!= null)
1004 m
.textWidth
= fmet
.stringWidth(m
.trimmedText
) + 3;
1006 m
.edgeSpacing
= new Insets(EDGE_SPACING
, EDGE_SPACING
, EDGE_SPACING
, EDGE_SPACING
);
1007 m
.borderSpacing
= new Insets(0, 0, 0, 0);
1009 switch (titlePosition
)
1012 m
.borderSpacing
.top
+= m
.textAscent
+ m
.textDescent
+ TEXT_SPACING
;
1016 m
.edgeSpacing
.top
+= m
.textAscent
+ m
.textDescent
+ TEXT_SPACING
;
1020 m
.edgeSpacing
.bottom
+= m
.textAscent
+ m
.textDescent
+ TEXT_SPACING
;
1024 m
.edgeSpacing
.bottom
+= Math
.max(m
.textAscent
- m
.borderInsets
.bottom
, 0);
1025 m
.borderSpacing
.bottom
+= m
.textDescent
;
1029 m
.borderSpacing
.bottom
+= m
.textAscent
+ m
.textDescent
+ TEXT_SPACING
;
1033 m
.borderSpacing
.top
+= m
.textAscent
;
1041 * A private helper class for holding the result of measuring the
1042 * distances of a TitledBorder. While it would be possible to cache
1043 * these objects, it does not seem to be worth the effort. Note that
1044 * invalidating the cache would be tricky, especially since there is
1045 * no notification mechanism that would inform the cache when
1046 * border has changed, so it would return different insets.
1048 private static class Measurements
1051 * The font used for displaying the title text. Note that it can
1052 * well be that the TitledBorder’s font is <code>null</code>,
1053 * which means that the font is to be retrieved from the current
1054 * LookAndFeel. In this case, this <code>font</code> field will
1055 * contain the result of the retrieval. Therefore, it is safe
1056 * to assume that his <code>font</code> field will never have
1057 * a <code>null</code> value.
1063 * The number of pixels between the base line and the top of the
1070 * The number of pixels between the base line and the bottom of
1077 * The title text after removing leading and trailing white space
1078 * characters. If the title consists only of white space, the
1079 * value of <code>trimmedText</code> will be <code>null</code>.
1085 * The width of the trimmed title text in pixels.
1091 * The border that constitues the "interior" border
1092 * underneath the title text.
1098 * The distance between the TitledBorder and the interior border.
1100 Insets borderSpacing
;
1104 * The width of the interior border, as returned by
1105 * <code>border.getBorderInsets()</code>.
1107 Insets borderInsets
;
1111 * The distance between the interior border and the nested
1112 * Component for which this TitledBorder is a border.
1118 * Determines the insets of the nested component when it has a
1119 * TitledBorder as its border. Used by {@link
1120 * TitledBorder#getBorderInsets()}.
1122 * @param i an Insets object for storing the results into, or
1123 * <code>null</code> to cause the creation of a
1126 * @return the <code>i</code> object, or a new Insets object
1127 * if <code>null</code> was passed for <code>i</code>.
1129 public Insets
getContentInsets(Insets i
)
1132 i
= new Insets(0, 0, 0, 0);
1133 i
.left
= borderSpacing
.left
+ borderInsets
.left
+ edgeSpacing
.left
;
1134 i
.right
= borderSpacing
.right
+ borderInsets
.right
+ edgeSpacing
.right
;
1135 i
.top
= borderSpacing
.top
+ borderInsets
.top
+ edgeSpacing
.top
;
1136 i
.bottom
= borderSpacing
.bottom
+ borderInsets
.bottom
+ edgeSpacing
.bottom
;
1142 * Calculates the minimum size needed for displaying the border
1143 * and its title. Used by {@link TitledBorder#getMiminumSize()}.
1145 public Dimension
getMinimumSize()
1150 insets
= getContentInsets(null);
1151 width
= Math
.max(insets
.left
+ insets
.right
, textWidth
+ 2 * TEXT_INSET_H
);
1152 return new Dimension(width
, insets
.top
+ insets
.bottom
);