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