OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [javax/] [swing/] [border/] [TitledBorder.java] - Blame information for rev 14

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.