1/*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package javax.swing;
26
27import java.awt.BasicStroke;
28import java.awt.Color;
29import java.awt.Font;
30import java.awt.Paint;
31import javax.swing.border.*;
32
33/**
34 * Factory class for vending standard <code>Border</code> objects.  Wherever
35 * possible, this factory will hand out references to shared
36 * <code>Border</code> instances.
37 * For further information and examples see
38 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/border.html">How
39 to Use Borders</a>,
40 * a section in <em>The Java Tutorial</em>.
41 *
42 * @author David Kloba
43 * @since 1.2
44 */
45public class BorderFactory
46{
47
48    /** Don't let anyone instantiate this class */
49    private BorderFactory() {
50    }
51
52
53//// LineBorder ///////////////////////////////////////////////////////////////
54    /**
55     * Creates a line border with the specified color.
56     *
57     * @param color  a <code>Color</code> to use for the line
58     * @return the <code>Border</code> object
59     */
60    public static Border createLineBorder(Color color) {
61        return new LineBorder(color, 1);
62    }
63
64    /**
65     * Creates a line border with the specified color
66     * and width. The width applies to all four sides of the
67     * border. To specify widths individually for the top,
68     * bottom, left, and right, use
69     * {@link #createMatteBorder(int,int,int,int,Color)}.
70     *
71     * @param color  a <code>Color</code> to use for the line
72     * @param thickness  an integer specifying the width in pixels
73     * @return the <code>Border</code> object
74     */
75    public static Border createLineBorder(Color color, int thickness)  {
76        return new LineBorder(color, thickness);
77    }
78
79    /**
80     * Creates a line border with the specified color, thickness, and corner shape.
81     *
82     * @param color      the color of the border
83     * @param thickness  the thickness of the border
84     * @param rounded    whether or not border corners should be round
85     * @return the {@code Border} object
86     *
87     * @see LineBorder#LineBorder(Color, int, boolean)
88     * @since 1.7
89     */
90    public static Border createLineBorder(Color color, int thickness, boolean rounded) {
91        return new LineBorder(color, thickness, rounded);
92    }
93
94//// BevelBorder /////////////////////////////////////////////////////////////
95///////////////////////////////////////////////////////////////////////////////
96    static final Border sharedRaisedBevel = new BevelBorder(BevelBorder.RAISED);
97    static final Border sharedLoweredBevel = new BevelBorder(BevelBorder.LOWERED);
98
99    /**
100     * Creates a border with a raised beveled edge, using
101     * brighter shades of the component's current background color
102     * for highlighting, and darker shading for shadows.
103     * (In a raised border, highlights are on top and shadows
104     *  are underneath.)
105     *
106     * @return the <code>Border</code> object
107     */
108    public static Border createRaisedBevelBorder() {
109        return createSharedBevel(BevelBorder.RAISED);
110    }
111
112    /**
113     * Creates a border with a lowered beveled edge, using
114     * brighter shades of the component's current background color
115     * for highlighting, and darker shading for shadows.
116     * (In a lowered border, shadows are on top and highlights
117     *  are underneath.)
118     *
119     * @return the <code>Border</code> object
120     */
121    public static Border createLoweredBevelBorder() {
122        return createSharedBevel(BevelBorder.LOWERED);
123    }
124
125    /**
126     * Creates a beveled border of the specified type, using
127     * brighter shades of the component's current background color
128     * for highlighting, and darker shading for shadows.
129     * (In a lowered border, shadows are on top and highlights
130     *  are underneath.)
131     *
132     * @param type  an integer specifying either
133     *                  <code>BevelBorder.LOWERED</code> or
134     *                  <code>BevelBorder.RAISED</code>
135     * @return the <code>Border</code> object
136     */
137    public static Border createBevelBorder(int type) {
138        return createSharedBevel(type);
139    }
140
141    /**
142     * Creates a beveled border of the specified type, using
143     * the specified highlighting and shadowing. The outer
144     * edge of the highlighted area uses a brighter shade of
145     * the highlight color. The inner edge of the shadow area
146     * uses a brighter shade of the shadow color.
147     *
148     * @param type  an integer specifying either
149     *                  <code>BevelBorder.LOWERED</code> or
150     *                  <code>BevelBorder.RAISED</code>
151     * @param highlight  a <code>Color</code> object for highlights
152     * @param shadow     a <code>Color</code> object for shadows
153     * @return the <code>Border</code> object
154     */
155    public static Border createBevelBorder(int type, Color highlight, Color shadow) {
156        return new BevelBorder(type, highlight, shadow);
157    }
158
159    /**
160     * Creates a beveled border of the specified type, using
161     * the specified colors for the inner and outer highlight
162     * and shadow areas.
163     *
164     * @param type  an integer specifying either
165     *          <code>BevelBorder.LOWERED</code> or
166     *          <code>BevelBorder.RAISED</code>
167     * @param highlightOuter  a <code>Color</code> object for the
168     *                  outer edge of the highlight area
169     * @param highlightInner  a <code>Color</code> object for the
170     *                  inner edge of the highlight area
171     * @param shadowOuter     a <code>Color</code> object for the
172     *                  outer edge of the shadow area
173     * @param shadowInner     a <code>Color</code> object for the
174     *                  inner edge of the shadow area
175     * @return the <code>Border</code> object
176     */
177    public static Border createBevelBorder(int type,
178                        Color highlightOuter, Color highlightInner,
179                        Color shadowOuter, Color shadowInner) {
180        return new BevelBorder(type, highlightOuter, highlightInner,
181                                        shadowOuter, shadowInner);
182    }
183
184    static Border createSharedBevel(int type)   {
185        if(type == BevelBorder.RAISED) {
186            return sharedRaisedBevel;
187        } else if(type == BevelBorder.LOWERED) {
188            return sharedLoweredBevel;
189        }
190        return null;
191    }
192
193//// SoftBevelBorder ///////////////////////////////////////////////////////////
194////////////////////////////////////////////////////////////////////////////////
195
196    private static Border sharedSoftRaisedBevel;
197    private static Border sharedSoftLoweredBevel;
198
199    /**
200     * Creates a beveled border with a raised edge and softened corners,
201     * using brighter shades of the component's current background color
202     * for highlighting, and darker shading for shadows.
203     * In a raised border, highlights are on top and shadows are underneath.
204     *
205     * @return the {@code Border} object
206     *
207     * @since 1.7
208     */
209    public static Border createRaisedSoftBevelBorder() {
210        if (sharedSoftRaisedBevel == null) {
211            sharedSoftRaisedBevel = new SoftBevelBorder(BevelBorder.RAISED);
212        }
213        return sharedSoftRaisedBevel;
214    }
215
216    /**
217     * Creates a beveled border with a lowered edge and softened corners,
218     * using brighter shades of the component's current background color
219     * for highlighting, and darker shading for shadows.
220     * In a lowered border, shadows are on top and highlights are underneath.
221     *
222     * @return the {@code Border} object
223     *
224     * @since 1.7
225     */
226    public static Border createLoweredSoftBevelBorder() {
227        if (sharedSoftLoweredBevel == null) {
228            sharedSoftLoweredBevel = new SoftBevelBorder(BevelBorder.LOWERED);
229        }
230        return sharedSoftLoweredBevel;
231    }
232
233    /**
234     * Creates a beveled border of the specified type with softened corners,
235     * using brighter shades of the component's current background color
236     * for highlighting, and darker shading for shadows.
237     * The type is either {@link BevelBorder#RAISED} or {@link BevelBorder#LOWERED}.
238     *
239     * @param type  a type of a bevel
240     * @return the {@code Border} object or {@code null}
241     *         if the specified type is not valid
242     *
243     * @see BevelBorder#BevelBorder(int)
244     * @since 1.7
245     */
246    public static Border createSoftBevelBorder(int type) {
247        if (type == BevelBorder.RAISED) {
248            return createRaisedSoftBevelBorder();
249        }
250        if (type == BevelBorder.LOWERED) {
251            return createLoweredSoftBevelBorder();
252        }
253        return null;
254    }
255
256    /**
257     * Creates a beveled border of the specified type with softened corners,
258     * using the specified highlighting and shadowing.
259     * The type is either {@link BevelBorder#RAISED} or {@link BevelBorder#LOWERED}.
260     * The outer edge of the highlight area uses
261     * a brighter shade of the {@code highlight} color.
262     * The inner edge of the shadow area uses
263     * a brighter shade of the {@code shadow} color.
264     *
265     * @param type       a type of a bevel
266     * @param highlight  a basic color of the highlight area
267     * @param shadow     a basic color of the shadow area
268     * @return the {@code Border} object
269     *
270     * @see BevelBorder#BevelBorder(int, Color, Color)
271     * @since 1.7
272     */
273    public static Border createSoftBevelBorder(int type, Color highlight, Color shadow) {
274        return new SoftBevelBorder(type, highlight, shadow);
275    }
276
277    /**
278     * Creates a beveled border of the specified type with softened corners,
279     * using the specified colors for the inner and outer edges
280     * of the highlight and the shadow areas.
281     * The type is either {@link BevelBorder#RAISED} or {@link BevelBorder#LOWERED}.
282     * Note: The shadow inner and outer colors are switched
283     * for a lowered bevel border.
284     *
285     * @param type            a type of a bevel
286     * @param highlightOuter  a color of the outer edge of the highlight area
287     * @param highlightInner  a color of the inner edge of the highlight area
288     * @param shadowOuter     a color of the outer edge of the shadow area
289     * @param shadowInner     a color of the inner edge of the shadow area
290     * @return the {@code Border} object
291     *
292     * @see BevelBorder#BevelBorder(int, Color, Color, Color, Color)
293     * @since 1.7
294     */
295    public static Border createSoftBevelBorder(int type, Color highlightOuter, Color highlightInner, Color shadowOuter, Color shadowInner) {
296        return new SoftBevelBorder(type, highlightOuter, highlightInner, shadowOuter, shadowInner);
297    }
298
299//// EtchedBorder ///////////////////////////////////////////////////////////
300
301    static final Border sharedEtchedBorder = new EtchedBorder();
302    private static Border sharedRaisedEtchedBorder;
303
304    /**
305     * Creates a border with an "etched" look using
306     * the component's current background color for
307     * highlighting and shading.
308     *
309     * @return the <code>Border</code> object
310     */
311    public static Border createEtchedBorder()    {
312        return sharedEtchedBorder;
313    }
314
315    /**
316     * Creates a border with an "etched" look using
317     * the specified highlighting and shading colors.
318     *
319     * @param highlight  a <code>Color</code> object for the border highlights
320     * @param shadow     a <code>Color</code> object for the border shadows
321     * @return the <code>Border</code> object
322     */
323    public static Border createEtchedBorder(Color highlight, Color shadow)    {
324        return new EtchedBorder(highlight, shadow);
325    }
326
327    /**
328     * Creates a border with an "etched" look using
329     * the component's current background color for
330     * highlighting and shading.
331     *
332     * @param type      one of <code>EtchedBorder.RAISED</code>, or
333     *                  <code>EtchedBorder.LOWERED</code>
334     * @return the <code>Border</code> object
335     * @exception IllegalArgumentException if type is not either
336     *                  <code>EtchedBorder.RAISED</code> or
337     *                  <code>EtchedBorder.LOWERED</code>
338     * @since 1.3
339     */
340    public static Border createEtchedBorder(int type)    {
341        switch (type) {
342        case EtchedBorder.RAISED:
343            if (sharedRaisedEtchedBorder == null) {
344                sharedRaisedEtchedBorder = new EtchedBorder
345                                           (EtchedBorder.RAISED);
346            }
347            return sharedRaisedEtchedBorder;
348        case EtchedBorder.LOWERED:
349            return sharedEtchedBorder;
350        default:
351            throw new IllegalArgumentException("type must be one of EtchedBorder.RAISED or EtchedBorder.LOWERED");
352        }
353    }
354
355    /**
356     * Creates a border with an "etched" look using
357     * the specified highlighting and shading colors.
358     *
359     * @param type      one of <code>EtchedBorder.RAISED</code>, or
360     *                  <code>EtchedBorder.LOWERED</code>
361     * @param highlight  a <code>Color</code> object for the border highlights
362     * @param shadow     a <code>Color</code> object for the border shadows
363     * @return the <code>Border</code> object
364     * @since 1.3
365     */
366    public static Border createEtchedBorder(int type, Color highlight,
367                                            Color shadow)    {
368        return new EtchedBorder(type, highlight, shadow);
369    }
370
371//// TitledBorder ////////////////////////////////////////////////////////////
372    /**
373     * Creates a new titled border with the specified title,
374     * the default border type (determined by the current look and feel),
375     * the default text position (determined by the current look and feel),
376     * the default justification (leading), and the default
377     * font and text color (determined by the current look and feel).
378     *
379     * @param title      a <code>String</code> containing the text of the title
380     * @return the <code>TitledBorder</code> object
381     */
382    public static TitledBorder createTitledBorder(String title)     {
383        return new TitledBorder(title);
384    }
385
386    /**
387     * Creates a new titled border with an empty title,
388     * the specified border object,
389     * the default text position (determined by the current look and feel),
390     * the default justification (leading), and the default
391     * font and text color (determined by the current look and feel).
392     *
393     * @param border     the <code>Border</code> object to add the title to; if
394     *                   <code>null</code> the <code>Border</code> is determined
395     *                   by the current look and feel.
396     * @return the <code>TitledBorder</code> object
397     */
398    public static TitledBorder createTitledBorder(Border border)       {
399        return new TitledBorder(border);
400    }
401
402    /**
403     * Adds a title to an existing border,
404     * with default positioning (determined by the current look and feel),
405     * default justification (leading) and the default
406     * font and text color (determined by the current look and feel).
407     *
408     * @param border     the <code>Border</code> object to add the title to
409     * @param title      a <code>String</code> containing the text of the title
410     * @return the <code>TitledBorder</code> object
411     */
412    public static TitledBorder createTitledBorder(Border border,
413                                                   String title) {
414        return new TitledBorder(border, title);
415    }
416
417    /**
418     * Adds a title to an existing border, with the specified
419     * positioning and using the default
420     * font and text color (determined by the current look and feel).
421     *
422     * @param border      the <code>Border</code> object to add the title to
423     * @param title       a <code>String</code> containing the text of the title
424     * @param titleJustification  an integer specifying the justification
425     *        of the title -- one of the following:
426     *<ul>
427     *<li><code>TitledBorder.LEFT</code>
428     *<li><code>TitledBorder.CENTER</code>
429     *<li><code>TitledBorder.RIGHT</code>
430     *<li><code>TitledBorder.LEADING</code>
431     *<li><code>TitledBorder.TRAILING</code>
432     *<li><code>TitledBorder.DEFAULT_JUSTIFICATION</code> (leading)
433     *</ul>
434     * @param titlePosition       an integer specifying the vertical position of
435     *        the text in relation to the border -- one of the following:
436     *<ul>
437     *<li><code> TitledBorder.ABOVE_TOP</code>
438     *<li><code>TitledBorder.TOP</code> (sitting on the top line)
439     *<li><code>TitledBorder.BELOW_TOP</code>
440     *<li><code>TitledBorder.ABOVE_BOTTOM</code>
441     *<li><code>TitledBorder.BOTTOM</code> (sitting on the bottom line)
442     *<li><code>TitledBorder.BELOW_BOTTOM</code>
443     *<li><code>TitledBorder.DEFAULT_POSITION</code> (the title position
444     *  is determined by the current look and feel)
445     *</ul>
446     * @return the <code>TitledBorder</code> object
447     */
448    public static TitledBorder createTitledBorder(Border border,
449                        String title,
450                        int titleJustification,
451                        int titlePosition)      {
452        return new TitledBorder(border, title, titleJustification,
453                        titlePosition);
454    }
455
456    /**
457     * Adds a title to an existing border, with the specified
458     * positioning and font, and using the default text color
459     * (determined by the current look and feel).
460     *
461     * @param border      the <code>Border</code> object to add the title to
462     * @param title       a <code>String</code> containing the text of the title
463     * @param titleJustification  an integer specifying the justification
464     *        of the title -- one of the following:
465     *<ul>
466     *<li><code>TitledBorder.LEFT</code>
467     *<li><code>TitledBorder.CENTER</code>
468     *<li><code>TitledBorder.RIGHT</code>
469     *<li><code>TitledBorder.LEADING</code>
470     *<li><code>TitledBorder.TRAILING</code>
471     *<li><code>TitledBorder.DEFAULT_JUSTIFICATION</code> (leading)
472     *</ul>
473     * @param titlePosition       an integer specifying the vertical position of
474     *        the text in relation to the border -- one of the following:
475     *<ul>
476     *<li><code> TitledBorder.ABOVE_TOP</code>
477     *<li><code>TitledBorder.TOP</code> (sitting on the top line)
478     *<li><code>TitledBorder.BELOW_TOP</code>
479     *<li><code>TitledBorder.ABOVE_BOTTOM</code>
480     *<li><code>TitledBorder.BOTTOM</code> (sitting on the bottom line)
481     *<li><code>TitledBorder.BELOW_BOTTOM</code>
482     *<li><code>TitledBorder.DEFAULT_POSITION</code> (the title position
483     *  is determined by the current look and feel)
484     *</ul>
485     * @param titleFont           a Font object specifying the title font
486     * @return the TitledBorder object
487     */
488    public static TitledBorder createTitledBorder(Border border,
489                        String title,
490                        int titleJustification,
491                        int titlePosition,
492                        Font titleFont) {
493        return new TitledBorder(border, title, titleJustification,
494                        titlePosition, titleFont);
495    }
496
497    /**
498     * Adds a title to an existing border, with the specified
499     * positioning, font and color.
500     *
501     * @param border      the <code>Border</code> object to add the title to
502     * @param title       a <code>String</code> containing the text of the title
503     * @param titleJustification  an integer specifying the justification
504     *        of the title -- one of the following:
505     *<ul>
506     *<li><code>TitledBorder.LEFT</code>
507     *<li><code>TitledBorder.CENTER</code>
508     *<li><code>TitledBorder.RIGHT</code>
509     *<li><code>TitledBorder.LEADING</code>
510     *<li><code>TitledBorder.TRAILING</code>
511     *<li><code>TitledBorder.DEFAULT_JUSTIFICATION</code> (leading)
512     *</ul>
513     * @param titlePosition       an integer specifying the vertical position of
514     *        the text in relation to the border -- one of the following:
515     *<ul>
516     *<li><code> TitledBorder.ABOVE_TOP</code>
517     *<li><code>TitledBorder.TOP</code> (sitting on the top line)
518     *<li><code>TitledBorder.BELOW_TOP</code>
519     *<li><code>TitledBorder.ABOVE_BOTTOM</code>
520     *<li><code>TitledBorder.BOTTOM</code> (sitting on the bottom line)
521     *<li><code>TitledBorder.BELOW_BOTTOM</code>
522     *<li><code>TitledBorder.DEFAULT_POSITION</code> (the title position
523     *  is determined by the current look and feel)
524     *</ul>
525     * @param titleFont   a <code>Font</code> object specifying the title font
526     * @param titleColor  a <code>Color</code> object specifying the title color
527     * @return the <code>TitledBorder</code> object
528     */
529    public static TitledBorder createTitledBorder(Border border,
530                        String title,
531                        int titleJustification,
532                        int titlePosition,
533                        Font titleFont,
534                        Color titleColor)       {
535        return new TitledBorder(border, title, titleJustification,
536                        titlePosition, titleFont, titleColor);
537    }
538//// EmptyBorder ///////////////////////////////////////////////////////////
539    static final Border emptyBorder = new EmptyBorder(0, 0, 0, 0);
540
541    /**
542     * Creates an empty border that takes up no space. (The width
543     * of the top, bottom, left, and right sides are all zero.)
544     *
545     * @return the <code>Border</code> object
546     */
547    public static Border createEmptyBorder() {
548        return emptyBorder;
549    }
550
551    /**
552     * Creates an empty border that takes up space but which does
553     * no drawing, specifying the width of the top, left, bottom, and
554     * right sides.
555     *
556     * @param top     an integer specifying the width of the top,
557     *                  in pixels
558     * @param left    an integer specifying the width of the left side,
559     *                  in pixels
560     * @param bottom  an integer specifying the width of the bottom,
561     *                  in pixels
562     * @param right   an integer specifying the width of the right side,
563     *                  in pixels
564     * @return the <code>Border</code> object
565     */
566    public static Border createEmptyBorder(int top, int left,
567                                                int bottom, int right) {
568        return new EmptyBorder(top, left, bottom, right);
569    }
570
571//// CompoundBorder ////////////////////////////////////////////////////////
572    /**
573     * Creates a compound border with a <code>null</code> inside edge and a
574     * <code>null</code> outside edge.
575     *
576     * @return the <code>CompoundBorder</code> object
577     */
578    public static CompoundBorder createCompoundBorder() {
579        return new CompoundBorder();
580    }
581
582    /**
583     * Creates a compound border specifying the border objects to use
584     * for the outside and inside edges.
585     *
586     * @param outsideBorder  a <code>Border</code> object for the outer
587     *                          edge of the compound border
588     * @param insideBorder   a <code>Border</code> object for the inner
589     *                          edge of the compound border
590     * @return the <code>CompoundBorder</code> object
591     */
592    public static CompoundBorder createCompoundBorder(Border outsideBorder,
593                                                Border insideBorder) {
594        return new CompoundBorder(outsideBorder, insideBorder);
595    }
596
597//// MatteBorder ////////////////////////////////////////////////////////
598    /**
599     * Creates a matte-look border using a solid color. (The difference between
600     * this border and a line border is that you can specify the individual
601     * border dimensions.)
602     *
603     * @param top     an integer specifying the width of the top,
604     *                          in pixels
605     * @param left    an integer specifying the width of the left side,
606     *                          in pixels
607     * @param bottom  an integer specifying the width of the right side,
608     *                          in pixels
609     * @param right   an integer specifying the width of the bottom,
610     *                          in pixels
611     * @param color   a <code>Color</code> to use for the border
612     * @return the <code>MatteBorder</code> object
613     */
614    public static MatteBorder createMatteBorder(int top, int left, int bottom, int right,
615                                                Color color) {
616        return new MatteBorder(top, left, bottom, right, color);
617    }
618
619    /**
620     * Creates a matte-look border that consists of multiple tiles of a
621     * specified icon. Multiple copies of the icon are placed side-by-side
622     * to fill up the border area.
623     * <p>
624     * Note:<br>
625     * If the icon doesn't load, the border area is painted gray.
626     *
627     * @param top     an integer specifying the width of the top,
628     *                          in pixels
629     * @param left    an integer specifying the width of the left side,
630     *                          in pixels
631     * @param bottom  an integer specifying the width of the right side,
632     *                          in pixels
633     * @param right   an integer specifying the width of the bottom,
634     *                          in pixels
635     * @param tileIcon  the <code>Icon</code> object used for the border tiles
636     * @return the <code>MatteBorder</code> object
637     */
638    public static MatteBorder createMatteBorder(int top, int left, int bottom, int right,
639                                                Icon tileIcon) {
640        return new MatteBorder(top, left, bottom, right, tileIcon);
641    }
642
643//// StrokeBorder //////////////////////////////////////////////////////////////
644////////////////////////////////////////////////////////////////////////////////
645
646    /**
647     * Creates a border of the specified {@code stroke}.
648     * The component's foreground color will be used to render the border.
649     *
650     * @param stroke  the {@link BasicStroke} object used to stroke a shape
651     * @return the {@code Border} object
652     *
653     * @throws NullPointerException if the specified {@code stroke} is {@code null}
654     *
655     * @since 1.7
656     */
657    public static Border createStrokeBorder(BasicStroke stroke) {
658        return new StrokeBorder(stroke);
659    }
660
661    /**
662     * Creates a border of the specified {@code stroke} and {@code paint}.
663     * If the specified {@code paint} is {@code null},
664     * the component's foreground color will be used to render the border.
665     *
666     * @param stroke  the {@link BasicStroke} object used to stroke a shape
667     * @param paint   the {@link Paint} object used to generate a color
668     * @return the {@code Border} object
669     *
670     * @throws NullPointerException if the specified {@code stroke} is {@code null}
671     *
672     * @since 1.7
673     */
674    public static Border createStrokeBorder(BasicStroke stroke, Paint paint) {
675        return new StrokeBorder(stroke, paint);
676    }
677
678//// DashedBorder //////////////////////////////////////////////////////////////
679////////////////////////////////////////////////////////////////////////////////
680
681    private static Border sharedDashedBorder;
682
683    /**
684     * Creates a dashed border of the specified {@code paint}.
685     * If the specified {@code paint} is {@code null},
686     * the component's foreground color will be used to render the border.
687     * The width of a dash line is equal to {@code 1}.
688     * The relative length of a dash line and
689     * the relative spacing between dash lines are equal to {@code 1}.
690     * A dash line is not rounded.
691     *
692     * @param paint  the {@link Paint} object used to generate a color
693     * @return the {@code Border} object
694     *
695     * @since 1.7
696     */
697    public static Border createDashedBorder(Paint paint) {
698        return createDashedBorder(paint, 1.0f, 1.0f, 1.0f, false);
699    }
700
701    /**
702     * Creates a dashed border of the specified {@code paint},
703     * relative {@code length}, and relative {@code spacing}.
704     * If the specified {@code paint} is {@code null},
705     * the component's foreground color will be used to render the border.
706     * The width of a dash line is equal to {@code 1}.
707     * A dash line is not rounded.
708     *
709     * @param paint    the {@link Paint} object used to generate a color
710     * @param length   the relative length of a dash line
711     * @param spacing  the relative spacing between dash lines
712     * @return the {@code Border} object
713     *
714     * @throws IllegalArgumentException if the specified {@code length} is less than {@code 1}, or
715     *                                  if the specified {@code spacing} is less than {@code 0}
716     * @since 1.7
717     */
718    public static Border createDashedBorder(Paint paint, float length, float spacing) {
719        return createDashedBorder(paint, 1.0f, length, spacing, false);
720    }
721
722    /**
723     * Creates a dashed border of the specified {@code paint}, {@code thickness},
724     * line shape, relative {@code length}, and relative {@code spacing}.
725     * If the specified {@code paint} is {@code null},
726     * the component's foreground color will be used to render the border.
727     *
728     * @param paint      the {@link Paint} object used to generate a color
729     * @param thickness  the width of a dash line
730     * @param length     the relative length of a dash line
731     * @param spacing    the relative spacing between dash lines
732     * @param rounded    whether or not line ends should be round
733     * @return the {@code Border} object
734     *
735     * @throws IllegalArgumentException if the specified {@code thickness} is less than {@code 1}, or
736     *                                  if the specified {@code length} is less than {@code 1}, or
737     *                                  if the specified {@code spacing} is less than {@code 0}
738     * @since 1.7
739     */
740    public static Border createDashedBorder(Paint paint, float thickness, float length, float spacing, boolean rounded) {
741        boolean shared = !rounded && (paint == null) && (thickness == 1.0f) && (length == 1.0f) && (spacing == 1.0f);
742        if (shared && (sharedDashedBorder != null)) {
743            return sharedDashedBorder;
744        }
745        if (thickness < 1.0f) {
746            throw new IllegalArgumentException("thickness is less than 1");
747        }
748        if (length < 1.0f) {
749            throw new IllegalArgumentException("length is less than 1");
750        }
751        if (spacing < 0.0f) {
752            throw new IllegalArgumentException("spacing is less than 0");
753        }
754        int cap = rounded ? BasicStroke.CAP_ROUND : BasicStroke.CAP_SQUARE;
755        int join = rounded ? BasicStroke.JOIN_ROUND : BasicStroke.JOIN_MITER;
756        float[] array = { thickness * (length - 1.0f), thickness * (spacing + 1.0f) };
757        Border border = createStrokeBorder(new BasicStroke(thickness, cap, join, thickness * 2.0f, array, 0.0f), paint);
758        if (shared) {
759            sharedDashedBorder = border;
760        }
761        return border;
762    }
763}
764