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 private static volatile boolean valid = false; 64 65 static volatile boolean xpStyleEnabled; 66 67 static void flush() { 68 // Could be called on Toolkit thread, so do not try to acquire locks 69 // to avoid deadlock with theme initialization 70 valid = false; 71 } 72 73 public static native boolean isThemed(); 74 75 public static boolean isXPStyleEnabled() { 76 return xpStyleEnabled; 77 } 78 79 // this should be called only with writeLock held 80 private static Long getThemeImpl(String widget) { 81 Long theme = widgetToTheme.get(widget); 82 if (theme == null) { 83 int i = widget.indexOf("::"); 84 if (i > 0) { 85 // We're using the syntax "subAppName::controlName" here, as used by msstyles. 86 // See documentation for SetWindowTheme on MSDN. 87 setWindowTheme(widget.substring(0, i)); 88 theme = openTheme(widget.substring(i+2)); 89 setWindowTheme(null); 90 } else { 91 theme = openTheme(widget); 92 } 93 widgetToTheme.put(widget, theme); 94 } 95 return theme; 96 } 97 98 // returns theme value 99 // this method should be invoked with readLock locked 100 private static Long getTheme(String widget) { 101 if (!valid) { 102 readLock.unlock(); 103 writeLock.lock(); 104 try { 105 if (!valid) { 106 // Close old themes. 107 for (Long value : widgetToTheme.values()) { 108 closeTheme(value); 109 } 110 widgetToTheme.clear(); 111 valid = true; 112 } 113 } finally { 114 readLock.lock(); 115 writeLock.unlock(); 116 } 117 } 118 119 // mostly copied from the javadoc for ReentrantReadWriteLock 120 Long theme = widgetToTheme.get(widget); 121 if (theme == null) { 122 readLock.unlock(); 123 writeLock.lock(); 124 try { 125 theme = getThemeImpl(widget); 126 } finally { 127 readLock.lock(); 128 writeLock.unlock();// Unlock write, still hold read 129 } 130 } 131 return theme; 132 } 133 134 private static native void paintBackground(int[] buffer, long theme, 135 int part, int state, int x, 136 int y, int w, int h, int stride); 137 138 public static void paintBackground(int[] buffer, String widget, 139 int part, int state, int x, int y, int w, int h, int stride) { 140 readLock.lock(); 141 try { 142 paintBackground(buffer, getTheme(widget), part, state, x, y, w, h, stride); 143 } finally { 144 readLock.unlock(); 145 } 146 } 147 148 private static native Insets getThemeMargins(long theme, int part, 149 int state, int marginType); 150 151 public static Insets getThemeMargins(String widget, int part, int state, int marginType) { 152 readLock.lock(); 153 try { 154 return getThemeMargins(getTheme(widget), part, state, marginType); 155 } finally { 156 readLock.unlock(); 157 } 158 } 159 160 private static native boolean isThemePartDefined(long theme, int part, int state); 161 162 public static boolean isThemePartDefined(String widget, int part, int state) { 163 readLock.lock(); 164 try { 165 return isThemePartDefined(getTheme(widget), part, state); 166 } finally { 167 readLock.unlock(); 168 } 169 } 170 171 private static native Color getColor(long theme, int part, int state, 172 int property); 173 174 public static Color getColor(String widget, int part, int state, int property) { 175 readLock.lock(); 176 try { 177 return getColor(getTheme(widget), part, state, property); 178 } finally { 179 readLock.unlock(); 180 } 181 } 182 183 private static native int getInt(long theme, int part, int state, 184 int property); 185 186 public static int getInt(String widget, int part, int state, int property) { 187 readLock.lock(); 188 try { 189 return getInt(getTheme(widget), part, state, property); 190 } finally { 191 readLock.unlock(); 192 } 193 } 194 195 private static native int getEnum(long theme, int part, int state, 196 int property); 197 198 public static int getEnum(String widget, int part, int state, int property) { 199 readLock.lock(); 200 try { 201 return getEnum(getTheme(widget), part, state, property); 202 } finally { 203 readLock.unlock(); 204 } 205 } 206 207 private static native boolean getBoolean(long theme, int part, int state, 208 int property); 209 210 public static boolean getBoolean(String widget, int part, int state, 211 int property) { 212 readLock.lock(); 213 try { 214 return getBoolean(getTheme(widget), part, state, property); 215 } finally { 216 readLock.unlock(); 217 } 218 } 219 220 private static native boolean getSysBoolean(long theme, int property); 221 222 public static boolean getSysBoolean(String widget, int property) { 223 readLock.lock(); 224 try { 225 return getSysBoolean(getTheme(widget), property); 226 } finally { 227 readLock.unlock(); 228 } 229 } 230 231 private static native Point getPoint(long theme, int part, int state, 232 int property); 233 234 public static Point getPoint(String widget, int part, int state, int property) { 235 readLock.lock(); 236 try { 237 return getPoint(getTheme(widget), part, state, property); 238 } finally { 239 readLock.unlock(); 240 } 241 } 242 243 private static native Dimension getPosition(long theme, int part, int state, 244 int property); 245 246 public static Dimension getPosition(String widget, int part, int state, 247 int property) { 248 readLock.lock(); 249 try { 250 return getPosition(getTheme(widget), part,state,property); 251 } finally { 252 readLock.unlock(); 253 } 254 } 255 256 private static native Dimension getPartSize(long theme, int part, 257 int state); 258 259 public static Dimension getPartSize(String widget, int part, int state) { 260 readLock.lock(); 261 try { 262 return getPartSize(getTheme(widget), part, state); 263 } finally { 264 readLock.unlock(); 265 } 266 } 267 268 private static native long openTheme(String widget); 269 270 private static native void closeTheme(long theme); 271 272 private static native void setWindowTheme(String subAppName); 273 274 private static native long getThemeTransitionDuration(long theme, int part, 275 int stateFrom, int stateTo, int propId); 276 277 public static long getThemeTransitionDuration(String widget, int part, 278 int stateFrom, int stateTo, int propId) { 279 readLock.lock(); 280 try { 281 return getThemeTransitionDuration(getTheme(widget), 282 part, stateFrom, stateTo, propId); 283 } finally { 284 readLock.unlock(); 285 } 286 } 287 288 public static native boolean isGetThemeTransitionDurationDefined(); 289 290 private static native Insets getThemeBackgroundContentMargins(long theme, 291 int part, int state, int boundingWidth, int boundingHeight); 292 293 public static Insets getThemeBackgroundContentMargins(String widget, 294 int part, int state, int boundingWidth, int boundingHeight) { 295 readLock.lock(); 296 try { 297 return getThemeBackgroundContentMargins(getTheme(widget), 298 part, state, boundingWidth, boundingHeight); 299 } finally { 300 readLock.unlock(); 301 } 302 } 303 }