1 19 20 package org.netbeans.modules.editor.settings.storage; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.lang.ref.WeakReference ; 25 import java.lang.reflect.Method ; 26 import java.util.ArrayList ; 27 import java.util.Arrays ; 28 import java.util.List ; 29 import java.util.Map ; 30 import java.util.WeakHashMap ; 31 import java.util.logging.Level ; 32 import java.util.logging.Logger ; 33 import org.netbeans.api.editor.mimelookup.MimeLookup; 34 import org.netbeans.api.editor.mimelookup.MimePath; 35 import org.netbeans.api.editor.settings.FontColorSettings; 36 import org.netbeans.api.editor.settings.KeyBindingSettings; 37 import org.netbeans.modules.editor.settings.storage.api.EditorSettings; 38 import org.netbeans.spi.editor.mimelookup.MimeDataProvider; 39 import org.openide.util.Lookup; 40 import org.openide.util.WeakListeners; 41 import org.openide.util.lookup.AbstractLookup; 42 import org.openide.util.lookup.InstanceContent; 43 import org.openide.util.lookup.Lookups; 44 import org.openide.util.lookup.ProxyLookup; 45 46 50 public final class SettingsProvider implements MimeDataProvider { 51 52 private static final Logger LOG = Logger.getLogger(SettingsProvider.class.getName()); 53 54 private final Map <MimePath, WeakReference <Lookup>> cache = new WeakHashMap <MimePath, WeakReference <Lookup>>(); 55 56 public SettingsProvider () { 57 } 58 59 65 public Lookup getLookup(MimePath mimePath) { 66 synchronized (cache) { 67 WeakReference <Lookup> ref = cache.get(mimePath); 68 Lookup lookup = ref == null ? null : ref.get(); 69 70 if (lookup == null) { 71 String path = mimePath.getPath(); 72 if (path.startsWith("test")) { int idx = path.indexOf('_'); if (idx == -1) { 75 throw new IllegalStateException ("Invalid mimePath: " + path); } 77 78 String profile = path.substring(0, idx); 80 MimePath realMimePath = MimePath.parse(path.substring(idx + 1)); 81 82 lookup = new ProxyLookup(new Lookup [] { 83 new MyLookup(realMimePath, profile), 84 Lookups.exclude( 85 MimeLookup.getLookup(realMimePath), 86 new Class [] { 87 FontColorSettings.class, 88 KeyBindingSettings.class 89 }) 90 }); 91 } else { 92 lookup = new MyLookup(mimePath, null); 93 } 94 95 cache.put(mimePath, new WeakReference <Lookup>(lookup)); 96 } 97 98 return lookup; 99 } 100 } 101 102 private static final class MyLookup extends AbstractLookup implements PropertyChangeListener { 103 104 private final MimePath mimePath; 105 private final MimePath [] allMimePaths; 106 private final boolean specialFcsProfile; 107 private String fcsProfile; 108 109 private final InstanceContent ic; 110 private Object fontColorSettings = null; 111 private Object keyBindingSettings = null; 112 113 private KeyBindingSettingsImpl kbsi; 114 115 public MyLookup(MimePath mimePath, String profile) { 116 this(mimePath, profile, new InstanceContent()); 117 } 118 119 private MyLookup(MimePath mimePath, String profile, InstanceContent ic) { 120 super(ic); 121 122 this.mimePath = mimePath; 123 this.allMimePaths = computeInheritedMimePaths(mimePath); 124 125 if (profile == null) { 126 String currentProfile = EditorSettings.getDefault().getCurrentFontColorProfile(); 128 this.fcsProfile = EditorSettingsImpl.getInstance().getInternalFontColorProfile(currentProfile); 129 this.specialFcsProfile = false; 130 } else { 131 this.fcsProfile = profile; 134 this.specialFcsProfile = true; 135 } 136 137 this.ic = ic; 138 139 EditorSettings es = EditorSettings.getDefault(); 141 es.addPropertyChangeListener(WeakListeners.propertyChange(this, es)); 142 143 this.kbsi = KeyBindingSettingsImpl.get(mimePath); 144 this.kbsi.addPropertyChangeListener(WeakListeners.propertyChange(this, this.kbsi)); 145 } 146 147 protected void initialize() { 148 synchronized (this) { 149 fontColorSettings = new CompositeFCS(allMimePaths, fcsProfile); 150 keyBindingSettings = this.kbsi.createInstanceForLookup(); 151 152 ic.set(Arrays.asList(new Object [] { 153 fontColorSettings, 154 keyBindingSettings 155 }), null); 156 } 157 } 158 159 public void propertyChange(PropertyChangeEvent evt) { 160 synchronized (this) { 161 boolean fcsChanged = false; 162 boolean kbsChanged = false; 163 164 168 if (this.kbsi == evt.getSource()) { 170 kbsChanged = true; 171 172 } else if (evt.getPropertyName() == null) { 173 if (!specialFcsProfile) { 175 String currentProfile = EditorSettings.getDefault().getCurrentFontColorProfile(); 176 fcsProfile = EditorSettingsImpl.getInstance().getInternalFontColorProfile(currentProfile); 177 } 178 fcsChanged = true; 179 180 } else if (evt.getPropertyName().equals(EditorSettingsImpl.PROP_HIGHLIGHT_COLORINGS)) { 181 String changedProfile = (String ) evt.getNewValue(); 182 if (changedProfile.equals(fcsProfile)) { 183 fcsChanged = true; 184 } 185 186 } else if (evt.getPropertyName().equals(EditorSettingsImpl.PROP_TOKEN_COLORINGS)) { 187 String changedProfile = (String ) evt.getNewValue(); 188 if (changedProfile.equals(fcsProfile)) { 189 MimePath changedMimePath = (MimePath) evt.getOldValue(); 190 if (isDerivedFromMimePath(changedMimePath)) { 191 fcsChanged = true; 192 } 193 } 194 195 } else if (evt.getPropertyName().equals(EditorSettingsImpl.PROP_CURRENT_FONT_COLOR_PROFILE)) { 196 if (!specialFcsProfile) { 197 String newProfile = (String ) evt.getNewValue(); 198 fcsProfile = EditorSettingsImpl.getInstance().getInternalFontColorProfile(newProfile); 199 fcsChanged = true; 200 } 201 } 202 203 boolean updateContents = false; 205 206 if (fcsChanged && fontColorSettings != null) { 207 fontColorSettings = new CompositeFCS(allMimePaths, fcsProfile); 208 updateContents = true; 209 } 210 211 if (kbsChanged && keyBindingSettings != null) { 212 keyBindingSettings = this.kbsi.createInstanceForLookup(); 213 updateContents = true; 214 } 215 216 if (updateContents) { 217 ic.set(Arrays.asList(new Object [] { 218 fontColorSettings, 219 keyBindingSettings 220 }), null); 221 } 222 } 223 } 224 225 private boolean isDerivedFromMimePath(MimePath mimePath) { 226 for(MimePath mp : allMimePaths) { 227 if (mp == mimePath) { 228 return true; 229 } 230 } 231 return false; 232 } 233 234 private static MimePath [] computeInheritedMimePaths(MimePath mimePath) { 235 List <String > paths = callSwitchLookupComputePaths(mimePath); 236 237 if (paths != null) { 238 ArrayList <MimePath> mimePaths = new ArrayList <MimePath>(paths.size()); 239 240 for (String path : paths) { 241 mimePaths.add(MimePath.parse(path)); 242 } 243 244 return mimePaths.toArray(new MimePath[mimePaths.size()]); 245 } else { 246 return new MimePath [] { mimePath, MimePath.EMPTY }; 247 } 248 } 249 250 @SuppressWarnings ("unchecked") 251 private static List <String > callSwitchLookupComputePaths(MimePath mimePath) { 252 try { 253 ClassLoader classLoader = Lookup.getDefault().lookup(ClassLoader .class); 254 Class clazz = classLoader.loadClass("org.netbeans.modules.editor.mimelookup.impl.SwitchLookup"); Method method = clazz.getDeclaredMethod("computePaths", MimePath.class, String .class, String .class); method.setAccessible(true); 257 List <String > paths = (List <String >) method.invoke(null, mimePath, null, null); 258 return paths; 259 } catch (Exception e) { 260 LOG.log(Level.WARNING, "Can't call org.netbeans.modules.editor.mimelookup.impl.SwitchLookup.computePath(MimeLookup, String, String).", e); return null; 262 } 263 } 264 } } 266 | Popular Tags |