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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* BasicBorders.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.plaf.basic;
40
 
41
import java.awt.Color;
42
import java.awt.Component;
43
import java.awt.Graphics;
44
import java.awt.Insets;
45
import java.awt.Rectangle;
46
import java.io.Serializable;
47
 
48
import javax.swing.AbstractButton;
49
import javax.swing.ButtonModel;
50
import javax.swing.JButton;
51
import javax.swing.JPopupMenu;
52
import javax.swing.JSplitPane;
53
import javax.swing.JToolBar;
54
import javax.swing.UIManager;
55
import javax.swing.border.AbstractBorder;
56
import javax.swing.border.BevelBorder;
57
import javax.swing.border.Border;
58
import javax.swing.plaf.BorderUIResource;
59
import javax.swing.plaf.UIResource;
60
import javax.swing.text.JTextComponent;
61
 
62
/**
63
 * Provides various borders for the Basic look and feel.
64
 *
65
 * @author Sascha Brawer (brawer@dandelis.ch)
66
 */
67
public class BasicBorders
68
{
69
  /**
70
   * A MarginBorder that gets shared by multiple components.
71
   * Created on demand by the private helper function {@link
72
   * #getMarginBorder()}.
73
   */
74
  private static MarginBorder sharedMarginBorder;
75
 
76
 
77
  /**
78
   * Returns a border for drawing push buttons.
79
   *
80
   * <p>The colors of the border are retrieved from the
81
   * <code>UIDefaults</code> of the currently active look and feel
82
   * using the keys <code>&#x201c;Button.shadow&#x201d;</code>,
83
   * <code>&#x201c;Button.darkShadow&#x201d;</code>,
84
   * <code>&#x201c;Button.light&#x201d;</code>, and
85
   * <code>&#x201c;Button.highlight&#x201d;</code>.
86
   *
87
   * <p><img src="doc-files/BasicBorders.ButtonBorder-1.png" width="300"
88
   * height="170" alt="[A screen shot of the returned border]" />
89
   *
90
   * @return a {@link
91
   *         javax.swing.plaf.BorderUIResource.CompoundBorderUIResource}
92
   *         whose outer border is a {@link ButtonBorder} and whose
93
   *         inner border is a {@link MarginBorder}.
94
   */
95
  public static Border getButtonBorder()
96
  {
97
    Border outer;
98
 
99
    /* The keys for UIDefaults have been determined by writing a
100
     * test program that dumps the UIDefaults to stdout; that program
101
     * was run on a JDK 1.4.1_01 for GNU/Linux. Note that in the API,
102
     * the key "light" is usually called "highlight", and "highlight"
103
     * is usually called "lightHighlight".
104
     */
105
    outer = new ButtonBorder(UIManager.getColor("Button.shadow"),
106
                             UIManager.getColor("Button.darkShadow"),
107
                             UIManager.getColor("Button.light"),
108
                             UIManager.getColor("Button.highlight"));
109
 
110
    /* While the inner border is shared between multiple buttons,
111
     * we do not share the outer border because ButtonBorders store
112
     * their border colors. We cannot guarantee that the colors
113
     * (which come from UIDefaults) are unchanged between invocations
114
     * of getButtonBorder. We could store the last colors, and share
115
     * the button border if the colors are the same as in the last
116
     * invocation, but it probably is not worth the effort.
117
     */
118
    return new BorderUIResource.CompoundBorderUIResource(
119
      outer,
120
      /* inner */ getMarginBorder());
121
  }
122
 
123
 
124
  /**
125
   * Returns a border for drawing radio buttons.
126
   *
127
   * <p>The colors of the border are retrieved from the
128
   * <code>UIDefaults</code> of the currently active look and feel
129
   * using the keys <code>&#x201c;RadioButton.shadow&#x201d;</code>,
130
   * <code>&#x201c;RadioButton.darkShadow&#x201d;</code>,
131
   * <code>&#x201c;RadioButton.light&#x201d;</code>, and
132
   * <code>&#x201c;RadioButton.highlight&#x201d;</code>.
133
   *
134
   * <p><img src="doc-files/BasicBorders.RadioButtonBorder-1.png" width="300"
135
   * height="135" alt="[A screen shot of the returned border]" />
136
   *
137
   * @return a {@link
138
   *         javax.swing.plaf.BorderUIResource.CompoundBorderUIResource}
139
   *         whose outer border is a {@link RadioButtonBorder} and whose
140
   *         inner border is a {@link MarginBorder}.
141
   */
142
  public static Border getRadioButtonBorder()
143
  {
144
    Border outer;
145
 
146
    /* The keys for UIDefaults have been determined by writing a
147
     * test program that dumps the UIDefaults to stdout; that program
148
     * was run on a JDK 1.4.1_01 for GNU/Linux. Note that in the API,
149
     * the key "light" is usually called "highlight", and "highlight"
150
     * is usually called "lightHighlight".
151
     */
152
    outer = new RadioButtonBorder(
153
      UIManager.getColor("RadioButton.shadow"),
154
      UIManager.getColor("RadioButton.darkShadow"),
155
      UIManager.getColor("RadioButton.light"),
156
      UIManager.getColor("RadioButton.highlight"));
157
 
158
    /* While the inner border is shared between multiple buttons, we
159
     * do not share the outer border because RadioButtonBorders, being
160
     * ButtonBorders, store their border colors. We cannot guarantee
161
     * that the colors (which come from UIDefaults) are unchanged
162
     * between invocations of getButtonBorder. We could store the last
163
     * colors, and share the button border if the colors are the same
164
     * as in the last invocation, but it probably is not worth the
165
     * effort.
166
     */
167
    return new BorderUIResource.CompoundBorderUIResource(
168
      outer,
169
      /* inner */ getMarginBorder());
170
  }
171
 
172
 
173
  /**
174
   * Returns a border for drawing toggle buttons.
175
   *
176
   * <p>The colors of the border are retrieved from the
177
   * <code>UIDefaults</code> of the currently active look and feel
178
   * using the keys <code>&#x201c;ToggleButton.shadow&#x201d;</code>,
179
   * <code>&#x201c;ToggleButton.darkShadow&#x201d;</code>,
180
   * <code>&#x201c;ToggleButton.light&#x201d;</code>, and
181
   * <code>&#x201c;ToggleButton.highlight&#x201d;</code>.
182
   *
183
   * <p><img src="doc-files/BasicBorders.ToggleButtonBorder-1.png" width="270"
184
   * height="135" alt="[A screen shot of the returned border]" />
185
   *
186
   * @return a {@link
187
   *         javax.swing.plaf.BorderUIResource.CompoundBorderUIResource}
188
   *         whose outer border is a {@link ToggleButtonBorder} and whose
189
   *         inner border is a {@link MarginBorder}.
190
   */
191
  public static Border getToggleButtonBorder()
192
  {
193
    Border outer;
194
 
195
    /* The keys for UIDefaults have been determined by writing a
196
     * test program that dumps the UIDefaults to stdout; that program
197
     * was run on a JDK 1.4.1_01 for GNU/Linux. Note that in the API,
198
     * the key "light" is usually called "highlight", and "highlight"
199
     * is usually called "lightHighlight".
200
     */
201
    outer = new ToggleButtonBorder(
202
      UIManager.getColor("ToggleButton.shadow"),
203
      UIManager.getColor("ToggleButton.darkShadow"),
204
      UIManager.getColor("ToggleButton.light"),
205
      UIManager.getColor("ToggleButton.highlight"));
206
 
207
    /* While the inner border is shared between multiple buttons, we
208
     * do not share the outer border because ToggleButtonBorders, being
209
     * ButtonBorders, store their border colors. We cannot guarantee
210
     * that the colors (which come from UIDefaults) are unchanged
211
     * between invocations of getButtonBorder. We could store the last
212
     * colors, and share the button border if the colors are the same
213
     * as in the last invocation, but it probably is not worth the
214
     * effort.
215
     */
216
    return new BorderUIResource.CompoundBorderUIResource(
217
      outer,
218
      /* inner */ getMarginBorder());
219
  }
220
 
221
 
222
  /**
223
   * Returns a border for drawing a two-pixel thick separator line
224
   * below menu bars.
225
   *
226
   * <p>The colors of the border are retrieved from the
227
   * <code>UIDefaults</code> of the currently active look and feel
228
   * using the keys <code>&#x201c;MenuBar.shadow&#x201d;</code> and
229
   * <code>&#x201c;MenuBar.highlight&#x201d;</code>.
230
   *
231
   * <p><img src="doc-files/BasicBorders.MenuBarBorder-1.png" width="500"
232
   * height="140" alt="[A screen shot of a JMenuBar with this border]" />
233
   *
234
   * @return a {@link MenuBarBorder}.
235
   *
236
   * @see javax.swing.JMenuBar
237
   */
238
  public static Border getMenuBarBorder()
239
  {
240
    /* See comment in methods above for why this border is not shared. */
241
    return new MenuBarBorder(UIManager.getColor("MenuBar.shadow"),
242
                             UIManager.getColor("MenuBar.highlight"));
243
  }
244
 
245
 
246
  /**
247
   * Returns a border for drawing a one-pixel thick border around
248
   * split panes that are interrupted where the divider joins the
249
   * border.
250
   *
251
   * <p>The colors of the border are retrieved from the
252
   * <code>UIDefaults</code> of the currently active look and feel
253
   * using the keys <code>&#x201c;SplitPane.darkShadow&#x201d;</code> and
254
   * <code>&#x201c;SplitPane.highlight&#x201d;</code>.
255
   *
256
   * <p><img src="doc-files/BasicBorders.SplitPaneBorder-1.png" width="520"
257
   * height="200" alt="[A screen shot for JSplitPane.HORIZONTAL_SPLIT]" />
258
   *
259
   * <p><img src="doc-files/BasicBorders.SplitPaneBorder-2.png" width="520"
260
   * height="200" alt="[A screen shot for JSplitPane.VERTICAL_SPLIT]" />
261
   *
262
   * @return a {@link SplitPaneBorder}.
263
   *
264
   * @see javax.swing.JSplitPane
265
   * @see #getSplitPaneDividerBorder()
266
   */
267
  public static Border getSplitPaneBorder()
268
  {
269
    /* See comment in methods above for why this border is not shared. */
270
    return new SplitPaneBorder(UIManager.getColor("SplitPane.highlight"),
271
                               UIManager.getColor("SplitPane.darkShadow"));
272
  }
273
 
274
 
275
  /**
276
   * Returns a border for drawing a one-pixel thick border around
277
   * the divider of split panes.
278
   *
279
   * <p>The colors of the edges that are adjacent to the child components
280
   * of the <code>JSplitPane</code> are retrieved from the
281
   * <code>UIDefaults</code> of the currently active look and feel
282
   * using the keys <code>&#x201c;SplitPane.darkShadow&#x201d;</code> and
283
   * <code>&#x201c;SplitPane.highlight&#x201d;</code>. The color of the
284
   * other two edges is the background color of the divider.
285
   *
286
   * <p><img src="doc-files/BasicBorders.SplitPaneDividerBorder-1.png"
287
   * width="520" height="200" alt=
288
   * "[A screen shot for JSplitPane.HORIZONTAL_SPLIT]" />
289
   *
290
   * @return an instance of <code>SplitPaneDividerBorder</code>, which is
291
   *         not a public API class of this package.
292
   *
293
   * @see javax.swing.JSplitPane
294
   * @see javax.swing.plaf.basic.BasicSplitPaneDivider
295
   * @see #getSplitPaneBorder()
296
   *
297
   * @since 1.3
298
   */
299
  public static Border getSplitPaneDividerBorder()
300
  {
301
    /* See comment in methods above for why this border is not shared. */
302
    return new SplitPaneDividerBorder();
303
  }
304
 
305
 
306
  /**
307
   * Returns a border for drawing a border around a text field
308
   * that makes the field appear as etched into the surface.
309
   *
310
   * <p>The colors of the border are retrieved from the
311
   * <code>UIDefaults</code> of the currently active look and feel
312
   * using the keys <code>&#x201c;TextField.shadow&#x201d;</code>,
313
   * <code>&#x201c;TextField.darkShadow&#x201d;</code>,
314
   * <code>&#x201c;TextField.light&#x201d;</code>, and
315
   * <code>&#x201c;TextField.highlight&#x201d;</code>.
316
   *
317
   * <p><img src="doc-files/BasicBorders.FieldBorder-1.png" width="500"
318
   * height="200" alt="[A screen shot of a border returned by
319
   * this method]" />
320
   *
321
   * @return an instance of {@link FieldBorder}.
322
   *
323
   * @see javax.swing.JTextField
324
   * @see javax.swing.text.JTextComponent
325
   */
326
  public static Border getTextFieldBorder()
327
  {
328
    /* See comment in methods above for why this border is not shared. */
329
    return new FieldBorder(
330
      UIManager.getColor("TextField.shadow"),
331
      UIManager.getColor("TextField.darkShadow"),
332
      UIManager.getColor("TextField.light"),
333
      UIManager.getColor("TextField.highlight"));
334
  }
335
 
336
 
337
  /**
338
   * Returns a two-pixel thick, green
339
   * <code>LineBorderUIResource</code>.  This is so ugly that look and
340
   * feels better use different borders for their progress bars, or
341
   * they will look really terrible.
342
   *
343
   * <p><img src="doc-files/BasicBorders-1.png" width="120" height="80"
344
   * alt="[A screen shot of a border returned by this method]" />
345
   */
346
  public static Border getProgressBarBorder()
347
  {
348
    /* There does not seem to exist a way to parametrize the color
349
     * or thickness of the border through UIDefaults.
350
     */
351
    return new BorderUIResource.LineBorderUIResource(Color.green, 2);
352
  }
353
 
354
 
355
  /**
356
   * Returns a border that is composed of a raised bevel border and a
357
   * one-pixel thick line border.
358
   *
359
   * <p><img src="doc-files/BasicBorders-2.png" width="300" height="200"
360
   * alt="[A screen shot of a border returned by this method]" />
361
   *
362
   * <p>The colors of the border are retrieved from the
363
   * <code>UIDefaults</code> of the currently active look and feel
364
   * using the keys <code>&#x201c;InternalFrame.borderShadow&#x201d;</code>,
365
   * <code>&#x201c;InternalFrame.borderDarkShadow&#x201d;</code>,
366
   * <code>&#x201c;InternalFrame.borderLight&#x201d;</code>,
367
   * <code>&#x201c;InternalFrame.borderHighlight&#x201d;</code>, and
368
   * (for the inner one-pixel thick line)
369
   * <code>&#x201c;InternalFrame.borderColor&#x201d;</code>.
370
   */
371
  public static Border getInternalFrameBorder()
372
  {
373
    Color shadow, darkShadow, highlight, lightHighlight, line;
374
 
375
    /* See comment in methods above for why this border is not shared. */
376
    shadow = UIManager.getColor("InternalFrame.borderShadow");
377
    darkShadow = UIManager.getColor("InternalFrame.borderDarkShadow");
378
    highlight = UIManager.getColor("InternalFrame.borderLight");
379
    lightHighlight = UIManager.getColor("InternalFrame.borderHighlight");
380
    line = UIManager.getColor("InternalFrame.borderColor");
381
 
382
    return new BorderUIResource.CompoundBorderUIResource(
383
      /* outer border */
384
      new BorderUIResource.BevelBorderUIResource(
385
        BevelBorder.RAISED,
386
        (highlight != null) ? highlight : Color.lightGray,
387
        (lightHighlight != null) ? lightHighlight : Color.white,
388
        (darkShadow != null) ? darkShadow : Color.black,
389
        (shadow != null) ? shadow : Color.gray),
390
 
391
      /* inner border */
392
      new BorderUIResource.LineBorderUIResource(
393
        (line != null) ? line : Color.lightGray));
394
  }
395
 
396
 
397
  /**
398
   * Returns a shared MarginBorder.
399
   */
400
  static Border getMarginBorder()  // intentionally not public
401
  {
402
    /* Swing is not designed to be thread-safe, so there is no
403
     * need to synchronize the access to the global variable.
404
     */
405
    if (sharedMarginBorder == null)
406
      sharedMarginBorder = new MarginBorder();
407
 
408
    return sharedMarginBorder;
409
  }
410
 
411
 
412
  /**
413
   * A border whose appearance depends on the state of
414
   * the enclosed button.
415
   *
416
   * <p><img src="doc-files/BasicBorders.ButtonBorder-1.png" width="300"
417
   * height="170" alt="[A screen shot of this border]" />
418
   *
419
   * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
420
   *
421
   * @author Sascha Brawer (brawer@dandelis.ch)
422
   */
423
  public static class ButtonBorder
424
    extends AbstractBorder
425
    implements Serializable, UIResource
426
  {
427
    /**
428
     * Determined using the <code>serialver</code> tool
429
     * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
430
     */
431
    static final long serialVersionUID = -157053874580739687L;
432
 
433
 
434
    /**
435
     * The color for drawing the shaded parts of the border.
436
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
437
     */
438
    protected Color shadow;
439
 
440
 
441
    /**
442
     * The color for drawing the dark shaded parts of the border.
443
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
444
     */
445
    protected Color darkShadow;
446
 
447
 
448
    /**
449
     * The color for drawing the highlighted parts of the border.
450
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
451
     */
452
    protected Color highlight;
453
 
454
 
455
    /**
456
     * The color for drawing the bright highlighted parts of the border.
457
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
458
     */
459
    protected Color lightHighlight;
460
 
461
 
462
    /**
463
     * Constructs a new border for drawing a button in the Basic
464
     * look and feel.
465
     *
466
     * @param shadow the shadow color.
467
     * @param darkShadow a darker variant of the shadow color.
468
     * @param highlight the highlight color.
469
     * @param lightHighlight a brighter variant of the highlight  color.
470
     */
471
    public ButtonBorder(Color shadow, Color darkShadow,
472
                        Color highlight, Color lightHighlight)
473
    {
474
      /* These colors usually come from the UIDefaults of the current
475
       * look and feel. Use fallback values if the colors are not
476
       * supplied.  The API specification is silent about what
477
       * behavior is expected for null colors, so users should not
478
       * rely on this fallback (which is why it is not documented in
479
       * the above Javadoc).
480
       */
481
      this.shadow = (shadow != null) ? shadow : Color.gray;
482
      this.darkShadow = (darkShadow != null) ? darkShadow : Color.black;
483
      this.highlight = (highlight != null) ? highlight : Color.lightGray;
484
      this.lightHighlight = (lightHighlight != null)
485
        ? lightHighlight
486
        : Color.white;
487
    }
488
 
489
 
490
    /**
491
     * Paints the ButtonBorder around a given component.
492
     *
493
     * @param c the component whose border is to be painted.
494
     * @param g the graphics for painting.
495
     * @param x the horizontal position for painting the border.
496
     * @param y the vertical position for painting the border.
497
     * @param width the width of the available area for painting the border.
498
     * @param height the height of the available area for painting the border.
499
     *
500
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
501
     */
502
    public void paintBorder(Component c, Graphics  g,
503
                            int x, int y, int width, int height)
504
    {
505
      ButtonModel bmodel = null;
506
 
507
      if (c instanceof AbstractButton)
508
        bmodel = ((AbstractButton) c).getModel();
509
 
510
      BasicGraphicsUtils.drawBezel(
511
        g, x, y, width, height,
512
        /* pressed */ (bmodel != null)
513
                        && /* mouse button pressed */ bmodel.isPressed()
514
                        && /* mouse inside */ bmodel.isArmed(),
515
        /* default */ (c instanceof JButton)
516
                        && ((JButton) c).isDefaultButton(),
517
        shadow, darkShadow, highlight, lightHighlight);
518
    }
519
 
520
 
521
    /**
522
     * Measures the width of this border.
523
     *
524
     * <p>Although the thickness of the actually painted border
525
     * depends on the state of the enclosed component, this
526
     * measurement always returns the same amount of pixels.  Indeed,
527
     * it would be rather confusing if a button was appearing to
528
     * change its size depending on whether it is pressed or not.
529
     *
530
     * @param c the component whose border is to be measured.
531
     *
532
     * @return an Insets object whose <code>left</code>,
533
     *         <code>right</code>, <code>top</code> and
534
     *         <code>bottom</code> fields indicate the width of the
535
     *         border at the respective edge.
536
     *
537
     * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
538
     */
539
    public Insets getBorderInsets(Component c)
540
    {
541
      /* There is no obvious reason for overriding this method, but we
542
       * try to have exactly the same API as the Sun reference
543
       * implementation.
544
       */
545
      return getBorderInsets(c, null);
546
    }
547
 
548
 
549
    /**
550
     * Measures the width of this border, storing the results into a
551
     * pre-existing Insets object.
552
     *
553
     * <p>Although the thickness of the actually painted border
554
     * depends on the state of the enclosed component, this
555
     * measurement always returns the same amount of pixels.  Indeed,
556
     * it would be rather confusing if a button was appearing to
557
     * change its size depending on whether it is pressed or not.
558
     *
559
     * @param insets an Insets object for holding the result values.
560
     *        After invoking this method, the <code>left</code>,
561
     *        <code>right</code>, <code>top</code> and
562
     *        <code>bottom</code> fields indicate the width of the
563
     *        border at the respective edge.
564
     *
565
     * @return the same object that was passed for <code>insets</code>.
566
     *
567
     * @see #getBorderInsets(Component)
568
     */
569
    public Insets getBorderInsets(Component c, Insets insets)
570
    {
571
      /* The exact amount has been determined using a test program
572
       * that was run on the Sun reference implementation. With
573
       * Apple/Sun JDK 1.3.1 on MacOS X 10.1.5, the result is
574
       * [3, 3, 3, 3]. With Sun JDK 1.4.1_01 on Linux/x86, the
575
       * result is [2, 3, 3, 3]. We use the values from the 1.4.1_01
576
       * release.
577
       */
578
      if (insets == null)
579
        return new Insets(2, 3, 3, 3);
580
 
581
      insets.top = 2;
582
      insets.bottom = insets.left = insets.right = 3;
583
      return insets;
584
    }
585
  }
586
 
587
 
588
  /**
589
   * A border that makes its enclosed component appear as lowered
590
   * into the surface. Typically used for text fields.
591
   *
592
   * <p><img src="doc-files/BasicBorders.FieldBorder-1.png" width="500"
593
   * height="200" alt="[A screen shot of this border]" />
594
   *
595
   * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawEtchedRect
596
   *
597
   * @author Sascha Brawer (brawer@dandelis.ch)
598
   */
599
  public static class FieldBorder
600
    extends AbstractBorder
601
    implements UIResource
602
  {
603
    /**
604
     * Determined using the <code>serialver</code> tool
605
     * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
606
     */
607
    static final long serialVersionUID = 949220756998454908L;
608
 
609
 
610
    /**
611
     * The color for drawing the outer half of the top and left
612
     * edges.
613
     */
614
    protected Color shadow;
615
 
616
 
617
    /**
618
     * The color for drawing the inner half of the top and left
619
     * edges.
620
     */
621
    protected Color darkShadow;
622
 
623
 
624
    /**
625
     * The color for drawing the inner half of the bottom and right
626
     * edges.
627
     */
628
    protected Color highlight;
629
 
630
 
631
    /**
632
     * The color for drawing the outer half of the bottom and right
633
     * edges.
634
     */
635
    protected Color lightHighlight;
636
 
637
 
638
    /**
639
     * Constructs a new border for drawing a text field in the Basic
640
     * look and feel.
641
     *
642
     * @param shadow the color for drawing the outer half
643
     *        of the top and left edges.
644
     *
645
     * @param darkShadow the color for drawing the inner half
646
     *        of the top and left edges.
647
     *
648
     * @param highlight the color for drawing the inner half
649
     *        of the bottom and right edges.
650
     *
651
     * @param lightHighlight the color for drawing the outer half
652
     *        of the bottom and right edges.
653
     */
654
    public FieldBorder(Color shadow, Color darkShadow,
655
                       Color highlight, Color lightHighlight)
656
    {
657
      /* These colors usually come from the UIDefaults of the current
658
       * look and feel. Use fallback values if the colors are not
659
       * supplied.  The API specification is silent about what
660
       * behavior is expected for null colors, so users should not
661
       * rely on this fallback (which is why it is not documented in
662
       * the above Javadoc).
663
       */
664
      this.shadow = (shadow != null) ? shadow : Color.gray;
665
      this.darkShadow = (darkShadow != null) ? darkShadow : Color.black;
666
      this.highlight = (highlight != null) ? highlight : Color.lightGray;
667
      this.lightHighlight = (lightHighlight != null)
668
        ? lightHighlight : Color.white;
669
    }
670
 
671
 
672
    /**
673
     * Paints the FieldBorder around a given component.
674
     *
675
     * @param c the component whose border is to be painted.
676
     * @param g the graphics for painting.
677
     * @param x the horizontal position for painting the border.
678
     * @param y the vertical position for painting the border.
679
     * @param width the width of the available area for painting the border.
680
     * @param height the height of the available area for painting the border.
681
     *
682
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawEtchedRect
683
     */
684
    public void paintBorder(Component c, Graphics  g,
685
                            int x, int y, int width, int height)
686
    {
687
      BasicGraphicsUtils.drawEtchedRect(g, x, y, width, height,
688
                                        shadow, darkShadow,
689
                                        highlight, lightHighlight);
690
    }
691
 
692
 
693
    /**
694
     * Measures the width of this border.
695
     *
696
     * @param c the component whose border is to be measured.
697
     *        If <code>c</code> is an instance of {@link
698
     *        javax.swing.text.JTextComponent}, its margin is
699
     *        added to the border size.
700
     *
701
     * @return an Insets object whose <code>left</code>,
702
     *         <code>right</code>, <code>top</code> and
703
     *         <code>bottom</code> fields indicate the width of the
704
     *         border at the respective edge.
705
     *
706
     * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
707
     */
708
    public Insets getBorderInsets(Component c)
709
    {
710
      return getBorderInsets(c, null);
711
    }
712
 
713
 
714
    /**
715
     * Measures the width of this border, storing the results into a
716
     * pre-existing Insets object.
717
     *
718
     * @param c the component whose border is to be measured.
719
     *        If <code>c</code> is an instance of {@link
720
     *        javax.swing.text.JTextComponent}, its margin is
721
     *        added to the border size.
722
     *
723
     * @param insets an Insets object for holding the result values.
724
     *        After invoking this method, the <code>left</code>,
725
     *        <code>right</code>, <code>top</code> and
726
     *        <code>bottom</code> fields indicate the width of the
727
     *        border at the respective edge.
728
     *
729
     * @return the same object that was passed for <code>insets</code>.
730
     *
731
     * @see #getBorderInsets(Component)
732
     */
733
    public Insets getBorderInsets(Component c, Insets insets)
734
    {
735
      if (insets == null)
736
        insets = new Insets(2, 2, 2, 2);
737
      else
738
        insets.top = insets.left = insets.bottom = insets.right = 2;
739
 
740
      if (c instanceof JTextComponent)
741
      {
742
        Insets margin = ((JTextComponent) c).getMargin();
743
        insets.top += margin.top;
744
        insets.left += margin.left;
745
        insets.bottom += margin.bottom;
746
        insets.right += margin.right;
747
      }
748
 
749
      return insets;
750
    }
751
  }
752
 
753
 
754
  /**
755
   * An invisible, but spacing border whose margin is determined
756
   * by calling the <code>getMargin()</code> method of the enclosed
757
   * component.  If the enclosed component has no such method,
758
   * this border will not occupy any space.
759
   *
760
   * <p><img src="doc-files/BasicBorders.MarginBorder-1.png" width="325"
761
   * height="200" alt="[An illustration that shows how MarginBorder
762
   * determines its borders]" />
763
   *
764
   * @author Sascha Brawer (brawer@dandelis.ch)
765
   */
766
  public static class MarginBorder
767
    extends AbstractBorder
768
    implements Serializable, UIResource
769
  {
770
    /**
771
     * Determined using the <code>serialver</code> tool
772
     * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
773
     */
774
    static final long serialVersionUID = -3035848353448896090L;
775
 
776
 
777
    /**
778
     * Constructs a new MarginBorder.
779
     */
780
    public MarginBorder()
781
    {
782
      // Nothing to do here.
783
    }
784
 
785
    /**
786
     * Measures the width of this border.
787
     *
788
     * @param c the component whose border is to be measured.
789
     *
790
     * @return an Insets object whose <code>left</code>, <code>right</code>,
791
     *         <code>top</code> and <code>bottom</code> fields indicate the
792
     *         width of the border at the respective edge.
793
     *
794
     * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
795
     */
796
    public Insets getBorderInsets(Component c)
797
    {
798
      return getBorderInsets(c, new Insets(0, 0, 0, 0));
799
    }
800
 
801
 
802
    /**
803
     * Determines the insets of this border by calling the
804
     * <code>getMargin()</code> method of the enclosed component.  The
805
     * resulting margin will be stored into the the <code>left</code>,
806
     * <code>right</code>, <code>top</code> and <code>bottom</code>
807
     * fields of the passed <code>insets</code> parameter.
808
     *
809
     * <p>Unfortunately, <code>getMargin()</code> is not a method of
810
     * {@link javax.swing.JComponent} or some other common superclass
811
     * of things with margins. While reflection could be used to
812
     * determine the existence of this method, this would be slow on
813
     * many virtual machines. Therefore, the current implementation
814
     * knows about {@link javax.swing.AbstractButton#getMargin()},
815
     * {@link javax.swing.JPopupMenu#getMargin()}, {@link
816
     * javax.swing.JToolBar#getMargin()}, and {@link
817
     * javax.swing.text.JTextComponent}. If <code>c</code> is an
818
     * instance of a known class, the respective
819
     * <code>getMargin()</code> method is called to determine the
820
     * correct margin. Otherwise, a zero-width margin is returned.
821
     *
822
     * @param c the component whose border is to be measured.
823
     *
824
     * @return the same object that was passed for <code>insets</code>,
825
     *         but with changed fields.
826
     */
827
    public Insets getBorderInsets(Component c, Insets insets)
828
    {
829
      Insets margin = null;
830
 
831
      /* This is terrible object-oriented design. See the above Javadoc
832
       * for an excuse.
833
       */
834
      if (c instanceof AbstractButton)
835
        margin = ((AbstractButton) c).getMargin();
836
      else if (c instanceof JPopupMenu)
837
        margin = ((JPopupMenu) c).getMargin();
838
      else if (c instanceof JToolBar)
839
        margin = ((JToolBar) c).getMargin();
840
      else if (c instanceof JTextComponent)
841
        margin = ((JTextComponent) c).getMargin();
842
 
843
      if (margin == null)
844
        insets.top = insets.left = insets.bottom = insets.right = 0;
845
      else
846
      {
847
        insets.top = margin.top;
848
        insets.left = margin.left;
849
        insets.bottom = margin.bottom;
850
        insets.right = margin.right;
851
      }
852
 
853
      return insets;
854
    }
855
  }
856
 
857
 
858
  /**
859
   * A border for drawing a separator line below JMenuBar.
860
   *
861
   * <p><img src="doc-files/BasicBorders.MenuBarBorder-1.png" width="500"
862
   * height="140" alt="[A screen shot of a JMenuBar with this border]" />
863
   *
864
   * @author Sascha Brawer (brawer@dandelis.ch)
865
   */
866
  public static class MenuBarBorder
867
    extends AbstractBorder
868
    implements UIResource
869
  {
870
    /**
871
     * Determined using the <code>serialver</code> tool
872
     * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
873
     */
874
    static final long serialVersionUID = -6909056571935227506L;
875
 
876
 
877
    /**
878
     * The shadow color, which is used for the upper line of the
879
     * two-pixel thick bottom edge.
880
     */
881
    private Color shadow;
882
 
883
 
884
    /**
885
     * The highlight color, which is used for the lower line of the
886
     * two-pixel thick bottom edge.
887
     */
888
    private Color highlight;
889
 
890
 
891
    /**
892
     * Constructs a new MenuBarBorder for drawing a JMenuBar in
893
     * the Basic look and feel.
894
     *
895
     * <p><img src="doc-files/BasicBorders.MenuBarBorder-1.png" width="500"
896
     * height="140" alt="[A screen shot of a JMenuBar with this
897
     * border]" />
898
     *
899
     * @param shadow the shadow color, which is used for the upper
900
     *        line of the two-pixel thick bottom edge.
901
     *
902
     * @param highlight the shadow color, which is used for the lower
903
     *        line of the two-pixel thick bottom edge.
904
     */
905
    public MenuBarBorder(Color shadow, Color highlight)
906
    {
907
      /* These colors usually come from the UIDefaults of the current
908
       * look and feel. Use fallback values if the colors are not
909
       * supplied.  The API specification is silent about what
910
       * behavior is expected for null colors, so users should not
911
       * rely on this fallback (which is why it is not documented in
912
       * the above Javadoc).
913
       */
914
      this.shadow = (shadow != null) ? shadow : Color.gray;
915
      this.highlight = (highlight != null) ? highlight : Color.white;
916
    }
917
 
918
 
919
    /**
920
     * Paints the MenuBarBorder around a given component.
921
     *
922
     * @param c the component whose border is to be painted, usually
923
     *        an instance of {@link javax.swing.JMenuBar}.
924
     *
925
     * @param g the graphics for painting.
926
     * @param x the horizontal position for painting the border.
927
     * @param y the vertical position for painting the border.
928
     * @param width the width of the available area for painting the border.
929
     * @param height the height of the available area for painting the border.
930
     */
931
    public void paintBorder(Component c, Graphics  g,
932
                            int x, int y, int width, int height)
933
    {
934
      Color oldColor;
935
 
936
      /* To understand this code, it might be helpful to look at the
937
       * image "BasicBorders.MenuBarBorder-1.png" that is included
938
       * with the JavaDoc. It is located in the "doc-files"
939
       * subdirectory.
940
       */
941
      oldColor = g.getColor();
942
      y = y + height - 2;
943
      try
944
      {
945
        g.setColor(shadow);
946
        g.drawLine(x, y, x + width - 2, y);
947
        g.drawLine(x, y + 1, x, y + 1);
948
        g.drawLine(x + width - 2, y + 1, x + width - 2, y + 1);
949
 
950
        g.setColor(highlight);
951
        g.drawLine(x + 1, y + 1, x + width - 3, y + 1);
952
        g.drawLine(x + width - 1, y, x + width - 1, y + 1);
953
      }
954
      finally
955
      {
956
        g.setColor(oldColor);
957
      }
958
    }
959
 
960
 
961
    /**
962
     * Measures the width of this border.
963
     *
964
     * @param c the component whose border is to be measured.
965
     *
966
     * @return an Insets object whose <code>left</code>,
967
     *         <code>right</code>, <code>top</code> and
968
     *         <code>bottom</code> fields indicate the width of the
969
     *         border at the respective edge.
970
     *
971
     * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
972
     */
973
    public Insets getBorderInsets(Component c)
974
    {
975
      /* There is no obvious reason for overriding this method, but we
976
       * try to have exactly the same API as the Sun reference
977
       * implementation.
978
       */
979
      return getBorderInsets(c, null);
980
    }
981
 
982
 
983
    /**
984
     * Measures the width of this border, storing the results into a
985
     * pre-existing Insets object.
986
     *
987
     * @param insets an Insets object for holding the result values.
988
     *        After invoking this method, the <code>left</code>,
989
     *        <code>right</code>, <code>top</code> and
990
     *        <code>bottom</code> fields indicate the width of the
991
     *        border at the respective edge.
992
     *
993
     * @return the same object that was passed for <code>insets</code>.
994
     *
995
     * @see #getBorderInsets(Component)
996
     */
997
    public Insets getBorderInsets(Component c, Insets insets)
998
    {
999
      /* The exact amount has been determined using a test program
1000
       * that was run on the Apple/Sun JDK 1.3.1 on MacOS X, and the
1001
       * Sun JDK 1.4.1_01 on GNU/Linux for x86. Both gave [0,0,2,0],
1002
       * which was expected from looking at the screen shot.
1003
       */
1004
      if (insets == null)
1005
        return new Insets(0, 0, 2, 0);
1006
 
1007
      insets.left = insets.right = insets.top = 0;
1008
      insets.bottom = 2;
1009
      return insets;
1010
    }
1011
  }
1012
 
1013
 
1014
  /**
1015
   * A border for drawing radio buttons in the Basic look and feel.
1016
   *
1017
   * <p><img src="doc-files/BasicBorders.RadioButtonBorder-1.png" width="300"
1018
   * height="135" alt="[A screen shot of this border]" />
1019
   *
1020
   * <p>Note about the screen shot: Normally, the
1021
   * <code>borderPainted</code> property is <code>false</code> for
1022
   * JRadioButtons. For this screen shot, it has been set to
1023
   * <code>true</code> so the borders get drawn. Also, a
1024
   * concretization of the Basic look and would typically provide
1025
   * icons for the various states of radio buttons.
1026
   *
1027
   * <p>Note that the focus rectangle is invisible If the radio button
1028
   * is currently selected. While it might be debatable whether this
1029
   * makes a lot of sense, this behavior can be observed in the Sun
1030
   * reference implementation (in JDK 1.3.1 and 1.4.1). The Classpath
1031
   * implementation tries to exactly replicate the JDK appearance.
1032
   *
1033
   * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
1034
   *
1035
   * @author Sascha Brawer (brawer@dandelis.ch)
1036
   */
1037
  public static class RadioButtonBorder
1038
    extends ButtonBorder
1039
  {
1040
    /**
1041
     * Determined using the <code>serialver</code> tool
1042
     * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
1043
     */
1044
    static final long serialVersionUID = 1596945751743747369L;
1045
 
1046
 
1047
    /**
1048
     * Constructs a new border for drawing a JRadioButton in
1049
     * the Basic look and feel.
1050
     *
1051
     * @param shadow the shadow color.
1052
     * @param darkShadow a darker variant of the shadow color.
1053
     * @param highlight the highlight color.
1054
     * @param lightHighlight a brighter variant of the highlight  color.
1055
     */
1056
    public RadioButtonBorder(Color shadow, Color darkShadow,
1057
                             Color highlight, Color lightHighlight)
1058
    {
1059
      /* The superclass ButtonBorder substitutes null arguments
1060
       * with fallback colors.
1061
       */
1062
      super(shadow, darkShadow, highlight, lightHighlight);
1063
    }
1064
 
1065
 
1066
    /**
1067
     * Paints the RadioButtonBorder around a given component.
1068
     *
1069
     * <p>The Sun implementation always seems to draw exactly
1070
     * the same border, irrespective of the state of the button.
1071
     * This is rather surprising, but GNU Classpath emulates the
1072
     * observable behavior.
1073
     *
1074
     * @param c the component whose border is to be painted.
1075
     * @param g the graphics for painting.
1076
     * @param x the horizontal position for painting the border.
1077
     * @param y the vertical position for painting the border.
1078
     * @param width the width of the available area for painting the border.
1079
     * @param height the height of the available area for painting the border.
1080
     *
1081
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
1082
     */
1083
    public void paintBorder(Component c, Graphics  g,
1084
                            int x, int y, int width, int height)
1085
    {
1086
      AbstractButton button = null;
1087
      ButtonModel bmodel = null;
1088
      boolean lowered = false;
1089
      boolean focused = false;
1090
 
1091
      if (c instanceof AbstractButton)
1092
      {
1093
        button = (AbstractButton) c;
1094
        bmodel = button.getModel();
1095
      }
1096
 
1097
      if (bmodel != null)
1098
      {
1099
        lowered = button.isSelected()
1100
          || (/* mouse inside */ bmodel.isArmed() && bmodel.isPressed());
1101
        focused = button.hasFocus() && button.isFocusPainted();
1102
      }
1103
 
1104
      if (lowered)
1105
        BasicGraphicsUtils.drawLoweredBezel(g, x, y, width, height,
1106
                                            shadow, darkShadow,
1107
                                            highlight, lightHighlight);
1108
      else
1109
        BasicGraphicsUtils.drawBezel(g, x, y, width, height,
1110
                                     /* isPressed */ false,
1111
                                     /* isPefault */ focused,
1112
                                     shadow, darkShadow,
1113
                                     highlight, lightHighlight);
1114
    }
1115
 
1116
 
1117
    /**
1118
     * Measures the width of this border.
1119
     *
1120
     * @param c the component whose border is to be measured.
1121
     *
1122
     * @return an Insets object whose <code>left</code>,
1123
     *         <code>right</code>, <code>top</code> and
1124
     *         <code>bottom</code> fields indicate the width of the
1125
     *         border at the respective edge.
1126
     *
1127
     * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
1128
     */
1129
    public Insets getBorderInsets(Component c)
1130
    {
1131
      /* There is no obvious reason for overriding this method, but we
1132
       * try to have exactly the same API as the Sun reference
1133
       * implementation.
1134
       */
1135
      return getBorderInsets(c, null);
1136
    }
1137
 
1138
 
1139
    /**
1140
     * Measures the width of this border, storing the results into a
1141
     * pre-existing Insets object.
1142
     *
1143
     * @param insets an Insets object for holding the result values.
1144
     *        After invoking this method, the <code>left</code>,
1145
     *        <code>right</code>, <code>top</code> and
1146
     *        <code>bottom</code> fields indicate the width of the
1147
     *        border at the respective edge.
1148
     *
1149
     * @return the same object that was passed for <code>insets</code>.
1150
     *
1151
     * @see #getBorderInsets(Component)
1152
     */
1153
    public Insets getBorderInsets(Component c, Insets insets)
1154
    {
1155
      /* The exact amount has been determined using a test program
1156
       * that was run on the Apple/Sun JDK 1.3.1 on MacOS X, and the
1157
       * Sun JDK 1.4.1_01 on GNU/Linux for x86. Both gave [2,2,2,2].
1158
       */
1159
      if (insets == null)
1160
        return new Insets(2, 2, 2, 2);
1161
 
1162
      insets.left = insets.right = insets.top = insets.bottom = 2;
1163
      return insets;
1164
    }
1165
  }
1166
 
1167
 
1168
  /**
1169
   * A one-pixel thick border for rollover buttons, for example in
1170
   * tool bars.
1171
   *
1172
   * @since 1.4
1173
   * @author Sascha Brawer (brawer@dandelis.ch)
1174
   */
1175
  public static class RolloverButtonBorder
1176
    extends ButtonBorder
1177
  {
1178
    /**
1179
     * Determined using the <code>serialver</code> tool
1180
     * of Sun JDK 1.4.1_01 on GNU/Linux 2.4.20 for x86.
1181
     */
1182
    static final long serialVersionUID = 1976364864896996846L;
1183
 
1184
 
1185
    /**
1186
     * Constructs a new border for drawing a roll-over button
1187
     * in the Basic look and feel.
1188
     *
1189
     * @param shadow the shadow color.
1190
     * @param darkShadow a darker variant of the shadow color.
1191
     * @param highlight the highlight color.
1192
     * @param lightHighlight a brighter variant of the highlight  color.
1193
     */
1194
    public RolloverButtonBorder(Color shadow, Color darkShadow,
1195
                                Color highlight, Color lightHighlight)
1196
    {
1197
      super(shadow, darkShadow, highlight, lightHighlight);
1198
    }
1199
 
1200
 
1201
    /**
1202
     * Paints the border around a rollover button.  If <code>c</code>
1203
     * is not an {@link javax.swing.AbstractButton} whose model
1204
     * returns <code>true</code> for {@link
1205
     * javax.swing.ButtonModel#isRollover}, nothing gets painted at
1206
     * all.
1207
     *
1208
     * @param c the button whose border is to be painted.
1209
     * @param g the graphics for painting.
1210
     * @param x the horizontal position for painting the border.
1211
     * @param y the vertical position for painting the border.
1212
     * @param width the width of the available area for painting the border.
1213
     * @param height the height of the available area for painting the border.
1214
     */
1215
    public void paintBorder(Component c, Graphics  g,
1216
                            int x, int y, int width, int height)
1217
    {
1218
      ButtonModel bmodel = null;
1219
      boolean drawPressed;
1220
      Color oldColor = g.getColor();
1221
      int x2, y2;
1222
 
1223
      if (c instanceof AbstractButton)
1224
        bmodel = ((AbstractButton) c).getModel();
1225
 
1226
      /* Draw nothing if c is not a rollover button. */
1227
      if ((bmodel == null) || !bmodel.isRollover())
1228
        return;
1229
 
1230
      /* Draw nothing if the mouse is pressed, but outside the button. */
1231
      if (bmodel.isPressed() && !bmodel.isArmed())
1232
        return;
1233
 
1234
      drawPressed = bmodel.isSelected() || bmodel.isPressed();
1235
      x2 = x + width - 1;
1236
      y2 = y + height - 1;
1237
 
1238
      try
1239
      {
1240
        g.setColor(drawPressed ? shadow : lightHighlight);
1241
        g.drawLine(x, y, x2 - 1, y);     // top edge
1242
        g.drawLine(x, y + 1, x, y2 - 1); // left edge
1243
 
1244
        g.setColor(drawPressed ? lightHighlight : shadow);
1245
        g.drawLine(x, y2, x2, y2);       // bottom edge
1246
        g.drawLine(x2, y, x2, y2 - 1);   // right edge
1247
      }
1248
      finally
1249
      {
1250
        g.setColor(oldColor);
1251
      }
1252
    }
1253
  }
1254
 
1255
 
1256
  /**
1257
   * A border for JSplitPanes in the Basic look and feel. The divider
1258
   * in the middle of the JSplitPane has its own border class, of which
1259
   * an instance can be obtained with {@link #getSplitPaneDividerBorder()}.
1260
   *
1261
   * <p><img src="doc-files/BasicBorders.SplitPaneBorder-1.png" width="520"
1262
   * height="200" alt="[A screen shot for JSplitPane.HORIZONTAL_SPLIT]" />
1263
   *
1264
   * <p><img src="doc-files/BasicBorders.SplitPaneBorder-2.png" width="520"
1265
   * height="200" alt="[A screen shot for JSplitPane.VERTICAL_SPLIT]" />
1266
   *
1267
   * <p>In contrast to the other borders of the Basic look and feel,
1268
   * this class is not serializable. While this might be unintended,
1269
   * GNU Classpath follows the specification in order to be fully
1270
   * compatible with the Sun reference implementation.
1271
   *
1272
   * <p>In the Sun JDK, the bottom edge of the divider also gets
1273
   * painted if the orientation of the enclosed JSplitPane is
1274
   * <code>JSplitPane.VERTICAL_SPLIT</code> (at least in versions
1275
   * 1.3.1 and 1.4.1).  GNU Classpath does not replicate this bug. A
1276
   * report has been filed with Sun (bug ID 4885629).
1277
   *
1278
   * <p>Note that the bottom left pixel of the border has a different
1279
   * color depending on the orientation of the enclosed JSplitPane.
1280
   * Although this is visually inconsistent, Classpath replicates the
1281
   * appearance of the Sun reference implementation. A bug report has
1282
   * been filed with Sun (review ID 188774).
1283
   *
1284
   * @see #getSplitPaneBorder()
1285
   * @see #getSplitPaneDividerBorder()
1286
   *
1287
   * @author Sascha Brawer (brawer@dandelis.ch)
1288
   */
1289
  public static class SplitPaneBorder implements Border, UIResource
1290
  {
1291
    /**
1292
     * Indicates that the top edge shall be not be painted
1293
     * by {@link #paintRect}.
1294
     */
1295
    private static final int SUPPRESS_TOP = 1;
1296
 
1297
 
1298
    /**
1299
     * Indicates that the left edge shall be not be painted
1300
     * by {@link #paintRect}.
1301
     */
1302
    private static final int SUPPRESS_LEFT = 2;
1303
 
1304
 
1305
    /**
1306
     * Indicates that the bottom edge shall be not be painted
1307
     * by {@link #paintRect}.
1308
     */
1309
    private static final int SUPPRESS_BOTTOM = 4;
1310
 
1311
 
1312
    /**
1313
     * Indicates that the right edge shall be not be painted
1314
     * by {@link #paintRect}.
1315
     */
1316
    private static final int SUPPRESS_RIGHT = 8;
1317
 
1318
 
1319
    /**
1320
     * The color for drawing the bottom and right edges of the border.
1321
     */
1322
    protected Color highlight;
1323
 
1324
 
1325
    /**
1326
     * The color for drawing the top and left edges of the border.
1327
     */
1328
    protected Color shadow;
1329
 
1330
 
1331
    /**
1332
     * Constructs a new border for drawing a JSplitPane in the Basic
1333
     * look and feel.  The divider in the middle of the JSplitPane has
1334
     * its own border class, <code>SplitPaneDividerBorder</code>.
1335
     *
1336
     * @param shadow the shadow color.
1337
     * @param highlight the highlight color.
1338
     */
1339
    public SplitPaneBorder(Color highlight, Color shadow)
1340
    {
1341
      /* These colors usually come from the UIDefaults of the current
1342
       * look and feel. Use fallback values if the colors are not
1343
       * supplied.  The API specification is silent about what
1344
       * behavior is expected for null colors, so users should not
1345
       * rely on this fallback (which is why it is not documented in
1346
       * the above Javadoc).
1347
       */
1348
      this.shadow = (shadow != null) ? shadow : Color.black;
1349
      this.highlight = (highlight != null) ? highlight : Color.white;
1350
    }
1351
 
1352
 
1353
    /**
1354
     * Paints the border around a <code>JSplitPane</code>.
1355
     *
1356
     * <p><img src="doc-files/BasicBorders.SplitPaneBorder-1.png" width="520"
1357
     * height="200" alt="[A screen shot for JSplitPane.HORIZONTAL_SPLIT]" />
1358
     *
1359
     * <p><img src="doc-files/BasicBorders.SplitPaneBorder-2.png" width="520"
1360
     * height="200" alt="[A screen shot for JSplitPane.VERTICAL_SPLIT]" />
1361
     *
1362
     * @param c the <code>JSplitPane</code> whose border is to be painted.
1363
     * @param g the graphics for painting.
1364
     * @param x the horizontal position for painting the border.
1365
     * @param y the vertical position for painting the border.
1366
     * @param width the width of the available area for painting the border.
1367
     * @param height the height of the available area for painting the border.
1368
     */
1369
    public void paintBorder(Component c, Graphics  g,
1370
                            int x, int y, int width, int height)
1371
    {
1372
      JSplitPane splitPane;
1373
      Component content;
1374
 
1375
      if (!(c instanceof JSplitPane))
1376
        return;
1377
 
1378
      splitPane = (JSplitPane) c;
1379
      switch (splitPane.getOrientation())
1380
      {
1381
      case JSplitPane.HORIZONTAL_SPLIT:
1382
        if ((content = splitPane.getLeftComponent()) != null)
1383
          paintRect(g, SUPPRESS_RIGHT, true, x, y, content.getBounds());
1384
        if ((content = splitPane.getRightComponent()) != null)
1385
          paintRect(g, SUPPRESS_LEFT, true, x, y, content.getBounds());
1386
        break;
1387
 
1388
      case JSplitPane.VERTICAL_SPLIT:
1389
        if ((content = splitPane.getTopComponent()) != null)
1390
          paintRect(g, SUPPRESS_BOTTOM, false, x, y, content.getBounds());
1391
        if ((content = splitPane.getBottomComponent()) != null)
1392
          paintRect(g, SUPPRESS_TOP, false, x, y, content.getBounds());
1393
        break;
1394
      }
1395
    }
1396
 
1397
 
1398
    /**
1399
     * Paints a border around a child of a <code>JSplitPane</code>,
1400
     * omitting some of the edges.
1401
     *
1402
     * @param g the graphics for painting.
1403
     *
1404
     * @param suppress a bit mask indicating the set of suppressed
1405
     *        edges, for example <code>SUPPRESS_TOP | SUPPRESS_RIGHT</code>.
1406
     *
1407
     * @param x the x coordinate of the SplitPaneBorder.
1408
     *
1409
     * @param y the y coordinate of the SplitPaneBorder.
1410
     *
1411
     * @param shadeBottomLeftPixel <code>true</code> to paint the
1412
     *        bottom left pixel in the shadow color,
1413
     *        <code>false</code> for the highlight color. The Basic
1414
     *        look and feel uses the highlight color for the bottom
1415
     *        left pixel of the border of a JSplitPane whose
1416
     *        orientation is VERTICAL_SPLIT, and the shadow color
1417
     *        otherwise. While this might be a strange distinction,
1418
     *        Classpath tries to look identical to the reference
1419
     *        implementation. A bug report has been filed with Sun;
1420
     *        its review ID is 188774. We currently replicate the
1421
     *        Sun behavior.
1422
     *
1423
     * @param rect the bounds of the child of JSplitPane whose
1424
     *        border is to be painted.
1425
     */
1426
    private void paintRect(Graphics g, int suppress,
1427
                           boolean shadeBottomLeftPixel,
1428
                           int x, int y,
1429
                           Rectangle rect)
1430
    {
1431
      if (rect == null)
1432
        return;
1433
 
1434
      /* On each edge, the border exceeds the enclosed child by one
1435
       * pixel. See the image "BasicBorders.SplitPaneBorder-1.png" in
1436
       * the directory "doc-files".
1437
       */
1438
      x += rect.x - 1;
1439
      y += rect.y - 1;
1440
      int right = x + rect.width + 1;
1441
      int bottom = y + rect.height + 1;
1442
 
1443
      Color oldColor = g.getColor();
1444
      try
1445
      {
1446
        g.setColor(shadow);
1447
        if ((suppress & SUPPRESS_TOP) == 0)
1448
          g.drawLine(x, y, right, y);
1449
        if ((suppress & SUPPRESS_LEFT) == 0)
1450
          g.drawLine(x, y, x, bottom);
1451
        else
1452
          g.drawLine(x, bottom, x, bottom); // one pixel
1453
 
1454
        g.setColor(highlight);
1455
        if ((suppress & SUPPRESS_BOTTOM) == 0)
1456
          g.drawLine(x + (shadeBottomLeftPixel ? 1 : 0), bottom, right, bottom);
1457
        else if (!shadeBottomLeftPixel)
1458
          g.drawLine(x, bottom, x, bottom); // one pixel
1459
 
1460
        if ((suppress & SUPPRESS_RIGHT) == 0)
1461
          g.drawLine(right, y, right, bottom);
1462
      }
1463
      finally
1464
      {
1465
        g.setColor(oldColor);
1466
      }
1467
    }
1468
 
1469
 
1470
    /**
1471
     * Measures the width of this border.
1472
     *
1473
     * @param c the component whose border is to be measured, usually
1474
     *        an instance of {@link javax.swing.JSplitPane}.
1475
     *
1476
     * @return an Insets object whose <code>left</code>,
1477
     *         <code>right</code>, <code>top</code> and
1478
     *         <code>bottom</code> fields indicate the width of the
1479
     *         border at the respective edge.
1480
     */
1481
    public Insets getBorderInsets(Component c)
1482
    {
1483
      return new Insets(1, 1, 1, 1);
1484
    }
1485
 
1486
 
1487
    /**
1488
     * Determines whether this border fills every pixel in its area
1489
     * when painting.
1490
     *
1491
     * @return <code>false</code> because this border does not
1492
     *         paint over the pixels where the divider joins
1493
     *         the border.
1494
     */
1495
    public boolean isBorderOpaque()
1496
    {
1497
      /* Strangely, the Sun implementation (tested with JDK 1.3.1 and
1498
       * 1.4.1_01) seems to always return true. It could be a bug,
1499
       * but without knowing the details of their implementation, it is
1500
       * hard to decide.
1501
       */
1502
      return false;
1503
    }
1504
  }
1505
 
1506
 
1507
  /**
1508
   * A border for the divider inside a JSplitPane.
1509
   *
1510
   * <p><img src="doc-files/BasicBorders.SplitPaneDividerBorder-1.png"
1511
   * width="520" height="200" alt="[A screen shot of this border]" />
1512
   *
1513
   * @author Sascha Brawer (brawer@dandelis.ch)
1514
   */
1515
  private static class SplitPaneDividerBorder
1516
    implements Border, UIResource, Serializable
1517
  {
1518
    /**
1519
     * Constructs a new border for drawing the divider of a JSplitPane
1520
     * in the Basic look and feel.  The outer parts of the JSplitPane have
1521
     * their own border class, <code>SplitPaneBorder</code>.
1522
     */
1523
    public SplitPaneDividerBorder()
1524
    {
1525
      // Nothing to do here.
1526
    }
1527
 
1528
    /**
1529
     * Paints the border around the divider of a <code>JSplitPane</code>.
1530
     *
1531
     * <p><img src="doc-files/BasicBorders.SplitPaneDividerBorder-1.png"
1532
     * width="520" height="200" alt="[A picture that shows which pixels
1533
     * get painted in what color]" />
1534
     *
1535
     * @param c the <code>JSplitPane</code> whose divider&#x2019;s border
1536
     *        is to be painted.
1537
     * @param g the graphics for painting.
1538
     * @param x the horizontal position for painting the border.
1539
     * @param y the vertical position for painting the border.
1540
     * @param width the width of the available area for painting the border.
1541
     * @param height the height of the available area for painting the border.
1542
     */
1543
    public void paintBorder(Component c, Graphics  g,
1544
                            int x, int y, int width, int height)
1545
    {
1546
      Color highlight = UIManager.getColor("SplitPane.highlight");
1547
      Color shadow = UIManager.getColor("SplitPane.shadow");
1548
      Color oldColor, dcol;
1549
      int x2, y2;
1550
      JSplitPane sp;
1551
 
1552
      sp = getSplitPane(c);
1553
      if (sp == null)
1554
        return;
1555
 
1556
      x2 = x + width - 1;
1557
      y2 = y + height - 1;
1558
      oldColor = g.getColor();
1559
      dcol = c.getBackground();
1560
      try
1561
      {
1562
        switch (sp.getOrientation())
1563
        {
1564
        case JSplitPane.HORIZONTAL_SPLIT:
1565
          g.setColor(dcol);
1566
          g.drawLine(x + 1, y, x2 - 1, y);
1567
          g.drawLine(x + 1, y2, x2 - 1, y2);
1568
          g.setColor(sp.getLeftComponent() != null ? highlight : dcol);
1569
          g.drawLine(x, y, x, y2);
1570
          g.setColor(sp.getRightComponent() != null ? shadow : dcol);
1571
          g.drawLine(x2, y, x2, y2);
1572
          break;
1573
 
1574
        case JSplitPane.VERTICAL_SPLIT:
1575
          g.setColor(dcol);
1576
          g.drawLine(x, y + 1, x, y2 - 1);
1577
          g.drawLine(x2, y + 1, x2, y2 - 1);
1578
          g.setColor(sp.getTopComponent() != null ? highlight : dcol);
1579
          g.drawLine(x, y, x2, y);
1580
          g.setColor(sp.getBottomComponent() != null ? shadow : dcol);
1581
          g.drawLine(x, y2, x2, y2);
1582
          break;
1583
        }
1584
      }
1585
      finally
1586
      {
1587
        g.setColor(oldColor);
1588
      }
1589
    }
1590
 
1591
 
1592
    /**
1593
     * Measures the width of this border.
1594
     *
1595
     * @param c the component whose border is to be measured, usually
1596
     *        an instance of {@link javax.swing.JSplitPane}.
1597
     *
1598
     * @return an Insets object whose <code>left</code>,
1599
     *         <code>right</code>, <code>top</code> and
1600
     *         <code>bottom</code> fields indicate the width of the
1601
     *         border at the respective edge.
1602
     */
1603
    public Insets getBorderInsets(Component c)
1604
    {
1605
      return new Insets(1, 1, 1, 1);
1606
    }
1607
 
1608
    /**
1609
     * Determines whether this border fills every pixel in its area
1610
     * when painting.
1611
     *
1612
     * @return <code>true</code>
1613
     */
1614
    public boolean isBorderOpaque()
1615
    {
1616
      return true;
1617
    }
1618
 
1619
 
1620
    /**
1621
     * Determines the JSplitPane whose divider is being painted.
1622
     *
1623
     * @param c an instance of BasicSplitPaneDivider.
1624
     *
1625
     * @return a <code>JSplitPane</code>, or <code>null</code> if
1626
     *         <code>c</code> is not an instance of {@link
1627
     *         javax.swing.plaf.basic.BasicSplitPaneDivider}.
1628
     */
1629
    private JSplitPane getSplitPane(Component c)
1630
    {
1631
      if (c instanceof BasicSplitPaneDivider)
1632
        return (((BasicSplitPaneDivider) c).getBasicSplitPaneUI())
1633
          .getSplitPane();
1634
      else
1635
        return null;
1636
    }
1637
  }
1638
 
1639
 
1640
  /**
1641
   * A border for toggle buttons in the Basic look and feel.
1642
   *
1643
   * <p><img src="doc-files/BasicBorders.ToggleButtonBorder-1.png"
1644
   * width="270" height="135" alt="[A screen shot of this border]" />
1645
   *
1646
   * <p>The Sun implementation always seems to draw exactly
1647
   * the same border, irrespective of the state of the button.
1648
   * This is rather surprising, but GNU Classpath emulates the
1649
   * observable behavior.
1650
   *
1651
   * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
1652
   *
1653
   * @author Sascha Brawer (brawer@dandelis.ch)
1654
   */
1655
  public static class ToggleButtonBorder
1656
    extends ButtonBorder
1657
  {
1658
    /**
1659
     * Determined using the <code>serialver</code> tool
1660
     * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5.
1661
     */
1662
    static final long serialVersionUID = -3528666548001058394L;
1663
 
1664
 
1665
    /**
1666
     * Constructs a new border for drawing a JToggleButton in
1667
     * the Basic look and feel.
1668
     *
1669
     * @param shadow the shadow color.
1670
     * @param darkShadow a darker variant of the shadow color.
1671
     * @param highlight the highlight color.
1672
     * @param lightHighlight a brighter variant of the highlight  color.
1673
     */
1674
    public ToggleButtonBorder(Color shadow, Color darkShadow,
1675
                              Color highlight, Color lightHighlight)
1676
    {
1677
      /* The superclass ButtonBorder substitutes null arguments
1678
       * with fallback colors.
1679
       */
1680
      super(shadow, darkShadow, highlight, lightHighlight);
1681
    }
1682
 
1683
 
1684
    /**
1685
     * Paints the ToggleButtonBorder around a given component.
1686
     *
1687
     * <p>The Sun implementation always seems to draw exactly
1688
     * the same border, irrespective of the state of the button.
1689
     * This is rather surprising, but GNU Classpath emulates the
1690
     * observable behavior.
1691
     *
1692
     * @param c the component whose border is to be painted.
1693
     * @param g the graphics for painting.
1694
     * @param x the horizontal position for painting the border.
1695
     * @param y the vertical position for painting the border.
1696
     * @param width the width of the available area for painting the border.
1697
     * @param height the height of the available area for painting the border.
1698
     *
1699
     * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel
1700
     */
1701
    public void paintBorder(Component c, Graphics  g,
1702
                            int x, int y, int width, int height)
1703
    {
1704
      /* The author of this code tried various variants for setting
1705
       * the state of the enclosed JToggleButton, but it seems that
1706
       * the drawn border is always identical. Weird, because this
1707
       * means that the user does not see whether the JToggleButton
1708
       * is selected or not.
1709
       */
1710
      BasicGraphicsUtils.drawBezel(g, x, y, width, height,
1711
                                   /* pressed */ false,
1712
                                   /* default */ false,
1713
                                   shadow, darkShadow,
1714
                                   highlight, lightHighlight);
1715
    }
1716
 
1717
 
1718
    /**
1719
     * Measures the width of this border.
1720
     *
1721
     * @param c the component whose border is to be measured.
1722
     *
1723
     * @return an Insets object whose <code>left</code>,
1724
     *         <code>right</code>, <code>top</code> and
1725
     *         <code>bottom</code> fields indicate the width of the
1726
     *         border at the respective edge.
1727
     *
1728
     * @see #getBorderInsets(java.awt.Component, java.awt.Insets)
1729
     */
1730
    public Insets getBorderInsets(Component c)
1731
    {
1732
      /* There is no obvious reason for overriding this method, but we
1733
       * try to have exactly the same API as the Sun reference
1734
       * implementation.
1735
       */
1736
      return getBorderInsets(c, null);
1737
    }
1738
 
1739
 
1740
    /**
1741
     * Measures the width of this border, storing the results into a
1742
     * pre-existing Insets object.
1743
     *
1744
     * @param insets an Insets object for holding the result values.
1745
     *        After invoking this method, the <code>left</code>,
1746
     *        <code>right</code>, <code>top</code> and
1747
     *        <code>bottom</code> fields indicate the width of the
1748
     *        border at the respective edge.
1749
     *
1750
     * @return the same object that was passed for <code>insets</code>.
1751
     *
1752
     * @see #getBorderInsets(Component)
1753
     */
1754
    public Insets getBorderInsets(Component c, Insets insets)
1755
    {
1756
      /* The exact amount has been determined using a test program
1757
       * that was run on the Apple/Sun JDK 1.3.1 on MacOS X, and the
1758
       * Sun JDK 1.4.1_01 on GNU/Linux for x86. Both gave [2,2,2,2].
1759
       */
1760
      if (insets == null)
1761
        return new Insets(2, 2, 2, 2);
1762
 
1763
      insets.left = insets.right = insets.top = insets.bottom = 2;
1764
      return insets;
1765
    }
1766
  }
1767
 
1768
}

powered by: WebSVN 2.1.0

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