1 19 20 package org.netbeans.modules.editor; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.lang.reflect.Field ; 25 import java.util.ArrayList ; 26 import java.util.HashSet ; 27 import java.util.Hashtable ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.logging.Level ; 31 import java.util.logging.Logger ; 32 import javax.swing.JEditorPane ; 33 import javax.swing.SwingUtilities ; 34 import javax.swing.text.EditorKit ; 35 import javax.swing.text.html.HTMLEditorKit ; 36 import javax.swing.text.rtf.RTFEditorKit ; 37 import org.netbeans.api.editor.mimelookup.MimeLookup; 38 import org.netbeans.api.editor.mimelookup.MimePath; 39 import org.netbeans.editor.AnnotationType; 40 import org.netbeans.editor.AnnotationTypes; 41 import org.netbeans.editor.BaseKit; 42 import org.netbeans.editor.FindSupport; 43 import org.netbeans.editor.FindSupport.SearchPatternWrapper; 44 import org.netbeans.editor.LocaleSupport; 45 import org.netbeans.editor.Settings; 46 import org.netbeans.modules.editor.options.AllOptions; 47 import org.netbeans.modules.editor.options.AllOptionsFolder; 48 import org.netbeans.modules.editor.options.AnnotationTypesFolder; 49 import org.netbeans.modules.editor.options.BaseOptions; 50 import org.openide.cookies.EditorCookie; 51 import org.openide.modules.ModuleInstall; 52 import org.openide.nodes.Node; 53 import org.openide.text.CloneableEditor; 54 import org.openide.util.Lookup; 55 import org.openide.windows.TopComponent; 56 import org.openidex.search.SearchHistory; 57 import org.openidex.search.SearchPattern; 58 59 64 public class EditorModule extends ModuleInstall { 65 66 private static final Logger LOG = Logger.getLogger(EditorModule.class.getName()); 67 68 private static final boolean debug = Boolean.getBoolean("netbeans.debug.editor.kits"); 69 70 private PropertyChangeListener searchSelectedPatternListener; 71 private PropertyChangeListener editorHistoryChangeListener; 72 73 74 public void restored () { 75 LocaleSupport.addLocalizer(new NbLocalizer(AllOptions.class)); 76 LocaleSupport.addLocalizer(new NbLocalizer(BaseKit.class)); 77 78 AnnotationTypes.getTypes().registerLoader( new AnnotationTypes.Loader() { 80 public void loadTypes() { 81 AnnotationTypesFolder.getAnnotationTypesFolder(); 82 } 83 public void loadSettings() { 84 BaseOptions bo = (BaseOptions)BaseOptions.findObject(BaseOptions.class, true); 86 87 Integer i = (Integer )bo.getSettingValue(AnnotationTypes.PROP_BACKGROUND_GLYPH_ALPHA); 88 if (i != null) 89 AnnotationTypes.getTypes().setBackgroundGlyphAlpha(i.intValue()); 90 Boolean b = (Boolean )bo.getSettingValue(AnnotationTypes.PROP_BACKGROUND_DRAWING); 91 if (b != null) 92 AnnotationTypes.getTypes().setBackgroundDrawing(b); 93 b = (Boolean )bo.getSettingValue(AnnotationTypes.PROP_COMBINE_GLYPHS); 94 if (b != null) 95 AnnotationTypes.getTypes().setCombineGlyphs(b); 96 b = (Boolean )bo.getSettingValue(AnnotationTypes.PROP_GLYPHS_OVER_LINE_NUMBERS); 97 if (b != null) 98 AnnotationTypes.getTypes().setGlyphsOverLineNumbers(b); 99 b = (Boolean )bo.getSettingValue(AnnotationTypes.PROP_SHOW_GLYPH_GUTTER); 100 if (b != null) 101 AnnotationTypes.getTypes().setShowGlyphGutter(b); 102 } 103 public void saveType(AnnotationType type) { 104 AnnotationTypesFolder.getAnnotationTypesFolder().saveAnnotationType(type); 105 } 106 public void saveSetting(String settingName, Object value) { 107 BaseOptions bo = (BaseOptions)BaseOptions.findObject(BaseOptions.class, true); 109 bo.setSettingValue(settingName, value); 110 } 111 } ); 112 113 116 initAndCheckEditorKitTypeRegistry("text/plain", null); 118 initAndCheckEditorKitTypeRegistry("text/html", HTMLEditorKit .class.getName()); 119 initAndCheckEditorKitTypeRegistry("text/rtf", RTFEditorKit .class.getName()); 120 initAndCheckEditorKitTypeRegistry("application/rtf", RTFEditorKit .class.getName()); 121 122 try { 124 Field keyField = JEditorPane .class.getDeclaredField("kitRegistryKey"); keyField.setAccessible(true); 126 Object key = keyField.get(JEditorPane .class); 127 Hashtable kitMapping = (Hashtable )sun.awt.AppContext.getAppContext().get(key); 129 sun.awt.AppContext.getAppContext().put(key, new HackMap(kitMapping)); 130 } catch (Throwable t) { 131 t.printStackTrace(); 132 } 133 134 143 145 searchSelectedPatternListener = new PropertyChangeListener (){ 146 147 public void propertyChange(PropertyChangeEvent evt){ 148 if (evt == null){ 149 return; 150 } 151 152 FindSupport fs = FindSupport.getFindSupport(); 153 if (SearchHistory.LAST_SELECTED.equals(evt.getPropertyName())){ 154 SearchPattern sp = SearchHistory.getDefault().getLastSelected(); 156 if (sp==null){ 157 return; 158 } 159 160 FindSupport.SearchPatternWrapper spw = new FindSupport.SearchPatternWrapper(sp.getSearchExpression(), 161 sp.isWholeWords(), sp.isMatchCase(), sp.isRegExp()); 162 fs.setLastSelected(spw); 164 } else if (SearchHistory.ADD_TO_HISTORY.equals(evt.getPropertyName())){ 165 List searchPatterns = SearchHistory.getDefault().getSearchPatterns(); 166 167 List history = new ArrayList (); 168 for (int i = 0; i<searchPatterns.size(); i++){ 169 SearchPattern sptr = ((SearchPattern)searchPatterns.get(i)); 170 SearchPatternWrapper spwrap = new SearchPatternWrapper(sptr.getSearchExpression(), 171 sptr.isWholeWords(), sptr.isMatchCase(), sptr.isRegExp()); 172 history.add(spwrap); 173 } 174 175 fs.setHistory(history); 176 } 177 } 178 }; 179 180 editorHistoryChangeListener = new PropertyChangeListener (){ 181 public void propertyChange(PropertyChangeEvent evt){ 182 183 if (evt == null || !FindSupport.FIND_HISTORY_PROP.equals(evt.getPropertyName())){ 184 return; 185 } 186 187 190 SearchPatternWrapper spw = (SearchPatternWrapper)evt.getNewValue(); 191 SearchPattern spLast = SearchHistory.getDefault().getLastSelected(); 192 193 if (spw == null || spw.getSearchExpression()==null || "".equals(spw.getSearchExpression()) ){ return; 195 } 196 198 SearchPattern sp = SearchPattern.create(spw.getSearchExpression(), 199 spw.isWholeWords(), spw.isMatchCase(), spw.isRegExp()); 200 201 if (sp == null || (sp.equals(spLast))){ 202 return; 203 } 204 205 SearchHistory.getDefault().add(sp); 206 SearchHistory.getDefault().setLastSelected(sp); 207 } 208 }; 209 210 SearchHistory.getDefault().addPropertyChangeListener(searchSelectedPatternListener); 211 FindSupport.getFindSupport().addPropertyChangeListener(editorHistoryChangeListener); 212 213 230 232 233 } 234 235 236 public void uninstalled() { 237 238 AllOptionsFolder.unregisterModuleRegListener(); 239 240 245 246 try { 248 Field keyField = JEditorPane .class.getDeclaredField("kitRegistryKey"); keyField.setAccessible(true); 250 Object key = keyField.get(JEditorPane .class); 251 HackMap kitMapping = (HackMap)sun.awt.AppContext.getAppContext().get(key); 252 if (kitMapping.getOriginal() != null) { 253 sun.awt.AppContext.getAppContext().put(key, kitMapping.getOriginal()); 254 } else { 255 sun.awt.AppContext.getAppContext().remove(key); 256 } 257 258 } catch (Throwable t) { 259 t.printStackTrace(); 260 } 261 262 SwingUtilities.invokeLater(new Runnable () { 264 public void run() { 265 266 HashSet set = new HashSet (); 269 set.addAll(TopComponent.getRegistry().getOpened()); 270 271 for (Iterator it = set.iterator(); it.hasNext(); ) { 272 TopComponent topComp = (TopComponent)it.next(); 273 if (!(topComp instanceof CloneableEditor)) 275 continue; 276 Node[] arr = topComp.getActivatedNodes(); 277 if (arr == null) 278 continue; 279 for (int i=0; i<arr.length; i++) { 280 EditorCookie ec = (EditorCookie)arr[i].getCookie(EditorCookie.class); 281 if (ec == null) 282 continue; 283 JEditorPane [] pane = ec.getOpenedPanes(); 284 if (pane == null) 285 continue; 286 for (int j=0; j<pane.length; j++) { 287 if (pane[j].getEditorKit() instanceof BaseKit) { 288 topComp.close(); 289 } 290 } 291 } 292 } 293 294 } 295 }); 296 } 297 298 299 private static class HackMap extends Hashtable { 300 301 private Hashtable delegate; 302 303 HackMap(Hashtable h) { 304 delegate = h; 305 306 if (debug) { 307 LOG.log(Level.INFO, "Original kit mappings: " + h); 309 try { 310 Field keyField = JEditorPane .class.getDeclaredField("kitTypeRegistryKey"); keyField.setAccessible(true); 312 Object key = keyField.get(JEditorPane .class); 313 Hashtable kitTypeMapping = (Hashtable )sun.awt.AppContext.getAppContext().get(key); 314 if (kitTypeMapping != null) { 315 sun.awt.AppContext.getAppContext().put(key, new DebugHashtable(kitTypeMapping)); 316 } 317 } catch (Throwable t) { 318 t.printStackTrace(); 319 } 320 } 321 } 322 323 private String getKitClassName(String type) { 324 try { 325 Field keyField = JEditorPane .class.getDeclaredField("kitTypeRegistryKey"); keyField.setAccessible(true); 327 Object key = keyField.get(JEditorPane .class); 328 Hashtable kitTypeMapping = (Hashtable )sun.awt.AppContext.getAppContext().get(key); 329 if (kitTypeMapping != null) { 330 return (String )kitTypeMapping.get(type); 331 } 332 } catch (Throwable t) { 333 t.printStackTrace(); 334 } 335 336 return null; 337 } 338 339 public Object get(Object key) { 340 synchronized (Settings.class) { 341 if (debug) LOG.log(Level.INFO, "HackMap.get key=" + key); 343 Object retVal = null; 344 345 if (delegate != null) { 346 retVal = delegate.get(key); 347 if (debug && retVal != null) { 348 LOG.log(Level.INFO, "Found cached instance kit=" + retVal + " for mimeType=" + key); } 350 } 351 352 if (key instanceof String ) { 353 String mimeType = (String ) key; 354 if (retVal == null || shouldUseNbKit(retVal.getClass().getName(), mimeType)) { 355 String kitClassName = getKitClassName(mimeType); 357 if (debug) { 358 LOG.log(Level.INFO, "Found kitClassName=" + kitClassName + " for mimeType=" + mimeType); } 360 361 if (kitClassName == null || shouldUseNbKit(kitClassName, mimeType)) { 362 Object kit = findKit(mimeType); 363 if (kit != null) { 364 retVal = kit; 365 if (debug) { 366 LOG.log(Level.INFO, "Found kit=" + retVal + " in xml layers for mimeType=" + mimeType); } 368 } 369 } 370 } 371 } 372 373 return retVal; 374 } } 376 377 public Object put(Object key, Object value) { 378 synchronized (Settings.class) { 379 if (debug) LOG.log(Level.INFO, "HackMap.put key=" + key + " value=" + value); 381 if (delegate == null) { 382 delegate = new Hashtable (); 383 } 384 385 Object ret = delegate.put(key,value); 386 387 if (debug) { 388 LOG.log(Level.INFO, "registering mimeType=" + key + " -> kitInstance=" + value + " original was " + ret); } 392 393 return ret; 394 } } 396 397 public Object remove(Object key) { 398 synchronized (Settings.class) { 399 if (debug) LOG.log(Level.INFO, "HackMap.remove key=" + key); 401 Object ret = (delegate != null) ? delegate.remove(key) : null; 402 403 if (debug) { 404 LOG.log(Level.INFO, "removing kitInstance=" + ret + " for mimeType=" + key); } 407 408 return ret; 409 } } 411 412 Hashtable getOriginal() { 413 return delegate; 414 } 415 416 private boolean shouldUseNbKit(String kitClass, String mimeType) { 417 if (mimeType.startsWith("text/html") || mimeType.startsWith("text/rtf") || mimeType.startsWith("application/rtf")) { 421 return false; 422 } else { 423 return kitClass.startsWith("javax.swing."); } 425 } 426 427 private EditorKit findKit(String mimeType) { 430 Lookup lookup = MimeLookup.getLookup(MimePath.parse(mimeType)); 431 EditorKit kit = (EditorKit ) lookup.lookup(EditorKit .class); 432 return kit == null ? null : (EditorKit ) kit.clone(); 433 } 434 } 435 436 private static final class DebugHashtable extends Hashtable { 437 438 DebugHashtable(Hashtable h) { 439 if (h != null) { 440 putAll(h); 441 LOG.log(Level.INFO, "Existing kit classNames mappings: " + this); } 443 } 444 445 public Object put(Object key, Object value) { 446 Object ret = super.put(key, value); 447 LOG.log(Level.INFO, "registering mimeType=" + key + " -> kitClassName=" + value + " original was " + ret); return ret; 451 } 452 453 public Object remove(Object key) { 454 Object ret = super.remove(key); 455 LOG.log(Level.INFO, "removing kitClassName=" + ret + " for mimeType=" + key); return ret; 458 } 459 460 } 461 462 private void initAndCheckEditorKitTypeRegistry(String mimeType, String expectedKitClass) { 463 String kitClass = JEditorPane.getEditorKitClassNameForContentType(mimeType); 464 if (kitClass == null) { 465 LOG.log(Level.WARNING, "Can't find JDK editor kit class for " + mimeType); } else if (expectedKitClass != null && !expectedKitClass.equals(kitClass)) { 467 LOG.log(Level.WARNING, "Wrong JDK editor kit class for " + mimeType + ". Expecting: " + expectedKitClass + ", but was: " + kitClass); } 471 } 472 } 473 | Popular Tags |