1 /*
   2  * Copyright (c) 2004, 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 sun.awt.windows;
  27 
  28 import java.awt.Color;
  29 import java.awt.Dimension;
  30 import java.awt.Insets;
  31 import java.awt.Point;
  32 import java.util.HashMap;
  33 import java.util.Map;
  34 import java.util.concurrent.locks.Lock;
  35 import java.util.concurrent.locks.ReadWriteLock;
  36 import java.util.concurrent.locks.ReentrantReadWriteLock;
  37 
  38 /* !!!! WARNING !!!!
  39  * This class has to be in sync with
  40  * src/solaris/classes/sun/awt/windows/ThemeReader.java
  41  * while we continue to build WinL&F on solaris
  42  */
  43 
  44 
  45 /**
  46  * Implements Theme Support for Windows XP.
  47  *
  48  * @author Sergey Salishev
  49  * @author Bino George
  50  * @author Igor Kushnirskiy
  51  */
  52 public final class ThemeReader {
  53 
  54     private static final Map<String, Long> widgetToTheme = new HashMap<>();
  55 
  56     // lock for the cache
  57     // reading should be done with readLock
  58     // writing with writeLock
  59     private static final ReadWriteLock readWriteLock =
  60         new ReentrantReadWriteLock();
  61     private static final Lock readLock = readWriteLock.readLock();
  62     private static final Lock writeLock = readWriteLock.writeLock();
  63 
  64     static volatile boolean xpStyleEnabled;
  65 
  66     static void flush() {
  67         writeLock.lock();
  68         try {
  69             // Close old themes.
  70             for (Long value : widgetToTheme.values()) {
  71                 closeTheme(value.longValue());
  72             }
  73             widgetToTheme.clear();
  74         } finally {
  75             writeLock.unlock();
  76         }
  77     }
  78 
  79     public static native boolean isThemed();
  80 
  81     public static boolean isXPStyleEnabled() {
  82         return xpStyleEnabled;
  83     }
  84 
  85     // this should be called only with writeLock held
  86     private static Long getThemeImpl(String widget) {
  87         Long theme = widgetToTheme.get(widget);
  88         if (theme == null) {
  89             int i = widget.indexOf("::");
  90             if (i > 0) {
  91                 // We're using the syntax "subAppName::controlName" here, as used by msstyles.
  92                 // See documentation for SetWindowTheme on MSDN.
  93                 setWindowTheme(widget.substring(0, i));
  94                 theme = openTheme(widget.substring(i+2));
  95                 setWindowTheme(null);
  96             } else {
  97                 theme = openTheme(widget);
  98             }
  99             widgetToTheme.put(widget, theme);
 100         }
 101         return theme;
 102     }
 103 
 104     // returns theme value
 105     // this method should be invoked with readLock locked
 106     private static Long getTheme(String widget) {
 107         // mostly copied from the javadoc for ReentrantReadWriteLock
 108         Long theme = widgetToTheme.get(widget);
 109         if (theme == null) {
 110             readLock.unlock();
 111             writeLock.lock();
 112             try {
 113                 theme = getThemeImpl(widget);
 114             } finally {
 115                 readLock.lock();
 116                 writeLock.unlock();// Unlock write, still hold read
 117             }
 118         }
 119         return theme;
 120     }
 121 
 122     private static native void paintBackground(int[] buffer, long theme,
 123                                                int part, int state, int x,
 124                                                int y, int w, int h, int stride);
 125 
 126     public static void paintBackground(int[] buffer, String widget,
 127            int part, int state, int x, int y, int w, int h, int stride) {
 128         readLock.lock();
 129         try {
 130             paintBackground(buffer, getTheme(widget), part, state, x, y, w, h, stride);
 131         } finally {
 132             readLock.unlock();
 133         }
 134     }
 135 
 136     private static native Insets getThemeMargins(long theme, int part,
 137                                                  int state, int marginType);
 138 
 139     public static Insets getThemeMargins(String widget, int part, int state, int marginType) {
 140         readLock.lock();
 141         try {
 142             return getThemeMargins(getTheme(widget), part, state, marginType);
 143         } finally {
 144             readLock.unlock();
 145         }
 146     }
 147 
 148     private static native boolean isThemePartDefined(long theme, int part, int state);
 149 
 150     public static boolean isThemePartDefined(String widget, int part, int state) {
 151         readLock.lock();
 152         try {
 153             return isThemePartDefined(getTheme(widget), part, state);
 154         } finally {
 155             readLock.unlock();
 156         }
 157     }
 158 
 159     private static native Color getColor(long theme, int part, int state,
 160                                          int property);
 161 
 162     public static Color getColor(String widget, int part, int state, int property) {
 163         readLock.lock();
 164         try {
 165             return getColor(getTheme(widget), part, state, property);
 166         } finally {
 167             readLock.unlock();
 168         }
 169     }
 170 
 171     private static native int getInt(long theme, int part, int state,
 172                                      int property);
 173 
 174     public static int getInt(String widget, int part, int state, int property) {
 175         readLock.lock();
 176         try {
 177             return getInt(getTheme(widget), part, state, property);
 178         } finally {
 179             readLock.unlock();
 180         }
 181     }
 182 
 183     private static native int getEnum(long theme, int part, int state,
 184                                       int property);
 185 
 186     public static int getEnum(String widget, int part, int state, int property) {
 187         readLock.lock();
 188         try {
 189             return getEnum(getTheme(widget), part, state, property);
 190         } finally {
 191             readLock.unlock();
 192         }
 193     }
 194 
 195     private static native boolean getBoolean(long theme, int part, int state,
 196                                              int property);
 197 
 198     public static boolean getBoolean(String widget, int part, int state,
 199                                      int property) {
 200         readLock.lock();
 201         try {
 202             return getBoolean(getTheme(widget), part, state, property);
 203         } finally {
 204             readLock.unlock();
 205         }
 206     }
 207 
 208     private static native boolean getSysBoolean(long theme, int property);
 209 
 210     public static boolean getSysBoolean(String widget, int property) {
 211         readLock.lock();
 212         try {
 213             return getSysBoolean(getTheme(widget), property);
 214         } finally {
 215             readLock.unlock();
 216         }
 217     }
 218 
 219     private static native Point getPoint(long theme, int part, int state,
 220                                          int property);
 221 
 222     public static Point getPoint(String widget, int part, int state, int property) {
 223         readLock.lock();
 224         try {
 225             return getPoint(getTheme(widget), part, state, property);
 226         } finally {
 227             readLock.unlock();
 228         }
 229     }
 230 
 231     private static native Dimension getPosition(long theme, int part, int state,
 232                                                 int property);
 233 
 234     public static Dimension getPosition(String widget, int part, int state,
 235                                         int property) {
 236         readLock.lock();
 237         try {
 238             return getPosition(getTheme(widget), part,state,property);
 239         } finally {
 240             readLock.unlock();
 241         }
 242     }
 243 
 244     private static native Dimension getPartSize(long theme, int part,
 245                                                 int state);
 246 
 247     public static Dimension getPartSize(String widget, int part, int state) {
 248         readLock.lock();
 249         try {
 250             return getPartSize(getTheme(widget), part, state);
 251         } finally {
 252             readLock.unlock();
 253         }
 254     }
 255 
 256     private static native long openTheme(String widget);
 257 
 258     private static native void closeTheme(long theme);
 259 
 260     private static native void setWindowTheme(String subAppName);
 261 
 262     private static native long getThemeTransitionDuration(long theme, int part,
 263                                         int stateFrom, int stateTo, int propId);
 264 
 265     public static long getThemeTransitionDuration(String widget, int part,
 266                                        int stateFrom, int stateTo, int propId) {
 267         readLock.lock();
 268         try {
 269             return getThemeTransitionDuration(getTheme(widget),
 270                                               part, stateFrom, stateTo, propId);
 271         } finally {
 272             readLock.unlock();
 273         }
 274     }
 275 
 276     public static native boolean isGetThemeTransitionDurationDefined();
 277 
 278     private static native Insets getThemeBackgroundContentMargins(long theme,
 279                      int part, int state, int boundingWidth, int boundingHeight);
 280 
 281     public static Insets getThemeBackgroundContentMargins(String widget,
 282                     int part, int state, int boundingWidth, int boundingHeight) {
 283         readLock.lock();
 284         try {
 285             return getThemeBackgroundContentMargins(getTheme(widget),
 286                                     part, state, boundingWidth, boundingHeight);
 287         } finally {
 288             readLock.unlock();
 289         }
 290     }
 291 }