aboutsummaryrefslogtreecommitdiff
path: root/libjava/javax/swing/border/TitledBorder.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/javax/swing/border/TitledBorder.java')
-rw-r--r--libjava/javax/swing/border/TitledBorder.java1112
1 files changed, 1061 insertions, 51 deletions
diff --git a/libjava/javax/swing/border/TitledBorder.java b/libjava/javax/swing/border/TitledBorder.java
index 2679ee68d3a..3b6a791630c 100644
--- a/libjava/javax/swing/border/TitledBorder.java
+++ b/libjava/javax/swing/border/TitledBorder.java
@@ -1,5 +1,5 @@
/* TitledBorder.java --
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,104 +42,1114 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
+import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import javax.swing.UIManager;
-public class TitledBorder extends AbstractBorder
+
+/**
+ * A border that paints a title on top of another border.
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+public class TitledBorder
+ extends AbstractBorder
{
- public static final int ABOVE_BOTTOM = 4;
+ /**
+ * A value for the <code>titlePosition</code> property that vertically
+ * positions the title text at the default vertical position, which
+ * is in the middle of the top line of the border.
+ *
+ * @see #getTitlePosition()
+ * @see #setTitlePosition(int)
+ */
+ public static final int DEFAULT_POSITION = 0;
+
+
+ /**
+ * A value for the <code>titlePosition</code> property that vertically
+ * positions the title text above the top line of the border.
+ *
+ * @see #getTitlePosition()
+ * @see #setTitlePosition(int)
+ */
public static final int ABOVE_TOP = 1;
- public static final int BELOW_BOTTOM = 6;
+
+
+ /**
+ * A value for the <code>titlePosition</code> property that vertically
+ * positions the title text at the middle of the top line
+ * of the border.
+ *
+ * @see #getTitlePosition()
+ * @see #setTitlePosition(int)
+ */
+ public static final int TOP = 2;
+
+
+ /**
+ * A value for the <code>titlePosition</code> property that vertically
+ * positions the title text below the top line of the border.
+ *
+ * @see #getTitlePosition()
+ * @see #setTitlePosition(int)
+ */
public static final int BELOW_TOP = 3;
+
+
+ /**
+ * A value for the <code>titlePosition</code> property that vertically
+ * positions the title text above the bottom line of the border.
+ *
+ * @see #getTitlePosition()
+ * @see #setTitlePosition(int)
+ */
+ public static final int ABOVE_BOTTOM = 4;
+
+
+ /**
+ * A value for the <code>titlePosition</code> property that vertically
+ * positions the title text at the center of the bottom line
+ * of the border.
+ *
+ * @see #getTitlePosition()
+ * @see #setTitlePosition(int)
+ */
public static final int BOTTOM = 5;
- public static final int CENTER = 2;
+
+
+ /**
+ * A value for the <code>titlePosition</code> property that vertically
+ * positions the title text below the bottom line of the border.
+ *
+ * @see #getTitlePosition()
+ * @see #setTitlePosition(int)
+ */
+ public static final int BELOW_BOTTOM = 6;
+
+
+ /**
+ * A value for the <code>titleJustification</code> property that
+ * horizontally aligns the title text with either the left or the
+ * right edge of the border, depending on the orientation of the
+ * component nested into the border. If the component orientation
+ * is left-to-right, the title text is aligned with the left edge;
+ * otherwise, it is aligned with the right edge. This is the same
+ * behavior as with {@link #LEADING}.
+ *
+ * @see #getTitleJustification()
+ * @see #setTitleJustification(int)
+ * @see java.awt.ComponentOrientation#isLeftToRight()
+ */
public static final int DEFAULT_JUSTIFICATION = 0;
- public static final int DEFAULT_POSITION = 0;
- public static final int LEADING = 4;
+
+
+ /**
+ * A value for the <code>titleJustification</code> property that
+ * horizontally aligns the title text with the left-hand edge of
+ * the border.
+ *
+ * @see #getTitleJustification()
+ * @see #setTitleJustification(int)
+ */
public static final int LEFT = 1;
+
+
+ /**
+ * A value for the <code>titleJustification</code> property that
+ * horizontally aligns the title text with the center of the border.
+ *
+ * @see #getTitleJustification()
+ * @see #setTitleJustification(int)
+ */
+ public static final int CENTER = 2;
+
+
+ /**
+ * A value for the <code>titleJustification</code> property that
+ * horizontally aligns the title text with the right-hand edge of
+ * the border.
+ *
+ * @see #getTitleJustification()
+ * @see #setTitleJustification(int)
+ */
public static final int RIGHT = 3;
- public static final int TOP = 2;
+
+
+ /**
+ * A value for the <code>titleJustification</code> property that
+ * horizontally aligns the title text with either the left or the
+ * right edge of the border, depending on the orientation of the
+ * component nested into the border. If the component orientation
+ * is left-to-right, the title text is aligned with the left edge;
+ * otherwise, it is aligned with the right edge. This is the same
+ * behavior as with {@link #DEFAULT_JUSTIFICATION}.
+ *
+ * @see #getTitleJustification()
+ * @see #setTitleJustification(int)
+ * @see java.awt.ComponentOrientation#isLeftToRight()
+ */
+ public static final int LEADING = 4;
+
+
+ /**
+ * A value for the <code>titleJustification</code> property that
+ * horizontally aligns the title text with either the right or the
+ * left edge of the border, depending on the orientation of the
+ * component nested into the border. If the component orientation
+ * is left-to-right, the title text is aligned with the right edge;
+ * otherwise, it is aligned with the left edge.
+ *
+ * @see #getTitleJustification()
+ * @see #setTitleJustification(int)
+ * @see java.awt.ComponentOrientation#isLeftToRight()
+ */
public static final int TRAILING = 5;
+
+ /**
+ * The number of pixels between the inside of {@link #border}
+ * and the bordered component.
+ */
protected static final int EDGE_SPACING = 2;
+
+
+ /**
+ * The number of pixels between the outside of this TitledBorder
+ * and the beginning (if left-aligned) or end (if right-aligned)
+ * of the title text.
+ */
protected static final int TEXT_INSET_H = 5;
+
+
+ /**
+ * The number of pixels between the title text and {@link #border}.
+ * This value is only relevant if the title text does not intersect
+ * {@link #border}. No intersection occurs if {@link #titlePosition}
+ * is one of {@link #ABOVE_TOP}, {@link #BELOW_TOP}, {@link #ABOVE_BOTTOM},
+ * or {@link #BELOW_BOTTOM}.
+ */
protected static final int TEXT_SPACING = 2;
- protected Border border;
+
+ /**
+ * Determined using the <code>serialver</code> tool of Apple/Sun JDK 1.3.1
+ * on MacOS X 10.1.5.
+ */
+ static final long serialVersionUID = 8012999415147721601L;
+
+
+ /**
+ * The title, or <code>null</code> to display no title.
+ */
protected String title;
- protected Color titleColor;
- protected Font titleFont;
- protected int titleJustification;
- protected int titlePosition;
- private static Border defaultBorder = new LineBorder (Color.black);
- private static Font defaultFont = null;
- private static Color defaultColor = Color.black;
+
+ /**
+ * The border underneath the title. If this value is
+ * <code>null</code>, the border will be retrieved from the {@link
+ * javax.swing.UIManager}&#x2019;s defaults table using the key
+ * <code>&quot;TitledBorder.border&quot;</code>.
+ */
+ protected Border border;
+
- public TitledBorder (String title)
+ /**
+ * The vertical position of the title text relative to the border,
+ * which is one of {@link #ABOVE_TOP}, {@link #TOP}, {@link
+ * #BELOW_TOP}, {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, {@link
+ * #BELOW_BOTTOM}, or {@link #DEFAULT_POSITION}.
+ */
+ protected int titlePosition;
+
+
+ /**
+ * The horizontal alignment of the title text in relation to the
+ * border, which is one of {@link #LEFT}, {@link #CENTER}, {@link
+ * #RIGHT}, {@link #LEADING}, {@link #TRAILING}, or {@link
+ * #DEFAULT_JUSTIFICATION}.
+ */
+ protected int titleJustification;
+
+
+ /**
+ * The font for displaying the title text. If this value is
+ * <code>null</code>, the font will be retrieved from the {@link
+ * javax.swing.UIManager}&#x2019;s defaults table using the key
+ * <code>&quot;TitledBorder.font&quot;</code>.
+ */
+ protected Font titleFont;
+
+
+ /**
+ * The color for displaying the title text. If this value is
+ * <code>null</code>, the color will be retrieved from the {@link
+ * javax.swing.UIManager}&#x2019;s defaults table using the key
+ * <code>&quot;TitledBorder.titleColor&quot;</code>.
+ */
+ protected Color titleColor;
+
+
+ /**
+ * Constructs a TitledBorder given the text of its title.
+ *
+ * @param title the title text, or <code>null</code> to use no title text.
+ */
+ public TitledBorder(String title)
{
- this (defaultBorder, title, DEFAULT_JUSTIFICATION, DEFAULT_POSITION,
- defaultFont, defaultColor);
+ this(/* border */ null,
+ title, DEFAULT_JUSTIFICATION, DEFAULT_POSITION,
+ /* titleFont */ null, /* titleColor */ null);
}
- public TitledBorder (Border border)
+
+ /**
+ * Constructs an initially untitled TitledBorder given another border.
+ *
+ * @param border the border underneath the title, or <code>null</code>
+ * to use a default from the current look and feel.
+ */
+ public TitledBorder(Border border)
{
- this (border, "", DEFAULT_JUSTIFICATION, DEFAULT_POSITION, defaultFont,
- defaultColor);
+ this(border, /* title */ "", DEFAULT_JUSTIFICATION, DEFAULT_POSITION,
+ /* titleFont */ null, /* titleColor */ null);
}
- public TitledBorder (Border border, String title)
+
+ /**
+ * Constructs a TitledBorder given its border and title text.
+ *
+ * @param border the border underneath the title, or <code>null</code>
+ * to use a default from the current look and feel.
+ *
+ * @param title the title text, or <code>null</code> to use no title
+ * text.
+ */
+ public TitledBorder(Border border, String title)
{
- this (border, title, DEFAULT_JUSTIFICATION, DEFAULT_POSITION, defaultFont,
- defaultColor);
+ this(border, title, DEFAULT_JUSTIFICATION, DEFAULT_POSITION,
+ /* titleFont */ null, /* titleColor */ null);
}
- public TitledBorder (Border border, String title, int titleJustification,
- int titlePosition)
+
+ /**
+ * Constructs a TitledBorder given its border, title text, horizontal
+ * alignment, and vertical position.
+ *
+ * @param border the border underneath the title, or <code>null</code>
+ * to use a default from the current look and feel.
+ *
+ * @param title the title text, or <code>null</code> to use no title
+ * text.
+ *
+ * @param titleJustification the horizontal alignment of the title
+ * text in relation to the border. The value must be one of
+ * {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING},
+ * {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}.
+
+ * @param titlePosition the vertical position of the title text
+ * in relation to the border. The value must be one of
+ * {@link #ABOVE_TOP}, {@link #TOP}, {@link #BELOW_TOP},
+ * {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, {@link #BELOW_BOTTOM},
+ * or {@link #DEFAULT_POSITION}.
+ *
+ * @throws IllegalArgumentException if <code>titleJustification</code>
+ * or <code>titlePosition</code> have an unsupported value.
+ */
+ public TitledBorder(Border border, String title, int titleJustification,
+ int titlePosition)
{
- this (border, title, titleJustification, titlePosition, defaultFont,
- defaultColor);
+ this(border, title, titleJustification, titlePosition,
+ /* titleFont */ null, /* titleColor */ null);
}
- public TitledBorder (Border border, String title, int titleJustification,
- int titlePosition, Font titleFont)
+
+ /**
+ * Constructs a TitledBorder given its border, title text, horizontal
+ * alignment, vertical position, and font.
+ *
+ * @param border the border underneath the title, or <code>null</code>
+ * to use a default from the current look and feel.
+ *
+ * @param title the title text, or <code>null</code> to use no title
+ * text.
+ *
+ * @param titleJustification the horizontal alignment of the title
+ * text in relation to the border. The value must be one of
+ * {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING},
+ * {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}.
+ *
+ * @param titlePosition the vertical position of the title text
+ * in relation to the border. The value must be one of
+ * {@link #ABOVE_TOP}, {@link #TOP}, {@link #BELOW_TOP},
+ * {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, {@link #BELOW_BOTTOM},
+ * or {@link #DEFAULT_POSITION}.
+ *
+ * @param titleFont the font for the title text, or <code>null</code>
+ * to use a default from the current look and feel.
+ *
+ * @throws IllegalArgumentException if <code>titleJustification</code>
+ * or <code>titlePosition</code> have an unsupported value.
+ */
+ public TitledBorder(Border border, String title, int titleJustification,
+ int titlePosition, Font titleFont)
{
- this (border, title, titleJustification, titlePosition, titleFont,
- defaultColor);
+ this(border, title, titleJustification, titlePosition, titleFont,
+ /* titleColor */ null);
}
- public TitledBorder (Border border, String title, int titleJustification,
- int titlePosition, Font titleFont, Color titleColor)
+
+ /**
+ * Constructs a TitledBorder given its border, title text, horizontal
+ * alignment, vertical position, font, and color.
+ *
+ * @param border the border underneath the title, or <code>null</code>
+ * to use a default from the current look and feel.
+ *
+ * @param title the title text, or <code>null</code> to use no title
+ * text.
+ *
+ * @param titleJustification the horizontal alignment of the title
+ * text in relation to the border. The value must be one of
+ * {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING},
+ * {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}.
+ *
+ * @param titlePosition the vertical position of the title text
+ * in relation to the border. The value must be one of
+ * {@link #ABOVE_TOP}, {@link #TOP}, {@link #BELOW_TOP},
+ * {@link #ABOVE_BOTTOM}, {@link #BOTTOM}, {@link #BELOW_BOTTOM},
+ * or {@link #DEFAULT_POSITION}.
+ *
+ * @param titleFont the font for the title text, or <code>null</code>
+ * to use a default from the current look and feel.
+ *
+ * @param titleColor the color for the title text, or <code>null</code>
+ * to use a default from the current look and feel.
+ *
+ * @throws IllegalArgumentException if <code>titleJustification</code>
+ * or <code>titlePosition</code> have an unsupported value.
+ */
+ public TitledBorder(Border border, String title, int titleJustification,
+ int titlePosition, Font titleFont, Color titleColor)
{
this.border = border;
this.title = title;
- this.titleJustification = titleJustification;
+
+ /* Invoking the setter methods ensures that the newly constructed
+ * TitledBorder has valid property values.
+ */
+ setTitleJustification(titleJustification);
+ setTitlePosition(titlePosition);
+
+ this.titleFont = titleFont;
+ this.titleColor = titleColor;
+ }
+
+
+ /**
+ * Paints the border and the title text.
+ *
+ * @param c the component whose border is to be painted.
+ * @param g the graphics for painting.
+ * @param x the horizontal position for painting the border.
+ * @param y the vertical position for painting the border.
+ * @param width the width of the available area for painting the border.
+ * @param height the height of the available area for painting the border.
+ */
+ public void paintBorder(Component c, Graphics g,
+ int x, int y, int width, int height)
+ {
+ Measurements mes = getMeasurements(c);
+ Font oldFont = g.getFont();
+ Color oldColor = g.getColor();
+
+ /**
+ * A local helper class for painting the border without changing
+ * any pixels inside the rectangle of the title text.
+ */
+ class BorderPainter
+ {
+ private Component c;
+ private Border b;
+ private int x, y, width, height;
+
+ /**
+ * Constructs a BorderPainter.
+ *
+ * @param c the component whose border is being painted.
+ * @param b the border object.
+ * @param x the x coordinate of the rectangle delimiting the border.
+ * @param y the y coordinate of the rectangle delimiting the border.
+ * @param width the width of the rectangle delimiting the border.
+ * @param height the width of the rectangle delimiting the border.
+ */
+ public BorderPainter(Component c, Border b,
+ int x, int y, int width, int height)
+ {
+ this.c = c;
+ this.b = b;
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+
+ /**
+ * Paints the entire border.
+ */
+ public void paint(Graphics g)
+ {
+ if (b != null)
+ b.paintBorder(c, g, x, y, width - 1, height - 1);
+ }
+
+
+ /**
+ * Paints the border, clipping the drawing operation to a
+ * given rectangular area.
+ */
+ private void paint(Graphics g,
+ int clipX, int clipY, int clipWidth, int clipHeight)
+ {
+ Shape oldClip = g.getClip();
+ try
+ {
+ g.clipRect(clipX, clipY, clipWidth, clipHeight);
+ paint(g);
+ }
+ finally
+ {
+ g.setClip(oldClip);
+ }
+ }
+
+
+ /**
+ * Paints the border without affecting a given rectangular area.
+ * This is used for painting the border without drawing anything
+ * underneath the title text.
+ *
+ * <p>Since we do not want to introduce unnecessary dependencies
+ * on Java 2D, we perform the clipping without constructive geometry
+ * (provided by java.awt.geom.Area). Instead, the border&#x2019;s
+ * bounding rectangle is split into smaller parts, which are then
+ * clipped and painted individually.:
+ *
+ * <p><pre>
+ * +--------------------+ +--------------------+
+ * | | | 1 |
+ * | +--------+ | +---+--------+-------+
+ * | | hole | | |====> | 2 | hole | 3 |
+ * | +--------+ | |---+--------+-------+
+ * | | | 4 |
+ * +--------------------+ +--------------------+</pre>
+ *
+ */
+ public void paintExcept(Graphics g,
+ int holeX, int holeY, int holeWidth, int holeHeight)
+ {
+ int stripeHeight;
+
+ stripeHeight = holeY - y;
+ if (stripeHeight > 0)
+ paint(g, x, y, width, stripeHeight); // patch #1 in the image above
+
+ stripeHeight = holeHeight;
+ if (stripeHeight > 0)
+ {
+ paint(g, x, holeY, holeX - x, stripeHeight); // patches #2 and #3
+ paint(g, holeX + holeWidth, holeY, width - (holeX + holeWidth), stripeHeight);
+ }
+
+ stripeHeight = height - (holeY - y + holeHeight);
+ if (stripeHeight > 0)
+ paint(g, x, y + height - stripeHeight, width, stripeHeight); // #4
+ }
+ };
+
+ BorderPainter bp;
+ int textX, textY, borderWidth, borderHeight;
+
+ borderWidth = width - (mes.borderSpacing.left + mes.borderSpacing.right);
+ borderHeight = height - (mes.borderSpacing.top + mes.borderSpacing.bottom);
+ bp = new BorderPainter(c, getBorder(),
+ x + mes.borderSpacing.left, y + mes.borderSpacing.top,
+ borderWidth, borderHeight);
+
+ switch (getRealTitleJustification(c))
+ {
+ case LEFT:
+ textX = x + TEXT_INSET_H;
+ break;
+
+ case CENTER:
+ textX = x + (borderWidth - mes.textWidth) / 2;
+ break;
+
+ case RIGHT:
+ textX = x + borderWidth - (mes.textWidth + TEXT_INSET_H);
+ break;
+
+ default:
+ throw new IllegalStateException();
+ }
+
+ switch (titlePosition)
+ {
+ case ABOVE_TOP:
+ textY = y;
+ break;
+
+ case TOP:
+ case DEFAULT_POSITION:
+ default:
+ textY = y + mes.borderSpacing.top + mes.borderInsets.top - mes.textAscent;
+ break;
+
+ case BELOW_TOP:
+ textY = y + mes.borderSpacing.top + mes.borderInsets.top + TEXT_SPACING;
+ break;
+
+ case ABOVE_BOTTOM:
+ textY = y + height - mes.borderSpacing.bottom - mes.borderInsets.bottom
+ - TEXT_SPACING - (mes.textAscent + mes.textDescent);
+ break;
+
+ case BOTTOM:
+ case BELOW_BOTTOM:
+ textY = y + height - (mes.textAscent + mes.textDescent);
+ break;
+ }
+
+ if (mes.trimmedText == null)
+ bp.paint(g);
+ else
+ {
+ try
+ {
+ g.setFont(mes.font);
+ g.setColor(getTitleColor());
+ g.drawString(mes.trimmedText, textX, textY + mes.textAscent);
+ }
+ finally
+ {
+ g.setFont(oldFont);
+ g.setColor(oldColor);
+ }
+ bp.paintExcept(g, textX - 2, textY,
+ mes.textWidth + 2, mes.textAscent + mes.textDescent);
+ }
+ }
+
+
+ /**
+ * Measures the width of this border.
+ *
+ * @param c the component whose border is to be measured.
+ *
+ * @return an Insets object whose <code>left</code>, <code>right</code>,
+ * <code>top</code> and <code>bottom</code> fields indicate the
+ * width of the border at the respective edge.
+ *
+ * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
+ */
+ public Insets getBorderInsets(Component c)
+ {
+ return getBorderInsets(c, new Insets(0, 0, 0, 0));
+ }
+
+
+ /**
+ * Measures the width of this border, storing the results into a
+ * pre-existing Insets object.
+ *
+ * @param insets an Insets object for holding the result values.
+ * After invoking this method, the <code>left</code>,
+ * <code>right</code>, <code>top</code> and
+ * <code>bottom</code> fields indicate the width of the
+ * border at the respective edge.
+ *
+ * @return the same object that was passed for <code>insets</code>.
+ *
+ * @see #getBorderInsets()
+ */
+ public Insets getBorderInsets(Component c, Insets insets)
+ {
+ return getMeasurements(c).getContentInsets(insets);
+ }
+
+
+ /**
+ * Returns <code>false</code>, indicating that there are pixels inside
+ * the area of this border where the background shines through.
+ *
+ * @return <code>false</code>.
+ */
+ public boolean isBorderOpaque()
+ {
+ /* Note that the AbstractBorder.isBorderOpaque would also return
+ * false, so there is actually no need to override the inherited
+ * implementation. However, GNU Classpath strives for exact
+ * compatibility with the Sun reference implementation, which
+ * overrides isBorderOpaque for unknown reasons.
+ */
+ return false;
+ }
+
+
+ /**
+ * Returns the text of the title.
+ *
+ * @return the title text, or <code>null</code> if no title is
+ * displayed.
+ */
+ public String getTitle()
+ {
+ return title;
+ }
+
+
+ /**
+ * Retrieves the border underneath the title. If no border has been
+ * set, or if it has been set to<code>null</code>, the current
+ * {@link javax.swing.LookAndFeel} will be asked for a border
+ * using the key <code>&quot;TitledBorder.border&quot;</code>.
+ *
+ * @return a border, or <code>null</code> if the current LookAndFeel
+ * does not provide a border for the key
+ * <code>&quot;TitledBorder.border&quot;</code>.
+ *
+ * @see javax.swing.UIManager#getBorder(Object)
+ */
+ public Border getBorder()
+ {
+ if (border != null)
+ return border;
+
+ return UIManager.getBorder("TitledBorder.border");
+ }
+
+
+ /**
+ * Returns the vertical position of the title text in relation
+ * to the border.
+ *
+ * @return one of the values {@link #ABOVE_TOP}, {@link #TOP},
+ * {@link #BELOW_TOP}, {@link #ABOVE_BOTTOM}, {@link #BOTTOM},
+ * {@link #BELOW_BOTTOM}, or {@link #DEFAULT_POSITION}.
+ */
+ public int getTitlePosition()
+ {
+ return titlePosition;
+ }
+
+
+ /**
+ * Returns the horizontal alignment of the title text in relation to
+ * the border.
+ *
+ * @return one of the values {@link #LEFT}, {@link #CENTER}, {@link
+ * #RIGHT}, {@link #LEADING}, {@link #TRAILING}, or {@link
+ * #DEFAULT_JUSTIFICATION}.
+ */
+ public int getTitleJustification()
+ {
+ return titleJustification;
+ }
+
+
+ /**
+ * Retrieves the font for displaying the title text. If no font has
+ * been set, or if it has been set to<code>null</code>, the current
+ * {@link javax.swing.LookAndFeel} will be asked for a font
+ * using the key <code>&quot;TitledBorder.font&quot;</code>.
+ *
+ * @return a font, or <code>null</code> if the current LookAndFeel
+ * does not provide a font for the key
+ * <code>&quot;TitledBorder.font&quot;</code>.
+ *
+ * @see javax.swing.UIManager#getFont(Object)
+ */
+ public Font getTitleFont()
+ {
+ if (titleFont != null)
+ return titleFont;
+
+ return UIManager.getFont("TitledBorder.font");
+ }
+
+
+ /**
+ * Retrieves the color for displaying the title text. If no color has
+ * been set, or if it has been set to<code>null</code>, the current
+ * {@link javax.swing.LookAndFeel} will be asked for a color
+ * using the key <code>&quot;TitledBorder.titleColor&quot;</code>.
+ *
+ * @return a color, or <code>null</code> if the current LookAndFeel
+ * does not provide a color for the key
+ * <code>&quot;TitledBorder.titleColor&quot;</code>.
+ *
+ * @see javax.swing.UIManager#getColor(Object)
+ */
+ public Color getTitleColor()
+ {
+ if (titleColor != null)
+ return titleColor;
+
+ return UIManager.getColor("TitledBorder.titleColor");
+ }
+
+
+ /**
+ * Sets the text of the title.
+ *
+ * @param title the new title text, or <code>null</code> for displaying
+ * no text at all.
+ */
+ public void setTitle(String title)
+ {
+ // Swing borders are not JavaBeans, thus no need to fire an event.
+ this.title = title;
+ }
+
+
+ /**
+ * Sets the border underneath the title.
+ *
+ * @param border a border, or <code>null</code> to use the
+ * border that is supplied by the current LookAndFeel.
+ *
+ * @see #getBorder()
+ */
+ public void setBorder(Border border)
+ {
+ // Swing borders are not JavaBeans, thus no need to fire an event.
+ this.border = border;
+ }
+
+
+ /**
+ * Sets the vertical position of the title text in relation
+ * to the border.
+ *
+ * @param titlePosition one of the values {@link #ABOVE_TOP},
+ * {@link #TOP}, {@link #BELOW_TOP}, {@link #ABOVE_BOTTOM},
+ * {@link #BOTTOM}, {@link #BELOW_BOTTOM},
+ * or {@link #DEFAULT_POSITION}.
+ *
+ * @throws IllegalArgumentException if an unsupported value is passed
+ * for <code>titlePosition</code>.
+ */
+ public void setTitlePosition(int titlePosition)
+ {
+ if ((titlePosition < DEFAULT_POSITION) || (titlePosition > BELOW_BOTTOM))
+ throw new IllegalArgumentException();
+
+ // Swing borders are not JavaBeans, thus no need to fire an event.
this.titlePosition = titlePosition;
+ }
+
+
+ /**
+ * Sets the horizontal alignment of the title text in relation to the border.
+ *
+ * @param titleJustification the new alignment, which must be one of
+ * {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING},
+ * {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}.
+ *
+ * @throws IllegalArgumentException if an unsupported value is passed
+ * for <code>titleJustification</code>.
+ */
+ public void setTitleJustification(int titleJustification)
+ {
+ if ((titleJustification < DEFAULT_JUSTIFICATION)
+ || (titleJustification > TRAILING))
+ throw new IllegalArgumentException();
+
+ // Swing borders are not JavaBeans, thus no need to fire an event.
+ this.titleJustification = titleJustification;
+ }
+
+
+ /**
+ * Sets the font for displaying the title text.
+ *
+ * @param titleFont the font, or <code>null</code> to use the font
+ * provided by the current {@link javax.swing.LookAndFeel}.
+ *
+ * @see #getTitleFont()
+ */
+ public void setTitleFont(Font titleFont)
+ {
+ // Swing borders are not JavaBeans, thus no need to fire an event.
this.titleFont = titleFont;
+ }
+
+
+ /**
+ * Sets the color for displaying the title text.
+ *
+ * @param titleColor the color, or <code>null</code> to use the color
+ * provided by the current {@link javax.swing.LookAndFeel}.
+ *
+ * @see #getTitleColor()
+ */
+ public void setTitleColor(Color titleColor)
+ {
+ // Swing borders are not JavaBeans, thus no need to fire an event.
this.titleColor = titleColor;
}
-
- public Insets getBorderInsets(Component c,
- Insets s)
+
+
+ /**
+ * Calculates the minimum size needed for displaying the border
+ * and its title.
+ *
+ * @param c the Component for which this TitledBorder consitutes
+ * a border.
+ */
+ public Dimension getMinimumSize(Component c)
+ {
+ return getMeasurements(c).getMinimumSize();
+ }
+
+
+ /**
+ * Returns the font that is used for displaying the title text for
+ * a given Component.
+ *
+ * @param c the Component for which this TitledBorder is the border.
+ *
+ * @return The font returned by {@link #getTitleFont()}, or a fallback
+ * if {@link #getTitleFont()} returned <code>null</code>.
+ */
+ protected Font getFont(Component c)
+ {
+ Font f;
+
+ f = getTitleFont();
+ if (f != null)
+ return f;
+
+ return new Font("Dialog", Font.PLAIN, 12);
+ }
+
+
+ /**
+ * Returns the horizontal alignment of the title text in relation to
+ * the border, mapping the component-dependent alignment constants
+ * {@link #LEADING}, {@link #TRAILING} and {@link #DEFAULT_JUSTIFICATION}
+ * to the correct value according to the embedded component&#x2019;s
+ * orientation.
+ *
+ * @param c the Component for which this TitledBorder is the border.
+ *
+ * @return one of the values {@link #LEFT}, {@link #CENTER}, or {@link
+ * #RIGHT}.
+ */
+ private int getRealTitleJustification(Component c)
+ {
+ switch (titleJustification)
+ {
+ case DEFAULT_JUSTIFICATION:
+ case LEADING:
+ if ((c == null) || c.getComponentOrientation().isLeftToRight())
+ return LEFT;
+ else
+ return RIGHT;
+
+ case TRAILING:
+ if ((c == null) || c.getComponentOrientation().isLeftToRight())
+ return RIGHT;
+ else
+ return LEFT;
+
+ default:
+ return titleJustification;
+ }
+ }
+
+
+ /**
+ * Performs various measurements for the current state of this TitledBorder
+ * and the given Component.
+ */
+ private Measurements getMeasurements(Component c)
+ {
+ Measurements m = new Measurements();
+ FontMetrics fmet;
+
+ m.font = getFont(c);
+ fmet = c.getFontMetrics(m.font);
+ m.border = getBorder();
+ if (m.border != null)
+ m.borderInsets = m.border.getBorderInsets(c);
+ else
+ m.borderInsets = new Insets(0, 0, 0, 0);
+
+ if (title != null)
{
- s.left = s.right = s.top = s.bottom = 5;
- return s;
+ m.trimmedText = title.trim();
+ if (m.trimmedText.length() == 0)
+ m.trimmedText = null;
}
+ m.textAscent = fmet.getAscent();
+ m.textDescent = fmet.getDescent();
+ if (m.trimmedText != null)
+ m.textWidth = fmet.stringWidth(m.trimmedText) + 3;
+
+ m.edgeSpacing = new Insets(EDGE_SPACING, EDGE_SPACING, EDGE_SPACING, EDGE_SPACING);
+ m.borderSpacing = new Insets(0, 0, 0, 0);
+
+ switch (titlePosition)
+ {
+ case ABOVE_TOP:
+ m.borderSpacing.top += m.textAscent + m.textDescent + TEXT_SPACING;
+ break;
+
+ case BELOW_TOP:
+ m.edgeSpacing.top += m.textAscent + m.textDescent + TEXT_SPACING;
+ break;
+
+ case ABOVE_BOTTOM:
+ m.edgeSpacing.bottom += m.textAscent + m.textDescent + TEXT_SPACING;
+ break;
+
+ case BOTTOM:
+ m.edgeSpacing.bottom += Math.max(m.textAscent - m.borderInsets.bottom, 0);
+ m.borderSpacing.bottom += m.textDescent;
+ break;
+
+ case BELOW_BOTTOM:
+ m.borderSpacing.bottom += m.textAscent + m.textDescent + TEXT_SPACING;
+ break;
+
+ default:
+ m.borderSpacing.top += m.textAscent;
+ }
+
+ return m;
+ }
+
+
+ /**
+ * A private helper class for holding the result of measuring the
+ * distances of a TitledBorder. While it would be possible to cache
+ * these objects, it does not seem to be worth the effort. Note that
+ * invalidating the cache would be tricky, especially since there is
+ * no notification mechanism that would inform the cache when
+ * border has changed, so it would return different insets.
+ */
+ private static class Measurements
+ {
+ /**
+ * The font used for displaying the title text. Note that it can
+ * well be that the TitledBorder&#x2019;s font is <code>null</code>,
+ * which means that the font is to be retrieved from the current
+ * LookAndFeel. In this case, this <code>font</code> field will
+ * contain the result of the retrieval. Therefore, it is safe
+ * to assume that his <code>font</code> field will never have
+ * a <code>null</code> value.
+ */
+ Font font;
+
+
+ /**
+ * The number of pixels between the base line and the top of the
+ * text box.
+ */
+ int textAscent;
+
+
+ /**
+ * The number of pixels between the base line and the bottom of
+ * the text box.
+ */
+ int textDescent;
+
+
+ /**
+ * The title text after removing leading and trailing white space
+ * characters. If the title consists only of white space, the
+ * value of <code>trimmedText</code> will be <code>null</code>.
+ */
+ String trimmedText;
+
+
+ /**
+ * The width of the trimmed title text in pixels.
+ */
+ int textWidth;
+
+
+ /**
+ * The border that constitues the &quot;interior&quot; border
+ * underneath the title text.
+ */
+ Border border;
+
+
+ /**
+ * The distance between the TitledBorder and the interior border.
+ */
+ Insets borderSpacing;
+
+ /**
+ * The width of the interior border, as returned by
+ * <code>border.getBorderInsets()</code>.
+ */
+ Insets borderInsets;
+
- public boolean isBorderOpaque()
+ /**
+ * The distance between the interior border and the nested
+ * Component for which this TitledBorder is a border.
+ */
+ Insets edgeSpacing;
+
+
+ /**
+ * Determines the insets of the nested component when it has a
+ * TitledBorder as its border. Used by {@link
+ * TitledBorder#getBorderInsets()}.
+ *
+ * @param i an Insets object for storing the results into, or
+ * <code>null</code> to cause the creation of a
+ * new instance.
+ *
+ * @return the <code>i</code> object, or a new Insets object
+ * if <code>null</code> was passed for <code>i</code>.
+ */
+ public Insets getContentInsets(Insets i)
{
- return false;
+ if (i == null)
+ i = new Insets(0, 0, 0, 0);
+ i.left = borderSpacing.left + borderInsets.left + edgeSpacing.left;
+ i.right = borderSpacing.right + borderInsets.right + edgeSpacing.right;
+ i.top = borderSpacing.top + borderInsets.top + edgeSpacing.top;
+ i.bottom = borderSpacing.bottom + borderInsets.bottom + edgeSpacing.bottom;
+ return i;
}
-
- public void paintBorder(Component c,
- Graphics g,
- int x,
- int y,
- int width,
- int height)
+
+
+ /**
+ * Calculates the minimum size needed for displaying the border
+ * and its title. Used by {@link TitledBorder#getMiminumSize()}.
+ */
+ public Dimension getMinimumSize()
{
+ int width;
+ Insets insets;
+
+ insets = getContentInsets(null);
+ width = Math.max(insets.left + insets.right, textWidth + 2 * TEXT_INSET_H);
+ return new Dimension(width, insets.top + insets.bottom);
}
+ }
}
-