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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [swing/] [plaf/] [basic/] [BasicGraphicsUtils.java] - Blame information for rev 772

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* BasicGraphicsUtils.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
package javax.swing.plaf.basic;
39
 
40
import gnu.classpath.SystemProperties;
41
 
42
import java.awt.Color;
43
import java.awt.Dimension;
44
import java.awt.Font;
45
import java.awt.FontMetrics;
46
import java.awt.Graphics;
47
import java.awt.Graphics2D;
48
import java.awt.Insets;
49
import java.awt.Rectangle;
50
import java.awt.font.FontRenderContext;
51
import java.awt.font.LineMetrics;
52
import java.awt.font.TextLayout;
53
import java.awt.geom.Rectangle2D;
54
 
55
import javax.swing.AbstractButton;
56
import javax.swing.Icon;
57
import javax.swing.JComponent;
58
import javax.swing.SwingUtilities;
59
 
60
 
61
/**
62
 * A utility class providing commonly used drawing and measurement
63
 * routines.
64
 *
65
 * @author Sascha Brawer (brawer@dandelis.ch)
66
 */
67
public class BasicGraphicsUtils
68
{
69
  /**
70
   * Used as a key for a client property to store cached TextLayouts in. This
71
   * is used for speed-up drawing of text in
72
   * {@link #drawString(Graphics, String, int, int, int)}.
73
   */
74
  static final String CACHED_TEXT_LAYOUT =
75
    "BasicGraphicsUtils.cachedTextLayout";
76
 
77
  /**
78
   * Constructor. It is utterly unclear why this class should
79
   * be constructable, but this is what the API specification
80
   * says.
81
   */
82
  public BasicGraphicsUtils()
83
  {
84
    // Nothing to do here.
85
  }
86
 
87
 
88
  /**
89
   * Draws a rectangle that appears etched into the surface, given
90
   * four colors that are used for drawing.
91
   *
92
   * <p><img src="doc-files/BasicGraphicsUtils-1.png" width="360"
93
   * height="200" alt="[An illustration that shows which pixels
94
   * get painted in what color]" />
95
   *
96
   * @param g the graphics into which the rectangle is drawn.
97
   * @param x the x coordinate of the rectangle.
98
   * @param y the y coordinate of the rectangle.
99
   * @param width the width of the rectangle in pixels.
100
   * @param height the height of the rectangle in pixels.
101
   *
102
   * @param shadow the color that will be used for painting
103
   *        the outer side of the top and left edges.
104
   *
105
   * @param darkShadow the color that will be used for painting
106
   *        the inner side of the top and left edges.
107
   *
108
   * @param highlight the color that will be used for painting
109
   *        the inner side of the bottom and right edges.
110
   *
111
   * @param lightHighlight the color that will be used for painting
112
   *        the outer side of the bottom and right edges.
113
   *
114
   * @see #getEtchedInsets()
115
   * @see javax.swing.border.EtchedBorder
116
   */
117
  public static void drawEtchedRect(Graphics g,
118
                                    int x, int y, int width, int height,
119
                                    Color shadow, Color darkShadow,
120
                                    Color highlight, Color lightHighlight)
121
  {
122
    Color oldColor;
123
    int x2, y2;
124
 
125
    oldColor = g.getColor();
126
    x2 = x + width - 1;
127
    y2 = y + height - 1;
128
 
129
    try
130
    {
131
      /* To understand this code, it might be helpful to look at the
132
       * image "BasicGraphicsUtils-1.png" that is included with the
133
       * JavaDoc. The file is located in the "doc-files" subdirectory.
134
       *
135
       * (x2, y2) is the coordinate of the most right and bottom pixel
136
       * to be painted.
137
       */
138
      g.setColor(shadow);
139
      g.drawLine(x, y, x2 - 1, y);                     // top, outer
140
      g.drawLine(x, y + 1, x, y2 - 1);                 // left, outer
141
 
142
      g.setColor(darkShadow);
143
      g.drawLine(x + 1, y + 1, x2 - 2, y + 1);         // top, inner
144
      g.drawLine(x + 1, y + 2, x + 1, y2 - 2);         // left, inner
145
 
146
      g.setColor(highlight);
147
      g.drawLine(x + 1, y2 - 1, x2 - 1, y2 - 1);       // bottom, inner
148
      g.drawLine(x2 - 1, y + 1, x2 - 1, y2 - 2);       // right, inner
149
 
150
      g.setColor(lightHighlight);
151
      g.drawLine(x, y2, x2, y2);                       // bottom, outer
152
      g.drawLine(x2, y, x2, y2 - 1);                   // right, outer
153
    }
154
    finally
155
    {
156
      g.setColor(oldColor);
157
    }
158
  }
159
 
160
 
161
  /**
162
   * Determines the width of the border that gets painted by
163
   * {@link #drawEtchedRect}.
164
   *
165
   * @return an <code>Insets</code> object whose <code>top</code>,
166
   *         <code>left</code>, <code>bottom</code> and
167
   *         <code>right</code> field contain the border width at the
168
   *         respective edge in pixels.
169
   */
170
  public static Insets getEtchedInsets()
171
  {
172
    return new Insets(2, 2, 2, 2);
173
  }
174
 
175
 
176
  /**
177
   * Draws a rectangle that appears etched into the surface, given
178
   * two colors that are used for drawing.
179
   *
180
   * <p><img src="doc-files/BasicGraphicsUtils-2.png" width="360"
181
   * height="200" alt="[An illustration that shows which pixels
182
   * get painted in what color]" />
183
   *
184
   * @param g the graphics into which the rectangle is drawn.
185
   * @param x the x coordinate of the rectangle.
186
   * @param y the y coordinate of the rectangle.
187
   * @param width the width of the rectangle in pixels.
188
   * @param height the height of the rectangle in pixels.
189
   *
190
   * @param shadow the color that will be used for painting the outer
191
   *        side of the top and left edges, and for the inner side of
192
   *        the bottom and right ones.
193
   *
194
   * @param highlight the color that will be used for painting the
195
   *        inner side of the top and left edges, and for the outer
196
   *        side of the bottom and right ones.
197
   *
198
   * @see #getGrooveInsets()
199
   * @see javax.swing.border.EtchedBorder
200
   */
201
  public static void drawGroove(Graphics g,
202
                                int x, int y, int width, int height,
203
                                Color shadow, Color highlight)
204
  {
205
    /* To understand this, it might be helpful to look at the image
206
     * "BasicGraphicsUtils-2.png" that is included with the JavaDoc,
207
     * and to compare it with "BasicGraphicsUtils-1.png" which shows
208
     * the pixels painted by drawEtchedRect.  These image files are
209
     * located in the "doc-files" subdirectory.
210
     */
211
    drawEtchedRect(g, x, y, width, height,
212
                   /* outer topLeft */     shadow,
213
                   /* inner topLeft */     highlight,
214
                   /* inner bottomRight */ shadow,
215
                   /* outer bottomRight */ highlight);
216
  }
217
 
218
 
219
  /**
220
   * Determines the width of the border that gets painted by
221
   * {@link #drawGroove}.
222
   *
223
   * @return an <code>Insets</code> object whose <code>top</code>,
224
   *         <code>left</code>, <code>bottom</code> and
225
   *         <code>right</code> field contain the border width at the
226
   *         respective edge in pixels.
227
   */
228
  public static Insets getGrooveInsets()
229
  {
230
    return new Insets(2, 2, 2, 2);
231
  }
232
 
233
 
234
  /**
235
   * Draws a border that is suitable for buttons of the Basic look and
236
   * feel.
237
   *
238
   * <p><img src="doc-files/BasicGraphicsUtils-3.png" width="500"
239
   * height="300" alt="[An illustration that shows which pixels
240
   * get painted in what color]" />
241
   *
242
   * @param g the graphics into which the rectangle is drawn.
243
   * @param x the x coordinate of the rectangle.
244
   * @param y the y coordinate of the rectangle.
245
   * @param width the width of the rectangle in pixels.
246
   * @param height the height of the rectangle in pixels.
247
   *
248
   * @param isPressed <code>true</code> to draw the button border
249
   *        with a pressed-in appearance; <code>false</code> for
250
   *        normal (unpressed) appearance.
251
   *
252
   * @param isDefault <code>true</code> to draw the border with
253
   *        the appearance it has when hitting the enter key in a
254
   *        dialog will simulate a click to this button;
255
   *        <code>false</code> for normal appearance.
256
   *
257
   * @param shadow the shadow color.
258
   * @param darkShadow a darker variant of the shadow color.
259
   * @param highlight the highlight color.
260
   * @param lightHighlight a brighter variant of the highlight  color.
261
   */
262
  public static void drawBezel(Graphics g,
263
                               int x, int y, int width, int height,
264
                               boolean isPressed, boolean isDefault,
265
                               Color shadow, Color darkShadow,
266
                               Color highlight, Color lightHighlight)
267
  {
268
    Color oldColor = g.getColor();
269
 
270
    /* To understand this, it might be helpful to look at the image
271
     * "BasicGraphicsUtils-3.png" that is included with the JavaDoc,
272
     * and to compare it with "BasicGraphicsUtils-1.png" which shows
273
     * the pixels painted by drawEtchedRect.  These image files are
274
     * located in the "doc-files" subdirectory.
275
     */
276
    try
277
    {
278
      if ((isPressed == false) && (isDefault == false))
279
      {
280
        drawEtchedRect(g, x, y, width, height,
281
                       lightHighlight, highlight,
282
                       shadow, darkShadow);
283
      }
284
 
285
      if ((isPressed == true) && (isDefault == false))
286
      {
287
        g.setColor(shadow);
288
        g.drawRect(x + 1, y + 1, width - 2, height - 2);
289
      }
290
 
291
      if ((isPressed == false) && (isDefault == true))
292
      {
293
        g.setColor(darkShadow);
294
        g.drawRect(x, y, width - 1, height - 1);
295
        drawEtchedRect(g, x + 1, y + 1, width - 2, height - 2,
296
                       lightHighlight, highlight,
297
                       shadow, darkShadow);
298
      }
299
 
300
      if ((isPressed == true) && (isDefault == true))
301
      {
302
        g.setColor(darkShadow);
303
        g.drawRect(x, y, width - 1, height - 1);
304
        g.setColor(shadow);
305
        g.drawRect(x + 1, y + 1, width - 3, height - 3);
306
      }
307
    }
308
    finally
309
    {
310
      g.setColor(oldColor);
311
    }
312
  }
313
 
314
 
315
  /**
316
   * Draws a rectangle that appears lowered into the surface, given
317
   * four colors that are used for drawing.
318
   *
319
   * <p><img src="doc-files/BasicGraphicsUtils-4.png" width="360"
320
   * height="200" alt="[An illustration that shows which pixels
321
   * get painted in what color]" />
322
   *
323
   * <p><strong>Compatibility with the Sun reference
324
   * implementation:</strong> The Sun reference implementation seems
325
   * to ignore the <code>x</code> and <code>y</code> arguments, at
326
   * least in JDK 1.3.1 and 1.4.1_01.  The method always draws the
327
   * rectangular area at location (0, 0). A bug report has been filed
328
   * with Sun; its &#x201c;bug ID&#x201d; is 4880003.  The GNU Classpath
329
   * implementation behaves correctly, thus not replicating this bug.
330
   *
331
   * @param g the graphics into which the rectangle is drawn.
332
   * @param x the x coordinate of the rectangle.
333
   * @param y the y coordinate of the rectangle.
334
   * @param width the width of the rectangle in pixels.
335
   * @param height the height of the rectangle in pixels.
336
   *
337
   * @param shadow the color that will be used for painting
338
   *        the inner side of the top and left edges.
339
   *
340
   * @param darkShadow the color that will be used for painting
341
   *        the outer side of the top and left edges.
342
   *
343
   * @param highlight the color that will be used for painting
344
   *        the inner side of the bottom and right edges.
345
   *
346
   * @param lightHighlight the color that will be used for painting
347
   *        the outer side of the bottom and right edges.
348
   */
349
  public static void drawLoweredBezel(Graphics g,
350
                                      int x, int y, int width, int height,
351
                                      Color shadow, Color darkShadow,
352
                                      Color highlight, Color lightHighlight)
353
  {
354
    /* Like drawEtchedRect, but swapping darkShadow and shadow.
355
     *
356
     * To understand this, it might be helpful to look at the image
357
     * "BasicGraphicsUtils-4.png" that is included with the JavaDoc,
358
     * and to compare it with "BasicGraphicsUtils-1.png" which shows
359
     * the pixels painted by drawEtchedRect.  These image files are
360
     * located in the "doc-files" subdirectory.
361
     */
362
    drawEtchedRect(g, x, y, width, height,
363
                   darkShadow, shadow,
364
                   highlight, lightHighlight);
365
  }
366
 
367
 
368
  /**
369
   * Draws a String at the given location, underlining the first
370
   * occurence of a specified character. The algorithm for determining
371
   * the underlined position is not sensitive to case. If the
372
   * character is not part of <code>text</code>, the text will be
373
   * drawn without underlining. Drawing is performed in the current
374
   * color and font of <code>g</code>.
375
   *
376
   * <p><img src="doc-files/BasicGraphicsUtils-5.png" width="500"
377
   * height="100" alt="[An illustration showing how to use the
378
   * method]" />
379
   *
380
   * @param g the graphics into which the String is drawn.
381
   *
382
   * @param text the String to draw.
383
   *
384
   * @param underlinedChar the character whose first occurence in
385
   *        <code>text</code> will be underlined. It is not clear
386
   *        why the API specification declares this argument to be
387
   *        of type <code>int</code> instead of <code>char</code>.
388
   *        While this would allow to pass Unicode characters outside
389
   *        Basic Multilingual Plane 0 (U+0000 .. U+FFFE), at least
390
   *        the GNU Classpath implementation does not underline
391
   *        anything if <code>underlinedChar</code> is outside
392
   *        the range of <code>char</code>.
393
   *
394
   * @param x the x coordinate of the text, as it would be passed to
395
   *        {@link java.awt.Graphics#drawString(java.lang.String,
396
   *        int, int)}.
397
   *
398
   * @param y the y coordinate of the text, as it would be passed to
399
   *        {@link java.awt.Graphics#drawString(java.lang.String,
400
   *        int, int)}.
401
   */
402
  public static void drawString(Graphics g, String text,
403
                                int underlinedChar, int x, int y)
404
  {
405
    int index = -1;
406
 
407
    /* It is intentional that lower case is used. In some languages,
408
     * the set of lowercase characters is larger than the set of
409
     * uppercase ones. Therefore, it is good practice to use lowercase
410
     * for such comparisons (which really means that the author of this
411
     * code can vaguely remember having read some Unicode techreport
412
     * with this recommendation, but is too lazy to look for the URL).
413
     */
414
    if ((underlinedChar >= 0) || (underlinedChar <= 0xffff))
415
      index = text.toLowerCase().indexOf(
416
        Character.toLowerCase((char) underlinedChar));
417
 
418
    drawStringUnderlineCharAt(g, text, index, x, y);
419
  }
420
 
421
 
422
  /**
423
   * Draws a String at the given location, underlining the character
424
   * at the specified index. Drawing is performed in the current color
425
   * and font of <code>g</code>.
426
   *
427
   * <p><img src="doc-files/BasicGraphicsUtils-5.png" width="500"
428
   * height="100" alt="[An illustration showing how to use the
429
   * method]" />
430
   *
431
   * @param g the graphics into which the String is drawn.
432
   *
433
   * @param text the String to draw.
434
   *
435
   * @param underlinedIndex the index of the underlined character in
436
   *        <code>text</code>.  If <code>underlinedIndex</code> falls
437
   *        outside the range <code>[0, text.length() - 1]</code>, the
438
   *        text will be drawn without underlining anything.
439
   *
440
   * @param x the x coordinate of the text, as it would be passed to
441
   *        {@link java.awt.Graphics#drawString(java.lang.String,
442
   *        int, int)}.
443
   *
444
   * @param y the y coordinate of the text, as it would be passed to
445
   *        {@link java.awt.Graphics#drawString(java.lang.String,
446
   *        int, int)}.
447
   *
448
   * @since 1.4
449
   */
450
  public static void drawStringUnderlineCharAt(Graphics g, String text,
451
                                               int underlinedIndex,
452
                                               int x, int y)
453
  {
454
    Graphics2D g2;
455
    Rectangle2D.Double underline;
456
    FontRenderContext frc;
457
    FontMetrics fmet;
458
    LineMetrics lineMetrics;
459
    Font font;
460
    TextLayout layout;
461
    double underlineX1, underlineX2;
462
    boolean drawUnderline;
463
    int textLength;
464
 
465
    textLength = text.length();
466
    if (textLength == 0)
467
      return;
468
 
469
    drawUnderline = (underlinedIndex >= 0) && (underlinedIndex < textLength);
470
 
471
    // FIXME: unfortunately pango and cairo can't agree on metrics
472
    // so for the time being we continue to *not* use TextLayouts.
473
    if (true || !(g instanceof Graphics2D))
474
    {
475
      /* Fall-back. This is likely to produce garbage for any text
476
       * containing right-to-left (Hebrew or Arabic) characters, even
477
       * if the underlined character is left-to-right.
478
       */
479
      g.drawString(text, x, y);
480
      if (drawUnderline)
481
      {
482
        fmet = g.getFontMetrics();
483
        g.fillRect(
484
          /* x */ x + fmet.stringWidth(text.substring(0, underlinedIndex)),
485
          /* y */ y + fmet.getDescent() - 1,
486
          /* width */ fmet.charWidth(text.charAt(underlinedIndex)),
487
          /* height */ 1);
488
      }
489
 
490
      return;
491
    }
492
 
493
    g2 = (Graphics2D) g;
494
    font = g2.getFont();
495
    frc = g2.getFontRenderContext();
496
    lineMetrics = font.getLineMetrics(text, frc);
497
    layout = new TextLayout(text, font, frc);
498
 
499
    /* Draw the text. */
500
    layout.draw(g2, x, y);
501
    if (!drawUnderline)
502
      return;
503
 
504
    underlineX1 = x + layout.getLogicalHighlightShape(
505
     underlinedIndex, underlinedIndex).getBounds2D().getX();
506
    underlineX2 = x + layout.getLogicalHighlightShape(
507
     underlinedIndex + 1, underlinedIndex + 1).getBounds2D().getX();
508
 
509
    underline = new Rectangle2D.Double();
510
    if (underlineX1 < underlineX2)
511
    {
512
      underline.x = underlineX1;
513
      underline.width = underlineX2 - underlineX1;
514
    }
515
    else
516
    {
517
      underline.x = underlineX2;
518
      underline.width = underlineX1 - underlineX2;
519
    }
520
 
521
 
522
    underline.height = lineMetrics.getUnderlineThickness();
523
    underline.y = lineMetrics.getUnderlineOffset();
524
    if (underline.y == 0)
525
    {
526
      /* Some fonts do not specify an underline offset, although they
527
       * actually should do so. In that case, the result of calling
528
       * lineMetrics.getUnderlineOffset() will be zero. Since it would
529
       * look very ugly if the underline was be positioned immediately
530
       * below the baseline, we check for this and move the underline
531
       * below the descent, as shown in the following ASCII picture:
532
       *
533
       *   #####       ##### #
534
       *  #     #     #     #
535
       *  #     #     #     #
536
       *  #     #     #     #
537
       *   #####       ######        ---- baseline (0)
538
       *                    #
539
       *                    #
540
       * ------------------###----------- lineMetrics.getDescent()
541
       */
542
      underline.y = lineMetrics.getDescent();
543
    }
544
 
545
    underline.y += y;
546
    g2.fill(underline);
547
  }
548
 
549
  /**
550
   * Draws a string on the specified component.
551
   *
552
   * @param c the component
553
   * @param g the Graphics context
554
   * @param text the string
555
   * @param underlinedChar the character to be underlined
556
   * @param x the X location
557
   * @param y the Y location
558
   */
559
  static void drawString(JComponent c, Graphics g, String text,
560
                                int underlinedChar, int x, int y)
561
  {
562
    int index = -1;
563
 
564
    /* It is intentional that lower case is used. In some languages,
565
     * the set of lowercase characters is larger than the set of
566
     * uppercase ones. Therefore, it is good practice to use lowercase
567
     * for such comparisons (which really means that the author of this
568
     * code can vaguely remember having read some Unicode techreport
569
     * with this recommendation, but is too lazy to look for the URL).
570
     */
571
    if ((underlinedChar >= 0) || (underlinedChar <= 0xffff))
572
      index = text.toLowerCase().indexOf(
573
        Character.toLowerCase((char) underlinedChar));
574
 
575
    drawStringUnderlineCharAt(c, g, text, index, x, y);
576
  }
577
 
578
 
579
  /**
580
   * Draws a String at the given location, underlining the character
581
   * at the specified index. Drawing is performed in the current color
582
   * and font of <code>g</code>.
583
   *
584
   * <p><img src="doc-files/BasicGraphicsUtils-5.png" width="500"
585
   * height="100" alt="[An illustration showing how to use the
586
   * method]" />
587
   *
588
   * This is an accelerated version of the method with the same name. It
589
   * uses a pre-laid out TextLayout stored in a client property.
590
   *
591
   * @param c the component that is drawn
592
   * @param g the graphics into which the String is drawn.
593
   *
594
   * @param text the String to draw.
595
   *
596
   * @param underlinedIndex the index of the underlined character in
597
   *        <code>text</code>.  If <code>underlinedIndex</code> falls
598
   *        outside the range <code>[0, text.length() - 1]</code>, the
599
   *        text will be drawn without underlining anything.
600
   *
601
   * @param x the x coordinate of the text, as it would be passed to
602
   *        {@link java.awt.Graphics#drawString(java.lang.String,
603
   *        int, int)}.
604
   *
605
   * @param y the y coordinate of the text, as it would be passed to
606
   *        {@link java.awt.Graphics#drawString(java.lang.String,
607
   *        int, int)}.
608
   */
609
  static void drawStringUnderlineCharAt(JComponent c, Graphics g, String text,
610
                                        int underlinedIndex,
611
                                        int x, int y)
612
  {
613
    Graphics2D g2;
614
    Rectangle2D.Double underline;
615
    FontRenderContext frc;
616
    FontMetrics fmet;
617
    LineMetrics lineMetrics;
618
    Font font;
619
    TextLayout layout;
620
    double underlineX1, underlineX2;
621
    boolean drawUnderline;
622
    int textLength;
623
 
624
    textLength = text.length();
625
    if (textLength == 0)
626
      return;
627
 
628
    drawUnderline = (underlinedIndex >= 0) && (underlinedIndex < textLength);
629
 
630
    // FIXME: unfortunately pango and cairo can't agree on metrics
631
    // so for the time being we continue to *not* use TextLayouts.
632
    if (!(g instanceof Graphics2D)
633
       || SystemProperties.getProperty("gnu.javax.swing.noGraphics2D") != null)
634
    {
635
      /* Fall-back. This is likely to produce garbage for any text
636
       * containing right-to-left (Hebrew or Arabic) characters, even
637
       * if the underlined character is left-to-right.
638
       */
639
      g.drawString(text, x, y);
640
      if (drawUnderline)
641
      {
642
        fmet = g.getFontMetrics();
643
        g.fillRect(
644
          /* x */ x + fmet.stringWidth(text.substring(0, underlinedIndex)),
645
          /* y */ y + 1,
646
          /* width */ fmet.charWidth(text.charAt(underlinedIndex)),
647
          /* height */ 1);
648
      }
649
 
650
      return;
651
    }
652
 
653
    g2 = (Graphics2D) g;
654
    font = g2.getFont();
655
    frc = g2.getFontRenderContext();
656
    lineMetrics = font.getLineMetrics(text, frc);
657
    layout = (TextLayout) c.getClientProperty(CACHED_TEXT_LAYOUT);
658
    if (layout == null)
659
      {
660
        layout = new TextLayout(text, font, frc);
661
        System.err.println("Unable to use cached TextLayout for: " + text);
662
      }
663
 
664
    /* Draw the text. */
665
    layout.draw(g2, x, y);
666
    if (!drawUnderline)
667
      return;
668
 
669
    underlineX1 = x + layout.getLogicalHighlightShape(
670
     underlinedIndex, underlinedIndex).getBounds2D().getX();
671
    underlineX2 = x + layout.getLogicalHighlightShape(
672
     underlinedIndex + 1, underlinedIndex + 1).getBounds2D().getX();
673
 
674
    underline = new Rectangle2D.Double();
675
    if (underlineX1 < underlineX2)
676
    {
677
      underline.x = underlineX1;
678
      underline.width = underlineX2 - underlineX1;
679
    }
680
    else
681
    {
682
      underline.x = underlineX2;
683
      underline.width = underlineX1 - underlineX2;
684
    }
685
 
686
 
687
    underline.height = lineMetrics.getUnderlineThickness();
688
    underline.y = lineMetrics.getUnderlineOffset();
689
    if (underline.y == 0)
690
    {
691
      /* Some fonts do not specify an underline offset, although they
692
       * actually should do so. In that case, the result of calling
693
       * lineMetrics.getUnderlineOffset() will be zero. Since it would
694
       * look very ugly if the underline was be positioned immediately
695
       * below the baseline, we check for this and move the underline
696
       * below the descent, as shown in the following ASCII picture:
697
       *
698
       *   #####       ##### #
699
       *  #     #     #     #
700
       *  #     #     #     #
701
       *  #     #     #     #
702
       *   #####       ######        ---- baseline (0)
703
       *                    #
704
       *                    #
705
       * ------------------###----------- lineMetrics.getDescent()
706
       */
707
      underline.y = lineMetrics.getDescent();
708
    }
709
 
710
    underline.y += y;
711
    g2.fill(underline);
712
  }
713
 
714
  /**
715
   * Draws a rectangle, simulating a dotted stroke by painting only
716
   * every second pixel along the one-pixel thick edge. The color of
717
   * those pixels is the current color of the Graphics <code>g</code>.
718
   * Any other pixels are left unchanged.
719
   *
720
   * <p><img src="doc-files/BasicGraphicsUtils-7.png" width="360"
721
   * height="200" alt="[An illustration that shows which pixels
722
   * get painted]" />
723
   *
724
   * @param g the graphics into which the rectangle is drawn.
725
   * @param x the x coordinate of the rectangle.
726
   * @param y the y coordinate of the rectangle.
727
   * @param width the width of the rectangle in pixels.
728
   * @param height the height of the rectangle in pixels.
729
   */
730
  public static void drawDashedRect(Graphics g,
731
                                    int x, int y, int width, int height)
732
  {
733
    int right = x + width - 1;
734
    int bottom = y + height - 1;
735
 
736
    /* Draw the top and bottom edge of the dotted rectangle. */
737
    for (int i = x; i <= right; i += 2)
738
    {
739
      g.drawLine(i, y, i, y);
740
      g.drawLine(i, bottom, i, bottom);
741
    }
742
 
743
    /* Draw the left and right edge of the dotted rectangle. */
744
    for (int i = y; i <= bottom; i += 2)
745
    {
746
      g.drawLine(x, i, x, i);
747
      g.drawLine(right, i, right, i);
748
    }
749
  }
750
 
751
  /**
752
   * Determines the preferred width and height of an AbstractButton,
753
   * given the gap between the button&#x2019;s text and icon.
754
   *
755
   * @param b the button whose preferred size is determined.
756
   *
757
   * @param textIconGap the gap between the button&#x2019;s text and
758
   *        icon.
759
   *
760
   * @return a <code>Dimension</code> object whose <code>width</code>
761
   *         and <code>height</code> fields indicate the preferred
762
   *         extent in pixels.
763
   *
764
   * @see javax.swing.SwingUtilities#layoutCompoundLabel(JComponent,
765
   *      FontMetrics, String, Icon, int, int, int, int, Rectangle, Rectangle,
766
   *      Rectangle, int)
767
   */
768
  public static Dimension getPreferredButtonSize(AbstractButton b,
769
                                                 int textIconGap)
770
  {
771
    // These cached rectangles are use here and in BasicButtonUI.paint(),
772
    // so these two methods must never be executed concurrently. Maybe
773
    // we must use other Rectangle instances here. OTOH, Swing is
774
    // designed to be not thread safe, and every layout and paint operation
775
    // should be performed from the EventDispatchThread, so it _should_ be
776
    // OK to do this optimization.
777
    Rectangle viewRect = BasicButtonUI.viewR;
778
    viewRect.x = 0;
779
    viewRect.y = 0;
780
    viewRect.width = Short.MAX_VALUE;
781
    viewRect.height = Short.MAX_VALUE;
782
    Rectangle iconRect = BasicButtonUI.iconR;
783
    iconRect.x = 0;
784
    iconRect.y = 0;
785
    iconRect.width = 0;
786
    iconRect.height = 0;
787
    Rectangle textRect = BasicButtonUI.textR;
788
    textRect.x = 0;
789
    textRect.y = 0;
790
    textRect.width = 0;
791
    textRect.height = 0;
792
 
793
   SwingUtilities.layoutCompoundLabel(
794
      b, // for the component orientation
795
      b.getFontMetrics(b.getFont()), // see comment above
796
      b.getText(),
797
      b.getIcon(),
798
      b.getVerticalAlignment(),
799
      b.getHorizontalAlignment(),
800
      b.getVerticalTextPosition(),
801
      b.getHorizontalTextPosition(),
802
      viewRect, iconRect, textRect,
803
      textIconGap);
804
 
805
    /*  +------------------------+       +------------------------+
806
     *  |                        |       |                        |
807
     *  | ICON                   |       | CONTENTCONTENTCONTENT  |
808
     *  |          TEXTTEXTTEXT  |  -->  | CONTENTCONTENTCONTENT  |
809
     *  |          TEXTTEXTTEXT  |       | CONTENTCONTENTCONTENT  |
810
     *  +------------------------+       +------------------------+
811
     */
812
 
813
    Rectangle contentRect =
814
      SwingUtilities.computeUnion(textRect.x, textRect.y, textRect.width,
815
                                  textRect.height, iconRect);
816
 
817
    Insets insets = b.getInsets();
818
    return new Dimension(insets.left + contentRect.width + insets.right,
819
                         insets.top + contentRect.height + insets.bottom);
820
  }
821
}

powered by: WebSVN 2.1.0

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