/[classpath]/classpath/javax/swing/border/TitledBorder.java
ViewVC logotype

Diff of /classpath/javax/swing/border/TitledBorder.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.3 by mkoch, Sat Jun 7 18:38:20 2003 UTC revision 1.4 by brawer, Thu Jun 12 02:11:46 2003 UTC
# Line 1  Line 1 
1  /* TitledBorder.java --  /* TitledBorder.java --
2     Copyright (C) 2002 Free Software Foundation, Inc.     Copyright (C) 2003 Free Software Foundation, Inc.
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 42  import java.awt.Color; Line 42  import java.awt.Color;
42  import java.awt.Component;  import java.awt.Component;
43  import java.awt.Dimension;  import java.awt.Dimension;
44  import java.awt.Font;  import java.awt.Font;
45    import java.awt.FontMetrics;
46  import java.awt.Graphics;  import java.awt.Graphics;
47  import java.awt.Insets;  import java.awt.Insets;
48    import java.awt.Rectangle;
49    import java.awt.Shape;
50    import javax.swing.UIManager;
51    
52  public class TitledBorder extends AbstractBorder  
53    /**
54     * A border that paints a title on top of another border.
55     *
56     * @author Sascha Brawer (brawer@dandelis.ch)
57     */
58    public class TitledBorder
59      extends AbstractBorder
60  {  {
61    public static final int ABOVE_BOTTOM = 4;    /**
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.
65       *
66       * @see #getTitlePosition()
67       * @see #setTitlePosition(int)
68       */
69      public static final int DEFAULT_POSITION = 0;
70    
71    
72      /**
73       * A value for the <code>titlePosition</code> property that vertically
74       * positions the title text above the top line of the border.
75       *
76       * @see #getTitlePosition()
77       * @see #setTitlePosition(int)
78       */
79    public static final int ABOVE_TOP = 1;    public static final int ABOVE_TOP = 1;
80    public static final int BELOW_BOTTOM = 6;  
81    
82      /**
83       * A value for the <code>titlePosition</code> property that vertically
84       * positions the title text at the middle of the top line
85       * of the border.
86       *
87       * @see #getTitlePosition()
88       * @see #setTitlePosition(int)
89       */
90      public static final int TOP = 2;
91    
92    
93      /**
94       * A value for the <code>titlePosition</code> property that vertically
95       * positions the title text below the top line of the border.
96       *
97       * @see #getTitlePosition()
98       * @see #setTitlePosition(int)
99       */
100    public static final int BELOW_TOP = 3;    public static final int BELOW_TOP = 3;
101    
102    
103      /**
104       * A value for the <code>titlePosition</code> property that vertically
105       * positions the title text above the bottom line of the border.
106       *
107       * @see #getTitlePosition()
108       * @see #setTitlePosition(int)
109       */
110      public static final int ABOVE_BOTTOM = 4;
111    
112    
113      /**
114       * A value for the <code>titlePosition</code> property that vertically
115       * positions the title text at the center of the bottom line
116       * of the border.
117       *
118       * @see #getTitlePosition()
119       * @see #setTitlePosition(int)
120       */
121    public static final int BOTTOM = 5;    public static final int BOTTOM = 5;
122    public static final int CENTER = 2;  
123    
124      /**
125       * A value for the <code>titlePosition</code> property that vertically
126       * positions the title text below the bottom line of the border.
127       *
128       * @see #getTitlePosition()
129       * @see #setTitlePosition(int)
130       */
131      public static final int BELOW_BOTTOM = 6;
132    
133    
134      /**
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}.
142       *
143       * @see #getTitleJustification()
144       * @see #setTitleJustification(int)
145       * @see java.awt.ComponentOrientation#isLeftToRight()
146       */
147    public static final int DEFAULT_JUSTIFICATION = 0;    public static final int DEFAULT_JUSTIFICATION = 0;
148    public static final int DEFAULT_POSITION = 0;  
149    public static final int LEADING = 4;  
150      /**
151       * A value for the <code>titleJustification</code> property that
152       * horizontally aligns the title text with the left-hand edge of
153       * the border.
154       *
155       * @see #getTitleJustification()
156       * @see #setTitleJustification(int)
157       */
158    public static final int LEFT = 1;    public static final int LEFT = 1;
159    
160    
161      /**
162       * A value for the <code>titleJustification</code> property that
163       * horizontally aligns the title text with the center of the border.
164       *
165       * @see #getTitleJustification()
166       * @see #setTitleJustification(int)
167       */
168      public static final int CENTER = 2;
169    
170    
171      /**
172       * A value for the <code>titleJustification</code> property that
173       * horizontally aligns the title text with the right-hand edge of
174       * the border.
175       *
176       * @see #getTitleJustification()
177       * @see #setTitleJustification(int)
178       */
179    public static final int RIGHT = 3;    public static final int RIGHT = 3;
180    public static final int TOP = 2;  
181    
182      /**
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}.
190       *
191       * @see #getTitleJustification()
192       * @see #setTitleJustification(int)
193       * @see java.awt.ComponentOrientation#isLeftToRight()
194       */
195      public static final int LEADING = 4;
196    
197    
198      /**
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.
205       *
206       * @see #getTitleJustification()
207       * @see #setTitleJustification(int)
208       * @see java.awt.ComponentOrientation#isLeftToRight()
209       */
210    public static final int TRAILING = 5;    public static final int TRAILING = 5;
211    
212    
213      /**
214       * The number of pixels between the inside of {@link #border}
215       * and the bordered component.
216       */
217    protected static final int EDGE_SPACING = 2;    protected static final int EDGE_SPACING = 2;
218    
219    
220      /**
221       * The number of pixels between the outside of this TitledBorder
222       * and the beginning (if left-aligned) or end (if right-aligned)
223       * of the title text.
224       */
225    protected static final int TEXT_INSET_H = 5;    protected static final int TEXT_INSET_H = 5;
226    
227    
228      /**
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}.
234       */
235    protected static final int TEXT_SPACING = 2;    protected static final int TEXT_SPACING = 2;
236    
237    protected Border border;  
238      /**
239       * Determined using the <code>serialver</code> tool of Apple/Sun JDK 1.3.1
240       * on MacOS X 10.1.5.
241       */
242      static final long serialVersionUID = 8012999415147721601L;
243      
244    
245      /**
246       * The title, or <code>null</code> to display no title.
247       */
248    protected String title;    protected String title;
   protected Color titleColor;  
   protected Font titleFont;  
   protected int titleJustification;  
   protected int titlePosition;  
249    
250    private static Border defaultBorder = new LineBorder (Color.black);  
251    private static Font defaultFont = null;    /**
252    private static Color defaultColor = Color.black;     * 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}&#x2019;s defaults table using the key
255       * <code>&quot;TitledBorder.border&quot;</code>.
256       */
257      protected Border border;
258    
259        
260    public TitledBorder (String title)    /**
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}.
265       */
266      protected int titlePosition;
267    
268    
269      /**
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}.
274       */
275      protected int titleJustification;
276    
277    
278      /**
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}&#x2019;s defaults table using the key
282       * <code>&quot;TitledBorder.font&quot;</code>.
283       */
284      protected Font titleFont;
285    
286    
287      /**
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}&#x2019;s defaults table using the key
291       * <code>&quot;TitledBorder.titleColor&quot;</code>.
292       */
293      protected Color titleColor;
294    
295    
296      /**
297       * Constructs a TitledBorder given the text of its title.
298       *
299       * @param title the title text, or <code>null</code> to use no title text.
300       */
301      public TitledBorder(String title)
302    {    {
303      this (defaultBorder, title, DEFAULT_JUSTIFICATION, DEFAULT_POSITION,      this(/* border */ null,
304            defaultFont, defaultColor);           title, DEFAULT_JUSTIFICATION, DEFAULT_POSITION,
305             /* titleFont */ null, /* titleColor */ null);
306    }    }
307    
308    public TitledBorder (Border border)  
309      /**
310       * Constructs an initially untitled TitledBorder given another border.
311       *
312       * @param border the border underneath the title, or <code>null</code>
313       *        to use a default from the current look and feel.
314       */
315      public TitledBorder(Border border)
316    {    {
317      this (border, "", DEFAULT_JUSTIFICATION, DEFAULT_POSITION, defaultFont,      this(border, /* title */ "", DEFAULT_JUSTIFICATION, DEFAULT_POSITION,
318            defaultColor);           /* titleFont */ null, /* titleColor */ null);
319    }    }
320        
321    public TitledBorder (Border border, String title)  
322      /**
323       * Constructs a TitledBorder given its border and title text.
324       *
325       * @param border the border underneath the title, or <code>null</code>
326       *        to use a default from the current look and feel.
327       *
328       * @param title the title text, or <code>null</code> to use no title
329       *        text.
330       */
331      public TitledBorder(Border border, String title)
332    {    {
333      this (border, title, DEFAULT_JUSTIFICATION, DEFAULT_POSITION, defaultFont,      this(border, title, DEFAULT_JUSTIFICATION, DEFAULT_POSITION,
334            defaultColor);           /* titleFont */ null, /* titleColor */ null);
335    }    }
336        
337    public TitledBorder (Border border, String title, int titleJustification,  
338                         int titlePosition)    /**
339       * Constructs a TitledBorder given its border, title text, horizontal
340       * alignment, and vertical position.
341       *
342       * @param border the border underneath the title, or <code>null</code>
343       *        to use a default from the current look and feel.
344       *
345       * @param title the title text, or <code>null</code> to use no title
346       *        text.
347       *
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}.
352      
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}.
358       *
359       * @throws IllegalArgumentException if <code>titleJustification</code>
360       *         or <code>titlePosition</code> have an unsupported value.
361       */
362      public TitledBorder(Border border, String title, int titleJustification,
363                          int titlePosition)
364    {    {
365      this (border, title, titleJustification, titlePosition, defaultFont,      this(border, title, titleJustification, titlePosition,
366            defaultColor);           /* titleFont */ null, /* titleColor */ null);
367    }    }
368        
369    public TitledBorder (Border border, String title, int titleJustification,  
370                         int titlePosition, Font titleFont)    /**
371       * Constructs a TitledBorder given its border, title text, horizontal
372       * alignment, vertical position, and font.
373       *
374       * @param border the border underneath the title, or <code>null</code>
375       *        to use a default from the current look and feel.
376       *
377       * @param title the title text, or <code>null</code> to use no title
378       *        text.
379       *
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}.
384       *
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}.
390       *
391       * @param titleFont the font for the title text, or <code>null</code>
392       *        to use a default from the current look and feel.
393       *
394       * @throws IllegalArgumentException if <code>titleJustification</code>
395       *         or <code>titlePosition</code> have an unsupported value.
396       */
397      public TitledBorder(Border border, String title, int titleJustification,
398                          int titlePosition, Font titleFont)
399    {    {
400      this (border, title, titleJustification, titlePosition, titleFont,      this(border, title, titleJustification, titlePosition, titleFont,
401            defaultColor);           /* titleColor */ null);
402    }    }
403        
404    public TitledBorder (Border border, String title, int titleJustification,  
405                         int titlePosition, Font titleFont, Color titleColor)    /**
406       * Constructs a TitledBorder given its border, title text, horizontal
407       * alignment, vertical position, font, and color.
408       *
409       * @param border the border underneath the title, or <code>null</code>
410       *        to use a default from the current look and feel.
411       *
412       * @param title the title text, or <code>null</code> to use no title
413       *        text.
414       *
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}.
419       *
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}.
425       *
426       * @param titleFont the font for the title text, or <code>null</code>
427       *        to use a default from the current look and feel.
428       *
429       * @param titleColor the color for the title text, or <code>null</code>
430       *        to use a default from the current look and feel.
431       *
432       * @throws IllegalArgumentException if <code>titleJustification</code>
433       *         or <code>titlePosition</code> have an unsupported value.
434       */
435      public TitledBorder(Border border, String title, int titleJustification,
436                          int titlePosition, Font titleFont, Color titleColor)
437    {    {
438      this.border = border;      this.border = border;
439      this.title = title;      this.title = title;
440      this.titleJustification = titleJustification;  
441        /* Invoking the setter methods ensures that the newly constructed
442         * TitledBorder has valid property values.
443         */
444        setTitleJustification(titleJustification);
445        setTitlePosition(titlePosition);
446    
447        this.titleFont = titleFont;
448        this.titleColor = titleColor;
449      }
450      
451      
452      /**
453       * Paints the border and the title text.
454       *
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.
461       */
462      public void paintBorder(Component c, Graphics  g,
463                              int x, int y, int width, int height)
464      {
465        Measurements mes = getMeasurements(c);
466        Font oldFont = g.getFont();
467        Color oldColor = g.getColor();
468    
469        /**
470         * A local helper class for painting the border without changing
471         * any pixels inside the rectangle of the title text.
472         */
473        class BorderPainter
474        {
475          private Component c;
476          private Border b;
477          private int x, y, width, height;
478    
479          /**
480           * Constructs a BorderPainter.
481           *
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.
488           */
489          public BorderPainter(Component c, Border b,
490                               int x, int y, int width, int height)
491          {
492            this.c = c;
493            this.b = b;
494            this.x = x;
495            this.y = y;
496            this.width = width;
497            this.height = height;
498          }
499    
500    
501          /**
502           * Paints the entire border.
503           */
504          public void paint(Graphics g)
505          {
506            if (b != null)
507              b.paintBorder(c, g, x, y, width - 1, height - 1);
508          }
509    
510    
511          /**
512           * Paints the border, clipping the drawing operation to a
513           * given rectangular area.
514           */
515          private void paint(Graphics g,
516                             int clipX, int clipY, int clipWidth, int clipHeight)
517          {
518            Shape oldClip = g.getClip();
519            try
520            {
521              g.clipRect(clipX, clipY, clipWidth, clipHeight);
522              paint(g);
523            }
524            finally
525            {
526              g.setClip(oldClip);
527            }
528          }
529    
530    
531          /**
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.
535           *
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&#x2019;s
539           * bounding rectangle is split into smaller parts, which are then
540           * clipped and painted individually.:
541           *
542           * <p><pre>
543           *    +--------------------+          +--------------------+
544           *    |                    |          |        1           |
545           *    |   +--------+       |          +---+--------+-------+
546           *    |   | hole   |       |  |====>  | 2 | hole   |   3   |
547           *    |   +--------+       |          |---+--------+-------+
548           *    |                    |          |        4           |
549           *    +--------------------+          +--------------------+</pre>
550           *
551           */
552          public void paintExcept(Graphics g,
553                                  int holeX, int holeY, int holeWidth, int holeHeight)
554          {
555            int stripeHeight;
556    
557            stripeHeight = holeY - y;
558            if (stripeHeight > 0)
559              paint(g, x, y, width, stripeHeight);   // patch #1 in the image above
560    
561            stripeHeight = holeHeight;
562            if (stripeHeight > 0)
563            {
564              paint(g, x, holeY, holeX - x, stripeHeight);  // patches #2 and #3
565              paint(g, holeX + holeWidth, holeY, width - (holeX + holeWidth), stripeHeight);
566            }
567    
568            stripeHeight = height - (holeY - y + holeHeight);
569            if (stripeHeight > 0)
570              paint(g, x, y + height - stripeHeight, width, stripeHeight); // #4
571          }
572        };
573    
574        BorderPainter bp;
575        int textX, textY, borderWidth, borderHeight;
576    
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);
582    
583        switch (getRealTitleJustification(c))
584        {
585        case LEFT:
586          textX = x + TEXT_INSET_H;
587          break;
588    
589        case CENTER:
590          textX = x + (borderWidth - mes.textWidth) / 2;
591          break;
592    
593        case RIGHT:
594          textX = x + borderWidth - (mes.textWidth + TEXT_INSET_H);
595          break;
596    
597        default:
598          throw new IllegalStateException();
599        }
600    
601        switch (titlePosition)
602        {
603        case ABOVE_TOP:
604          textY = y;
605          break;
606    
607        case TOP:
608        case DEFAULT_POSITION:
609        default:
610          textY = y + mes.borderSpacing.top + mes.borderInsets.top - mes.textAscent;
611          break;
612    
613        case BELOW_TOP:
614          textY = y + mes.borderSpacing.top + mes.borderInsets.top + TEXT_SPACING;
615          break;
616    
617        case ABOVE_BOTTOM:
618          textY = y + height - mes.borderSpacing.bottom - mes.borderInsets.bottom
619            - TEXT_SPACING - (mes.textAscent + mes.textDescent);
620          break;
621    
622        case BOTTOM:
623        case BELOW_BOTTOM:
624          textY = y + height - (mes.textAscent + mes.textDescent);
625          break;
626        }
627    
628        if (mes.trimmedText == null)
629          bp.paint(g);
630        else
631        {
632          try
633          {
634            g.setFont(mes.font);
635            g.setColor(getTitleColor());
636            g.drawString(mes.trimmedText, textX, textY + mes.textAscent);
637          }
638          finally
639          {
640            g.setFont(oldFont);
641            g.setColor(oldColor);
642          }
643          bp.paintExcept(g, textX - 2, textY,
644                         mes.textWidth + 2, mes.textAscent + mes.textDescent);
645        }
646      }
647      
648      
649      /**
650       * Determines the insets of this border.
651       *
652       * @param c the component whose border is to be measured.
653       * @return the insets of this border.
654       */
655      public Insets getBorderInsets(Component c)
656      {
657        return getBorderInsets(c, new Insets(0, 0, 0, 0));
658      }
659      
660    
661      /**
662       * Determines the insets of this border, storing the result
663       * into the given Insets object.
664       *
665       * @param insets an Insets object for holding the insets of this
666       *        border.
667       *
668       * @return the same object that was passed for <code>insets</code>,
669       *         but with changed field values.
670       */
671      public Insets getBorderInsets(Component c, Insets insets)
672      {
673        return getMeasurements(c).getContentInsets(insets);
674      }
675      
676      
677      /**
678       * Returns <code>false</code>, indicating that there are pixels inside
679       * the area of this border where the background shines through.
680       *
681       * @return <code>false</code>.
682       */
683      public boolean isBorderOpaque()
684      {
685        /* Note that the AbstractBorder.isBorderOpaque would also return
686         * false, so there is actually no need to override the inherited
687         * implementation. However, GNU Classpath strives for exact
688         * compatibility with the Sun reference implementation, which
689         * overrides isBorderOpaque for unknown reasons.
690         */
691        return false;
692      }
693    
694    
695      /**
696       * Returns the text of the title.
697       *
698       * @return the title text, or <code>null</code> if no title is
699       *         displayed.
700       */
701      public String getTitle()
702      {
703        return title;
704      }
705    
706    
707      /**
708       * Retrieves the border underneath the title. If no border has been
709       * set, or if it has been set to<code>null</code>, the current
710       * {@link javax.swing.LookAndFeel} will be asked for a border
711       * using the key <code>&quot;TitledBorder.border&quot;</code>.
712       *
713       * @return a border, or <code>null</code> if the current LookAndFeel
714       *         does not provide a border for the key
715       *         <code>&quot;TitledBorder.border&quot;</code>.
716       *
717       * @see javax.swing.UIManager#getBorder(Object)
718       */
719      public Border getBorder()
720      {
721        if (border != null)
722          return border;
723    
724        return UIManager.getBorder("TitledBorder.border");
725      }
726    
727    
728      /**
729       * Returns the vertical position of the title text in relation
730       * to the border.
731       *
732       * @return one of the values {@link #ABOVE_TOP}, {@link #TOP},
733       *         {@link #BELOW_TOP}, {@link #ABOVE_BOTTOM}, {@link #BOTTOM},
734       *         {@link #BELOW_BOTTOM}, or {@link #DEFAULT_POSITION}.
735       */
736      public int getTitlePosition()
737      {
738        return titlePosition;
739      }
740    
741    
742      /**
743       * Returns the horizontal alignment of the title text in relation to
744       * the border.
745       *
746       * @return one of the values {@link #LEFT}, {@link #CENTER}, {@link
747       *         #RIGHT}, {@link #LEADING}, {@link #TRAILING}, or {@link
748       *         #DEFAULT_JUSTIFICATION}.
749       */
750      public int getTitleJustification()
751      {
752        return titleJustification;
753      }
754    
755    
756      /**
757       * Retrieves the font for displaying the title text. If no font has
758       * been set, or if it has been set to<code>null</code>, the current
759       * {@link javax.swing.LookAndFeel} will be asked for a font
760       * using the key <code>&quot;TitledBorder.font&quot;</code>.
761       *
762       * @return a font, or <code>null</code> if the current LookAndFeel
763       *         does not provide a font for the key
764       *         <code>&quot;TitledBorder.font&quot;</code>.
765       *
766       * @see javax.swing.UIManager#getFont(Object)
767       */
768      public Font getTitleFont()
769      {
770        if (titleFont != null)
771          return titleFont;
772    
773        return UIManager.getFont("TitledBorder.font");
774      }
775    
776    
777      /**
778       * Retrieves the color for displaying the title text. If no color has
779       * been set, or if it has been set to<code>null</code>, the current
780       * {@link javax.swing.LookAndFeel} will be asked for a color
781       * using the key <code>&quot;TitledBorder.titleColor&quot;</code>.
782       *
783       * @return a color, or <code>null</code> if the current LookAndFeel
784       *         does not provide a color for the key
785       *         <code>&quot;TitledBorder.titleColor&quot;</code>.
786       *
787       * @see javax.swing.UIManager#getColor(Object)
788       */
789      public Color getTitleColor()
790      {
791        if (titleColor != null)
792          return titleColor;
793    
794        return UIManager.getColor("TitledBorder.titleColor");
795      }
796    
797    
798      /**
799       * Sets the text of the title.
800       *
801       * @param title the new title text, or <code>null</code> for displaying
802       *        no text at all.
803       */
804      public void setTitle(String title)
805      {
806        // Swing borders are not JavaBeans, thus no need to fire an event.
807        this.title = title;
808      }
809    
810    
811      /**
812       * Sets the border underneath the title.
813       *
814       * @param border a border, or <code>null</code> to use the
815       *        border that is supplied by the current LookAndFeel.
816       *
817       * @see #getBorder()
818       */
819      public void setBorder(Border border)
820      {
821        // Swing borders are not JavaBeans, thus no need to fire an event.
822        this.border = border;
823      }
824    
825    
826      /**
827       * Sets the vertical position of the title text in relation
828       * to the border.
829       *
830       * @param titlePosition one of the values {@link #ABOVE_TOP},
831       *        {@link #TOP}, {@link #BELOW_TOP}, {@link #ABOVE_BOTTOM},
832       *        {@link #BOTTOM}, {@link #BELOW_BOTTOM},
833       *        or {@link #DEFAULT_POSITION}.
834       *
835       * @throws IllegalArgumentException if an unsupported value is passed
836       *         for <code>titlePosition</code>.
837       */
838      public void setTitlePosition(int titlePosition)
839      {
840        if ((titlePosition < DEFAULT_POSITION) || (titlePosition > BELOW_BOTTOM))
841          throw new IllegalArgumentException();
842    
843        // Swing borders are not JavaBeans, thus no need to fire an event.
844      this.titlePosition = titlePosition;      this.titlePosition = titlePosition;
845      }
846    
847    
848      /**
849       * Sets the horizontal alignment of the title text in relation to the border.
850       *
851       * @param titleJustification the new alignment, which must be one of
852       *        {@link #LEFT}, {@link #CENTER}, {@link #RIGHT}, {@link #LEADING},
853       *        {@link #TRAILING}, or {@link #DEFAULT_JUSTIFICATION}.
854       *
855       * @throws IllegalArgumentException if an unsupported value is passed
856       *         for <code>titleJustification</code>.
857       */
858      public void setTitleJustification(int titleJustification)
859      {
860        if ((titleJustification < DEFAULT_JUSTIFICATION)
861            || (titleJustification > TRAILING))
862          throw new IllegalArgumentException();
863    
864        // Swing borders are not JavaBeans, thus no need to fire an event.
865        this.titleJustification = titleJustification;
866      }
867    
868    
869      /**
870       * Sets the font for displaying the title text.
871       *
872       * @param titleFont the font, or <code>null</code> to use the font
873       *        provided by the current {@link javax.swing.LookAndFeel}.
874       *
875       * @see #getTitleFont()
876       */
877      public void setTitleFont(Font titleFont)
878      {
879        // Swing borders are not JavaBeans, thus no need to fire an event.
880      this.titleFont = titleFont;      this.titleFont = titleFont;
881      }
882    
883    
884      /**
885       * Sets the color for displaying the title text.
886       *
887       * @param titleColor the color, or <code>null</code> to use the color
888       *        provided by the current {@link javax.swing.LookAndFeel}.
889       *
890       * @see #getTitleColor()
891       */
892      public void setTitleColor(Color titleColor)
893      {
894        // Swing borders are not JavaBeans, thus no need to fire an event.
895      this.titleColor = titleColor;      this.titleColor = titleColor;
896    }    }
897        
898      public Insets getBorderInsets(Component  c,  
899                                    Insets s)    /**
900       * Calculates the minimum size needed for displaying the border
901       * and its title.
902       *
903       * @param c the Component for which this TitledBorder consitutes
904       *        a border.
905       */
906      public Dimension getMinimumSize(Component c)
907      {
908        return getMeasurements(c).getMinimumSize();
909      }
910    
911    
912      /**
913       * Returns the font that is used for displaying the title text for
914       * a given Component.
915       *
916       * @param c the Component for which this TitledBorder is the border.
917       *
918       * @return The font returned by {@link #getTitleFont()}, or a fallback
919       *         if {@link #getTitleFont()} returned <code>null</code>.
920       */
921      protected Font getFont(Component c)
922      {
923        Font f;
924    
925        f = getTitleFont();
926        if (f != null)
927          return f;
928    
929        return new Font("Dialog", Font.PLAIN, 12);
930      }
931    
932    
933      /**
934       * Returns the horizontal alignment of the title text in relation to
935       * the border, mapping the component-dependent alignment constants
936       * {@link #LEADING}, {@link #TRAILING} and {@link #DEFAULT_JUSTIFICATION}
937       * to the correct value according to the embedded component&#x2019;s
938       * orientation.
939       *
940       * @param c the Component for which this TitledBorder is the border.
941       *
942       * @return one of the values {@link #LEFT}, {@link #CENTER}, or {@link
943       *         #RIGHT}.
944       */
945      private int getRealTitleJustification(Component c)
946      {
947        switch (titleJustification)
948        {
949        case DEFAULT_JUSTIFICATION:
950        case LEADING:
951          if ((c == null) || c.getComponentOrientation().isLeftToRight())
952            return LEFT;
953          else
954            return RIGHT;
955    
956        case TRAILING:
957          if ((c == null) || c.getComponentOrientation().isLeftToRight())
958            return RIGHT;
959          else
960            return LEFT;
961    
962        default:
963          return titleJustification;
964        }
965      }
966    
967    
968      /**
969       * Performs various measurements for the current state of this TitledBorder
970       * and the given Component.
971       */
972      private Measurements getMeasurements(Component c)
973      {
974        Measurements m = new Measurements();
975        FontMetrics fmet;
976    
977        m.font = getFont(c);
978        fmet = c.getFontMetrics(m.font);
979        m.border = getBorder();
980        if (m.border != null)
981          m.borderInsets = m.border.getBorderInsets(c);
982        else
983          m.borderInsets = new Insets(0, 0, 0, 0);
984    
985        if (title != null)
986      {      {
987          s.left = s.right = s.top = s.bottom = 5;        m.trimmedText = title.trim();
988          return s;        if (m.trimmedText.length() == 0)
989            m.trimmedText = null;
990      }      }
991            
992        m.textAscent = fmet.getAscent();
993        m.textDescent = fmet.getDescent();
994        if (m.trimmedText != null)
995          m.textWidth = fmet.stringWidth(m.trimmedText) + 3;
996    
997        m.edgeSpacing = new Insets(EDGE_SPACING, EDGE_SPACING, EDGE_SPACING, EDGE_SPACING);
998        m.borderSpacing = new Insets(0, 0, 0, 0);
999    
1000        switch (titlePosition)
1001        {
1002        case ABOVE_TOP:
1003          m.borderSpacing.top += m.textAscent + m.textDescent + TEXT_SPACING;
1004          break;
1005    
1006        case BELOW_TOP:
1007          m.edgeSpacing.top += m.textAscent + m.textDescent + TEXT_SPACING;
1008          break;
1009    
1010        case ABOVE_BOTTOM:
1011          m.edgeSpacing.bottom += m.textAscent + m.textDescent + TEXT_SPACING;
1012          break;
1013    
1014        case BOTTOM:
1015          m.edgeSpacing.bottom += Math.max(m.textAscent - m.borderInsets.bottom, 0);
1016          m.borderSpacing.bottom += m.textDescent;
1017          break;
1018    
1019        case BELOW_BOTTOM:
1020          m.borderSpacing.bottom += m.textAscent + m.textDescent + TEXT_SPACING;
1021          break;
1022    
1023        default:
1024          m.borderSpacing.top += m.textAscent;
1025        }
1026    
1027        return m;
1028      }
1029    
1030    
1031      /**
1032       * A private helper class for holding the result of measuring the
1033       * distances of a TitledBorder.  While it would be possible to cache
1034       * these objects, it does not seem to be worth the effort. Note that
1035       * invalidating the cache would be tricky, especially since there is
1036       * no notification mechanism that would inform the cache when
1037       * border has changed, so it would return different insets.
1038       */
1039      private static class Measurements
1040      {
1041        /**
1042         * The font used for displaying the title text. Note that it can
1043         * well be that the TitledBorder&#x2019;s font is <code>null</code>,
1044         * which means that the font is to be retrieved from the current
1045         * LookAndFeel. In this case, this <code>font</code> field will
1046         * contain the result of the retrieval. Therefore, it is safe
1047         * to assume that his <code>font</code> field will never have
1048         * a <code>null</code> value.
1049         */
1050        Font font;
1051    
1052    
1053        /**
1054         * The number of pixels between the base line and the top of the
1055         * text box.
1056         */
1057        int textAscent;
1058    
1059    
1060        /**
1061         * The number of pixels between the base line and the bottom of
1062         * the text box.
1063         */
1064        int textDescent;
1065    
1066    
1067        /**
1068         * The title text after removing leading and trailing white space
1069         * characters. If the title consists only of white space, the
1070         * value of <code>trimmedText</code> will be <code>null</code>.
1071         */
1072        String trimmedText;
1073    
1074    
1075        /**
1076         * The width of the trimmed title text in pixels.
1077         */
1078        int textWidth;
1079    
1080    
1081        /**
1082         * The border that constitues the &quot;interior&quot; border
1083         * underneath the title text.
1084         */
1085        Border border;
1086    
1087    
1088        /**
1089         * The distance between the TitledBorder and the interior border.
1090         */
1091        Insets borderSpacing;
1092    
1093            
1094        /**
1095         * The width of the interior border, as returned by
1096         * <code>border.getBorderInsets()</code>.
1097         */
1098        Insets borderInsets;
1099    
1100            
1101      public boolean isBorderOpaque()      /**
1102         * The distance between the interior border and the nested
1103         * Component for which this TitledBorder is a border.
1104         */
1105        Insets edgeSpacing;
1106    
1107    
1108        /**
1109         * Determines the insets of the nested component when it has a
1110         * TitledBorder as its border. Used by {@link
1111         * TitledBorder#getBorderInsets()}.
1112         *
1113         * @param i an Insets object for storing the results into, or
1114         *        <code>null</code> to cause the creation of a
1115         *        new instance.
1116         *
1117         * @return the <code>i</code> object, or a new Insets object
1118         *         if <code>null</code> was passed for <code>i</code>.
1119         */
1120        public Insets getContentInsets(Insets i)
1121      {      {
1122          return false;        if (i == null)
1123            i = new Insets(0, 0, 0, 0);
1124          i.left = borderSpacing.left + borderInsets.left + edgeSpacing.left;
1125          i.right = borderSpacing.right + borderInsets.right + edgeSpacing.right;
1126          i.top = borderSpacing.top + borderInsets.top + edgeSpacing.top;
1127          i.bottom = borderSpacing.bottom + borderInsets.bottom + edgeSpacing.bottom;
1128          return i;
1129      }      }
1130        
1131      public void paintBorder(Component c,  
1132                              Graphics  g,      /**
1133                              int  x,       * Calculates the minimum size needed for displaying the border
1134                              int  y,       * and its title. Used by {@link TitledBorder#getMiminumSize()}.
1135                              int  width,       */
1136                              int  height)      public Dimension getMinimumSize()
1137      {      {
1138          int width;
1139          Insets insets;
1140    
1141          insets = getContentInsets(null);
1142          width = Math.max(insets.left + insets.right, textWidth + 2 * TEXT_INSET_H);
1143          return new Dimension(width, insets.top + insets.bottom);
1144      }      }
1145      }
1146  }  }
   

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26