1 19 20 package org.netbeans.swing.plaf.gtk; 21 22 import javax.swing.*; 23 import java.awt.*; 24 import java.beans.PropertyChangeEvent ; 25 import java.beans.PropertyChangeListener ; 26 import java.lang.reflect.Constructor ; 27 import java.lang.reflect.Field ; 28 import java.lang.reflect.Method ; 29 import java.util.HashSet ; 30 import java.util.Iterator ; 31 32 37 final class ThemeValue implements UIDefaults.ActiveValue { 38 private final Object fallback; 39 private final Object aRegion; 40 private Object aColorType = null; 41 private boolean darken = false; 42 43 private Object value = null; 44 45 private static Boolean functioning = null; 46 47 48 public ThemeValue(Object region, Object colorType, Object fallback) { 49 this.fallback = fallback; 50 this.aRegion = region; 51 this.aColorType = colorType; 52 register(this); 53 } 54 55 56 public ThemeValue(Object region, Object colorType, Object fallback, boolean darken) { 57 this.fallback = fallback; 58 this.aRegion = region; 59 this.aColorType = colorType; 60 this.darken = darken; 61 register(this); 62 } 63 64 public ThemeValue (Object region, Font fallback) { 65 this.fallback = fallback; 66 this.aRegion = region; 67 register(this); 68 } 69 70 public Object createValue(UIDefaults table) { 71 if (value == null) { 72 if (!functioning()) { 73 value = fallback; 74 } else { 75 if (fallback instanceof Font) { 76 Object val = getFont(); 77 if (ct++ < 4) { 78 return val; 80 } 81 value = val; 82 } else { 83 value = getColor(); 84 } 85 } 86 } 87 return value != null ? value : fallback; 88 } 89 90 private int ct = 0; 91 92 void clear() { 93 value = null; 94 } 95 96 public Font getFont() { 97 Object style = getSynthStyle (aRegion); 98 if (Boolean.TRUE.equals(functioning)) { 99 try { 100 Font result = (Font) synthStyle_getFontForState.invoke (style, 101 new Object [] { 102 getSynthContext () 103 }); 104 if (result == null) { 105 result = (Font) fallback; 106 } 107 return result; 108 } catch (Exception e) { 109 functioning = Boolean.FALSE; 110 if (log) { 111 e.printStackTrace(); 112 } 113 } 114 } 115 return null; 117 } 118 119 private static boolean log = Boolean.getBoolean ("themeValue.log"); 120 121 public Color getColor () { 122 Object style = getSynthStyle (aRegion); 123 if (Boolean.TRUE.equals(functioning)) { 124 try { 125 Color result = (Color) synthStyle_getColorForState.invoke (style, 126 new Object [] { 127 getSynthContext (), 128 aColorType 129 }); 130 if (result == null) { 131 result = (Color) fallback; 132 } 133 if (darken) { 134 result = result.darker(); 135 } 136 return result; 137 } catch (Exception e) { 138 functioning = Boolean.FALSE; 139 if (log) { 140 e.printStackTrace(); 141 } 142 } 143 } 144 return null; 146 } 147 148 public static boolean functioning() { 149 if (functioning == null) { 150 checkFunctioning(); 151 } 152 return functioning.booleanValue(); 153 } 154 155 private static void checkFunctioning() { 156 functioning = Boolean.FALSE; 157 try { 158 gtkLookAndFeel = Class.forName ("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); synthLookAndFeel = Class.forName ("javax.swing.plaf.synth.SynthLookAndFeel"); region = Class.forName ("javax.swing.plaf.synth.Region"); synthStyle = Class.forName ("javax.swing.plaf.synth.SynthStyle"); synthContext = Class.forName ("javax.swing.plaf.synth.SynthContext"); colorType = Class.forName ("javax.swing.plaf.synth.ColorType"); gtkColorType = Class.forName ("com.sun.java.swing.plaf.gtk.GTKColorType"); synthUI = Class.forName ("sun.swing.plaf.synth.SynthUI"); 167 168 synthContextConstructor = synthContext.getDeclaredConstructor( 169 JComponent.class, 170 region, synthStyle, 171 Integer.TYPE 172 ); 173 synthContextConstructor.setAccessible(true); 174 175 synthStyle_getColorForState = synthStyle.getDeclaredMethod ("getColorForState", synthContext, colorType ); 177 178 synthStyle_getColorForState.setAccessible(true); 179 180 synthStyle_getFontForState = synthStyle.getDeclaredMethod ("getFontForState", synthContext ); 182 183 synthStyle_getFontForState.setAccessible(true); 184 185 186 LIGHT = valueOfField (gtkColorType, "LIGHT"); DARK = valueOfField (gtkColorType, "DARK"); MID = valueOfField (gtkColorType, "MID"); BLACK = valueOfField (gtkColorType, "BLACK"); WHITE = valueOfField (gtkColorType, "WHITE"); TEXT_FOREGROUND = valueOfField (colorType, "TEXT_FOREGROUND"); TEXT_BACKGROUND = valueOfField (colorType, "TEXT_BACKGROUND"); FOCUS = valueOfField (colorType, "FOCUS"); 195 synthContext_getContext = synthContext.getDeclaredMethod ("getContext", 196 new Class [] { 197 Class .class, JComponent.class, region, synthStyle, Integer.TYPE 198 }); 199 synthContext_getContext.setAccessible(true); 200 201 synthLookAndFeel_getStyle = synthLookAndFeel.getDeclaredMethod ("getStyle", 202 JComponent.class, region 203 ); 204 synthLookAndFeel_getStyle.setAccessible (true); 205 206 REGION_BUTTON = valueOfField (region, "BUTTON"); REGION_PANEL = valueOfField (region, "PANEL"); REGION_SCROLLBAR_THUMB = valueOfField (region, "SCROLL_BAR_THUMB"); REGION_TAB = valueOfField (region, "TABBED_PANE_TAB"); REGION_INTFRAME = valueOfField (region, "INTERNAL_FRAME_TITLE_PANE"); 212 synthUI_getContext = synthUI.getDeclaredMethod ("getContext", JComponent.class ); 214 functioning = Boolean.TRUE; 215 } catch (Exception e) { 216 System.err.println ("Cannot initialize GTK colors - using hardcoded defaults " + e.getMessage()); if (log) { 218 e.printStackTrace(); 219 } 220 return; 221 } 222 } 223 224 private static JButton getDummyButton() { 225 if (dummyButton == null) { 226 dummyButton = new JButton(); 227 CellRendererPane crp = new CellRendererPane(); 228 crp.add (dummyButton); 229 } 230 ButtonModel mdl = dummyButton.getModel(); 231 return dummyButton; 232 } 233 234 private static JButton dummyButton = null; 235 236 private static Object getSynthContext () { 237 try { 238 JButton dummyButton = getDummyButton(); 239 240 if (synthUI.isAssignableFrom(dummyButton.getUI().getClass())) { 241 return synthUI_getContext.invoke (dummyButton.getUI(), new Object [] {dummyButton}); 242 } else { 243 throw new IllegalStateException ("I don't have a SynthButtonUI to play with"); } 245 } catch (Exception e) { 246 functioning = Boolean.FALSE; 247 if (log) { 248 e.printStackTrace(); 249 } 250 return null; 251 } 252 } 253 254 private static Object getSynthStyle (Object region) { 255 try { 256 return synthLookAndFeel_getStyle.invoke (null, new Object [] { getDummyButton(), region} ); 257 } catch (Exception e) { 258 functioning = Boolean.FALSE; 259 if (log) { 260 e.printStackTrace(); 261 } 262 return null; 263 } 264 } 265 266 private static Object valueOfField (Class clazz, String field) throws NoSuchFieldException , IllegalAccessException { 267 Field f = clazz.getDeclaredField(field); 268 f.setAccessible(true); 269 return f.get(null); 270 } 271 272 private static Class <?> synthLookAndFeel = null; 273 private static Class <?> gtkLookAndFeel = null; 274 private static Class <?> colorType = null; 275 private static Class <?> region = null; 276 private static Class <?> synthStyle = null; 277 private static Class <?> synthContext = null; 278 private static Class <?> gtkColorType = null; 279 private static Class <?> synthUI = null; 280 281 private static Constructor synthContextConstructor; 282 private static Method synthStyle_getColorForState = null; 283 private static Method synthStyle_getFontForState = null; 284 private static Method synthLookAndFeel_getStyle = null; 285 286 private static Method synthContext_getContext = null; 287 private static Method synthUI_getContext = null; 288 289 static Object REGION_BUTTON = null; 291 static Object REGION_PANEL = null; 292 static Object REGION_SCROLLBAR_THUMB = null; 293 static Object REGION_TAB = null; 294 static Object REGION_INTFRAME = null; 295 296 static Object LIGHT = null; 297 static Object DARK = null; 298 static Object BLACK = null; 299 static Object WHITE = null; 300 static Object MID = null; 301 static Object TEXT_FOREGROUND = null; 302 static Object TEXT_BACKGROUND = null; 303 static Object FOCUS = null; 304 305 306 private static HashSet <ThemeValue> instances = null; 307 310 private static synchronized void register (ThemeValue value) { 311 if (instances == null) { 312 instances = new HashSet <ThemeValue>(); 313 registerPcl(); 314 } 315 instances.add (value); 316 } 317 318 private static void registerPcl() { 319 PropertyChangeListener l = new Listener (); 320 UIManager.addPropertyChangeListener(l); 321 322 325 Toolkit.getDefaultToolkit().addPropertyChangeListener( 326 "gnome.Gtk/FontName", l); Toolkit.getDefaultToolkit().addPropertyChangeListener( 328 "gnome.Xft/DPI", l); Toolkit.getDefaultToolkit().addPropertyChangeListener( 330 "gnome.Net/ThemeName", l); 332 } 333 334 private static class Listener implements PropertyChangeListener { 335 public void propertyChange (PropertyChangeEvent pce) { 336 if (pce.getSource() instanceof UIManager && "lookAndFeel".equals( pce.getPropertyName())) { 338 339 String s = UIManager.getLookAndFeel().getClass().getName(); 340 if (s.indexOf("gtk") < 0) { UIManager.removePropertyChangeListener(this); 343 Toolkit.getDefaultToolkit().removePropertyChangeListener( 344 "gnome.Gtk/FontName", this); Toolkit.getDefaultToolkit().removePropertyChangeListener( 346 "gnome.Xft/DPI", this); Toolkit.getDefaultToolkit().removePropertyChangeListener( 348 "gnome.Net/ThemeName", this); } 350 } else { 351 for (ThemeValue tv: instances) { 352 tv.clear(); 353 } 354 } 355 } 356 } 357 358 static { 359 functioning(); 363 } 364 } 365 | Popular Tags |