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