1 19 package org.netbeans.modules.editor.hints; 20 21 import java.beans.PropertyChangeEvent ; 22 import java.beans.PropertyChangeListener ; 23 import java.beans.PropertyChangeSupport ; 24 import java.io.IOException ; 25 import java.util.ArrayList ; 26 import java.util.Collection ; 27 import java.util.Collections ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Set ; 31 import javax.swing.event.ChangeEvent ; 32 import javax.swing.event.ChangeListener ; 33 import javax.swing.text.BadLocationException ; 34 import javax.swing.text.Document ; 35 import javax.swing.text.Position ; 36 import javax.swing.text.StyledDocument ; 37 import org.netbeans.editor.BaseDocument; 38 import org.netbeans.editor.Utilities; 39 import org.netbeans.spi.editor.hints.ErrorDescription; 40 import org.netbeans.spi.editor.hints.Fix; 41 import org.netbeans.spi.editor.hints.LazyFixList; 42 import org.openide.ErrorManager; 43 import org.openide.cookies.EditorCookie; 44 import org.openide.filesystems.FileObject; 45 import org.openide.loaders.DataObject; 46 import org.openide.text.CloneableEditorSupport; 47 import org.openide.text.EditorSupport; 48 import org.openide.text.NbDocument; 49 import org.openide.text.PositionBounds; 50 import org.openide.text.PositionRef; 51 52 56 public final class HintsControllerImpl { 57 58 61 private HintsControllerImpl() { 62 } 63 64 public static Collection <FileObject> coveredFiles() { 65 return AnnotationHolder.coveredFiles(); 66 } 67 68 public static List <ErrorDescription> getErrors(FileObject file) { 69 AnnotationHolder holder = AnnotationHolder.getInstance(file); 70 71 if (holder == null) { 72 return Collections.<ErrorDescription>emptyList(); 73 } 74 75 return holder.getErrors(); 76 } 77 78 public static void setErrors(Document doc, String layer, Collection <? extends ErrorDescription> errors) { 79 DataObject od = (DataObject) doc.getProperty(Document.StreamDescriptionProperty); 80 81 if (od == null) 82 return ; 83 84 try { 85 setErrorsImpl(od.getPrimaryFile(), layer, errors); 86 } catch (IOException e) { 87 ErrorManager.getDefault().notify(e); 88 } 89 } 90 91 public static void setErrors(FileObject file, String layer, Collection <? extends ErrorDescription> errors) { 92 try { 93 setErrorsImpl(file, layer, errors); 94 } catch (IOException e) { 95 ErrorManager.getDefault().notify(e); 96 } 97 } 98 99 private static void setErrorsImpl(FileObject file, String layer, Collection <? extends ErrorDescription> errors) throws IOException { 100 AnnotationHolder holder = AnnotationHolder.getInstance(file); 101 102 if (holder != null) { 103 holder.setErrorDescriptions(layer,errors); 104 } 105 106 } 110 111 private static void computeLineSpan(Document doc, int[] offsets) throws BadLocationException { 112 String text = doc.getText(offsets[0], offsets[1] - offsets[0]); 113 int column = 0; 114 int length = text.length(); 115 116 while (column < text.length() && Character.isWhitespace(text.charAt(column))) { 117 column++; 118 } 119 120 while (length > 0 && Character.isWhitespace(text.charAt(length - 1))) 121 length--; 122 123 offsets[1] = offsets[0] + length; 124 offsets[0] += column; 125 126 if (offsets[1] < offsets[0]) { 127 offsets[0] = offsets[1]; 129 } 130 } 131 132 static int[] computeLineSpan(Document doc, int lineNumber) throws BadLocationException { 133 int lineStartOffset = NbDocument.findLineOffset((StyledDocument ) doc, lineNumber - 1); 134 int lineEndOffset; 135 136 if (doc instanceof BaseDocument) { 137 lineEndOffset = Utilities.getRowEnd((BaseDocument) doc, lineStartOffset); 138 } else { 139 String lineText = doc.getText(lineStartOffset, doc.getLength() - lineStartOffset); 141 142 lineText = lineText.indexOf('\n') != (-1) ? lineText.substring(0, lineText.indexOf('\n')) : lineText; 143 lineEndOffset = lineStartOffset + lineText.length(); 144 } 145 146 int[] span = new int[] {lineStartOffset, lineEndOffset}; 147 148 computeLineSpan(doc, span); 149 150 return span; 151 } 152 153 public static PositionBounds fullLine(Document doc, int lineNumber) { 154 DataObject file = (DataObject) doc.getProperty(Document.StreamDescriptionProperty); 155 156 if (file == null) 157 return null; 158 159 try { 160 int[] span = computeLineSpan(doc, lineNumber); 161 162 return linePart(file.getPrimaryFile(), span[0], span[1]); 163 } catch (BadLocationException e) { 164 ErrorManager.getDefault().notify(e); 165 return null; 166 } 167 } 168 169 public static PositionBounds linePart(Document doc, final Position start, final Position end) { 170 DataObject od = (DataObject) doc.getProperty(Document.StreamDescriptionProperty); 171 172 if (od == null) 173 return null; 174 175 EditorCookie ec = od.getCookie(EditorCookie.class); 176 177 if (ec instanceof CloneableEditorSupport) { 178 final CloneableEditorSupport ces = (CloneableEditorSupport) ec; 179 180 final PositionRef[] refs = new PositionRef[2]; 181 182 doc.render(new Runnable () { 183 public void run() { 184 refs[0] = ces.createPositionRef(start.getOffset(), Position.Bias.Forward); 185 refs[1] = ces.createPositionRef(end.getOffset(), Position.Bias.Backward); 186 } 187 }); 188 189 return new PositionBounds(refs[0], refs[1]); 190 } 191 192 if (ec instanceof EditorSupport) { 193 final EditorSupport es = (EditorSupport) ec; 194 195 final PositionRef[] refs = new PositionRef[2]; 196 197 doc.render(new Runnable () { 198 public void run() { 199 refs[0] = es.createPositionRef(start.getOffset(), Position.Bias.Forward); 200 refs[1] = es.createPositionRef(end.getOffset(), Position.Bias.Backward); 201 } 202 }); 203 204 return new PositionBounds(refs[0], refs[1]); 205 } 206 207 return null; 208 } 209 210 public static PositionBounds linePart(FileObject file, int start, int end) { 211 try { 212 DataObject od = DataObject.find(file); 213 214 if (od == null) 215 return null; 216 217 EditorCookie ec = od.getCookie(EditorCookie.class); 218 219 if (!(ec instanceof CloneableEditorSupport)) { 220 return null; 221 } 222 223 final CloneableEditorSupport ces = (CloneableEditorSupport) ec; 224 225 return new PositionBounds(ces.createPositionRef(start, Position.Bias.Forward), ces.createPositionRef(end, Position.Bias.Backward)); 226 } catch (IOException e) { 227 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 228 return null; 229 } 230 } 231 232 public static boolean isInError(Set <FileObject> fos) { 233 for (Iterator <FileObject> i = fos.iterator(); i.hasNext(); ) { 234 FileObject f = i.next(); 235 236 if (isInError(f)) { 237 return true; 238 } 239 } 240 241 return false; 242 } 243 244 public static boolean isInError(FileObject fo) { 245 250 return false; 253 } 254 255 279 private static List <ChangeListener > listeners = new ArrayList <ChangeListener >(); 280 281 public static synchronized void addChangeListener(ChangeListener l) { 282 listeners.add(l); 283 } 284 285 public static synchronized void removeChangeListener(ChangeListener l) { 286 listeners.remove(l); 287 } 288 289 private static void fireChanges() { 290 List <ChangeListener > ls; 291 292 synchronized (HintsControllerImpl.class) { 293 ls = new ArrayList <ChangeListener >(listeners); 294 } 295 296 ChangeEvent e = new ChangeEvent (HintsControllerImpl.class); 297 298 for (ChangeListener l : ls) { 299 l.stateChanged(e); 300 } 301 } 302 303 public static class CompoundLazyFixList implements LazyFixList, PropertyChangeListener { 304 305 private List <LazyFixList> delegates; 306 307 private List <Fix> fixesCache; 308 private Boolean computedCache; 309 private Boolean probablyContainsFixesCache; 310 311 private PropertyChangeSupport pcs; 312 313 public CompoundLazyFixList(List <LazyFixList> delegates) { 314 this.delegates = delegates; 315 this.pcs = new PropertyChangeSupport (this); 316 317 for (LazyFixList l : delegates) { 318 l.addPropertyChangeListener(this); 319 } 320 } 321 322 public void addPropertyChangeListener(PropertyChangeListener l) { 323 pcs.addPropertyChangeListener(l); 324 } 325 326 public void removePropertyChangeListener(PropertyChangeListener l) { 327 pcs.removePropertyChangeListener(l); 328 } 329 330 public synchronized boolean probablyContainsFixes() { 331 if (probablyContainsFixesCache == null) { 332 boolean result = false; 333 334 for (LazyFixList l : delegates) { 335 result |= l.probablyContainsFixes(); 336 } 337 338 probablyContainsFixesCache = Boolean.valueOf(result); 339 } 340 341 return probablyContainsFixesCache; 342 } 343 344 public synchronized List <Fix> getFixes() { 345 if (fixesCache == null) { 346 fixesCache = new ArrayList <Fix>(); 347 348 for (LazyFixList l : delegates) { 349 fixesCache.addAll(l.getFixes()); 350 } 351 } 352 353 return fixesCache; 354 } 355 356 public synchronized boolean isComputed() { 357 if (computedCache == null) { 358 boolean result = true; 359 360 for (LazyFixList l : delegates) { 361 result &= l.isComputed(); 362 } 363 364 computedCache = Boolean.valueOf(result); 365 } 366 367 return computedCache; 368 } 369 370 public void propertyChange(PropertyChangeEvent evt) { 371 if (PROP_FIXES.equals(evt.getPropertyName())) { 372 synchronized (this) { 373 fixesCache = null; 374 } 375 pcs.firePropertyChange(PROP_FIXES, null, null); 376 return; 377 } 378 379 if (PROP_COMPUTED.equals(evt.getPropertyName())) { 380 synchronized (this) { 381 computedCache = null; 382 } 383 pcs.firePropertyChange(PROP_COMPUTED, null, null); 384 } 385 } 386 387 } 388 389 } 390 | Popular Tags |