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 void flush() { 65 writeLock.lock(); 66 try { 67 // Close old themes. 68 for (Long value : widgetToTheme.values()) { 69 closeTheme(value.longValue()); 70 } 71 widgetToTheme.clear(); 72 } finally { 73 writeLock.unlock(); 74 } 75 } 76 77 public static native boolean isThemed(); 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 // mostly copied from the javadoc for ReentrantReadWriteLock 102 Long theme = widgetToTheme.get(widget); 103 if (theme == null) { 104 readLock.unlock(); 105 writeLock.lock(); 106 try { 107 theme = getThemeImpl(widget); 108 } finally { 109 readLock.lock(); 110 writeLock.unlock();// Unlock write, still hold read 111 } 112 } 113 return theme; 114 } 115 116 private static native void paintBackground(int[] buffer, long theme, 117 int part, int state, int x, 118 int y, int w, int h, int stride); 119 120 public static void paintBackground(int[] buffer, String widget, 121 int part, int state, int x, int y, int w, int h, int stride) { 122 readLock.lock(); 123 try { 124 paintBackground(buffer, getTheme(widget), part, state, x, y, w, h, stride); 125 } finally { 126 readLock.unlock(); 127 } 128 } 129 130 private static native Insets getThemeMargins(long theme, int part, 131 int state, int marginType); 132 133 public static Insets getThemeMargins(String widget, int part, int state, int marginType) { 134 readLock.lock(); 135 try { 136 return getThemeMargins(getTheme(widget), part, state, marginType); 137 } finally { 138 readLock.unlock(); 139 } 140 } 141 142 private static native boolean isThemePartDefined(long theme, int part, int state); 143 144 public static boolean isThemePartDefined(String widget, int part, int state) { 145 readLock.lock(); 146 try { 147 return isThemePartDefined(getTheme(widget), part, state); 148 } finally { 149 readLock.unlock(); 150 } 151 } 152 153 private static native Color getColor(long theme, int part, int state, 154 int property); 155 156 public static Color getColor(String widget, int part, int state, int property) { 157 readLock.lock(); 158 try { 159 return getColor(getTheme(widget), part, state, property); 160 } finally { 161 readLock.unlock(); 162 } 163 } 164 165 private static native int getInt(long theme, int part, int state, 166 int property); 167 168 public static int getInt(String widget, int part, int state, int property) { 169 readLock.lock(); 170 try { 171 return getInt(getTheme(widget), part, state, property); 172 } finally { 173 readLock.unlock(); 174 } 175 } 176 177 private static native int getEnum(long theme, int part, int state, 178 int property); 179 180 public static int getEnum(String widget, int part, int state, int property) { 181 readLock.lock(); 182 try { 183 return getEnum(getTheme(widget), part, state, property); 184 } finally { 185 readLock.unlock(); 186 } 187 } 188 189 private static native boolean getBoolean(long theme, int part, int state, 190 int property); 191 192 public static boolean getBoolean(String widget, int part, int state, 193 int property) { 194 readLock.lock(); 195 try { 196 return getBoolean(getTheme(widget), part, state, property); 197 } finally { 198 readLock.unlock(); 199 } 200 } 201 202 private static native boolean getSysBoolean(long theme, int property); 203 204 public static boolean getSysBoolean(String widget, int property) { 205 readLock.lock(); 206 try { 207 return getSysBoolean(getTheme(widget), property); 208 } finally { 209 readLock.unlock(); 210 } 211 } 212 213 private static native Point getPoint(long theme, int part, int state, 214 int property); 215 216 public static Point getPoint(String widget, int part, int state, int property) { 217 readLock.lock(); 218 try { 219 return getPoint(getTheme(widget), part, state, property); 220 } finally { 221 readLock.unlock(); 222 } 223 } 224 225 private static native Dimension getPosition(long theme, int part, int state, 226 int property); 227 228 public static Dimension getPosition(String widget, int part, int state, 229 int property) { 230 readLock.lock(); 231 try { 232 return getPosition(getTheme(widget), part,state,property); 233 } finally { 234 readLock.unlock(); 235 } 236 } 237 238 private static native Dimension getPartSize(long theme, int part, 239 int state); 240 241 public static Dimension getPartSize(String widget, int part, int state) { 242 readLock.lock(); 243 try { 244 return getPartSize(getTheme(widget), part, state); 245 } finally { 246 readLock.unlock(); 247 } 248 } 249 250 private static native long openTheme(String widget); 251 252 private static native void closeTheme(long theme); 253 254 private static native void setWindowTheme(String subAppName); 255 256 private static native long getThemeTransitionDuration(long theme, int part, 257 int stateFrom, int stateTo, int propId); 258 259 public static long getThemeTransitionDuration(String widget, int part, 260 int stateFrom, int stateTo, int propId) { 261 readLock.lock(); 262 try { 263 return getThemeTransitionDuration(getTheme(widget), 264 part, stateFrom, stateTo, propId); 265 } finally { 266 readLock.unlock(); 267 } 268 } 269 270 public static native boolean isGetThemeTransitionDurationDefined(); 271 272 private static native Insets getThemeBackgroundContentMargins(long theme, 273 int part, int state, int boundingWidth, int boundingHeight); 274 275 public static Insets getThemeBackgroundContentMargins(String widget, 276 int part, int state, int boundingWidth, int boundingHeight) { 277 readLock.lock(); 278 try { 279 return getThemeBackgroundContentMargins(getTheme(widget), 280 part, state, boundingWidth, boundingHeight); 281 } finally { 282 readLock.unlock(); 283 } 284 } 285 }