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