1 /* MetalIconFactory.java --
2    Copyright (C) 2005, 2006, 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.metal;
40 
41 import java.awt.Color;
42 import java.awt.Component;
43 import java.awt.Graphics;
44 import java.io.Serializable;
45 
46 import javax.swing.AbstractButton;
47 import javax.swing.Icon;
48 import javax.swing.JCheckBox;
49 import javax.swing.JCheckBoxMenuItem;
50 import javax.swing.JFileChooser;
51 import javax.swing.JInternalFrame;
52 import javax.swing.JRadioButton;
53 import javax.swing.JRadioButtonMenuItem;
54 import javax.swing.JSlider;
55 import javax.swing.SwingConstants;
56 import javax.swing.UIManager;
57 import javax.swing.plaf.UIResource;
58 
59 
60 /**
61  * Creates icons for the {@link MetalLookAndFeel}.
62  */
63 public class MetalIconFactory implements Serializable
64 {
65 
66   /** A constant representing "dark". */
67   public static final boolean DARK = false;
68 
69   /** A constant representing "light". */
70   public static final boolean LIGHT = true;
71 
72   /** A shared instance of the MenuArrowIcon. */
73   private static Icon menuArrow;
74 
75   /** A shared instance of the MenuItemArrowIcon. */
76   private static Icon menuItemArrow;
77 
78   /**
79    * An icon displayed for {@link JCheckBoxMenuItem} components.
80    */
81   private static class CheckBoxMenuItemIcon
82     implements Icon, UIResource, Serializable
83   {
84     /**
85      * Creates a new icon instance.
86      */
CheckBoxMenuItemIcon()87     public CheckBoxMenuItemIcon()
88     {
89       // Nothing to do here.
90     }
91 
92     /**
93      * Returns the width of the icon, in pixels.
94      *
95      * @return The width of the icon (10 pixels).
96      */
getIconWidth()97     public int getIconWidth()
98     {
99       return 10;
100     }
101 
102     /**
103      * Returns the height of the icon, in pixels.
104      *
105      * @return The height of the icon (10 pixels).
106      */
getIconHeight()107     public int getIconHeight()
108     {
109       return 10;
110     }
111 
112     /**
113      * Paints the icon.
114      *
115      * @param c  the component.
116      * @param g  the graphics device.
117      * @param x  the x-coordinate.
118      * @param y  the y-coordinate.
119      */
paintIcon(Component c, Graphics g, int x, int y)120     public void paintIcon(Component c, Graphics g, int x, int y)
121     {
122       JCheckBoxMenuItem item = (JCheckBoxMenuItem) c;
123 
124       if (item.isArmed())
125         g.setColor(MetalLookAndFeel.getBlack());
126       else
127         g.setColor(MetalLookAndFeel.getControlDarkShadow());
128       g.drawLine(x, y, x + 8, y);
129       g.drawLine(x, y + 1, x, y + 8);
130       g.drawLine(x + 2, y + 8, x + 8, y + 8);
131       g.drawLine(x + 8, y + 2, x + 8, y + 7);
132 
133       g.setColor(MetalLookAndFeel.getWhite());
134       g.drawLine(x + 1, y + 1, x + 7, y + 1);
135       g.drawLine(x + 1, y + 2, x + 1, y + 7);
136       g.drawLine(x + 1, y + 9, x + 9, y + 9);
137       g.drawLine(x + 9, y + 1, x + 9, y + 8);
138 
139       // if the item is selected, we should draw a tick
140       if (item.isSelected())
141       {
142         g.setColor(MetalLookAndFeel.getBlack());
143         g.fillRect(x + 2, y + 2, 2, 5);
144         for (int i = 0; i < 6; i++)
145           g.drawLine(x + 8 - i, y + i, x + 9 - i, y + i);
146       }
147 
148     }
149   }
150 
151   /**
152    * An icon used for the "detail view" button on a {@link JFileChooser} under
153    * the {@link MetalLookAndFeel}.
154    *
155    * @see MetalIconFactory#getFileChooserDetailViewIcon()
156    */
157   private static class FileChooserDetailViewIcon
158     implements Icon, UIResource, Serializable
159   {
160 
161     /**
162      * Creates a new icon.
163      */
FileChooserDetailViewIcon()164     public FileChooserDetailViewIcon()
165     {
166       // Nothing to do here.
167     }
168 
169     /**
170      * Returns the width of the icon, in pixels.
171      *
172      * @return The width of the icon.
173      */
getIconWidth()174     public int getIconWidth()
175     {
176       return 18;
177     }
178 
179     /**
180      * Returns the height of the icon, in pixels.
181      *
182      * @return The height of the icon.
183      */
getIconHeight()184     public int getIconHeight()
185     {
186       return 18;
187     }
188 
189     /**
190      * Paints the icon using colors from the {@link MetalLookAndFeel}.
191      *
192      * @param c  the component (ignored).
193      * @param g  the graphics device.
194      * @param x  the x-coordinate for the top-left of the icon.
195      * @param y  the y-coordinate for the top-left of the icon.
196      */
paintIcon(Component c, Graphics g, int x, int y)197     public void paintIcon(Component c, Graphics g, int x, int y)
198     {
199       Color savedColor = g.getColor();
200       g.setColor(MetalLookAndFeel.getBlack());
201 
202       // file 1 outline
203       g.drawLine(x + 2, y + 2, x + 5, y + 2);
204       g.drawLine(x + 6, y + 3, x + 6, y + 7);
205       g.drawLine(x + 2, y + 7, x + 6, y + 7);
206       g.drawLine(x + 2, y + 2, x + 2, y + 7);
207 
208       // file 2 outline
209       g.drawLine(x + 2, y + 10, x + 5, y + 10);
210       g.drawLine(x + 6, y + 11, x + 6, y + 15);
211       g.drawLine(x + 2, y + 15, x + 6, y + 15);
212       g.drawLine(x + 2, y + 10, x + 2, y + 15);
213 
214       // detail lines
215       g.drawLine(x + 8, y + 5, x + 15, y + 5);
216       g.drawLine(x + 8, y + 13, x + 15, y + 13);
217 
218       // fill files
219       g.setColor(MetalLookAndFeel.getPrimaryControl());
220       g.fillRect(x + 3, y + 3, 3, 4);
221       g.fillRect(x + 3, y + 11, 3, 4);
222 
223       // highlight files
224       g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
225       g.drawLine(x + 4, y + 4, x + 4, y + 5);
226       g.drawLine(x + 4, y + 12, x + 4, y + 13);
227 
228       g.setColor(savedColor);
229     }
230   }
231 
232   /**
233    * An icon used for the "home folder" button on a {@link JFileChooser} under
234    * the {@link MetalLookAndFeel}.
235    *
236    * @see MetalIconFactory#getFileChooserHomeFolderIcon()
237    */
238   private static class FileChooserHomeFolderIcon
239     implements Icon, UIResource, Serializable
240   {
241 
242     /**
243      * Creates a new icon.
244      */
FileChooserHomeFolderIcon()245     public FileChooserHomeFolderIcon()
246     {
247       // Nothing to do here.
248     }
249 
250     /**
251      * Returns the width of the icon, in pixels.
252      *
253      * @return The width of the icon.
254      */
getIconWidth()255     public int getIconWidth()
256     {
257       return 18;
258     }
259 
260     /**
261      * Returns the height of the icon, in pixels.
262      *
263      * @return The height of the icon.
264      */
getIconHeight()265     public int getIconHeight()
266     {
267       return 18;
268     }
269 
270     /**
271      * Paints the icon using colors from the {@link MetalLookAndFeel}.
272      *
273      * @param c  the component (ignored).
274      * @param g  the graphics device.
275      * @param x  the x-coordinate for the top-left of the icon.
276      * @param y  the y-coordinate for the top-left of the icon.
277      */
paintIcon(Component c, Graphics g, int x, int y)278     public void paintIcon(Component c, Graphics g, int x, int y)
279     {
280       Color savedColor = g.getColor();
281       g.setColor(MetalLookAndFeel.getBlack());
282 
283       // roof
284       g.drawLine(x + 1, y + 8, x + 8, y + 1);
285       g.drawLine(x + 8, y + 1, x + 15, y + 8);
286 
287       // base of house
288       g.drawLine(x + 3, y + 6, x + 3, y + 15);
289       g.drawLine(x + 3, y + 15, x + 13, y + 15);
290       g.drawLine(x + 13, y + 6, x + 13, y + 15);
291 
292       // door frame
293       g.drawLine(x + 6, y + 9, x + 6, y + 15);
294       g.drawLine(x + 6, y + 9, x + 10, y + 9);
295       g.drawLine(x + 10, y + 9, x + 10, y + 15);
296 
297       // chimney
298       g.drawLine(x + 11, y + 2, x + 11, y + 4);
299       g.drawLine(x + 12, y + 2, x + 12, y + 5);
300 
301       g.setColor(MetalLookAndFeel.getControlDarkShadow());
302 
303       // roof paint
304       int xx = x + 8;
305       for (int i = 0; i < 4; i++)
306         g.drawLine(xx - i, y + 2 + i, xx + i, y + 2 + i);
307       g.fillRect(x + 4, y + 6, 9, 2);
308 
309       // door knob
310       g.drawLine(x + 9, y + 12, x + 9, y + 12);
311 
312       // house paint
313       g.setColor(MetalLookAndFeel.getPrimaryControl());
314       g.drawLine(x + 4, y + 8, x + 12, y + 8);
315       g.fillRect(x + 4, y + 9, 2, 6);
316       g.fillRect(x + 11, y + 9, 2, 6);
317 
318       g.setColor(savedColor);
319     }
320   }
321 
322   /**
323    * An icon used for the "list view" button on a {@link JFileChooser} under
324    * the {@link MetalLookAndFeel}.
325    *
326    * @see MetalIconFactory#getFileChooserListViewIcon()
327    */
328   private static class FileChooserListViewIcon
329     implements Icon, UIResource, Serializable
330   {
331     /**
332      * Creates a new icon.
333      */
FileChooserListViewIcon()334     public FileChooserListViewIcon()
335     {
336       // Nothing to do here.
337     }
338 
339     /**
340      * Returns the width of the icon, in pixels.
341      *
342      * @return The width of the icon.
343      */
getIconWidth()344     public int getIconWidth()
345     {
346       return 18;
347     }
348 
349     /**
350      * Returns the height of the icon, in pixels.
351      *
352      * @return The height of the icon.
353      */
getIconHeight()354     public int getIconHeight()
355     {
356       return 18;
357     }
358 
359     /**
360      * Paints the icon using colors from the {@link MetalLookAndFeel}.
361      *
362      * @param c  the component (ignored).
363      * @param g  the graphics device.
364      * @param x  the x-coordinate for the top-left of the icon.
365      * @param y  the y-coordinate for the top-left of the icon.
366      */
paintIcon(Component c, Graphics g, int x, int y)367     public void paintIcon(Component c, Graphics g, int x, int y)
368     {
369       Color savedColor = g.getColor();
370       g.setColor(MetalLookAndFeel.getBlack());
371 
372       // file 1 outline
373       g.drawLine(x + 2, y + 2, x + 5, y + 2);
374       g.drawLine(x + 6, y + 3, x + 6, y + 7);
375       g.drawLine(x + 2, y + 7, x + 6, y + 7);
376       g.drawLine(x + 2, y + 2, x + 2, y + 7);
377 
378       // file 2 outline
379       g.drawLine(x + 2, y + 10, x + 5, y + 10);
380       g.drawLine(x + 6, y + 11, x + 6, y + 15);
381       g.drawLine(x + 2, y + 15, x + 6, y + 15);
382       g.drawLine(x + 2, y + 10, x + 2, y + 15);
383 
384       // file 3 outline
385       g.drawLine(x + 10, y + 2, x + 13, y + 2);
386       g.drawLine(x + 14, y + 3, x + 14, y + 7);
387       g.drawLine(x + 10, y + 7, x + 14, y + 7);
388       g.drawLine(x + 10, y + 2, x + 10, y + 7);
389 
390       // file 4 outline
391       g.drawLine(x + 10, y + 10, x + 13, y + 10);
392       g.drawLine(x + 14, y + 11, x + 14, y + 15);
393       g.drawLine(x + 10, y + 15, x + 14, y + 15);
394       g.drawLine(x + 10, y + 10, x + 10, y + 15);
395 
396       g.drawLine(x + 8, y + 5, x + 8, y + 5);
397       g.drawLine(x + 8, y + 13, x + 8, y + 13);
398       g.drawLine(x + 16, y + 5, x + 16, y + 5);
399       g.drawLine(x + 16, y + 13, x + 16, y + 13);
400 
401       // fill files
402       g.setColor(MetalLookAndFeel.getPrimaryControl());
403       g.fillRect(x + 3, y + 3, 3, 4);
404       g.fillRect(x + 3, y + 11, 3, 4);
405       g.fillRect(x + 11, y + 3, 3, 4);
406       g.fillRect(x + 11, y + 11, 3, 4);
407 
408       // highlight files
409       g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
410       g.drawLine(x + 4, y + 4, x + 4, y + 5);
411       g.drawLine(x + 4, y + 12, x + 4, y + 13);
412       g.drawLine(x + 12, y + 4, x + 12, y + 5);
413       g.drawLine(x + 12, y + 12, x + 12, y + 13);
414 
415       g.setColor(savedColor);
416     }
417   }
418 
419   /**
420    * An icon used for the "new folder" button on a {@link JFileChooser} under
421    * the {@link MetalLookAndFeel}.
422    *
423    * @see MetalIconFactory#getFileChooserNewFolderIcon()
424    */
425   private static class FileChooserNewFolderIcon
426     implements Icon, UIResource, Serializable
427   {
428     /**
429      * Creates a new icon.
430      */
FileChooserNewFolderIcon()431     public FileChooserNewFolderIcon()
432     {
433       // Nothing to do here.
434     }
435 
436     /**
437      * Returns the width of the icon, in pixels.
438      *
439      * @return The width of the icon.
440      */
getIconWidth()441     public int getIconWidth()
442     {
443       return 18;
444     }
445 
446     /**
447      * Returns the height of the icon, in pixels.
448      *
449      * @return The height of the icon.
450      */
getIconHeight()451     public int getIconHeight()
452     {
453       return 18;
454     }
455 
456     /**
457      * Paints the icon using colors from the {@link MetalLookAndFeel}.
458      *
459      * @param c  the component (ignored).
460      * @param g  the graphics device.
461      * @param x  the x-coordinate for the top-left of the icon.
462      * @param y  the y-coordinate for the top-left of the icon.
463      */
paintIcon(Component c, Graphics g, int x, int y)464     public void paintIcon(Component c, Graphics g, int x, int y)
465     {
466       Color savedColor = g.getColor();
467       g.setColor(MetalLookAndFeel.getBlack());
468 
469       g.drawLine(x + 2, y + 5, x + 9, y + 5);
470       g.drawLine(x + 10, y + 6, x + 15, y + 6);
471       g.drawLine(x + 15, y + 5, x + 15, y + 14);
472       g.drawLine(x + 2, y + 14, x + 15, y + 14);
473       g.drawLine(x + 1, y + 6, x + 1, y + 14);
474 
475       g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
476       g.drawLine(x + 11, y + 3, x + 15, y + 3);
477       g.drawLine(x + 10, y + 4, x + 15, y + 4);
478 
479       g.setColor(MetalLookAndFeel.getPrimaryControl());
480       g.fillRect(x + 3, y + 7, 7, 7);
481       g.fillRect(x + 10, y + 8, 5, 6);
482       g.drawLine(x + 10, y + 5, x + 14, y + 5);
483 
484       g.setColor(MetalLookAndFeel.getPrimaryControlHighlight());
485       g.drawLine(x + 10, y + 7, x + 14, y + 7);
486       g.drawLine(x + 2, y + 6, x + 9, y + 6);
487       g.drawLine(x + 2, y + 6, x + 2, y + 13);
488       g.setColor(savedColor);
489     }
490   }
491 
492   /**
493    * An icon used for the "up folder" button on a {@link JFileChooser} under
494    * the {@link MetalLookAndFeel}.
495    *
496    * @see MetalIconFactory#getFileChooserNewFolderIcon()
497    */
498   private static class FileChooserUpFolderIcon extends FileChooserNewFolderIcon
499   {
500     /**
501      * Creates a new icon.
502      */
FileChooserUpFolderIcon()503     public FileChooserUpFolderIcon()
504     {
505       // Nothing to do here.
506     }
507 
508     /**
509      * Paints the icon using colors from the {@link MetalLookAndFeel}.
510      *
511      * @param c  the component (ignored).
512      * @param g  the graphics device.
513      * @param x  the x-coordinate for the top-left of the icon.
514      * @param y  the y-coordinate for the top-left of the icon.
515      */
paintIcon(Component c, Graphics g, int x, int y)516     public void paintIcon(Component c, Graphics g, int x, int y)
517     {
518       Color savedColor = g.getColor();
519 
520       // draw the folder
521       super.paintIcon(c, g, x, y);
522 
523       // now draw the up arrow
524       g.setColor(MetalLookAndFeel.getBlack());
525       g.drawLine(x + 8, y + 9, x + 8, y + 16);
526       int xx = x + 8;
527       for (int i = 0; i < 4; i++)
528         g.drawLine(xx - i, y + 9 + i, xx + i, y + 9 + i);
529       g.setColor(savedColor);
530     }
531   }
532 
533   /**
534    * An icon representing a file (drawn as a piece of paper with the top-right
535    * corner turned down).
536    */
537   public static class FileIcon16 implements Icon, Serializable
538   {
539     /**
540      * Returns the width of the icon, in pixels.
541      *
542      * @return The width of the icon.
543      */
getIconWidth()544     public int getIconWidth()
545     {
546       return 16;
547     }
548 
549     /**
550      * Returns the height of the icon, in pixels.  The height returned is
551      * <code>16</code> plus the value returned by
552      * {@link #getAdditionalHeight()}.
553      *
554      * @return The height of the icon.
555      */
getIconHeight()556     public int getIconHeight()
557     {
558       return 16 + getAdditionalHeight();
559     }
560 
561     /**
562      * Paints the icon at the location (x, y).
563      *
564      * @param c  the component.
565      * @param g  the graphics context.
566      * @param x  the x coordinate.
567      * @param y  the y coordinate.
568      */
paintIcon(Component c, Graphics g, int x, int y)569     public void paintIcon(Component c, Graphics g, int x, int y)
570     {
571       y = y + getShift();
572       g.setColor(MetalLookAndFeel.getBlack());
573       g.drawLine(x, y, x + 9, y);
574       g.drawLine(x, y + 1, x, y + 15);
575       g.drawLine(x, y + 15, x + 12, y + 15);
576       g.drawLine(x + 12, y + 15, x + 12, y + 6);
577       g.drawLine(x + 12, y + 6, x + 9, y);
578 
579       g.drawLine(x + 7, y + 2, x + 11, y + 6);
580       g.drawLine(x + 8, y + 1, x + 9, y + 1);
581 
582       g.setColor(MetalLookAndFeel.getPrimaryControl());
583       g.drawLine(x + 1, y + 1, x + 7, y + 1);
584       g.drawLine(x + 1, y + 1, x + 1, y + 14);
585       g.drawLine(x + 1, y + 14, x + 11, y + 14);
586       g.drawLine(x + 11, y + 14, x + 11, y + 7);
587       g.drawLine(x + 8, y + 2, x + 10, y + 4);
588     }
589 
590     /**
591      * Returns the additional height for the icon.  The
592      * {@link #getIconHeight()} method adds this value to the icon height it
593      * returns.  Subclasses can override this method to adjust the icon height.
594      *
595      * @return The additional height (<code>0</code> unless overridden).
596      */
getAdditionalHeight()597     public int getAdditionalHeight()
598     {
599       return 0;
600     }
601 
602     /**
603      * Returns the vertical shift, in pixels, applied when painting the icon.
604      * The default value is zero, but subclasses may override this (for
605      * example, see {@link TreeLeafIcon}).
606      *
607      * @return The shift.
608      */
getShift()609     public int getShift()
610     {
611       return 0;
612     }
613 
614   }
615 
616   /**
617    * An icon representing a folder.
618    */
619   public static class FolderIcon16 implements Icon, Serializable
620   {
621     /**
622      * Returns the width of the icon, in pixels.
623      *
624      * @return The width of the icon.
625      */
getIconWidth()626     public int getIconWidth()
627     {
628       return 16;
629     }
630 
631     /**
632      * Returns the height of the icon, in pixels.  The height returned is
633      * <code>16</code> plus the value returned by
634      * {@link #getAdditionalHeight()}.
635      *
636      * @return The height of the icon.
637      */
getIconHeight()638     public int getIconHeight()
639     {
640       return 16 + getAdditionalHeight();
641     }
642 
643     /**
644      * Paints the icon at the location (x, y).
645      *
646      * @param c  the component.
647      * @param g  the graphics device.
648      * @param x  the x coordinate.
649      * @param y  the y coordinate.
650      */
paintIcon(Component c, Graphics g, int x, int y)651     public void paintIcon(Component c, Graphics g, int x, int y)
652     {
653       y = y + getShift();
654       g.setColor(MetalLookAndFeel.getBlack());
655       g.drawLine(x, y + 6, x, y + 15);
656       g.drawLine(x, y + 15, x + 15, y + 15);
657       g.drawLine(x + 15, y + 15, x + 15, y + 5);
658       g.drawLine(x + 14, y + 6, x + 9, y + 6);
659       g.drawLine(x + 8, y + 5, x + 1, y + 5);
660       g.setColor(MetalLookAndFeel.getPrimaryControl());
661       g.fillRect(x + 2, y + 7, 7, 8);
662       g.fillRect(x + 9, y + 8, 6, 7);
663       g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
664       g.drawLine(x + 9, y + 5, x + 14, y + 5);
665       g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
666       g.drawLine(x + 9, y + 4, x + 15, y + 4);
667       g.drawLine(x + 10, y + 3, x + 15, y + 3);
668     }
669 
670     /**
671      * Returns the additional height for the icon.  The
672      * {@link #getIconHeight()} method adds this value to the icon height it
673      * returns.  Subclasses can override this method to adjust the icon height.
674      *
675      * @return The additional height (<code>0</code> unless overridden).
676      */
getAdditionalHeight()677     public int getAdditionalHeight()
678     {
679       return 0;
680     }
681 
682     /**
683      * Returns the vertical shift, in pixels, applied when painting the icon.
684      * The default value is zero, but subclasses may override this (for
685      * example, see {@link TreeFolderIcon}).
686      *
687      * @return The shift.
688      */
getShift()689     public int getShift()
690     {
691       return 0;
692     }
693 
694   }
695 
696   /**
697    * An icon used by the {@link MetalInternalFrameUI} class when the frame
698    * is displayed as a palette.
699    *
700    * @since 1.3
701    */
702   public static class PaletteCloseIcon
703     implements Icon, Serializable, UIResource
704   {
705     /**
706      * Returns the width of the icon, in pixels.
707      *
708      * @return The width of the icon.
709      */
getIconWidth()710     public int getIconWidth()
711     {
712       return 7;
713     }
714 
715     /**
716      * Returns the height of the icon, in pixels.
717      *
718      * @return The height of the icon.
719      */
getIconHeight()720     public int getIconHeight()
721     {
722       return 7;
723     }
724 
725     /**
726      * Paints the icon using colors from the {@link MetalLookAndFeel}.
727      *
728      * @param c  the component (ignored).
729      * @param g  the graphics device.
730      * @param x  the x-coordinate for the top-left of the icon.
731      * @param y  the y-coordinate for the top-left of the icon.
732      */
paintIcon(Component c, Graphics g, int x, int y)733     public void paintIcon(Component c, Graphics g, int x, int y)
734     {
735       Color savedColor = g.getColor();
736       AbstractButton button = (AbstractButton) c;
737       if (button.getModel().isPressed())
738         g.setColor(MetalLookAndFeel.getBlack());
739       else
740         g.setColor(MetalLookAndFeel.getControlDarkShadow());
741       g.fillRect(x + 2, y + 2, 3, 3);
742       g.drawLine(x + 1, y, x + 1, y + 2);
743       g.drawLine(x, y + 1, x + 2, y + 1);
744       g.drawLine(x + 5, y, x + 5, y + 2);
745       g.drawLine(x + 4, y + 1, x + 6, y + 1);
746       g.drawLine(x + 1, y + 4, x + 1, y + 6);
747       g.drawLine(x, y + 5, x + 2, y + 5);
748       g.drawLine(x + 5, y + 4, x + 5, y + 6);
749       g.drawLine(x + 4, y + 5, x + 6, y + 5);
750       g.setColor(MetalLookAndFeel.getControlHighlight());
751       g.drawLine(x + 2, y + 6, x + 3, y + 5);
752       g.drawLine(x + 5, y + 3, x + 6, y + 2);
753       g.drawLine(x + 6, y + 6, x + 6, y + 6);
754       g.setColor(savedColor);
755     }
756   }
757 
758   /**
759    * An {@link Icon} implementation for {@link JCheckBox}es in the
760    * Metal Look &amp; Feel.
761    *
762    * @author Roman Kennke (roman@kennke.org)
763    */
764   static class RadioButtonIcon implements Icon, UIResource, Serializable
765   {
766 
767     /**
768      * This is used as a mask when painting the gradient. See
769      * {@link MetalUtils#paintGradient(java.awt.Graphics, int, int, int, int,
770      *  float, float, java.awt.Color, java.awt.Color, java.awt.Color, int,
771      *  int[][])} for details.
772      */
773     private static int[][] gradientMask = new int[][] {{3, 7}, {1, 9}, {1, 9},
774                                                        {0, 10}, {0, 10}, {0, 10},
775                                                        {0, 10}, {1, 9}, {1, 9},
776                                                        {3, 7}};
777 
778     /**
779      * Returns the width of the icon in pixels.
780      *
781      * @return the width of the icon in pixels
782      */
getIconWidth()783     public int getIconWidth()
784     {
785       return 13;
786     }
787 
788     /**
789      * Returns the height of the icon in pixels.
790      *
791      * @return the height of the icon in pixels
792      */
getIconHeight()793     public int getIconHeight()
794     {
795       return 13;
796     }
797 
798     /**
799      * Paints the icon, taking into account whether or not the component is
800      * enabled, selected and/or armed.
801      *
802      * @param c the Component to draw on (must be an instance of
803      *          {@link JRadioButton})
804      * @param g the Graphics context to draw with
805      * @param x the X position
806      * @param y the Y position
807      */
paintIcon(Component c, Graphics g, int x, int y)808     public void paintIcon(Component c, Graphics g, int x, int y)
809     {
810       if (UIManager.get("RadioButton.gradient") != null)
811         MetalUtils.paintGradient(g, x + 2, y + 2, 8, 8,
812                               SwingConstants.VERTICAL, "RadioButton.gradient",
813                               gradientMask);
814 
815       Color savedColor = g.getColor();
816       JRadioButton b = (JRadioButton) c;
817 
818       // draw outer circle
819       if (b.isEnabled())
820         g.setColor(MetalLookAndFeel.getControlDarkShadow());
821       else
822         g.setColor(MetalLookAndFeel.getControlDisabled());
823       g.drawLine(x + 2, y + 1, x + 3, y + 1);
824       g.drawLine(x + 4, y, x + 7, y);
825       g.drawLine(x + 8, y + 1, x + 9, y + 1);
826       g.drawLine(x + 10, y + 2, x + 10, y + 3);
827       g.drawLine(x + 11, y + 4, x + 11, y + 7);
828       g.drawLine(x + 10, y + 8, x + 10, y + 9);
829       g.drawLine(x + 8, y + 10, x + 9, y + 10);
830       g.drawLine(x + 4, y + 11, x + 7, y + 11);
831       g.drawLine(x + 2, y + 10, x + 3, y + 10);
832       g.drawLine(x + 1, y + 9, x + 1, y + 8);
833       g.drawLine(x, y + 7, x, y + 4);
834       g.drawLine(x + 1, y + 2, x + 1, y + 3);
835 
836       if (b.getModel().isArmed())
837         {
838           g.setColor(MetalLookAndFeel.getControlShadow());
839           g.drawLine(x + 4, y + 1, x + 7, y + 1);
840           g.drawLine(x + 4, y + 10, x + 7, y + 10);
841           g.drawLine(x + 1, y + 4, x + 1, y + 7);
842           g.drawLine(x + 10, y + 4, x + 10, y + 7);
843           g.fillRect(x + 2, y + 2, 8, 8);
844         }
845       else
846         {
847           // only draw inner highlight if not filled
848           if (b.isEnabled())
849             {
850               g.setColor(MetalLookAndFeel.getWhite());
851 
852               g.drawLine(x + 2, y + 8, x + 2, y + 9);
853               g.drawLine(x + 1, y + 4, x + 1, y + 7);
854               g.drawLine(x + 2, y + 2, x + 2, y + 3);
855               g.drawLine(x + 3, y + 2, x + 3, y + 2);
856               g.drawLine(x + 4, y + 1, x + 7, y + 1);
857               g.drawLine(x + 8, y + 2, x + 9, y + 2);
858             }
859         }
860 
861       // draw outer highlight
862       if (b.isEnabled())
863         {
864           g.setColor(MetalLookAndFeel.getWhite());
865 
866           // outer
867           g.drawLine(x + 10, y + 1, x + 10, y + 1);
868           g.drawLine(x + 11, y + 2, x + 11, y + 3);
869           g.drawLine(x + 12, y + 4, x + 12, y + 7);
870           g.drawLine(x + 11, y + 8, x + 11, y + 9);
871           g.drawLine(x + 10, y + 10, x + 10, y + 10);
872           g.drawLine(x + 8, y + 11, x + 9, y + 11);
873           g.drawLine(x + 4, y + 12, x + 7, y + 12);
874           g.drawLine(x + 2, y + 11, x + 3, y + 11);
875         }
876 
877       if (b.isSelected())
878         {
879           if (b.isEnabled())
880             g.setColor(MetalLookAndFeel.getBlack());
881           else
882             g.setColor(MetalLookAndFeel.getControlDisabled());
883           g.drawLine(x + 4, y + 3, x + 7, y + 3);
884           g.fillRect(x + 3, y + 4, 6, 4);
885           g.drawLine(x + 4, y + 8, x + 7, y + 8);
886         }
887       g.setColor(savedColor);
888     }
889   }
890 
891   /**
892    * An icon displayed for {@link JRadioButtonMenuItem} components.
893    */
894   private static class RadioButtonMenuItemIcon
895     implements Icon, UIResource, Serializable
896   {
897     /**
898      * Creates a new icon instance.
899      */
RadioButtonMenuItemIcon()900     public RadioButtonMenuItemIcon()
901     {
902       // Nothing to do here.
903     }
904 
905     /**
906      * Returns the width of the icon, in pixels.
907      *
908      * @return The width of the icon.
909      */
getIconWidth()910     public int getIconWidth()
911     {
912       return 10;
913     }
914 
915     /**
916      * Returns the height of the icon, in pixels.
917      *
918      * @return The height of the icon.
919      */
getIconHeight()920     public int getIconHeight()
921     {
922       return 10;
923     }
924 
925     /**
926      * Paints the icon.
927      *
928      * @param c  the component.
929      * @param g  the graphics device.
930      * @param x  the x-coordinate.
931      * @param y  the y-coordinate.
932      */
paintIcon(Component c, Graphics g, int x, int y)933     public void paintIcon(Component c, Graphics g, int x, int y)
934     {
935       Color savedColor = g.getColor();
936       JRadioButtonMenuItem item = (JRadioButtonMenuItem) c;
937       g.setColor(MetalLookAndFeel.getBlack());
938       g.drawLine(x + 2, y, x + 6, y);
939       g.drawLine(x + 7, y + 1, x + 7, y + 1);
940       g.drawLine(x + 8, y + 2, x + 8, y + 6);
941       g.drawLine(x + 7, y + 7, x + 7, y + 7);
942       g.drawLine(x + 2, y + 8, x + 6, y + 8);
943       g.drawLine(x + 1, y + 7, x + 1, y + 7);
944       g.drawLine(x, y + 2, x, y + 6);
945       g.drawLine(x + 1, y + 1, x + 1, y + 1);
946 
947       if (item.isSelected())
948         {
949           g.drawLine(x + 3, y + 2, x + 5, y + 2);
950           g.fillRect(x + 2, y + 3, 5, 3);
951           g.drawLine(x + 3, y + 6, x + 5, y + 6);
952         }
953 
954       // highlight
955       g.setColor(MetalLookAndFeel.getControlHighlight());
956       g.drawLine(x + 3, y + 1, x + 6, y + 1);
957       g.drawLine(x + 8, y + 1, x + 8, y + 1);
958       g.drawLine(x + 9, y + 2, x + 9, y + 7);
959       g.drawLine(x + 8, y + 8, x + 8, y + 8);
960       g.drawLine(x + 2, y + 9, x + 7, y + 9);
961       g.drawLine(x + 1, y + 8, x + 1, y + 8);
962       g.drawLine(x + 1, y + 3, x + 1, y + 6);
963       g.drawLine(x + 2, y + 2, x + 2, y + 2);
964       g.setColor(savedColor);
965     }
966   }
967 
968   /**
969    * The icon used to display the thumb control on a horizontally oriented
970    * {@link JSlider} component.
971    */
972   private static class HorizontalSliderThumbIcon
973     implements Icon, UIResource, Serializable
974   {
975 
976     /**
977      * This mask is used to paint the gradient in the shape of the thumb.
978      */
979     int[][] gradientMask = new int[][] { {0, 12}, {0, 12}, {0, 12}, {0, 12},
980                                          {0, 12}, {0, 12}, {0, 12}, {1, 11},
981                                          {2, 10}, {3, 9}, {4, 8}, {5, 7},
982                                          {6, 6}};
983 
984     /**
985      * Creates a new instance.
986      */
HorizontalSliderThumbIcon()987     public HorizontalSliderThumbIcon()
988     {
989       // Nothing to do here.
990     }
991 
992     /**
993      * Returns the width of the icon, in pixels.
994      *
995      * @return The width of the icon.
996      */
getIconWidth()997     public int getIconWidth()
998     {
999       return 15;
1000     }
1001 
1002     /**
1003      * Returns the height of the icon, in pixels.
1004      *
1005      * @return The height of the icon.
1006      */
getIconHeight()1007     public int getIconHeight()
1008     {
1009       return 16;
1010     }
1011 
1012     /**
1013      * Paints the icon, taking into account whether or not the component has
1014      * the focus.
1015      *
1016      * @param c  the component.
1017      * @param g  the graphics device.
1018      * @param x  the x-coordinate.
1019      * @param y  the y-coordinate.
1020      */
paintIcon(Component c, Graphics g, int x, int y)1021     public void paintIcon(Component c, Graphics g, int x, int y)
1022     {
1023       boolean enabled = false;
1024       boolean focus = false;
1025       if (c != null)
1026         {
1027           enabled = c.isEnabled();
1028           focus = c.hasFocus();
1029         }
1030 
1031       // draw the outline
1032       if (enabled)
1033         g.setColor(MetalLookAndFeel.getBlack());
1034       else
1035         g.setColor(MetalLookAndFeel.getControlDarkShadow());
1036       g.drawLine(x + 1, y, x + 13, y);
1037       g.drawLine(x + 14, y + 1, x + 14, y + 7);
1038       g.drawLine(x + 14, y + 8, x + 7, y + 15);
1039       g.drawLine(x + 6, y + 14, x, y + 8);
1040       g.drawLine(x, y + 7, x, y + 1);
1041 
1042 // The following is commented out until the masking for the gradient painting
1043 // is working correctly
1044 //      // Fill the icon.
1045 //      if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme
1046 //          && enabled)
1047 //        {
1048 //          String gradient;
1049 //          if (focus)
1050 //            gradient = "Slider.focusGradient";
1051 //          else
1052 //            gradient = "Slider.gradient";
1053 //          MetalUtils.paintGradient(g, x + 1, y + 2, 12, 13,
1054 //                                   SwingConstants.VERTICAL, gradient,
1055 //                                   gradientMask);
1056 //        }
1057 //      else
1058         {
1059           if (focus)
1060             g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
1061           else
1062             g.setColor(MetalLookAndFeel.getControl());
1063           g.fillRect(x + 1, y + 2, 13, 7);
1064           g.drawLine(x + 2, y + 9, x + 12, y + 9);
1065           g.drawLine(x + 3, y + 10, x + 11, y + 10);
1066           g.drawLine(x + 4, y + 11, x + 10, y + 11);
1067           g.drawLine(x + 5, y + 12, x + 9, y + 12);
1068           g.drawLine(x + 6, y + 13, x + 8, y + 13);
1069           g.drawLine(x + 7, y + 14, x + 7, y + 14);
1070         }
1071 
1072       // If the slider is enabled, draw dots and highlights.
1073       if (c.isEnabled()
1074           && !(MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme))
1075         {
1076           if (focus)
1077             g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
1078           else
1079             g.setColor(MetalLookAndFeel.getBlack());
1080           g.drawLine(x + 3, y + 3, x + 3, y + 3);
1081           g.drawLine(x + 7, y + 3, x + 7, y + 3);
1082           g.drawLine(x + 11, y + 3, x + 11, y + 3);
1083 
1084           g.drawLine(x + 5, y + 5, x + 5, y + 5);
1085           g.drawLine(x + 9, y + 5, x + 9, y + 5);
1086 
1087           g.drawLine(x + 3, y + 7, x + 3, y + 7);
1088           g.drawLine(x + 7, y + 7, x + 7, y + 7);
1089           g.drawLine(x + 11, y + 7, x + 11, y + 7);
1090 
1091           // Draw highlights
1092           if (focus)
1093             g.setColor(MetalLookAndFeel.getPrimaryControl());
1094           else
1095             g.setColor(MetalLookAndFeel.getWhite());
1096           g.drawLine(x + 1, y + 1, x + 13, y + 1);
1097           g.drawLine(x + 1, y + 2, x + 1, y + 8);
1098           g.drawLine(x + 2, y + 2, x + 2, y + 2);
1099           g.drawLine(x + 6, y + 2, x + 6, y + 2);
1100           g.drawLine(x + 10, y + 2, x + 10, y + 2);
1101 
1102           g.drawLine(x + 4, y + 4, x + 4, y + 4);
1103           g.drawLine(x + 8, y + 4, x + 8, y + 4);
1104 
1105           g.drawLine(x + 2, y + 6, x + 2, y + 6);
1106           g.drawLine(x + 6, y + 6, x + 6, y + 6);
1107           g.drawLine(x + 10, y + 6, x + 10, y + 6);
1108         }
1109 
1110     }
1111   }
1112 
1113   /**
1114    * An icon used for the 'close' button in the title frame of a
1115    * {@link JInternalFrame}.
1116    */
1117   private static class InternalFrameCloseIcon
1118     implements Icon, UIResource, Serializable
1119   {
1120     /** The icon size in pixels. */
1121     private int size;
1122 
1123     /**
1124      * Creates a new icon.
1125      *
1126      * @param size  the icon size (width and height) in pixels.
1127      */
InternalFrameCloseIcon(int size)1128     public InternalFrameCloseIcon(int size)
1129     {
1130       this.size = size;
1131     }
1132 
1133     /**
1134      * Returns the width of the icon, in pixels.
1135      *
1136      * @return The width of the icon.
1137      */
getIconWidth()1138     public int getIconWidth()
1139     {
1140       return size;
1141     }
1142 
1143     /**
1144      * Returns the height of the icon, in pixels.
1145      *
1146      * @return The height of the icon.
1147      */
getIconHeight()1148     public int getIconHeight()
1149     {
1150       return size;
1151     }
1152 
1153     /**
1154      * Paints the icon.
1155      *
1156      * @param c  the component (an {@link JInternalFrame} is expected).
1157      * @param g  the graphics device.
1158      * @param x  the x-coordinate.
1159      * @param y  the y-coordinate.
1160      */
paintIcon(Component c, Graphics g, int x, int y)1161     public void paintIcon(Component c, Graphics g, int x, int y)
1162     {
1163       Color savedColor = g.getColor();
1164       AbstractButton b = (AbstractButton) c;
1165 
1166       // fill the interior
1167       if (b.getModel().isPressed())
1168         // FIXME: also need to take into account whether the internal frame is
1169         // selected
1170         g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
1171       else
1172         g.setColor(MetalLookAndFeel.getPrimaryControl());
1173       g.fillRect(x + 2, y + 2, 10, 10);
1174 
1175       // draw the outline box and the cross
1176       if (b.getModel().isPressed())
1177         g.setColor(MetalLookAndFeel.getBlack());
1178       else
1179         {
1180           // FIXME: also need to take into account whether the internal frame is
1181           // selected
1182           boolean selected = true;
1183           if (selected)
1184             g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
1185           else
1186             g.setColor(MetalLookAndFeel.getControlDarkShadow());
1187         }
1188       g.drawLine(x + 1, y + 1, x + 13, y + 1);
1189       g.drawLine(x + 1, y + 2, x + 1, y + 12);
1190       g.drawLine(x + 1, y + 13, x + 13, y + 13);
1191       g.drawLine(x + 13, y + 2, x + 13, y + 12);
1192       g.drawLine(x + 2, y + 12, x + 2, y + 12);
1193       g.drawLine(x + 12, y + 2, x + 12, y + 2);
1194 
1195       g.fillRect(x + 4, y + 4, 2, 2);
1196       g.fillRect(x + 5, y + 5, 4, 4);
1197       g.drawLine(x + 9, y + 4, x + 10, y + 4);
1198       g.drawLine(x + 9, y + 4, x + 9, y + 5);
1199       g.drawLine(x + 4, y + 9, x + 4, y + 10);
1200       g.drawLine(x + 4, y + 9, x + 5, y + 9);
1201       g.drawLine(x + 9, y + 8, x + 9, y + 10);
1202       g.drawLine(x + 8, y + 9, x + 10, y + 9);
1203 
1204       g.setColor(MetalLookAndFeel.getBlack());
1205       g.drawLine(x, y, x + 13, y);
1206       g.drawLine(x, y + 1, x, y + 13);
1207       g.drawLine(x + 3, y + 4, x + 4, y + 3);
1208       g.drawLine(x + 3, y + 9, x + 5, y + 7);
1209       g.drawLine(x + 7, y + 5, x + 9, y + 3);
1210 
1211       g.drawLine(x + 12, y + 3, x + 12, y + 11);
1212       g.drawLine(x + 3, y + 12, x + 12, y + 12);
1213 
1214       g.setColor(MetalLookAndFeel.getWhite());
1215       g.drawLine(x + 1, y + 14, x + 14, y + 14);
1216       g.drawLine(x + 14, y + 1, x + 14, y + 14);
1217 
1218       if (!b.getModel().isPressed())
1219         {
1220           g.drawLine(x + 5, y + 10, x + 5, y + 10);
1221           g.drawLine(x + 6, y + 9, x + 7, y + 9);
1222           g.drawLine(x + 10, y + 5, x + 10, y + 5);
1223           g.drawLine(x + 9, y + 6, x + 9, y + 7);
1224           g.drawLine(x + 10, y + 10, x + 11, y + 10);
1225           g.drawLine(x + 10, y + 11, x + 10, y + 11);
1226         }
1227       g.setColor(savedColor);
1228     }
1229   }
1230 
1231   /**
1232    * The icon displayed at the top-left corner of a {@link JInternalFrame}.
1233    */
1234   private static class InternalFrameDefaultMenuIcon
1235     implements Icon, UIResource, Serializable
1236   {
1237 
1238     /**
1239      * Creates a new instance.
1240      */
InternalFrameDefaultMenuIcon()1241     public InternalFrameDefaultMenuIcon()
1242     {
1243       // Nothing to do here.
1244     }
1245 
1246     /**
1247      * Returns the width of the icon, in pixels.
1248      *
1249      * @return The width of the icon.
1250      */
getIconWidth()1251     public int getIconWidth()
1252     {
1253       return 16;
1254     }
1255 
1256     /**
1257      * Returns the height of the icon, in pixels.
1258      *
1259      * @return The height of the icon.
1260      */
getIconHeight()1261     public int getIconHeight()
1262     {
1263       return 16;
1264     }
1265 
1266     /**
1267      * Paints the icon at the specified location.
1268      *
1269      * @param c  the component.
1270      * @param g  the graphics device.
1271      * @param x  the x coordinate.
1272      * @param y  the y coordinate.
1273      */
paintIcon(Component c, Graphics g, int x, int y)1274     public void paintIcon(Component c, Graphics g, int x, int y)
1275     {
1276       g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
1277       g.fillRect(x + 1, y, 14, 2);
1278       g.fillRect(x, y + 1, 2, 14);
1279       g.fillRect(x + 1, y + 14, 14, 2);
1280       g.fillRect(x + 14, y + 1, 2, 14);
1281       g.drawLine(x + 2, y + 5, x + 14, y + 5);
1282 
1283       g.setColor(MetalLookAndFeel.getPrimaryControl());
1284       g.fillRect(x + 2, y + 2, 12, 3);
1285 
1286       g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
1287       g.drawLine(x + 3, y + 3, x + 3, y + 3);
1288       g.drawLine(x + 6, y + 3, x + 6, y + 3);
1289       g.drawLine(x + 9, y + 3, x + 9, y + 3);
1290       g.drawLine(x + 12, y + 3, x + 12, y + 3);
1291 
1292       g.setColor(MetalLookAndFeel.getWhite());
1293       g.fillRect(x + 2, y + 6, 12, 8);
1294       g.drawLine(x + 2, y + 2, x + 2, y + 2);
1295       g.drawLine(x + 5, y + 2, x + 5, y + 2);
1296       g.drawLine(x + 8, y + 2, x + 8, y + 2);
1297       g.drawLine(x + 11, y + 2, x + 11, y + 2);
1298     }
1299   }
1300 
1301   /**
1302    * An icon used in the title frame of a {@link JInternalFrame}.  When you
1303    * maximise an internal frame, this icon will replace the 'maximise' icon to
1304    * provide a 'restore' option.
1305    */
1306   private static class InternalFrameAltMaximizeIcon
1307     implements Icon, UIResource, Serializable
1308   {
1309     /** The icon size in pixels. */
1310     private int size;
1311 
1312     /**
1313      * Creates a new icon.
1314      *
1315      * @param size  the icon size in pixels.
1316      */
InternalFrameAltMaximizeIcon(int size)1317     public InternalFrameAltMaximizeIcon(int size)
1318     {
1319       this.size = size;
1320     }
1321 
1322     /**
1323      * Returns the width of the icon, in pixels.
1324      *
1325      * @return The width of the icon.
1326      */
getIconWidth()1327     public int getIconWidth()
1328     {
1329       return size;
1330     }
1331 
1332     /**
1333      * Returns the height of the icon, in pixels.
1334      *
1335      * @return The height of the icon.
1336      */
getIconHeight()1337     public int getIconHeight()
1338     {
1339       return size;
1340     }
1341 
1342     /**
1343      * Paints the icon at the specified location.
1344      *
1345      * @param c  the component.
1346      * @param g  the graphics device.
1347      * @param x  the x coordinate.
1348      * @param y  the y coordinate.
1349      */
paintIcon(Component c, Graphics g, int x, int y)1350     public void paintIcon(Component c, Graphics g, int x, int y)
1351     {
1352       Color savedColor = g.getColor();
1353 
1354       AbstractButton b = (AbstractButton) c;
1355 
1356       // fill the small box interior
1357       if (b.getModel().isPressed())
1358         g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
1359       else
1360         g.setColor(MetalLookAndFeel.getPrimaryControl());
1361       g.fillRect(x + 2, y + 6, 7, 7);
1362 
1363 
1364       if (b.getModel().isPressed())
1365         g.setColor(MetalLookAndFeel.getBlack());
1366       else
1367         g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
1368 
1369       g.drawLine(x + 12, y + 1, x + 13, y + 1);
1370       g.drawLine(x + 11, y + 2, x + 12, y + 2);
1371       g.drawLine(x + 10, y + 3, x + 11, y + 3);
1372       g.drawLine(x + 8, y + 2, x + 8, y + 3);
1373       g.fillRect(x + 8, y + 4, 3, 3);
1374       g.drawLine(x + 11, y + 6, x + 12, y + 6);
1375 
1376       g.drawLine(x + 1, y + 5, x + 5, y + 5);
1377       g.drawLine(x + 1, y + 6, x + 1, y + 12);
1378       g.drawLine(x + 9, y + 9, x + 9, y + 12);
1379       g.drawLine(x + 1, y + 13, x + 9, y + 13);
1380 
1381       g.drawLine(x + 2, y + 12, x + 2, y + 12);
1382 
1383       g.setColor(MetalLookAndFeel.getBlack());
1384       g.drawLine(x + 12, y, x + 9, y + 3);
1385       g.drawLine(x + 7, y + 1, x + 8, y + 1);
1386       g.drawLine(x + 7, y + 2, x + 7, y + 6);
1387       g.drawLine(x + 11, y + 5, x + 12, y + 5);
1388       g.drawLine(x, y + 4, x + 5, y + 4);
1389       g.drawLine(x, y + 5, x, y + 13);
1390       g.drawLine(x + 3, y + 12, x + 8, y + 12);
1391       g.drawLine(x + 8, y + 8, x + 8, y + 11);
1392       g.drawLine(x + 9, y + 8, x + 9, y + 8);
1393 
1394       g.setColor(MetalLookAndFeel.getWhite());
1395       g.drawLine(x + 9, y + 2, x + 9, y + 2);
1396       g.drawLine(x + 11, y + 4, x + 13, y + 2);
1397       g.drawLine(x + 13, y + 6, x + 13, y + 6);
1398       g.drawLine(x + 8, y + 7, x + 13, y + 7);
1399       g.drawLine(x + 6, y + 5, x + 6, y + 5);
1400       g.drawLine(x + 10, y + 8, x + 10, y + 13);
1401       g.drawLine(x + 1, y + 14, x + 10, y + 14);
1402 
1403       if (!b.getModel().isPressed())
1404         {
1405           g.drawLine(x + 2, y + 6, x + 6, y + 6);
1406           g.drawLine(x + 2, y + 6, x + 2, y + 11);
1407         }
1408 
1409       g.setColor(savedColor);
1410     }
1411   }
1412 
1413   /**
1414    * An icon used for the 'maximize' button in the title frame of a
1415    * {@link JInternalFrame}.
1416    */
1417   private static class InternalFrameMaximizeIcon
1418     implements Icon, UIResource, Serializable
1419   {
1420 
1421     /**
1422      * Creates a new instance.
1423      */
InternalFrameMaximizeIcon()1424     public InternalFrameMaximizeIcon()
1425     {
1426       // Nothing to do here.
1427     }
1428 
1429     /**
1430      * Returns the width of the icon, in pixels.
1431      *
1432      * @return The width of the icon.
1433      */
getIconWidth()1434     public int getIconWidth()
1435     {
1436       return 16;
1437     }
1438 
1439     /**
1440      * Returns the height of the icon, in pixels.
1441      *
1442      * @return The height of the icon.
1443      */
getIconHeight()1444     public int getIconHeight()
1445     {
1446       return 16;
1447     }
1448 
1449     /**
1450      * Paints the icon at the specified location.
1451      *
1452      * @param c  the component.
1453      * @param g  the graphics device.
1454      * @param x  the x coordinate.
1455      * @param y  the y coordinate.
1456      */
paintIcon(Component c, Graphics g, int x, int y)1457     public void paintIcon(Component c, Graphics g, int x, int y)
1458     {
1459       Color savedColor = g.getColor();
1460 
1461       AbstractButton b = (AbstractButton) c;
1462 
1463       // fill the interior
1464       if (b.getModel().isPressed())
1465         g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
1466       else
1467         g.setColor(MetalLookAndFeel.getPrimaryControl());
1468       g.fillRect(x + 2, y + 6, 7, 7);
1469 
1470       if (b.getModel().isPressed())
1471         g.setColor(MetalLookAndFeel.getBlack());
1472       else
1473         g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
1474 
1475       g.drawLine(x + 9, y + 1, x + 10, y + 1);
1476       g.fillRect(x + 11, y + 1, 3, 3);
1477       g.fillRect(x + 12, y + 4, 2, 2);
1478       g.drawLine(x + 10, y + 3, x + 10, y + 3);
1479       g.drawLine(x + 9, y + 4, x + 10, y + 4);
1480       g.drawLine(x + 1, y + 5, x + 9, y + 5);
1481       g.drawLine(x + 1, y + 6, x + 1, y + 12);
1482       g.drawLine(x + 9, y + 6, x + 9, y + 12);
1483       g.drawLine(x + 1, y + 13, x + 9, y + 13);
1484 
1485       // fill
1486       g.drawLine(x + 7, y + 6, x + 8, y + 6);
1487       g.drawLine(x + 6, y + 7, x + 8, y + 7);
1488       g.drawLine(x + 5, y + 8, x + 6, y + 8);
1489       g.drawLine(x + 4, y + 9, x + 5, y + 9);
1490       g.drawLine(x + 3, y + 10, x + 4, y + 10);
1491       g.drawLine(x + 2, y + 11, x + 3, y + 11);
1492       g.drawLine(x + 2, y + 12, x + 4, y + 12);
1493       g.drawLine(x + 8, y + 8, x + 8, y + 8);
1494 
1495       // draw black
1496       g.setColor(MetalLookAndFeel.getBlack());
1497       g.drawLine(x + 8, y, x + 13, y);
1498       g.drawLine(x + 8, y + 1, x + 8, y + 1);
1499       g.drawLine(x + 10, y + 2, x + 9, y + 3);
1500       g.drawLine(x, y + 4, x + 8, y + 4);
1501       g.drawLine(x, y + 5, x, y + 13);
1502 
1503       g.drawLine(x + 2, y + 10, x + 6, y + 6);
1504       g.drawLine(x + 8, y + 9, x + 8, y + 11);
1505       g.drawLine(x + 5, y + 12, x + 8, y + 12);
1506 
1507       // draw white
1508       g.setColor(MetalLookAndFeel.getWhite());
1509       if (!b.getModel().isPressed())
1510         {
1511           g.drawLine(x + 2, y + 6, x + 5, y + 6);
1512           g.drawLine(x + 2, y + 7, x + 2, y + 9);
1513           g.drawLine(x + 4, y + 11, x + 7, y + 8);
1514         }
1515 
1516       g.drawLine(x + 1, y + 14, x + 10, y + 14);
1517       g.drawLine(x + 10, y + 5, x + 10, y + 13);
1518 
1519       g.drawLine(x + 9, y + 2, x + 9, y + 2);
1520       g.drawLine(x + 11, y + 4, x + 11, y + 5);
1521       g.drawLine(x + 13, y + 6, x + 14, y + 6);
1522       g.drawLine(x + 14, y + 1, x + 14, y + 5);
1523       g.setColor(savedColor);
1524     }
1525   }
1526 
1527   /**
1528    * An icon used in the title frame of a {@link JInternalFrame}.
1529    */
1530   private static class InternalFrameMinimizeIcon
1531     implements Icon, UIResource, Serializable
1532   {
1533 
1534     /**
1535      * Creates a new instance.
1536      */
InternalFrameMinimizeIcon()1537     public InternalFrameMinimizeIcon()
1538     {
1539       // Nothing to do here.
1540     }
1541 
1542     /**
1543      * Returns the width of the icon, in pixels.
1544      *
1545      * @return The width of the icon.
1546      */
getIconWidth()1547     public int getIconWidth()
1548     {
1549       return 16;
1550     }
1551 
1552     /**
1553      * Returns the height of the icon, in pixels.
1554      *
1555      * @return The height of the icon.
1556      */
getIconHeight()1557     public int getIconHeight()
1558     {
1559       return 16;
1560     }
1561 
1562     /**
1563      * Paints the icon at the specified location.
1564      *
1565      * @param c  the component.
1566      * @param g  the graphics device.
1567      * @param x  the x coordinate.
1568      * @param y  the y coordinate.
1569      */
paintIcon(Component c, Graphics g, int x, int y)1570     public void paintIcon(Component c, Graphics g, int x, int y)
1571     {
1572       Color savedColor = g.getColor();
1573 
1574       AbstractButton b = (AbstractButton) c;
1575 
1576       if (b.getModel().isPressed())
1577         g.setColor(MetalLookAndFeel.getBlack());
1578       else
1579         // FIXME: here the color depends on whether or not the internal frame
1580         // is selected
1581         g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
1582 
1583       g.drawLine(x + 12, y + 1, x + 13, y + 1);
1584       g.drawLine(x + 11, y + 2, x + 12, y + 2);
1585       g.drawLine(x + 10, y + 3, x + 11, y + 3);
1586       g.drawLine(x + 8, y + 2, x + 8, y + 3);
1587       g.fillRect(x + 8, y + 4, 3, 3);
1588       g.drawLine(x + 11, y + 6, x + 12, y + 6);
1589 
1590       g.drawLine(x + 1, y + 8, x + 6, y + 8);
1591       g.drawLine(x + 1, y + 9, x + 1, y + 12);
1592       g.drawLine(x + 6, y + 9, x + 6, y + 12);
1593       g.drawLine(x + 1, y + 13, x + 6, y + 13);
1594 
1595       g.drawLine(x + 5, y + 9, x + 5, y + 9);
1596       g.drawLine(x + 2, y + 12, x + 2, y + 12);
1597 
1598       g.setColor(MetalLookAndFeel.getBlack());
1599       g.drawLine(x + 12, y, x + 9, y + 3);
1600       g.drawLine(x + 7, y + 1, x + 8, y + 1);
1601       g.drawLine(x + 7, y + 2, x + 7, y + 6);
1602       g.drawLine(x, y + 7, x + 6, y + 7);
1603       g.drawLine(x, y + 8, x, y + 13);
1604       g.drawLine(x + 3, y + 12, x + 5, y + 12);
1605       g.drawLine(x + 5, y + 10, x + 5, y + 11);
1606       g.drawLine(x + 11, y + 5, x + 12, y + 5);
1607 
1608       g.setColor(MetalLookAndFeel.getWhite());
1609       g.drawLine(x + 9, y + 2, x + 9, y + 2);
1610       g.drawLine(x + 11, y + 4, x + 13, y + 2);
1611       g.drawLine(x + 13, y + 6, x + 13, y + 6);
1612       g.drawLine(x + 8, y + 7, x + 13, y + 7);
1613       g.drawLine(x + 7, y + 9, x + 7, y + 13);
1614       g.drawLine(x + 1, y + 14, x + 7, y + 14);
1615 
1616       if (b.getModel().isPressed())
1617         {
1618           g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
1619           g.fillRect(x + 2, y + 9, 3, 3);
1620         }
1621       else
1622         {
1623           g.drawLine(x + 2, y + 9, x + 4, y + 9);
1624           g.drawLine(x + 2, y + 10, x + 2, y + 11);
1625         }
1626 
1627       g.setColor(savedColor);
1628     }
1629   }
1630 
1631   /**
1632    * The icon used to display the thumb control on a horizontally oriented
1633    * {@link JSlider} component.
1634    */
1635   private static class VerticalSliderThumbIcon
1636     implements Icon, UIResource, Serializable
1637   {
1638     /**
1639      * This mask is used to paint the gradient in the shape of the thumb.
1640      */
1641     int[][] gradientMask = new int[][] { {0, 12}, {0, 12}, {0, 12}, {0, 12},
1642                                          {0, 12}, {0, 12}, {0, 12}, {1, 11},
1643                                          {2, 10}, {3, 9}, {4, 8}, {5, 7},
1644                                          {6, 6}};
1645 
1646     /**
1647      * Creates a new instance.
1648      */
VerticalSliderThumbIcon()1649     public VerticalSliderThumbIcon()
1650     {
1651       // Nothing to do here.
1652     }
1653 
1654     /**
1655      * Returns the width of the icon, in pixels.
1656      *
1657      * @return The width of the icon.
1658      */
getIconWidth()1659     public int getIconWidth()
1660     {
1661       return 16;
1662     }
1663 
1664     /**
1665      * Returns the height of the icon, in pixels.
1666      *
1667      * @return The height of the icon.
1668      */
getIconHeight()1669     public int getIconHeight()
1670     {
1671       return 15;
1672     }
1673 
1674     /**
1675      * Paints the icon taking into account whether the slider control has the
1676      * focus or not.
1677      *
1678      * @param c  the slider (must be a non-<code>null</code> instance of
1679      *           {@link JSlider}.
1680      * @param g  the graphics device.
1681      * @param x  the x-coordinate.
1682      * @param y  the y-coordinate.
1683      */
paintIcon(Component c, Graphics g, int x, int y)1684     public void paintIcon(Component c, Graphics g, int x, int y)
1685     {
1686       boolean enabled = false;
1687       boolean focus = false;
1688       if (c != null)
1689         {
1690           enabled = c.isEnabled();
1691           focus = c.hasFocus();
1692         }
1693 
1694       // draw the outline
1695       if (enabled)
1696         g.setColor(MetalLookAndFeel.getBlack());
1697       else
1698         g.setColor(MetalLookAndFeel.getControlDarkShadow());
1699       g.drawLine(x + 1, y, x + 7, y);
1700       g.drawLine(x + 8, y, x + 15, y + 7);
1701       g.drawLine(x + 14, y + 8, x + 8, y + 14);
1702       g.drawLine(x + 8, y + 14, x + 1, y + 14);
1703       g.drawLine(x, y + 13, x, y + 1);
1704 
1705 //    The following is commented out until the masking for the gradient painting
1706 //    is working correctly
1707 //      // Fill the icon.
1708 //      if (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme
1709 //          && enabled)
1710 //        {
1711 //          String gradient;
1712 //          if (focus)
1713 //            gradient = "Slider.focusGradient";
1714 //          else
1715 //            gradient = "Slider.gradient";
1716 //          MetalUtils.paintGradient(g, x + 2, y + 1, 13, 12,
1717 //                                   SwingConstants.HORIZONTAL, gradient,
1718 //                                   gradientMask);
1719 //        }
1720 //      else
1721         {
1722           if (focus)
1723             g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
1724           else
1725             g.setColor(MetalLookAndFeel.getControl());
1726           g.fillRect(x + 2, y + 1, 7, 13);
1727           g.drawLine(x + 9, y + 2, x + 9, y + 12);
1728           g.drawLine(x + 10, y + 3, x + 10, y + 11);
1729           g.drawLine(x + 11, y + 4, x + 11, y + 10);
1730           g.drawLine(x + 12, y + 5, x + 12, y + 9);
1731           g.drawLine(x + 13, y + 6, x + 13, y + 8);
1732           g.drawLine(x + 14, y + 7, x + 14, y + 7);
1733         }
1734 
1735       // if the slider is enabled, draw dots and highlights
1736       if (enabled
1737           && ! (MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme))
1738         {
1739           if (focus)
1740             g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
1741           else
1742             g.setColor(MetalLookAndFeel.getBlack());
1743           g.drawLine(x + 3, y + 3, x + 3, y + 3);
1744           g.drawLine(x + 3, y + 7, x + 3, y + 7);
1745           g.drawLine(x + 3, y + 11, x + 3, y + 11);
1746 
1747           g.drawLine(x + 5, y + 5, x + 5, y + 5);
1748           g.drawLine(x + 5, y + 9, x + 5, y + 9);
1749 
1750           g.drawLine(x + 7, y + 3, x + 7, y + 3);
1751           g.drawLine(x + 7, y + 7, x + 7, y + 7);
1752           g.drawLine(x + 7, y + 11, x + 7, y + 11);
1753 
1754           // draw highlights
1755           if (focus)
1756             g.setColor(MetalLookAndFeel.getPrimaryControl());
1757           else
1758             g.setColor(MetalLookAndFeel.getWhite());
1759           g.drawLine(x + 1, y + 1, x + 8, y + 1);
1760           g.drawLine(x + 1, y + 2, x + 1, y + 13);
1761           g.drawLine(x + 2, y + 2, x + 2, y + 2);
1762           g.drawLine(x + 2, y + 6, x + 2, y + 6);
1763           g.drawLine(x + 2, y + 10, x + 2, y + 10);
1764 
1765           g.drawLine(x + 4, y + 4, x + 4, y + 4);
1766           g.drawLine(x + 4, y + 8, x + 4, y + 8);
1767 
1768           g.drawLine(x + 6, y + 2, x + 6, y + 2);
1769           g.drawLine(x + 6, y + 6, x + 6, y + 6);
1770           g.drawLine(x + 6, y + 10, x + 6, y + 10);
1771 
1772         }
1773     }
1774   }
1775 
1776   /**
1777    * A tree control icon.  This icon can be in one of two states: expanded and
1778    * collapsed.
1779    */
1780   public static class TreeControlIcon implements Icon, Serializable
1781   {
1782 
1783     /** ???. */
1784     protected boolean isLight;
1785 
1786     /** A flag that controls whether or not the icon is collapsed. */
1787     private boolean collapsed;
1788 
1789     /**
1790      * Creates a new icon.
1791      *
1792      * @param isCollapsed  a flag that controls whether the icon is in the
1793      *                     collapsed state or the expanded state.
1794      */
TreeControlIcon(boolean isCollapsed)1795     public TreeControlIcon(boolean isCollapsed)
1796     {
1797       collapsed = isCollapsed;
1798     }
1799 
1800     /**
1801      * Returns the width of the icon, in pixels.
1802      *
1803      * @return The width of the icon.
1804      */
getIconWidth()1805     public int getIconWidth()
1806     {
1807       return 18;
1808     }
1809     /**
1810      * Returns the height of the icon, in pixels.
1811      *
1812      * @return The height of the icon.
1813      */
getIconHeight()1814     public int getIconHeight()
1815     {
1816       return 18;
1817     }
1818 
1819     /**
1820      * Paints the icon at the location (x, y).
1821      *
1822      * @param c the component.
1823      * @param g the graphics device.
1824      * @param x the x coordinate.
1825      * @param y the y coordinate.
1826      */
paintIcon(Component c, Graphics g, int x, int y)1827     public void paintIcon(Component c, Graphics g, int x, int y)
1828     {
1829       // TODO: pick up appropriate UI colors
1830       Color dark = new Color(99, 130, 191);
1831       Color light = new Color(163, 184, 204);
1832       Color white = Color.white;
1833 
1834       x += 8;
1835       y += 6;
1836 
1837       final int w = 6;
1838       final int wHalf = (w >> 2);
1839       g.setColor(light);
1840       g.drawOval(x, y, w, w);
1841       g.setColor(dark);
1842       g.fillOval(x + 1, y + 1, w - 1, w - 1);
1843 
1844       if (collapsed)
1845         g.fillRect(x + w, y + wHalf + 1, w, 2);
1846       else
1847         g.fillRect(x + wHalf + 1, y + w, 2, w);
1848 
1849       g.setColor(white);
1850       g.fillRect(x + wHalf + 1, y + wHalf + 1, 2, 2);
1851 
1852     }
1853 
1854     /**
1855      * Simply calls {@link #paintIcon(Component, Graphics, int, int)}.
1856      *
1857      * @param c  the component.
1858      * @param g  the graphics device.
1859      * @param x  the x coordinate.
1860      * @param y  the y coordinate.
1861      */
paintMe(Component c, Graphics g, int x, int y)1862     public void paintMe(Component c, Graphics g, int x, int y)
1863     {
1864       paintIcon(c, g, x, y);
1865     }
1866   }
1867 
1868   /**
1869    * A tree folder icon.
1870    */
1871   public static class TreeFolderIcon extends FolderIcon16
1872   {
1873     /**
1874      * Creates a new instance.
1875      */
TreeFolderIcon()1876     public TreeFolderIcon()
1877     {
1878       // Nothing to do here.
1879     }
1880 
1881     /**
1882      * Returns the additional height for this icon, in this case <code>2</code>
1883      * pixels.
1884      *
1885      * @return <code>2</code>.
1886      */
getAdditionalHeight()1887     public int getAdditionalHeight()
1888     {
1889       return 2;
1890     }
1891 
1892     /**
1893      * Returns the vertical shift, in pixels, applied when painting the icon.
1894      * This overridden method returns <code>-1</code>.
1895      *
1896      * @return The shift.
1897      */
getShift()1898     public int getShift()
1899     {
1900       return -1;
1901     }
1902   }
1903 
1904   /**
1905    * A tree leaf icon.
1906    */
1907   public static class TreeLeafIcon extends FileIcon16
1908   {
1909     /**
1910      * Creates a new instance.
1911      */
TreeLeafIcon()1912     public TreeLeafIcon()
1913     {
1914       // Nothing to do here.
1915     }
1916 
1917     /**
1918      * Returns the additional height for this icon, in this case <code>4</code>
1919      * pixels.
1920      *
1921      * @return <code>4</code>.
1922      */
getAdditionalHeight()1923     public int getAdditionalHeight()
1924     {
1925       return 4;
1926     }
1927 
1928     /**
1929      * Returns the vertical shift, in pixels, applied when painting the icon.
1930      * This overridden method returns <code>2</code>.
1931      *
1932      * @return The shift.
1933      */
getShift()1934     public int getShift()
1935     {
1936       return 2;
1937     }
1938   }
1939 
1940   /**
1941    * An icon representing a hard disk.
1942    *
1943    * @see MetalIconFactory#getTreeHardDriveIcon()
1944    */
1945   private static class TreeHardDriveIcon
1946     implements Icon, UIResource, Serializable
1947   {
1948 
1949     /**
1950      * Creates a new icon instance.
1951      */
TreeHardDriveIcon()1952     public TreeHardDriveIcon()
1953     {
1954       // Nothing to do here.
1955     }
1956 
1957     /**
1958      * Returns the width of the icon, in pixels.
1959      *
1960      * @return <code>16</code>.
1961      */
getIconWidth()1962     public int getIconWidth()
1963     {
1964       return 16;
1965     }
1966 
1967     /**
1968      * Returns the height of the icon, in pixels.
1969      *
1970      * @return <code>16</code>.
1971      */
getIconHeight()1972     public int getIconHeight()
1973     {
1974       return 16;
1975     }
1976 
1977     /**
1978      * Paints the icon at the specified location, using colors from the
1979      * current theme.
1980      *
1981      * @param c  the component (ignored).
1982      * @param g  the graphics device.
1983      * @param x  the x-coordinate for the top-left of the icon.
1984      * @param y  the y-coordinate for the top-left of the icon.
1985      */
paintIcon(Component c, Graphics g, int x, int y)1986     public void paintIcon(Component c, Graphics g, int x, int y)
1987     {
1988       Color saved = g.getColor();
1989       g.setColor(MetalLookAndFeel.getBlack());
1990       g.drawLine(x + 1, y + 4, x + 1, y + 5);
1991       g.drawLine(x + 14, y + 4, x + 14, y + 5);
1992       g.drawLine(x + 1, y + 7, x + 1, y + 8);
1993       g.drawLine(x + 14, y + 7, x + 14, y + 8);
1994       g.drawLine(x + 1, y + 10, x + 1, y + 11);
1995       g.drawLine(x + 14, y + 10, x + 14, y + 11);
1996 
1997       g.drawLine(x + 2, y + 3, x + 3, y + 3);
1998       g.drawLine(x + 12, y + 3, x + 13, y + 3);
1999       g.drawLine(x + 2, y + 6, x + 3, y + 6);
2000       g.drawLine(x + 12, y + 6, x + 13, y + 6);
2001       g.drawLine(x + 2, y + 9, x + 3, y + 9);
2002       g.drawLine(x + 12, y + 9, x + 13, y + 9);
2003       g.drawLine(x + 2, y + 12, x + 3, y + 12);
2004       g.drawLine(x + 12, y + 12, x + 13, y + 12);
2005 
2006       g.drawLine(x + 4, y + 2, x + 11, y + 2);
2007       g.drawLine(x + 4, y + 7, x + 11, y + 7);
2008       g.drawLine(x + 4, y + 10, x + 11, y + 10);
2009       g.drawLine(x + 4, y + 13, x + 11, y + 13);
2010 
2011       g.setColor(MetalLookAndFeel.getWhite());
2012       g.fillRect(x + 4, y + 3, 2, 2);
2013       g.drawLine(x + 6, y + 4, x + 6, y + 4);
2014       g.drawLine(x + 7, y + 3, x + 9, y + 3);
2015       g.drawLine(x + 8, y + 4, x + 8, y + 4);
2016       g.drawLine(x + 11, y + 3, x + 11, y + 3);
2017       g.fillRect(x + 2, y + 4, 2, 2);
2018       g.fillRect(x + 2, y + 7, 2, 2);
2019       g.fillRect(x + 2, y + 10, 2, 2);
2020       g.drawLine(x + 4, y + 6, x + 4, y + 6);
2021       g.drawLine(x + 4, y + 9, x + 4, y + 9);
2022       g.drawLine(x + 4, y + 12, x + 4, y + 12);
2023 
2024       g.setColor(MetalLookAndFeel.getControlShadow());
2025       g.drawLine(x + 13, y + 4, x + 13, y + 4);
2026       g.drawLine(x + 12, y + 5, x + 13, y + 5);
2027       g.drawLine(x + 13, y + 7, x + 13, y + 7);
2028       g.drawLine(x + 12, y + 8, x + 13, y + 8);
2029       g.drawLine(x + 13, y + 10, x + 13, y + 10);
2030       g.drawLine(x + 12, y + 11, x + 13, y + 11);
2031 
2032       g.drawLine(x + 10, y + 5, x + 10, y + 5);
2033       g.drawLine(x + 7, y + 6, x + 7, y + 6);
2034       g.drawLine(x + 9, y + 6, x + 9, y + 6);
2035       g.drawLine(x + 11, y + 6, x + 11, y + 6);
2036 
2037       g.drawLine(x + 10, y + 8, x + 10, y + 8);
2038       g.drawLine(x + 7, y + 9, x + 7, y + 9);
2039       g.drawLine(x + 9, y + 9, x + 9, y + 9);
2040       g.drawLine(x + 11, y + 9, x + 11, y + 9);
2041 
2042       g.drawLine(x + 10, y + 11, x + 10, y + 11);
2043       g.drawLine(x + 7, y + 12, x + 7, y + 12);
2044       g.drawLine(x + 9, y + 12, x + 9, y + 12);
2045       g.drawLine(x + 11, y + 12, x + 11, y + 12);
2046 
2047       g.setColor(saved);
2048     }
2049   }
2050 
2051   /**
2052    * An icon representing a floppy disk.
2053    *
2054    * @see MetalIconFactory#getTreeFloppyDriveIcon()
2055    */
2056   private static class TreeFloppyDriveIcon
2057     implements Icon, UIResource, Serializable
2058   {
2059 
2060     /**
2061      * Creates a new icon instance.
2062      */
TreeFloppyDriveIcon()2063     public TreeFloppyDriveIcon()
2064     {
2065       // Nothing to do here.
2066     }
2067 
2068     /**
2069      * Returns the width of the icon, in pixels.
2070      *
2071      * @return <code>16</code>.
2072      */
getIconWidth()2073     public int getIconWidth()
2074     {
2075       return 16;
2076     }
2077 
2078     /**
2079      * Returns the height of the icon, in pixels.
2080      *
2081      * @return <code>16</code>.
2082      */
getIconHeight()2083     public int getIconHeight()
2084     {
2085       return 16;
2086     }
2087 
2088     /**
2089      * Paints the icon at the specified location, using colors from the
2090      * current theme.
2091      *
2092      * @param c  the component (ignored).
2093      * @param g  the graphics device.
2094      * @param x  the x-coordinate for the top-left of the icon.
2095      * @param y  the y-coordinate for the top-left of the icon.
2096      */
paintIcon(Component c, Graphics g, int x, int y)2097     public void paintIcon(Component c, Graphics g, int x, int y)
2098     {
2099       Color saved = g.getColor();
2100 
2101       g.setColor(MetalLookAndFeel.getBlack());
2102       g.drawLine(x + 1, y + 1, x + 13, y + 1);
2103       g.drawLine(x + 1, y + 1, x + 1, y + 14);
2104       g.drawLine(x + 1, y + 14, x + 14, y + 14);
2105       g.drawLine(x + 14, y + 2, x + 14, y + 14);
2106 
2107       g.setColor(MetalLookAndFeel.getPrimaryControl());
2108       g.fillRect(x + 2, y + 2, 12, 12);
2109 
2110       g.setColor(MetalLookAndFeel.getControlShadow());
2111       g.fillRect(x + 5, y + 2, 6, 5);
2112       g.drawLine(x + 4, y + 8, x + 11, y + 8);
2113       g.drawLine(x + 3, y + 9, x + 3, y + 13);
2114       g.drawLine(x + 12, y + 9, x + 12, y + 13);
2115 
2116       g.setColor(MetalLookAndFeel.getWhite());
2117       g.fillRect(x + 8, y + 3, 2, 3);
2118       g.fillRect(x + 4, y + 9, 8, 5);
2119 
2120       g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
2121       g.drawLine(x + 5, y + 10, x + 9, y + 10);
2122       g.drawLine(x + 5, y + 12, x + 8, y + 12);
2123 
2124       g.setColor(saved);
2125     }
2126   }
2127 
2128   /**
2129    * An icon representing a computer.
2130    *
2131    * @see MetalIconFactory#getTreeComputerIcon()
2132    */
2133   private static class TreeComputerIcon
2134     implements Icon, UIResource, Serializable
2135   {
2136 
2137     /**
2138      * Creates a new icon instance.
2139      */
TreeComputerIcon()2140     public TreeComputerIcon()
2141     {
2142       // Nothing to do here.
2143     }
2144 
2145     /**
2146      * Returns the width of the icon, in pixels.
2147      *
2148      * @return <code>16</code>.
2149      */
getIconWidth()2150     public int getIconWidth()
2151     {
2152       return 16;
2153     }
2154 
2155     /**
2156      * Returns the height of the icon, in pixels.
2157      *
2158      * @return <code>16</code>.
2159      */
getIconHeight()2160     public int getIconHeight()
2161     {
2162       return 16;
2163     }
2164 
2165     /**
2166      * Paints the icon at the specified location, using colors from the
2167      * current theme.
2168      *
2169      * @param c  the component (ignored).
2170      * @param g  the graphics device.
2171      * @param x  the x-coordinate for the top-left of the icon.
2172      * @param y  the y-coordinate for the top-left of the icon.
2173      */
paintIcon(Component c, Graphics g, int x, int y)2174     public void paintIcon(Component c, Graphics g, int x, int y)
2175     {
2176       Color saved = g.getColor();
2177 
2178       g.setColor(MetalLookAndFeel.getBlack());
2179       g.drawLine(x + 3, y + 1, x + 12, y + 1);
2180       g.drawLine(x + 2, y + 2, x + 2, y + 8);
2181       g.drawLine(x + 13, y + 2, x + 13, y + 8);
2182       g.drawLine(x + 3, y + 9, x + 3, y + 9);
2183       g.drawLine(x + 12, y + 9, x + 12, y + 9);
2184       g.drawRect(x + 1, y + 10, 13, 4);
2185       g.drawLine(x + 5, y + 3, x + 10, y + 3);
2186       g.drawLine(x + 5, y + 8, x + 10, y + 8);
2187       g.drawLine(x + 4, y + 4, x + 4, y + 7);
2188       g.drawLine(x + 11, y + 4, x + 11, y + 7);
2189 
2190       g.setColor(MetalLookAndFeel.getPrimaryControl());
2191       g.fillRect(x + 5, y + 4, 6, 4);
2192 
2193       g.setColor(MetalLookAndFeel.getControlShadow());
2194       g.drawLine(x + 6, y + 12, x + 8, y + 12);
2195       g.drawLine(x + 10, y + 12, x + 12, y + 12);
2196       g.setColor(saved);
2197     }
2198   }
2199 
2200   /** The icon returned by {@link #getCheckBoxIcon()}. */
2201   private static Icon checkBoxIcon;
2202 
2203   /** The icon returned by {@link #getCheckBoxMenuItemIcon()}. */
2204   private static Icon checkBoxMenuItemIcon;
2205 
2206   /** The icon returned by {@link #getFileChooserDetailViewIcon()}. */
2207   private static Icon fileChooserDetailViewIcon;
2208 
2209   /** The icon returned by {@link #getFileChooserHomeFolderIcon()}. */
2210   private static Icon fileChooserHomeFolderIcon;
2211 
2212   /** The icon returned by {@link #getFileChooserListViewIcon()}. */
2213   private static Icon fileChooserListViewIcon;
2214 
2215   /** The icon returned by {@link #getFileChooserNewFolderIcon()}. */
2216   private static Icon fileChooserNewFolderIcon;
2217 
2218   /** The icon returned by {@link #getFileChooserUpFolderIcon()}. */
2219   private static Icon fileChooserUpFolderIcon;
2220 
2221   /** The cached RadioButtonIcon instance. */
2222   private static RadioButtonIcon radioButtonIcon;
2223 
2224   /** The icon returned by {@link #getRadioButtonMenuItemIcon()}. */
2225   private static Icon radioButtonMenuItemIcon;
2226 
2227   /** The icon returned by {@link #getInternalFrameDefaultMenuIcon()}. */
2228   private static Icon internalFrameDefaultMenuIcon;
2229 
2230   /** The icon returned by {@link #getTreeComputerIcon()}. */
2231   private static Icon treeComputerIcon;
2232 
2233   /** The icon instance returned by {@link #getTreeFloppyDriveIcon()}. */
2234   private static Icon treeFloppyDriveIcon;
2235 
2236   /** The icon instance returned by {@link #getTreeHardDriveIcon()}. */
2237   private static Icon treeHardDriveIcon;
2238 
2239   /** The icon instance returned by {@link #getHorizontalSliderThumbIcon()}. */
2240   private static Icon horizontalSliderThumbIcon;
2241 
2242   /** The icon instance returned by {@link #getVerticalSliderThumbIcon()}. */
2243   private static Icon verticalSliderThumbIcon;
2244 
2245   /**
2246    * Creates a new instance.  All the methods are static, so creating an
2247    * instance isn't necessary.
2248    */
MetalIconFactory()2249   public MetalIconFactory()
2250   {
2251     // Nothing to do here.
2252   }
2253 
2254   /**
2255    * Returns an icon for use when rendering the {@link JCheckBox} component.
2256    *
2257    * @return A check box icon.
2258    *
2259    * @since 1.3
2260    */
getCheckBoxIcon()2261   public static Icon getCheckBoxIcon()
2262   {
2263     if (checkBoxIcon == null)
2264       checkBoxIcon = new MetalCheckBoxIcon();
2265     return checkBoxIcon;
2266   }
2267 
2268   /**
2269    * Returns an icon for use when rendering the {@link JCheckBoxMenuItem}
2270    * component.
2271    *
2272    * @return An icon.
2273    */
getCheckBoxMenuItemIcon()2274   public static Icon getCheckBoxMenuItemIcon()
2275   {
2276     if (checkBoxMenuItemIcon == null)
2277       checkBoxMenuItemIcon = new CheckBoxMenuItemIcon();
2278     return checkBoxMenuItemIcon;
2279   }
2280 
2281   /**
2282    * Returns an icon for use by the {@link JFileChooser} component.
2283    *
2284    * @return An icon.
2285    */
getFileChooserDetailViewIcon()2286   public static Icon getFileChooserDetailViewIcon()
2287   {
2288     if (fileChooserDetailViewIcon == null)
2289       fileChooserDetailViewIcon = new FileChooserDetailViewIcon();
2290     return fileChooserDetailViewIcon;
2291   }
2292 
2293   /**
2294    * Returns an icon for use by the {@link JFileChooser} component.
2295    *
2296    * @return An icon.
2297    */
getFileChooserHomeFolderIcon()2298   public static Icon getFileChooserHomeFolderIcon()
2299   {
2300     if (fileChooserHomeFolderIcon == null)
2301       fileChooserHomeFolderIcon = new FileChooserHomeFolderIcon();
2302     return fileChooserHomeFolderIcon;
2303   }
2304 
2305   /**
2306    * Returns an icon for use by the {@link JFileChooser} component.
2307    *
2308    * @return An icon.
2309    */
getFileChooserListViewIcon()2310   public static Icon getFileChooserListViewIcon()
2311   {
2312     if (fileChooserListViewIcon == null)
2313       fileChooserListViewIcon = new FileChooserListViewIcon();
2314     return fileChooserListViewIcon;
2315   }
2316 
2317   /**
2318    * Returns an icon for use by the {@link JFileChooser} component.
2319    *
2320    * @return An icon.
2321    */
getFileChooserNewFolderIcon()2322   public static Icon getFileChooserNewFolderIcon()
2323   {
2324     if (fileChooserNewFolderIcon == null)
2325       fileChooserNewFolderIcon = new FileChooserNewFolderIcon();
2326     return fileChooserNewFolderIcon;
2327   }
2328 
2329   /**
2330    * Returns an icon for use by the {@link JFileChooser} component.
2331    *
2332    * @return An icon.
2333    */
getFileChooserUpFolderIcon()2334   public static Icon getFileChooserUpFolderIcon()
2335   {
2336     if (fileChooserUpFolderIcon == null)
2337       fileChooserUpFolderIcon = new FileChooserUpFolderIcon();
2338     return fileChooserUpFolderIcon;
2339   }
2340 
2341   /**
2342    * Returns an icon for RadioButtons in the Metal L&amp;F.
2343    *
2344    * @return an icon for RadioButtons in the Metal L&amp;F
2345    */
getRadioButtonIcon()2346   public static Icon getRadioButtonIcon()
2347   {
2348     if (radioButtonIcon == null)
2349       radioButtonIcon = new RadioButtonIcon();
2350     return radioButtonIcon;
2351   }
2352 
2353   /**
2354    * Creates a new instance of the icon used in a {@link JRadioButtonMenuItem}.
2355    *
2356    * @return A new icon instance.
2357    */
getRadioButtonMenuItemIcon()2358   public static Icon getRadioButtonMenuItemIcon()
2359   {
2360     if (radioButtonMenuItemIcon == null)
2361       radioButtonMenuItemIcon = new RadioButtonMenuItemIcon();
2362     return radioButtonMenuItemIcon;
2363   }
2364 
2365   /**
2366    * Returns the icon used to display the thumb for a horizontally oriented
2367    * {@link JSlider}.
2368    *
2369    * @return The icon.
2370    */
getHorizontalSliderThumbIcon()2371   public static Icon getHorizontalSliderThumbIcon()
2372   {
2373     if (horizontalSliderThumbIcon == null)
2374       horizontalSliderThumbIcon = new HorizontalSliderThumbIcon();
2375     return horizontalSliderThumbIcon;
2376   }
2377 
2378   /**
2379    * Creates a new icon used to represent the 'close' button in the title
2380    * pane of a {@link JInternalFrame}.
2381    *
2382    * @param size  the icon size.
2383    *
2384    * @return A close icon.
2385    */
getInternalFrameCloseIcon(int size)2386   public static Icon getInternalFrameCloseIcon(int size)
2387   {
2388     return new InternalFrameCloseIcon(size);
2389   }
2390 
2391   /**
2392    * Creates a new icon for the menu in a {@link JInternalFrame}.  This is the
2393    * icon displayed at the top left of the frame.
2394    *
2395    * @return A menu icon.
2396    */
getInternalFrameDefaultMenuIcon()2397   public static Icon getInternalFrameDefaultMenuIcon()
2398   {
2399     if (internalFrameDefaultMenuIcon == null)
2400       internalFrameDefaultMenuIcon = new InternalFrameDefaultMenuIcon();
2401     return internalFrameDefaultMenuIcon;
2402   }
2403 
2404   /**
2405    * Creates a new icon for the 'maximize' button in a {@link JInternalFrame}.
2406    *
2407    * @param size  the icon size in pixels.
2408    *
2409    * @return The icon.
2410    *
2411    * @see #getInternalFrameAltMaximizeIcon(int)
2412    */
getInternalFrameMaximizeIcon(int size)2413   public static Icon getInternalFrameMaximizeIcon(int size)
2414   {
2415     return new InternalFrameMaximizeIcon();
2416   }
2417 
2418   /**
2419    * Returns the icon used for the minimize button in the frame title for a
2420    * {@link JInternalFrame}.
2421    *
2422    * @param size  the icon size in pixels (ignored by this implementation).
2423    *
2424    * @return The icon.
2425    */
getInternalFrameMinimizeIcon(int size)2426   public static Icon getInternalFrameMinimizeIcon(int size)
2427   {
2428     return new InternalFrameMinimizeIcon();
2429   }
2430 
2431   /**
2432    * Creates a new icon for the 'restore' button in a {@link JInternalFrame}
2433    * that has been maximised.
2434    *
2435    * @param size  the icon size in pixels.
2436    *
2437    * @return The icon.
2438    *
2439    * @see #getInternalFrameMaximizeIcon(int)
2440    */
getInternalFrameAltMaximizeIcon(int size)2441   public static Icon getInternalFrameAltMaximizeIcon(int size)
2442   {
2443     return new InternalFrameAltMaximizeIcon(size);
2444   }
2445 
2446   /**
2447    * Returns the icon used to display the thumb for a vertically oriented
2448    * {@link JSlider}.
2449    *
2450    * @return The icon.
2451    */
getVerticalSliderThumbIcon()2452   public static Icon getVerticalSliderThumbIcon()
2453   {
2454     if (verticalSliderThumbIcon == null)
2455       verticalSliderThumbIcon = new VerticalSliderThumbIcon();
2456     return verticalSliderThumbIcon;
2457   }
2458 
2459   /**
2460    * Creates and returns a new tree folder icon.
2461    *
2462    * @return A new tree folder icon.
2463    */
getTreeFolderIcon()2464   public static Icon getTreeFolderIcon()
2465   {
2466     return new TreeFolderIcon();
2467   }
2468 
2469   /**
2470    * Creates and returns a new tree leaf icon.
2471    *
2472    * @return A new tree leaf icon.
2473    */
getTreeLeafIcon()2474   public static Icon getTreeLeafIcon()
2475   {
2476     return new TreeLeafIcon();
2477   }
2478 
2479   /**
2480    * Creates and returns a tree control icon.
2481    *
2482    * @param isCollapsed  a flag that controls whether the icon is in the
2483    *                     collapsed or expanded state.
2484    *
2485    * @return A tree control icon.
2486    */
getTreeControlIcon(boolean isCollapsed)2487   public static Icon getTreeControlIcon(boolean isCollapsed)
2488   {
2489     return new TreeControlIcon(isCollapsed);
2490   }
2491 
2492   /**
2493    * Returns a <code>16x16</code> icon representing a computer.
2494    *
2495    * @return The icon.
2496    */
getTreeComputerIcon()2497   public static Icon getTreeComputerIcon()
2498   {
2499     if (treeComputerIcon == null)
2500       treeComputerIcon = new TreeComputerIcon();
2501     return treeComputerIcon;
2502   }
2503 
2504   /**
2505    * Returns a <code>16x16</code> icon representing a floppy disk.
2506    *
2507    * @return The icon.
2508    */
getTreeFloppyDriveIcon()2509   public static Icon getTreeFloppyDriveIcon()
2510   {
2511     if (treeFloppyDriveIcon == null)
2512       treeFloppyDriveIcon = new TreeFloppyDriveIcon();
2513     return treeFloppyDriveIcon;
2514   }
2515 
2516   /**
2517    * Returns a <code>16x16</code> icon representing a hard disk.
2518    *
2519    * @return The icon.
2520    */
getTreeHardDriveIcon()2521   public static Icon getTreeHardDriveIcon()
2522   {
2523     if (treeHardDriveIcon == null)
2524       treeHardDriveIcon = new TreeHardDriveIcon();
2525     return treeHardDriveIcon;
2526   }
2527 
2528   /**
2529    * Returns a new instance of a 4 x 8 icon showing a small black triangle that
2530    * points to the right.  This is displayed in menu items that have a
2531    * sub menu.
2532    *
2533    * @return The icon.
2534    */
getMenuArrowIcon()2535   public static Icon getMenuArrowIcon()
2536   {
2537     if (menuArrow == null)
2538       menuArrow = new Icon()
2539       {
2540         public int getIconHeight()
2541         {
2542           return 8;
2543         }
2544 
2545         public int getIconWidth()
2546         {
2547           return 4;
2548         }
2549 
2550         public void paintIcon(Component c, Graphics g, int x, int y)
2551         {
2552           Color saved = g.getColor();
2553           g.setColor(Color.BLACK);
2554           for (int i = 0; i < 4; i++)
2555             g.drawLine(x + i, y + i, x + i, y + 7 - i);
2556           g.setColor(saved);
2557         }
2558       };
2559     return menuArrow;
2560   }
2561 
2562   /**
2563    * Returns a new instance of a 4 x 8 icon showing a small black triangle that
2564    * points to the right. This is displayed in menu items that have a sub menu.
2565    *
2566    * @return The icon.
2567    */
getMenuItemArrowIcon()2568   public static Icon getMenuItemArrowIcon()
2569   {
2570     if (menuItemArrow == null)
2571       menuItemArrow = new Icon()
2572       {
2573         public int getIconHeight()
2574         {
2575           return 8;
2576         }
2577 
2578         public int getIconWidth()
2579         {
2580           return 4;
2581         }
2582 
2583         public void paintIcon(Component c, Graphics g, int x, int y)
2584         {
2585           Color saved = g.getColor();
2586           g.setColor(Color.BLACK);
2587           for (int i = 0; i < 4; i++)
2588             g.drawLine(x + i, y + i, x + i, y + 7 - i);
2589           g.setColor(saved);
2590         }
2591       };
2592     return menuItemArrow;
2593   }
2594 
2595   /**
2596    * Returns a new instance of a 13 x 13 icon showing a small black check mark.
2597    *
2598    * @return The icon.
2599    */
getMenuItemCheckIcon()2600   public static Icon getMenuItemCheckIcon()
2601   {
2602     return new Icon()
2603     {
2604       public int getIconHeight()
2605       {
2606         return 13;
2607       }
2608 
2609       public int getIconWidth()
2610       {
2611         return 13;
2612       }
2613 
2614       public void paintIcon(Component c, Graphics g, int x, int y)
2615       {
2616         Color saved = g.getColor();
2617         g.setColor(Color.BLACK);
2618         g.drawLine(3 + x, 5 + y, 3 + x, 9 + y);
2619         g.drawLine(4 + x, 5 + y, 4 + x, 9 + y);
2620         g.drawLine(5 + x, 7 + y, 9 + x, 3 + y);
2621         g.drawLine(5 + x, 8 + y, 9 + x, 4 + y);
2622         g.setColor(saved);
2623       }
2624     };
2625   }
2626 }
2627