1 19 20 package org.netbeans.modules.editor.impl.highlighting; 21 22 import java.util.Collection ; 23 import java.util.ConcurrentModificationException ; 24 import java.util.NoSuchElementException ; 25 import java.util.logging.Level ; 26 import java.util.logging.Logger ; 27 import javax.swing.text.AttributeSet ; 28 import javax.swing.text.Document ; 29 import javax.swing.text.SimpleAttributeSet ; 30 import org.netbeans.api.editor.mimelookup.MimeLookup; 31 import org.netbeans.api.editor.mimelookup.MimePath; 32 import org.netbeans.api.editor.settings.AttributesUtilities; 33 import org.netbeans.api.editor.settings.FontColorNames; 34 import org.netbeans.api.editor.settings.FontColorSettings; 35 import org.netbeans.editor.GuardedDocument; 36 import org.netbeans.editor.MarkBlock; 37 import org.netbeans.editor.MarkBlockChain; 38 import org.netbeans.spi.editor.highlighting.HighlightsSequence; 39 import org.netbeans.spi.editor.highlighting.support.AbstractHighlightsContainer; 40 import org.openide.util.Lookup; 41 import org.openide.util.LookupEvent; 42 import org.openide.util.LookupListener; 43 44 48 public final class GuardedBlocksHighlighting extends AbstractHighlightsContainer implements LookupListener { 49 50 private static final Logger LOG = Logger.getLogger(GuardedBlocksHighlighting.class.getName()); 51 public static final String LAYER_TYPE_ID = "org.netbeans.modules.editor.oldlibbridge.GuardedBlocksHighlighting"; 53 private final Document document; 54 private final MimePath mimePath; 55 private final Lookup.Result<FontColorSettings> lookupResult; 56 57 private long version = 0; 58 private AttributeSet attribs = null; 59 60 61 public GuardedBlocksHighlighting(Document document, String mimeType) { 62 this.document = document; 63 this.mimePath = MimePath.parse(mimeType); 64 this.lookupResult = MimeLookup.getLookup(mimePath).lookup(new Lookup.Template<FontColorSettings>(FontColorSettings.class)); 65 this.lookupResult.addLookupListener(this); 66 } 67 68 public HighlightsSequence getHighlights(int startOffset, int endOffset) { 69 synchronized (this) { 70 if (document instanceof GuardedDocument) { 71 MarkBlockChain guardedBlocks = ((GuardedDocument) document).getGuardedBlockChain(); 72 return new HSImpl(version, guardedBlocks, startOffset, endOffset); 73 } else { 74 return HighlightsSequence.EMPTY; 75 } 76 } 77 } 78 79 83 public void resultChanged(LookupEvent ev) { 84 synchronized (this) { 85 attribs = null; 86 version++; 87 } 88 89 document.render(new Runnable () { 90 public void run() { 91 fireHighlightsChange(0, Integer.MAX_VALUE); 92 } 93 }); 94 } 95 96 100 private final class HSImpl implements HighlightsSequence { 101 102 private final long version; 103 private final MarkBlockChain guardedBlocks; 104 private final int startOffset; 105 private final int endOffset; 106 107 private boolean init = false; 108 private MarkBlock block; 109 110 public HSImpl(long version, MarkBlockChain guardedBlocks, int startOffset, int endOffset) { 111 this.version = version; 112 this.guardedBlocks = guardedBlocks; 113 this.startOffset = startOffset; 114 this.endOffset = endOffset; 115 } 116 117 public boolean moveNext() { 118 if (!init) { 119 init = true; 120 121 block = guardedBlocks.getChain(); 122 123 while(null != block) { 124 if (block.getEndOffset() > startOffset) { 125 break; 126 } 127 128 if (LOG.isLoggable(Level.FINE)) { 129 LOG.fine("Skipping block: " + block + ", blockStart = " + block.getStartOffset() + ", blockEnd = " + block.getEndOffset() + ", startOffset = " + startOffset + ", endOffset = " + endOffset ); 135 } 136 137 block = block.getNext(); 138 } 139 } else if (block != null) { 140 block = block.getNext(); 141 } 142 143 if (block != null && block.getStartOffset() > endOffset) { 144 block = null; 145 } 146 147 if (LOG.isLoggable(Level.FINE)) { 148 if (block != null) { 149 LOG.fine("Next block: " + block + ", blockStart = " + block.getStartOffset() + ", blockEnd = " + block.getEndOffset() + ", startOffset = " + startOffset + ", endOffset = " + endOffset ); 155 } else { 156 LOG.fine("Next block: null"); } 158 } 159 160 return block != null; 161 } 162 163 public int getStartOffset() { 164 synchronized (GuardedBlocksHighlighting.this) { 165 checkVersion(); 166 167 if (!init) { 168 throw new NoSuchElementException ("Call moveNext() first."); } else if (block == null) { 170 throw new NoSuchElementException (); 171 } 172 173 return Math.max(block.getStartOffset(), startOffset); 174 } 175 } 176 177 public int getEndOffset() { 178 synchronized (GuardedBlocksHighlighting.this) { 179 checkVersion(); 180 181 if (!init) { 182 throw new NoSuchElementException ("Call moveNext() first."); } else if (block == null) { 184 throw new NoSuchElementException (); 185 } 186 187 return Math.min(block.getEndOffset(), endOffset); 188 } 189 } 190 191 public AttributeSet getAttributes() { 192 synchronized (GuardedBlocksHighlighting.this) { 193 checkVersion(); 194 195 if (!init) { 196 throw new NoSuchElementException ("Call moveNext() first."); } else if (block == null) { 198 throw new NoSuchElementException (); 199 } 200 201 if (attribs == null) { 202 Collection <? extends FontColorSettings> allFcs = lookupResult.allInstances(); 203 if (!allFcs.isEmpty()) { 204 FontColorSettings fcs = allFcs.iterator().next(); 205 attribs = fcs.getFontColors(FontColorNames.GUARDED_COLORING); 206 } 207 208 if (attribs == null) { 209 attribs = SimpleAttributeSet.EMPTY; 210 } else { 211 attribs = AttributesUtilities.createImmutable( 212 attribs, 213 AttributesUtilities.createImmutable(ATTR_EXTENDS_EOL, Boolean.TRUE) 214 ); 215 } 216 } 217 218 return attribs; 219 } 220 } 221 222 private void checkVersion() { 223 if (this.version != GuardedBlocksHighlighting.this.version) { 224 throw new ConcurrentModificationException (); 225 } 226 } 227 } 229 } 230 | Popular Tags |