1 /*
   2  * Copyright (c) 2003, 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 
  26 package javax.swing.plaf.metal;
  27 
  28 import java.awt.*;
  29 import java.net.URL;
  30 import java.util.*;
  31 import javax.swing.*;
  32 import javax.swing.plaf.*;
  33 import sun.swing.SwingUtilities2;
  34 import sun.swing.PrintColorUIResource;
  35 import sun.swing.SwingLazyValue;
  36 
  37 /**
  38  * The default theme for the {@code MetalLookAndFeel}.
  39  * <p>
  40  * The designers
  41  * of the Metal Look and Feel strive to keep the default look up to
  42  * date, possibly through the use of new themes in the future.
  43  * Therefore, developers should only use this class directly when they
  44  * wish to customize the "Ocean" look, or force it to be the current
  45  * theme, regardless of future updates.
  46 
  47  * <p>
  48  * All colors returned by {@code OceanTheme} are completely
  49  * opaque.
  50  *
  51  * @since 1.5
  52  * @see MetalLookAndFeel#setCurrentTheme
  53  */
  54 @SuppressWarnings("serial") // Superclass is not serializable across versions
  55 public class OceanTheme extends DefaultMetalTheme {
  56     private static final ColorUIResource PRIMARY1 =
  57                               new ColorUIResource(0x6382BF);
  58     private static final ColorUIResource PRIMARY2 =
  59                               new ColorUIResource(0xA3B8CC);
  60     private static final ColorUIResource PRIMARY3 =
  61                               new ColorUIResource(0xB8CFE5);
  62     private static final ColorUIResource SECONDARY1 =
  63                               new ColorUIResource(0x7A8A99);
  64     private static final ColorUIResource SECONDARY2 =
  65                               new ColorUIResource(0xB8CFE5);
  66     private static final ColorUIResource SECONDARY3 =
  67                               new ColorUIResource(0xEEEEEE);
  68 
  69     private static final ColorUIResource CONTROL_TEXT_COLOR =
  70                               new PrintColorUIResource(0x333333, Color.BLACK);
  71     private static final ColorUIResource INACTIVE_CONTROL_TEXT_COLOR =
  72                               new ColorUIResource(0x999999);
  73     private static final ColorUIResource MENU_DISABLED_FOREGROUND =
  74                               new ColorUIResource(0x999999);
  75     private static final ColorUIResource OCEAN_BLACK =
  76                               new PrintColorUIResource(0x333333, Color.BLACK);
  77 
  78     private static final ColorUIResource OCEAN_DROP =
  79                               new ColorUIResource(0xD2E9FF);
  80 
  81     // ComponentOrientation Icon
  82     // Delegates to different icons based on component orientation
  83     private static class COIcon extends IconUIResource {
  84         private Icon rtl;
  85 
  86         public COIcon(Icon ltr, Icon rtl) {
  87             super(ltr);
  88             this.rtl = rtl;
  89         }
  90 
  91         public void paintIcon(Component c, Graphics g, int x, int y) {
  92             if (MetalUtils.isLeftToRight(c)) {
  93                 super.paintIcon(c, g, x, y);
  94             } else {
  95                 rtl.paintIcon(c, g, x, y);
  96             }
  97         }
  98     }
  99 
 100     // InternalFrame Icon
 101     // Delegates to different icons based on button state
 102     @SuppressWarnings("serial") // Superclass is not serializable across versions
 103     private static class IFIcon extends IconUIResource {
 104         private Icon pressed;
 105 
 106         public IFIcon(Icon normal, Icon pressed) {
 107             super(normal);
 108             this.pressed = pressed;
 109         }
 110 
 111         public void paintIcon(Component c, Graphics g, int x, int y) {
 112             ButtonModel model = ((AbstractButton)c).getModel();
 113             if (model.isPressed() && model.isArmed()) {
 114                 pressed.paintIcon(c, g, x, y);
 115             } else {
 116                 super.paintIcon(c, g, x, y);
 117             }
 118         }
 119     }
 120 
 121     /**
 122      * Creates an instance of <code>OceanTheme</code>
 123      */
 124     public OceanTheme() {
 125     }
 126 
 127     /**
 128      * Add this theme's custom entries to the defaults table.
 129      *
 130      * @param table the defaults table, non-null
 131      * @throws NullPointerException if {@code table} is {@code null}
 132      */
 133     public void addCustomEntriesToTable(UIDefaults table) {
 134         Object focusBorder = new SwingLazyValue(
 135                       "javax.swing.plaf.BorderUIResource$LineBorderUIResource",
 136                       new Object[] {getPrimary1()});
 137         // .30 0 DDE8F3 white secondary2
 138         java.util.List buttonGradient = Arrays.asList(
 139                  new Object[] {new Float(.3f), new Float(0f),
 140                  new ColorUIResource(0xDDE8F3), getWhite(), getSecondary2() });
 141 
 142         // Other possible properties that aren't defined:
 143         //
 144         // Used when generating the disabled Icons, provides the region to
 145         // constrain grays to.
 146         // Button.disabledGrayRange -> Object[] of Integers giving min/max
 147         // InternalFrame.inactiveTitleGradient -> Gradient when the
 148         //   internal frame is inactive.
 149         Color cccccc = new ColorUIResource(0xCCCCCC);
 150         Color dadada = new ColorUIResource(0xDADADA);
 151         Color c8ddf2 = new ColorUIResource(0xC8DDF2);
 152         Object directoryIcon = getIconResource("icons/ocean/directory.gif");
 153         Object fileIcon = getIconResource("icons/ocean/file.gif");
 154         java.util.List sliderGradient = Arrays.asList(new Object[] {
 155             new Float(.3f), new Float(.2f),
 156             c8ddf2, getWhite(), new ColorUIResource(SECONDARY2) });
 157 
 158         Object[] defaults = new Object[] {
 159             "Button.gradient", buttonGradient,
 160             "Button.rollover", Boolean.TRUE,
 161             "Button.toolBarBorderBackground", INACTIVE_CONTROL_TEXT_COLOR,
 162             "Button.disabledToolBarBorderBackground", cccccc,
 163             "Button.rolloverIconType", "ocean",
 164 
 165             "CheckBox.rollover", Boolean.TRUE,
 166             "CheckBox.gradient", buttonGradient,
 167 
 168             "CheckBoxMenuItem.gradient", buttonGradient,
 169 
 170             // home2
 171             "FileChooser.homeFolderIcon",
 172                  getIconResource("icons/ocean/homeFolder.gif"),
 173             // directory2
 174             "FileChooser.newFolderIcon",
 175                  getIconResource("icons/ocean/newFolder.gif"),
 176             // updir2
 177             "FileChooser.upFolderIcon",
 178                  getIconResource("icons/ocean/upFolder.gif"),
 179 
 180             // computer2
 181             "FileView.computerIcon",
 182                  getIconResource("icons/ocean/computer.gif"),
 183             "FileView.directoryIcon", directoryIcon,
 184             // disk2
 185             "FileView.hardDriveIcon",
 186                  getIconResource("icons/ocean/hardDrive.gif"),
 187             "FileView.fileIcon", fileIcon,
 188             // floppy2
 189             "FileView.floppyDriveIcon",
 190                  getIconResource("icons/ocean/floppy.gif"),
 191 
 192             "Label.disabledForeground", getInactiveControlTextColor(),
 193 
 194             "Menu.opaque", Boolean.FALSE,
 195 
 196             "MenuBar.gradient", Arrays.asList(new Object[] {
 197                      new Float(1f), new Float(0f),
 198                      getWhite(), dadada,
 199                      new ColorUIResource(dadada) }),
 200             "MenuBar.borderColor", cccccc,
 201 
 202             "InternalFrame.activeTitleGradient", buttonGradient,
 203             // close2
 204             "InternalFrame.closeIcon",
 205                      new UIDefaults.LazyValue() {
 206                          public Object createValue(UIDefaults table) {
 207                              return new IFIcon(getHastenedIcon("icons/ocean/close.gif", table),
 208                                                getHastenedIcon("icons/ocean/close-pressed.gif", table));
 209                          }
 210                      },
 211             // minimize
 212             "InternalFrame.iconifyIcon",
 213                      new UIDefaults.LazyValue() {
 214                          public Object createValue(UIDefaults table) {
 215                              return new IFIcon(getHastenedIcon("icons/ocean/iconify.gif", table),
 216                                                getHastenedIcon("icons/ocean/iconify-pressed.gif", table));
 217                          }
 218                      },
 219             // restore
 220             "InternalFrame.minimizeIcon",
 221                      new UIDefaults.LazyValue() {
 222                          public Object createValue(UIDefaults table) {
 223                              return new IFIcon(getHastenedIcon("icons/ocean/minimize.gif", table),
 224                                                getHastenedIcon("icons/ocean/minimize-pressed.gif", table));
 225                          }
 226                      },
 227             // menubutton3
 228             "InternalFrame.icon",
 229                      getIconResource("icons/ocean/menu.gif"),
 230             // maximize2
 231             "InternalFrame.maximizeIcon",
 232                      new UIDefaults.LazyValue() {
 233                          public Object createValue(UIDefaults table) {
 234                              return new IFIcon(getHastenedIcon("icons/ocean/maximize.gif", table),
 235                                                getHastenedIcon("icons/ocean/maximize-pressed.gif", table));
 236                          }
 237                      },
 238             // paletteclose
 239             "InternalFrame.paletteCloseIcon",
 240                      new UIDefaults.LazyValue() {
 241                          public Object createValue(UIDefaults table) {
 242                              return new IFIcon(getHastenedIcon("icons/ocean/paletteClose.gif", table),
 243                                                getHastenedIcon("icons/ocean/paletteClose-pressed.gif", table));
 244                          }
 245                      },
 246 
 247             "List.focusCellHighlightBorder", focusBorder,
 248 
 249             "MenuBarUI", "javax.swing.plaf.metal.MetalMenuBarUI",
 250 
 251             "OptionPane.errorIcon",
 252                    getIconResource("icons/ocean/error.png"),
 253             "OptionPane.informationIcon",
 254                    getIconResource("icons/ocean/info.png"),
 255             "OptionPane.questionIcon",
 256                    getIconResource("icons/ocean/question.png"),
 257             "OptionPane.warningIcon",
 258                    getIconResource("icons/ocean/warning.png"),
 259 
 260             "RadioButton.gradient", buttonGradient,
 261             "RadioButton.rollover", Boolean.TRUE,
 262 
 263             "RadioButtonMenuItem.gradient", buttonGradient,
 264 
 265             "ScrollBar.gradient", buttonGradient,
 266 
 267             "Slider.altTrackColor", new ColorUIResource(0xD2E2EF),
 268             "Slider.gradient", sliderGradient,
 269             "Slider.focusGradient", sliderGradient,
 270 
 271             "SplitPane.oneTouchButtonsOpaque", Boolean.FALSE,
 272             "SplitPane.dividerFocusColor", c8ddf2,
 273 
 274             "TabbedPane.borderHightlightColor", getPrimary1(),
 275             "TabbedPane.contentAreaColor", c8ddf2,
 276             "TabbedPane.contentBorderInsets", new Insets(4, 2, 3, 3),
 277             "TabbedPane.selected", c8ddf2,
 278             "TabbedPane.tabAreaBackground", dadada,
 279             "TabbedPane.tabAreaInsets", new Insets(2, 2, 0, 6),
 280             "TabbedPane.unselectedBackground", SECONDARY3,
 281 
 282             "Table.focusCellHighlightBorder", focusBorder,
 283             "Table.gridColor", SECONDARY1,
 284             "TableHeader.focusCellBackground", c8ddf2,
 285 
 286             "ToggleButton.gradient", buttonGradient,
 287 
 288             "ToolBar.borderColor", cccccc,
 289             "ToolBar.isRollover", Boolean.TRUE,
 290 
 291             "Tree.closedIcon", directoryIcon,
 292 
 293             "Tree.collapsedIcon",
 294                   new UIDefaults.LazyValue() {
 295                       public Object createValue(UIDefaults table) {
 296                           return new COIcon(getHastenedIcon("icons/ocean/collapsed.gif", table),
 297                                             getHastenedIcon("icons/ocean/collapsed-rtl.gif", table));
 298                       }
 299                   },
 300 
 301             "Tree.expandedIcon",
 302                   getIconResource("icons/ocean/expanded.gif"),
 303             "Tree.leafIcon", fileIcon,
 304             "Tree.openIcon", directoryIcon,
 305             "Tree.selectionBorderColor", getPrimary1(),
 306             "Tree.dropLineColor", getPrimary1(),
 307             "Table.dropLineColor", getPrimary1(),
 308             "Table.dropLineShortColor", OCEAN_BLACK,
 309 
 310             "Table.dropCellBackground", OCEAN_DROP,
 311             "Tree.dropCellBackground", OCEAN_DROP,
 312             "List.dropCellBackground", OCEAN_DROP,
 313             "List.dropLineColor", getPrimary1()
 314         };
 315         table.putDefaults(defaults);
 316     }
 317 
 318     /**
 319      * Overriden to enable picking up the system fonts, if applicable.
 320      */
 321     boolean isSystemTheme() {
 322         return true;
 323     }
 324 
 325     /**
 326      * Return the name of this theme, "Ocean".
 327      *
 328      * @return "Ocean"
 329      */
 330     public String getName() {
 331         return "Ocean";
 332     }
 333 
 334     /**
 335      * Returns the primary 1 color. This returns a color with an rgb hex value
 336      * of {@code 0x6382BF}.
 337      *
 338      * @return the primary 1 color
 339      * @see java.awt.Color#decode
 340      */
 341     protected ColorUIResource getPrimary1() {
 342         return PRIMARY1;
 343     }
 344 
 345     /**
 346      * Returns the primary 2 color. This returns a color with an rgb hex value
 347      * of {@code 0xA3B8CC}.
 348      *
 349      * @return the primary 2 color
 350      * @see java.awt.Color#decode
 351      */
 352     protected ColorUIResource getPrimary2() {
 353         return PRIMARY2;
 354     }
 355 
 356     /**
 357      * Returns the primary 3 color. This returns a color with an rgb hex value
 358      * of {@code 0xB8CFE5}.
 359      *
 360      * @return the primary 3 color
 361      * @see java.awt.Color#decode
 362      */
 363     protected ColorUIResource getPrimary3() {
 364         return PRIMARY3;
 365     }
 366 
 367     /**
 368      * Returns the secondary 1 color. This returns a color with an rgb hex
 369      * value of {@code 0x7A8A99}.
 370      *
 371      * @return the secondary 1 color
 372      * @see java.awt.Color#decode
 373      */
 374     protected ColorUIResource getSecondary1() {
 375         return SECONDARY1;
 376     }
 377 
 378     /**
 379      * Returns the secondary 2 color. This returns a color with an rgb hex
 380      * value of {@code 0xB8CFE5}.
 381      *
 382      * @return the secondary 2 color
 383      * @see java.awt.Color#decode
 384      */
 385     protected ColorUIResource getSecondary2() {
 386         return SECONDARY2;
 387     }
 388 
 389     /**
 390      * Returns the secondary 3 color. This returns a color with an rgb hex
 391      * value of {@code 0xEEEEEE}.
 392      *
 393      * @return the secondary 3 color
 394      * @see java.awt.Color#decode
 395      */
 396     protected ColorUIResource getSecondary3() {
 397         return SECONDARY3;
 398     }
 399 
 400     /**
 401      * Returns the black color. This returns a color with an rgb hex
 402      * value of {@code 0x333333}.
 403      *
 404      * @return the black color
 405      * @see java.awt.Color#decode
 406      */
 407     protected ColorUIResource getBlack() {
 408         return OCEAN_BLACK;
 409     }
 410 
 411     /**
 412      * Returns the desktop color. This returns a color with an rgb hex
 413      * value of {@code 0xFFFFFF}.
 414      *
 415      * @return the desktop color
 416      * @see java.awt.Color#decode
 417      */
 418     public ColorUIResource getDesktopColor() {
 419         return MetalTheme.white;
 420     }
 421 
 422     /**
 423      * Returns the inactive control text color. This returns a color with an
 424      * rgb hex value of {@code 0x999999}.
 425      *
 426      * @return the inactive control text color
 427      */
 428     public ColorUIResource getInactiveControlTextColor() {
 429         return INACTIVE_CONTROL_TEXT_COLOR;
 430     }
 431 
 432     /**
 433      * Returns the control text color. This returns a color with an
 434      * rgb hex value of {@code 0x333333}.
 435      *
 436      * @return the control text color
 437      */
 438     public ColorUIResource getControlTextColor() {
 439         return CONTROL_TEXT_COLOR;
 440     }
 441 
 442     /**
 443      * Returns the menu disabled foreground color. This returns a color with an
 444      * rgb hex value of {@code 0x999999}.
 445      *
 446      * @return the menu disabled foreground color
 447      */
 448     public ColorUIResource getMenuDisabledForeground() {
 449         return MENU_DISABLED_FOREGROUND;
 450     }
 451 
 452     private Object getIconResource(String iconID) {
 453         return SwingUtilities2.makeIcon(getClass(), OceanTheme.class, iconID);
 454     }
 455 
 456     // makes use of getIconResource() to fetch an icon and then hastens it
 457     // - calls createValue() on it and returns the actual icon
 458     private Icon getHastenedIcon(String iconID, UIDefaults table) {
 459         Object res = getIconResource(iconID);
 460         return (Icon)((UIDefaults.LazyValue)res).createValue(table);
 461     }
 462 }