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