001 /* MetalBorders.java
002 Copyright (C) 2005, 2006, Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package javax.swing.plaf.metal;
040
041 import java.awt.Color;
042 import java.awt.Component;
043 import java.awt.Graphics;
044 import java.awt.Insets;
045
046 import javax.swing.AbstractButton;
047 import javax.swing.ButtonModel;
048 import javax.swing.JButton;
049 import javax.swing.JInternalFrame;
050 import javax.swing.JMenu;
051 import javax.swing.JMenuBar;
052 import javax.swing.JMenuItem;
053 import javax.swing.JOptionPane;
054 import javax.swing.JScrollPane;
055 import javax.swing.JTextField;
056 import javax.swing.JToggleButton;
057 import javax.swing.JToolBar;
058 import javax.swing.SwingConstants;
059 import javax.swing.UIManager;
060 import javax.swing.border.AbstractBorder;
061 import javax.swing.border.Border;
062 import javax.swing.border.CompoundBorder;
063 import javax.swing.plaf.BorderUIResource;
064 import javax.swing.plaf.UIResource;
065 import javax.swing.plaf.basic.BasicBorders;
066 import javax.swing.text.JTextComponent;
067
068
069 /**
070 * A factory class that creates borders for the different Swing components.
071 *
072 * @author Roman Kennke (roman@kennke.org)
073 */
074 public class MetalBorders
075 {
076
077 /** The shared instance for getButtonBorder(). */
078 private static Border buttonBorder;
079
080 /** The shared instance for getToggleButtonBorder(). */
081 private static Border toggleButtonBorder;
082
083 /** The shared instance for getDesktopIconBorder(). */
084 private static Border desktopIconBorder;
085
086 /** The shared instance for getRolloverButtonBorder(). */
087 private static Border toolbarButtonBorder;
088
089 /** The shared instance for getTextFieldBorder(). */
090 private static Border textFieldBorder;
091
092 /** The shared instance for getTextBorder(). */
093 private static Border textBorder;
094
095 /** The shared instance for getRolloverBorder(). */
096 private static Border rolloverBorder;
097
098 /**
099 * A MarginBorder that gets shared by multiple components.
100 * Created on demand by the private helper function {@link
101 * #getMarginBorder()}.
102 */
103 private static BasicBorders.MarginBorder marginBorder;
104
105 /**
106 * <p>A border used for {@link JButton} components.</p>
107 *
108 * <p>This {@link Border} implementation can handle only instances of
109 * {@link AbstractButton} and their subclasses.</p>
110 *
111 * <p>If the Metal Look and Feel's current theme is 'Ocean' the border
112 * will be painted with a special highlight when the mouse cursor if
113 * over the button (ie. the property <code>rollover</code> of the
114 * button's model is <code>true</code>) and is not a <b>direct</b>
115 * child of a {@link JToolBar}.</p>
116 */
117 public static class ButtonBorder extends AbstractBorder implements UIResource
118 {
119 /** The borders insets. */
120 protected static Insets borderInsets = new Insets(3, 3, 3, 3);
121
122 /**
123 * Creates a new instance of <code>ButtonBorder</code>.
124 */
125 public ButtonBorder()
126 {
127 // Nothing to do here.
128 }
129
130 /**
131 * Paints the button border.
132 *
133 * @param c the component for which we paint the border
134 * @param g the Graphics context to use
135 * @param x the X coordinate of the upper left corner of c
136 * @param y the Y coordinate of the upper left corner of c
137 * @param w the width of c
138 * @param h the height of c
139 */
140 public void paintBorder(Component c, Graphics g, int x, int y, int w,
141 int h)
142 {
143 // With the OceanTheme the button border is painted entirely different.
144 // However, I couldn't figure out how this is determined besides checking
145 // for instanceof OceanTheme. The button painting is definitely not
146 // influenced by a UI default property and it is definitely performed
147 // by the same Border class.
148 if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)
149 paintOceanButtonBorder(c, g, x, y, w, h);
150 else
151 paintDefaultButtonBorder(c, g, x, y, w, h);
152 }
153
154 /**
155 * Paints the button border for the DefaultMetalTheme.
156 *
157 * @param c the component (button)
158 * @param g the graphics object to use
159 * @param x the upper left corner of the component, X coordinate
160 * @param y the upper left corner of the component, Y coordinate
161 * @param w the width of the component
162 * @param h the height of the component
163 */
164 private void paintDefaultButtonBorder(Component c, Graphics g, int x,
165 int y, int w, int h)
166 {
167 ButtonModel bmodel = null;
168
169 // The RI will fail with a ClassCastException in such a situation.
170 // This code tries to be more helpful.
171 if (c instanceof AbstractButton)
172 bmodel = ((AbstractButton) c).getModel();
173 else
174 throw new IllegalStateException("A ButtonBorder is supposed to work "
175 + "only with AbstractButton and"
176 + "subclasses.");
177
178 Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
179 Color shadow = MetalLookAndFeel.getControlShadow();
180 Color light = MetalLookAndFeel.getControlHighlight();
181 Color middle = MetalLookAndFeel.getControl();
182
183 if (c.isEnabled())
184 {
185 // draw dark border
186 g.setColor(darkShadow);
187 g.drawRect(x, y, w - 2, h - 2);
188
189 // If the button is the default button, we paint a special border,
190 // regardless of the pressed state.
191 if (c instanceof JButton && ((JButton) c).isDefaultButton())
192 {
193 g.drawRect(x + 1, y + 1, w - 4, h - 4);
194 // Draw white highlight.
195 g.setColor(light);
196 g.drawLine(x + 2, y + 2, x + w - 4, y + 2);
197 g.drawLine(x + 2, y + 2, x + 2, y + h - 4);
198 g.drawLine(x + 2, y + h - 1, x + w - 1, y + h - 1);
199 g.drawLine(x + w - 1, y + 2, x + w - 1, y + h - 1);
200 // Draw crossing pixels.
201 g.setColor(middle);
202 g.fillRect(x + w - 2, y + 2, 1, 1);
203 g.fillRect(x + 2, y + h - 2, 1, 1);
204 }
205 else
206 {
207 // The normal border. This is used when the button is not
208 // pressed or the button is not armed.
209 if (! (bmodel.isPressed() && bmodel.isArmed()))
210 {
211 // draw light border
212 g.setColor(light);
213 g.drawRect(x + 1, y + 1, w - 2, h - 2);
214
215 // draw crossing pixels of both borders
216 g.setColor(middle);
217 g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
218 g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
219 }
220 // The pressed border. This border is painted only when
221 // the button is both pressed and armed.
222 else
223 {
224 // draw light border
225 g.setColor(light);
226 g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
227 g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
228
229 // draw shadow border
230 g.setColor(middle);
231 g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
232 g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
233
234 // draw crossing pixels of both borders
235 g.setColor(shadow);
236 g.drawRect(x + 1, y + h - 2, 0, 0);
237 g.drawRect(x + w - 2, y + 1, 0, 0);
238 }
239 }
240 }
241 else
242 {
243 // draw disabled border
244 g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
245 g.drawRect(x, y, w - 2, h - 2);
246 }
247 }
248
249 /**
250 * Paints the button border for the OceanTheme.
251 *
252 * @param c the button
253 * @param g the graphics context
254 * @param x the X coordinate of the upper left corner of the painting rect
255 * @param y the Y coordinate of the upper left corner of the painting rect
256 * @param w the width of the painting rect
257 * @param h the height of the painting rect
258 */
259 private void paintOceanButtonBorder(Component c, Graphics g, int x,
260 int y, int w, int h)
261 {
262 ButtonModel bmodel = null;
263
264 // The RI will fail with a ClassCastException in such a situation.
265 // This code tries to be more helpful.
266 if (c instanceof AbstractButton)
267 bmodel = ((AbstractButton) c).getModel();
268 else
269 throw new IllegalStateException("A ButtonBorder is supposed to work "
270 + "only with AbstractButton and"
271 + "subclasses.");
272
273 Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
274 Color shadow = MetalLookAndFeel.getControlShadow();
275 Color light = MetalLookAndFeel.getControlHighlight();
276 Color middle = MetalLookAndFeel.getControl();
277
278 if (c.isEnabled())
279 {
280 // Paint the pressed border if the button is pressed, or if
281 // the button is the default button. In the OceanTheme, the default
282 // button has the same border as a pressed button.
283 if (bmodel.isPressed() || ((c instanceof JButton)
284 && ((JButton) c).isDefaultButton()))
285 {
286 // Draw fat border.
287 g.setColor(darkShadow);
288 g.drawRect(x, y, w - 1, h - 1);
289 g.drawRect(x + 1, y + 1, w - 3, h - 3);
290 }
291 else if (bmodel.isRollover() && !(c.getParent() instanceof JToolBar))
292 {
293 // Paint a bigger border when the mouse is over the button but
294 // only if it is *not* part of a JToolBar.
295 g.setColor(shadow);
296 g.drawRect(x, y, w - 1, h - 1);
297 g.drawRect(x + 2, y + 2, w - 5, h - 5);
298 g.setColor(darkShadow);
299 g.drawRect(x + 1, y + 1, w - 3, h - 3);
300 }
301 else
302 {
303 g.setColor(darkShadow);
304 g.drawRect(x, y, w - 1, h - 1);
305 }
306 }
307 else
308 {
309 // draw disabled border
310 g.setColor(MetalLookAndFeel.getInactiveControlTextColor());
311 g.drawRect(x, y, w - 2, h - 2);
312 }
313 }
314
315 /**
316 * Returns the insets of the <code>ButtonBorder</code>.
317 *
318 * @param c the component for which the border is used (ignored).
319 *
320 * @return The insets of the <code>ButtonBorder</code>.
321 */
322 public Insets getBorderInsets(Component c)
323 {
324 return borderInsets;
325 }
326
327 /**
328 * Returns the insets of the <code>ButtonBorder</code> in the specified
329 * <code>newInsets</code> object.
330 *
331 * @param c the component for which the border is used (ignored).
332 * @param newInsets the insets object where to put the values (
333 * <code>null</code> not permitted).
334 *
335 * @return The <code>newInsets</code> reference.
336 */
337 public Insets getBorderInsets(Component c, Insets newInsets)
338 {
339 newInsets.bottom = borderInsets.bottom;
340 newInsets.left = borderInsets.left;
341 newInsets.right = borderInsets.right;
342 newInsets.top = borderInsets.top;
343 return newInsets;
344 }
345 }
346
347 /**
348 * A border used when painting {@link JInternalFrame} instances.
349 */
350 static class DesktopIconBorder extends AbstractBorder
351 implements UIResource
352 {
353 /**
354 * Creates a new border instance.
355 */
356 public DesktopIconBorder()
357 {
358 // Nothing to do here.
359 }
360
361 /**
362 * Returns the border insets.
363 *
364 * @param c the component (ignored).
365 *
366 * @return The border insets.
367 */
368 public Insets getBorderInsets(Component c)
369 {
370 return getBorderInsets(c, null);
371 }
372
373 /**
374 * Returns the border insets.
375 *
376 * @param c the component (ignored).
377 * @return The border insets.
378 */
379 public Insets getBorderInsets(Component c, Insets newInsets)
380 {
381 if (newInsets == null)
382 newInsets = new Insets(3, 3, 2, 3);
383 else
384 {
385 newInsets.top = 3;
386 newInsets.left = 3;
387 newInsets.bottom = 2;
388 newInsets.right = 3;
389 }
390 return newInsets;
391 }
392
393 /**
394 * Paints the border for the specified component.
395 *
396 * @param c the component.
397 * @param g the graphics device.
398 * @param x the x-coordinate.
399 * @param y the y-coordinate.
400 * @param w the width.
401 * @param h the height.
402 */
403 public void paintBorder(Component c, Graphics g, int x, int y, int w,
404 int h)
405 {
406 g.setColor(MetalLookAndFeel.getControlDarkShadow());
407 g.drawRect(x, y, w - 1, h - 1);
408 }
409
410 }
411
412 /**
413 * A simple 3D border.
414 */
415 public static class Flush3DBorder extends AbstractBorder
416 implements UIResource
417 {
418 private static final Insets borderInsets = new Insets(2, 2, 2, 2);
419
420 /**
421 * Creates a new border instance.
422 */
423 public Flush3DBorder()
424 {
425 // Nothing to do here.
426 }
427
428 /**
429 * Returns the border insets.
430 *
431 * @param c the component (ignored).
432 *
433 * @return The border insets.
434 */
435 public Insets getBorderInsets(Component c)
436 {
437 return borderInsets;
438 }
439
440 /**
441 * Returns the border insets.
442 *
443 * @param c the component (ignored).
444 * @param newInsets an existing insets instance, that will be populated
445 * with the border insets and returned as the result
446 * (<code>null</code> not permitted).
447 *
448 * @return The <code>newInsets</code> reference.
449 */
450 public Insets getBorderInsets(Component c, Insets newInsets)
451 {
452 newInsets.top = borderInsets.top;
453 newInsets.left = borderInsets.left;
454 newInsets.bottom = borderInsets.bottom;
455 newInsets.right = borderInsets.right;
456 return newInsets;
457 }
458
459 /**
460 * Paints the border for the specified component.
461 *
462 * @param c the component (ignored).
463 * @param g the graphics device.
464 * @param x the x-coordinate.
465 * @param y the y-coordinate.
466 * @param w the width.
467 * @param h the height.
468 */
469 public void paintBorder(Component c, Graphics g, int x, int y, int w,
470 int h)
471 {
472 Color savedColor = g.getColor();
473 g.setColor(MetalLookAndFeel.getControlDarkShadow());
474 g.drawRect(x, y, w - 2, h - 2);
475 g.setColor(MetalLookAndFeel.getControlHighlight());
476 g.drawRect(x + 1, y + 1, w - 2, h - 2);
477 g.setColor(MetalLookAndFeel.getControl());
478 g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
479 g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
480 g.setColor(savedColor);
481 }
482
483 }
484
485 /**
486 * A border used for a {@link JInternalFrame} when it is being used as a
487 * palette.
488 *
489 * @since 1.3
490 */
491 public static class PaletteBorder extends AbstractBorder
492 implements UIResource
493 {
494 private static final Insets borderInsets = new Insets(1, 1, 1, 1);
495
496 /**
497 * Creates a new <code>PaletteBorder</code>.
498 */
499 public PaletteBorder()
500 {
501 // Nothing to do here.
502 }
503
504 /**
505 * Returns the border insets.
506 *
507 * @param c the component (ignored).
508 *
509 * @return The border insets.
510 */
511 public Insets getBorderInsets(Component c)
512 {
513 return borderInsets;
514 }
515
516 /**
517 * Returns the border insets.
518 *
519 * @param c the component (ignored).
520 * @param newInsets an existing insets instance, that will be populated
521 * with the border insets and returned as the result
522 * (<code>null</code> not permitted).
523 *
524 * @return The <code>newInsets</code> reference.
525 */
526 public Insets getBorderInsets(Component c, Insets newInsets)
527 {
528 newInsets.top = borderInsets.top;
529 newInsets.left = borderInsets.left;
530 newInsets.bottom = borderInsets.bottom;
531 newInsets.right = borderInsets.right;
532 return newInsets;
533 }
534
535 /**
536 * Paints the border for the specified component.
537 *
538 * @param c the component (ignored).
539 * @param g the graphics device.
540 * @param x the x-coordinate.
541 * @param y the y-coordinate.
542 * @param w the width.
543 * @param h the height.
544 */
545 public void paintBorder(Component c, Graphics g, int x, int y, int w,
546 int h)
547 {
548 Color savedColor = g.getColor();
549
550 // draw the outline
551 g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
552 g.drawRect(x, y, w - 1, h - 1);
553
554 // put a dot in each corner
555 g.setColor(MetalLookAndFeel.getControl());
556 g.fillRect(x, y, 1, 1);
557 g.fillRect(x + w - 1, y, 1, 1);
558 g.fillRect(x + w - 1, y + h - 1, 1, 1);
559 g.fillRect(x, y + h - 1, 1, 1);
560 g.setColor(savedColor);
561 }
562
563 }
564
565 /**
566 * A border used for the {@link JTextField} component.
567 */
568 public static class TextFieldBorder extends Flush3DBorder
569 implements UIResource
570 {
571 /**
572 * Creates a new border instance.
573 */
574 public TextFieldBorder()
575 {
576 // Nothing to do here.
577 }
578
579 /**
580 * Paints the border for the specified component.
581 *
582 * @param c the component (ignored).
583 * @param g the graphics device.
584 * @param x the x-coordinate.
585 * @param y the y-coordinate.
586 * @param w the width.
587 * @param h the height.
588 */
589 public void paintBorder(Component c, Graphics g, int x, int y, int w,
590 int h)
591 {
592 boolean enabledTextBorder;
593 if (c instanceof JTextComponent)
594 {
595 JTextComponent tc = (JTextComponent) c;
596 enabledTextBorder = tc.isEnabled() && tc.isEditable();
597 }
598 else
599 enabledTextBorder = false;
600
601 if (enabledTextBorder)
602 super.paintBorder(c, g, x, y, w, h);
603 else
604 {
605 Color savedColor = g.getColor();
606 g.setColor(MetalLookAndFeel.getControlShadow());
607 g.drawRect(x, y, w - 1, h - 1);
608 g.setColor(savedColor);
609 }
610 }
611
612 }
613
614 /**
615 * A border used for the {@link JInternalFrame} component.
616 */
617 public static class InternalFrameBorder extends AbstractBorder
618 implements UIResource
619 {
620 private static final Insets borderInsets = new Insets(5, 5, 5, 5);
621
622 /**
623 * Creates a new border instance.
624 */
625 public InternalFrameBorder()
626 {
627 // Nothing to do here.
628 }
629
630 /**
631 * Returns the border insets.
632 *
633 * @param c the component (ignored).
634 *
635 * @return The border insets.
636 */
637 public Insets getBorderInsets(Component c)
638 {
639 return borderInsets;
640 }
641
642 /**
643 * Returns the border insets.
644 *
645 * @param c the component (ignored).
646 * @param newInsets an existing insets instance, that will be populated
647 * with the border insets and returned as the result
648 * (<code>null</code> not permitted).
649 *
650 * @return The <code>newInsets</code> reference.
651 */
652 public Insets getBorderInsets(Component c, Insets newInsets)
653 {
654 newInsets.top = borderInsets.top;
655 newInsets.left = borderInsets.left;
656 newInsets.bottom = borderInsets.bottom;
657 newInsets.right = borderInsets.right;
658 return newInsets;
659 }
660
661 /**
662 * Paints the border for the specified component.
663 *
664 * @param c the component.
665 * @param g the graphics device.
666 * @param x the x-coordinate.
667 * @param y the y-coordinate.
668 * @param w the width.
669 * @param h the height.
670 */
671 public void paintBorder(Component c, Graphics g, int x, int y, int w,
672 int h)
673 {
674
675 JInternalFrame f = (JInternalFrame) c;
676 if (f.isSelected())
677 g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
678 else
679 g.setColor(MetalLookAndFeel.getControlDarkShadow());
680
681 // fill the border background
682 g.fillRect(x, y, w, 5);
683 g.fillRect(x, y, 5, h);
684 g.fillRect(x + w - 5, y, 5, h);
685 g.fillRect(x, y + h - 5, w, 5);
686
687 // draw a dot in each corner
688 g.setColor(MetalLookAndFeel.getControl());
689 g.fillRect(x, y, 1, 1);
690 g.fillRect(x + w - 1, y, 1, 1);
691 g.fillRect(x + w - 1, y + h - 1, 1, 1);
692 g.fillRect(x, y + h - 1, 1, 1);
693
694 // draw the lines
695 g.setColor(MetalLookAndFeel.getBlack());
696 g.drawLine(x + 14, y + 2, x + w - 15, y + 2);
697 g.drawLine(x + 14, y + h - 3, x + w - 15, y + h - 3);
698 g.drawLine(x + 2, y + 14, x + 2, y + h - 15);
699 g.drawLine(x + w - 3, y + 14, x + w - 3, y + h - 15);
700
701 // draw the line highlights
702 if (f.isSelected())
703 g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
704 else
705 g.setColor(MetalLookAndFeel.getControlShadow());
706 g.drawLine(x + 15, y + 3, x + w - 14, y + 3);
707 g.drawLine(x + 15, y + h - 2, x + w - 14, y + h - 2);
708 g.drawLine(x + 3, y + 15, x + 3, y + h - 14);
709 g.drawLine(x + w - 2, y + 15, x + w - 2, y + h - 14);
710 }
711
712 }
713
714 /**
715 * A border used for {@link JInternalFrame} components that are
716 * presented as dialogs (by the {@link JOptionPane} class).
717 */
718 public static class OptionDialogBorder extends AbstractBorder
719 implements UIResource
720 {
721
722 /**
723 * Creates a new border instance.
724 */
725 public OptionDialogBorder()
726 {
727 // Nothing to do here.
728 }
729
730 /**
731 * Returns the border insets.
732 *
733 * @param c the component (ignored).
734 *
735 * @return The border insets.
736 */
737 public Insets getBorderInsets(Component c)
738 {
739 return getBorderInsets(c, null);
740 }
741
742 /**
743 * Returns the border insets.
744 *
745 * @param c the component (ignored).
746 * @return The border insets.
747 */
748 public Insets getBorderInsets(Component c, Insets newInsets)
749 {
750 if (newInsets == null)
751 newInsets = new Insets(3, 3, 3, 3);
752 else
753 {
754 newInsets.top = 3;
755 newInsets.left = 3;
756 newInsets.bottom = 3;
757 newInsets.right = 3;
758 }
759 return newInsets;
760 }
761
762 /**
763 * Paints the border for the specified component.
764 *
765 * @param c the component.
766 * @param g the graphics device.
767 * @param x the x-coordinate.
768 * @param y the y-coordinate.
769 * @param w the width.
770 * @param h the height.
771 */
772 public void paintBorder(Component c, Graphics g, int x, int y, int w,
773 int h)
774 {
775
776 JInternalFrame f = (JInternalFrame) c;
777 g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
778 if (f.getContentPane() instanceof JOptionPane)
779 {
780 JOptionPane pane = (JOptionPane) f.getContentPane();
781 int type = pane.getMessageType();
782 if (type == JOptionPane.QUESTION_MESSAGE)
783 {
784 Color bc = UIManager.getColor(
785 "OptionPane.questionDialog.border.background");
786 if (bc != null)
787 g.setColor(bc);
788 }
789 if (type == JOptionPane.WARNING_MESSAGE)
790 {
791 Color bc = UIManager.getColor(
792 "OptionPane.warningDialog.border.background");
793 if (bc != null)
794 g.setColor(bc);
795 }
796 else if (type == JOptionPane.ERROR_MESSAGE)
797 {
798 Color bc = UIManager.getColor(
799 "OptionPane.errorDialog.border.background");
800 if (bc != null)
801 g.setColor(bc);
802 }
803 }
804
805 // fill the border background
806 g.fillRect(x, y, w, 3);
807 g.fillRect(x, y, 3, h);
808 g.fillRect(x + w - 3, y, 3, h);
809 g.fillRect(x, y + h - 3, w, 3);
810
811 // draw a dot in each corner
812 g.setColor(MetalLookAndFeel.getControl());
813 g.fillRect(x, y, 1, 1);
814 g.fillRect(x + w - 1, y, 1, 1);
815 g.fillRect(x + w - 1, y + h - 1, 1, 1);
816 g.fillRect(x, y + h - 1, 1, 1);
817
818 }
819
820 }
821
822 /**
823 * A border used for {@link JMenu} and {@link JMenuItem} components.
824 */
825 public static class MenuItemBorder extends AbstractBorder
826 implements UIResource
827 {
828 /** The border insets. */
829 protected static Insets borderInsets = new Insets(2, 2, 2, 2);
830
831 /**
832 * Creates a new border instance.
833 */
834 public MenuItemBorder()
835 {
836 // Nothing to do here.
837 }
838
839 /**
840 * Paints the border for the component. A border is painted only if the
841 * component is a selected {@link JMenu} or an armed {@link JMenuItem}.
842 *
843 * @param c the component.
844 * @param g the graphics device.
845 * @param x the x-coordinate of the border area.
846 * @param y the y-coordinate of the border area.
847 * @param w the width of the border area.
848 * @param h the height of the border area.
849 */
850 public void paintBorder(Component c, Graphics g, int x, int y, int w,
851 int h)
852 {
853 Color dark = MetalLookAndFeel.getPrimaryControlDarkShadow();
854 Color light = MetalLookAndFeel.getPrimaryControlHighlight();
855 if (c instanceof JMenu)
856 {
857 JMenu menu = (JMenu) c;
858 if (menu.isSelected())
859 {
860 g.setColor(dark);
861 g.drawLine(x, y, x, y + h);
862 g.drawLine(x, y, x + w, y);
863 g.drawLine(x + w - 2, y + 1, x + w - 2, y + h);
864 g.setColor(light);
865 g.drawLine(x + w - 1, y + 1, x + w - 1, y + h);
866 }
867 }
868 else if (c instanceof JMenuItem)
869 {
870 JMenuItem item = (JMenuItem) c;
871 if (item.isArmed())
872 {
873 g.setColor(dark);
874 g.drawLine(x, y, x + w, y);
875 g.setColor(light);
876 g.drawLine(x, y + h - 1, x + w, y + h - 1);
877 }
878 else
879 {
880 // Normally we draw a light line on the left.
881 g.setColor(light);
882 g.drawLine(x, y, x, y + h);
883 }
884 }
885 }
886
887 /**
888 * Returns the border insets.
889 *
890 * @param c the component (ignored).
891 *
892 * @return The border insets.
893 */
894 public Insets getBorderInsets(Component c)
895 {
896 return borderInsets;
897 }
898
899 /**
900 * Populates <code>insets</code> with the border insets, then returns it.
901 *
902 * @param c the component (ignored).
903 * @param insets the object to populate with the border insets.
904 *
905 * @return The border insets.
906 *
907 * @throws NullPointerException if <code>insets</code> is <code>null</code>.
908 */
909 public Insets getBorderInsets(Component c, Insets insets)
910 {
911 insets.left = borderInsets.left;
912 insets.top = borderInsets.top;
913 insets.bottom = borderInsets.bottom;
914 insets.right = borderInsets.right;
915 return insets;
916 }
917 }
918
919 /**
920 * A border used for {@link JMenuBar} components.
921 */
922 public static class MenuBarBorder
923 extends AbstractBorder
924 implements UIResource
925 {
926 /** The border insets. */
927 protected static Insets borderInsets = new Insets(1, 0, 1, 0);
928
929 /**
930 * Creates a new border instance.
931 */
932 public MenuBarBorder()
933 {
934 }
935
936 /**
937 * Paints the border for the component. A border is painted only if the
938 * component is a selected {@link JMenu} or an armed {@link JMenuItem}.
939 *
940 * @param c the component.
941 * @param g the graphics device.
942 * @param x the x-coordinate of the border area.
943 * @param y the y-coordinate of the border area.
944 * @param w the width of the border area.
945 * @param h the height of the border area.
946 */
947 public void paintBorder(Component c, Graphics g, int x, int y, int w,
948 int h)
949 {
950 // Although it is not correct to decide on the static property
951 // currentTheme which color to use the RI does it like that.
952 // The trouble is that by simply changing the current theme to
953 // e.g. DefaultMetalLookAndFeel this method will use another color
954 // although a change in painting behavior should be expected only
955 // after setting a new look and feel and updating all components.
956 if(MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme)
957 g.setColor(UIManager.getColor("MenuBar.borderColor"));
958 else
959 g.setColor(MetalLookAndFeel.getControlShadow());
960
961 g.drawLine(x, y + h - 1, x + w, y + h - 1);
962 }
963
964 /**
965 * Returns the border insets.
966 *
967 * @param c the component (ignored).
968 *
969 * @return The border insets.
970 */
971 public Insets getBorderInsets(Component c)
972 {
973 return borderInsets;
974 }
975
976 /**
977 * Populates <code>insets</code> with the border insets, then returns it.
978 *
979 * @param c the component (ignored).
980 * @param insets the object to populate with the border insets.
981 *
982 * @return The border insets.
983 *
984 * @throws NullPointerException if <code>insets</code> is <code>null</code>.
985 */
986 public Insets getBorderInsets(Component c, Insets insets)
987 {
988 insets.left = borderInsets.left;
989 insets.top = borderInsets.top;
990 insets.bottom = borderInsets.bottom;
991 insets.right = borderInsets.right;
992 return insets;
993 }
994 }
995
996 /**
997 * A border for {@link JScrollPane} components.
998 */
999 public static class ScrollPaneBorder
1000 extends AbstractBorder
1001 implements UIResource
1002 {
1003 /** The border insets. */
1004 private static Insets insets = new Insets(1, 1, 2, 2);
1005
1006 /**
1007 * Constructs a new ScrollPaneBorder.
1008 */
1009 public ScrollPaneBorder()
1010 {
1011 // Nothing to do here.
1012 }
1013
1014 /**
1015 * Returns the insets of the border for the Component <code>c</code>.
1016 *
1017 * @param c the Component for which we return the border insets
1018 */
1019 public Insets getBorderInsets(Component c)
1020 {
1021 return insets;
1022 }
1023
1024 /**
1025 * Paints the border.
1026 *
1027 * @param c the Component for which the border is painted
1028 * @param g the Graphics context
1029 * @param x the X coordinate of the upper left corner of the border
1030 * @param y the Y coordinate of the upper left corner of the border
1031 * @param w the width of the border
1032 * @param h the height of the border
1033 */
1034 public void paintBorder(Component c, Graphics g, int x, int y,
1035 int w, int h)
1036 {
1037 Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
1038 Color shadow = MetalLookAndFeel.getControlShadow();
1039 Color light = MetalLookAndFeel.getWhite();
1040 Color middle = MetalLookAndFeel.getControl();
1041
1042 // paint top border line
1043 g.setColor(darkShadow);
1044 g.drawLine(x, y, x + w - 2, y);
1045
1046 // paint left border line
1047 g.drawLine(x, y, x, y + h - 2);
1048
1049 // paint right inner border line
1050 g.drawLine(x + w - 2, y, x + w - 2, y + h + 1);
1051
1052 // paint bottom inner border line
1053 g.drawLine(x + 2, y + h - 2, x + w - 2, y + h - 2);
1054
1055 // draw right outer border line
1056 g.setColor(light);
1057 g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
1058
1059 // draw bottom outer border line
1060 g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
1061
1062 // paint the lighter points
1063 g.setColor(middle);
1064 g.drawLine(x + w - 1, y, x + w - 1, y);
1065 g.drawLine(x + w - 2, y + 2, x + w - 2, y + 2);
1066 g.drawLine(x, y + h - 1, x, y + h - 1);
1067 g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
1068
1069 }
1070
1071 }
1072
1073 /**
1074 * A button border that is only visible when the mouse pointer is within
1075 * the button's bounds.
1076 */
1077 public static class RolloverButtonBorder
1078 extends MetalBorders.ButtonBorder
1079 {
1080 /**
1081 * Creates a new border instance.
1082 */
1083 public RolloverButtonBorder()
1084 {
1085 // Nothing to do here.
1086 }
1087
1088 /**
1089 * Paints the border.
1090 *
1091 * @param c the component.
1092 * @param g the graphics device.
1093 * @param x the x-coordinate.
1094 * @param y the y-coordinate.
1095 * @param w the width.
1096 * @param h the height.
1097 */
1098 public void paintBorder(Component c, Graphics g, int x, int y, int w,
1099 int h)
1100 {
1101 // TODO: What should be done here? Obviously the ButtonBorder already
1102 // handles the rollover state in Sun's impl. Maybe this is only there
1103 // for backwards compatibility.
1104 super.paintBorder(c, g, x, y, w, h);
1105 }
1106 }
1107
1108 /**
1109 * This border is used in Toolbar buttons as inner border.
1110 */
1111 static class RolloverMarginBorder extends AbstractBorder
1112 {
1113 /** The borders insets. */
1114 protected static Insets borderInsets = new Insets(3, 3, 3, 3);
1115
1116 /**
1117 * Creates a new instance of RolloverBorder.
1118 */
1119 public RolloverMarginBorder()
1120 {
1121 // Nothing to do here.
1122 }
1123
1124 /**
1125 * Returns the insets of the RolloverBorder.
1126 *
1127 * @param c the component for which the border is used
1128 *
1129 * @return the insets of the RolloverBorder
1130 */
1131 public Insets getBorderInsets(Component c)
1132 {
1133 return getBorderInsets(c, null);
1134 }
1135
1136 /**
1137 * Returns the insets of the RolloverMarginBorder in the specified
1138 * Insets object.
1139 *
1140 * @param c the component for which the border is used
1141 * @param newInsets the insets object where to put the values
1142 *
1143 * @return the insets of the RolloverMarginBorder
1144 */
1145 public Insets getBorderInsets(Component c, Insets newInsets)
1146 {
1147 if (newInsets == null)
1148 newInsets = new Insets(0, 0, 0, 0);
1149
1150 AbstractButton b = (AbstractButton) c;
1151 Insets margin = b.getMargin();
1152 newInsets.bottom = borderInsets.bottom;
1153 newInsets.left = borderInsets.left;
1154 newInsets.right = borderInsets.right;
1155 newInsets.top = borderInsets.top;
1156 return newInsets;
1157 }
1158 }
1159
1160 /**
1161 * A border implementation for popup menus.
1162 */
1163 public static class PopupMenuBorder
1164 extends AbstractBorder
1165 implements UIResource
1166 {
1167
1168 /** The border's insets. */
1169 protected static Insets borderInsets = new Insets(3, 1, 2, 1);
1170
1171 /**
1172 * Constructs a new PopupMenuBorder.
1173 */
1174 public PopupMenuBorder()
1175 {
1176 // Nothing to do here.
1177 }
1178
1179 /**
1180 * Returns the insets of the border, creating a new Insets instance
1181 * with each call.
1182 *
1183 * @param c the component for which we return the border insets
1184 * (not used here)
1185 */
1186 public Insets getBorderInsets(Component c)
1187 {
1188 return getBorderInsets(c, null);
1189 }
1190
1191 /**
1192 * Returns the insets of the border, using the supplied Insets instance.
1193 *
1194 * @param c the component for which we return the border insets
1195 * (not used here)
1196 * @param i the Insets instance to fill with the Insets values
1197 */
1198 public Insets getBorderInsets(Component c, Insets i)
1199 {
1200 Insets insets;
1201 if (i == null)
1202 insets = new Insets(borderInsets.top, borderInsets.left,
1203 borderInsets.bottom, borderInsets.right);
1204 else
1205 {
1206 insets = i;
1207 insets.top = borderInsets.top;
1208 insets.left = borderInsets.left;
1209 insets.bottom = borderInsets.bottom;
1210 insets.right = borderInsets.right;
1211 }
1212
1213 return insets;
1214 }
1215
1216 /**
1217 * Paints the border for component <code>c</code> using the
1218 * Graphics context <code>g</code> with the dimension
1219 * <code>x, y, w, h</code>.
1220 *
1221 * @param c the component for which we paint the border
1222 * @param g the Graphics context to use
1223 * @param x the X coordinate of the upper left corner of c
1224 * @param y the Y coordinate of the upper left corner of c
1225 * @param w the width of c
1226 * @param h the height of c
1227 */
1228 public void paintBorder(Component c, Graphics g, int x, int y, int w,
1229 int h)
1230 {
1231 Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow();
1232 Color light = MetalLookAndFeel.getPrimaryControlHighlight();
1233
1234 // draw dark outer border
1235 g.setColor(darkShadow);
1236 g.drawRect(x, y, w - 1, h - 1);
1237
1238 // draw highlighted inner border (only top and left)
1239 g.setColor(light);
1240 g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
1241 }
1242
1243 }
1244
1245 /**
1246 * A border used for the {@link JToggleButton} component.
1247 *
1248 * @since 1.3
1249 */
1250 public static class ToggleButtonBorder
1251 extends ButtonBorder
1252 {
1253 /**
1254 * Creates a new border instance.
1255 */
1256 public ToggleButtonBorder()
1257 {
1258 // Nothing to do here.
1259 }
1260
1261 /**
1262 * Paints the toggle button border.
1263 *
1264 * @param c the component for which we paint the border
1265 * @param g the Graphics context to use
1266 * @param x the X coordinate of the upper left corner of c
1267 * @param y the Y coordinate of the upper left corner of c
1268 * @param w the width of c
1269 * @param h the height of c
1270 */
1271 public void paintBorder(Component c, Graphics g, int x, int y, int w,
1272 int h)
1273 {
1274 ButtonModel bmodel = null;
1275
1276 if (c instanceof AbstractButton)
1277 bmodel = ((AbstractButton) c).getModel();
1278
1279 Color darkShadow = MetalLookAndFeel.getControlDarkShadow();
1280 Color shadow = MetalLookAndFeel.getControlShadow();
1281 Color light = MetalLookAndFeel.getWhite();
1282 Color middle = MetalLookAndFeel.getControl();
1283
1284 if (c.isEnabled())
1285 {
1286 // draw dark border
1287 g.setColor(darkShadow);
1288 g.drawRect(x, y, w - 2, h - 2);
1289
1290 if (!bmodel.isArmed())
1291 {
1292 // draw light border
1293 g.setColor(light);
1294 g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
1295 g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
1296 if (bmodel.isSelected())
1297 g.setColor(middle);
1298 g.drawLine(x + 1, y + 1, x + w - 3, y + 1);
1299 g.drawLine(x + 1, y + 1, x + 1, y + h - 3);
1300
1301 // draw crossing pixels of both borders
1302 g.setColor(shadow);
1303 g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
1304 g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
1305 }
1306 else
1307 {
1308 // draw light border
1309 g.setColor(light);
1310 g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1);
1311 g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
1312
1313 // draw shadow border
1314 g.setColor(shadow);
1315 g.drawLine(x + 1, y + 1, x + w - 2, y + 1);
1316 g.drawLine(x + 1, y + 1, x + 1, y + h - 2);
1317
1318 // draw crossing pixels of both borders
1319 g.setColor(shadow);
1320 g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2);
1321 g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1);
1322
1323 }
1324 // draw corners
1325 g.setColor(middle);
1326 g.drawLine(x, y + h - 1, x, y + h - 1);
1327 g.drawLine(x + w - 1, y, x + w - 1, y);
1328 }
1329 else
1330 {
1331 // draw disabled border
1332 g.setColor(MetalLookAndFeel.getControlDisabled());
1333 g.drawRect(x, y, w - 2, h - 2);
1334 }
1335 }
1336 }
1337
1338 /**
1339 * A border used for the {@link JToolBar} component.
1340 */
1341 public static class ToolBarBorder extends AbstractBorder
1342 implements UIResource, SwingConstants
1343 {
1344 /**
1345 * Creates a new border instance.
1346 */
1347 public ToolBarBorder()
1348 {
1349 // Nothing to do here.
1350 }
1351
1352 /**
1353 * Returns the border insets.
1354 *
1355 * @param c the component (ignored).
1356 *
1357 * @return The border insets.
1358 */
1359 public Insets getBorderInsets(Component c)
1360 {
1361 return getBorderInsets(c, null);
1362 }
1363
1364 /**
1365 * Returns the border insets.
1366 *
1367 * @param c the component (ignored).
1368 * @return The border insets.
1369 */
1370 public Insets getBorderInsets(Component c, Insets newInsets)
1371 {
1372 JToolBar tb = (JToolBar) c;
1373 if (tb.getOrientation() == JToolBar.HORIZONTAL)
1374 {
1375 if (newInsets == null)
1376 newInsets = new Insets(2, 16, 2, 2);
1377 else
1378 {
1379 newInsets.top = 2;
1380 newInsets.left = 16;
1381 newInsets.bottom = 2;
1382 newInsets.right = 2;
1383 }
1384 return newInsets;
1385 }
1386 else // assume JToolBar.VERTICAL
1387 {
1388 if (newInsets == null)
1389 newInsets = new Insets(16, 2, 2, 2);
1390 else
1391 {
1392 newInsets.top = 16;
1393 newInsets.left = 2;
1394 newInsets.bottom = 2;
1395 newInsets.right = 2;
1396 }
1397 return newInsets;
1398 }
1399
1400 }
1401
1402 /**
1403 * Paints the border for the specified component.
1404 *
1405 * @param c the component.
1406 * @param g the graphics device.
1407 * @param x the x-coordinate.
1408 * @param y the y-coordinate.
1409 * @param w the width.
1410 * @param h the height.
1411 */
1412 public void paintBorder(Component c, Graphics g, int x, int y, int w,
1413 int h)
1414 {
1415
1416 JToolBar tb = (JToolBar) c;
1417 if (tb.getOrientation() == JToolBar.HORIZONTAL)
1418 {
1419 MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + 11, y + h - 5,
1420 MetalLookAndFeel.getControlHighlight(),
1421 MetalLookAndFeel.getControlDarkShadow());
1422 }
1423 else
1424 {
1425 MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + w - 5, y + 11,
1426 MetalLookAndFeel.getControlHighlight(),
1427 MetalLookAndFeel.getControlDarkShadow());
1428 }
1429 }
1430
1431 }
1432
1433 /**
1434 * A border for table header cells.
1435 *
1436 * @since 1.3
1437 */
1438 public static class TableHeaderBorder extends AbstractBorder
1439 {
1440 /**
1441 * The insets of this border.
1442 */
1443 // TODO: According to tests that I have done, this is really the border
1444 // that should be returned by getBorderInsets(). However, the name
1445 // is very distracting. Is there any deeper meaning in it?
1446 protected Insets editorBorderInsets;
1447
1448 /**
1449 * Creates a new instance of <code>TableHeaderBorder</code>.
1450 */
1451 public TableHeaderBorder()
1452 {
1453 editorBorderInsets = new Insets(1, 1, 1, 1);
1454 }
1455
1456 /**
1457 * Return the insets of this border.
1458 *
1459 * @return the insets of this border
1460 */
1461 public Insets getBorderInsets(Component c)
1462 {
1463 return editorBorderInsets;
1464 }
1465
1466 /**
1467 * Paints the border.
1468 *
1469 * @param c the component for which to paint the border
1470 * @param g the graphics context to use
1471 * @param x the x cooridinate of the border rectangle
1472 * @param y the y cooridinate of the border rectangle
1473 * @param w the width of the border rectangle
1474 * @param h the height of the border rectangle
1475 */
1476 public void paintBorder(Component c, Graphics g, int x, int y, int w, int h)
1477 {
1478 Color dark = MetalLookAndFeel.getControlDarkShadow();
1479 Color light = MetalLookAndFeel.getWhite();
1480 Color old = g.getColor();
1481 g.setColor(light);
1482 g.drawLine(x, y, x + w - 2, y);
1483 g.drawLine(x, y, x, y + h - 2);
1484 g.setColor(dark);
1485 g.drawLine(x + w - 1, y, x + w - 1, y + h - 1);
1486 g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1);
1487 g.setColor(old);
1488 }
1489 }
1490
1491 /**
1492 * Returns a border for Swing buttons in the Metal Look & Feel.
1493 *
1494 * @return a border for Swing buttons in the Metal Look & Feel
1495 */
1496 public static Border getButtonBorder()
1497 {
1498 if (buttonBorder == null)
1499 {
1500 Border outer = new ButtonBorder();
1501 Border inner = getMarginBorder();
1502 buttonBorder = new BorderUIResource.CompoundBorderUIResource(outer,
1503 inner);
1504 }
1505 return buttonBorder;
1506 }
1507
1508 /**
1509 * Returns a border for use with {@link JToggleButton} components.
1510 *
1511 * @return A border.
1512 *
1513 * @since 1.3
1514 */
1515 public static Border getToggleButtonBorder()
1516 {
1517 if (toggleButtonBorder == null)
1518 {
1519 Border outer = new ToggleButtonBorder();
1520 Border inner = getMarginBorder();
1521 toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource(
1522 outer, inner);
1523 }
1524 return toggleButtonBorder;
1525 }
1526
1527 /**
1528 * Returns a border instance that is used with a {@link JInternalFrame} when
1529 * it is in the iconified state.
1530 *
1531 * @return A border.
1532 *
1533 * @since 1.3
1534 */
1535 public static Border getDesktopIconBorder()
1536 {
1537 if (desktopIconBorder == null)
1538 desktopIconBorder = new DesktopIconBorder();
1539 return desktopIconBorder;
1540 }
1541
1542 /**
1543 * Returns a border for use by the {@link JTextField} component.
1544 *
1545 * @return A border.
1546 *
1547 * @since 1.3
1548 */
1549 public static Border getTextFieldBorder()
1550 {
1551 if (textFieldBorder == null)
1552 {
1553 Border inner = getMarginBorder();
1554 Border outer = new TextFieldBorder();
1555 textFieldBorder =
1556 new BorderUIResource.CompoundBorderUIResource(outer, inner);
1557 }
1558 return textFieldBorder;
1559 }
1560
1561 /**
1562 * Returns the border that is used for text components (except text fields,
1563 * which use {@link #getTextFieldBorder}.
1564 *
1565 * @return the border that is used for text components
1566 *
1567 * @since 1.3
1568 */
1569 public static Border getTextBorder()
1570 {
1571 if (textBorder == null)
1572 {
1573 Border inner = getMarginBorder();
1574 Border outer = new Flush3DBorder();
1575 textBorder =
1576 new BorderUIResource.CompoundBorderUIResource(outer, inner);
1577 }
1578 return textBorder;
1579 }
1580
1581 /**
1582 * Returns a border for Toolbar buttons in the Metal Look & Feel.
1583 *
1584 * @return a border for Toolbar buttons in the Metal Look & Feel
1585 */
1586 static Border getToolbarButtonBorder()
1587 {
1588 if (toolbarButtonBorder == null)
1589 {
1590 Border outer = new ButtonBorder();
1591 Border inner = new RolloverMarginBorder();
1592 toolbarButtonBorder = new CompoundBorder(outer, inner);
1593 }
1594 return toolbarButtonBorder;
1595 }
1596
1597 /**
1598 * Returns a shared instance of {@link BasicBorders.MarginBorder}.
1599 *
1600 * @return a shared instance of {@link BasicBorders.MarginBorder}
1601 */
1602 static Border getMarginBorder()
1603 {
1604 if (marginBorder == null)
1605 marginBorder = new BasicBorders.MarginBorder();
1606 return marginBorder;
1607 }
1608
1609 /**
1610 * Returns a shared instance of a compound border for rollover buttons.
1611 *
1612 * @return A shared border instance.
1613 */
1614 static Border getRolloverBorder()
1615 {
1616 if (rolloverBorder == null)
1617 {
1618 Border outer = new MetalBorders.RolloverButtonBorder();
1619 Border inner = MetalBorders.getMarginBorder();
1620 rolloverBorder = new BorderUIResource.CompoundBorderUIResource(outer,
1621 inner);
1622 }
1623 return rolloverBorder;
1624 }
1625
1626 }