public TrafficLightRenderer(Project project, Document document, PsiFile file) { myProject = project; myDaemonCodeAnalyzer = project == null ? null : (DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(project); myDocument = document; myFile = file; mySeverityRegistrar = SeverityRegistrar.getInstance(myProject); refresh(); if (project != null) { MarkupModelEx model = (MarkupModelEx) DocumentMarkupModel.forDocument(document, project, true); model.addMarkupModelListener( this, new MarkupModelListener() { @Override public void afterAdded(@NotNull RangeHighlighterEx highlighter) { incErrorCount(highlighter, 1); } @Override public void beforeRemoved(@NotNull RangeHighlighterEx highlighter) { incErrorCount(highlighter, -1); } @Override public void attributesChanged(@NotNull RangeHighlighterEx highlighter) {} }); for (RangeHighlighter rangeHighlighter : model.getAllHighlighters()) { incErrorCount(rangeHighlighter, 1); } } }
public void testRangeHighlighterLinesInRangeForLongLinePerformance() throws Exception { final int N = 50000; Document document = EditorFactory.getInstance().createDocument(StringUtil.repeatSymbol('x', 2 * N)); final MarkupModelEx markupModel = (MarkupModelEx) DocumentMarkupModel.forDocument(document, ourProject, true); for (int i = 0; i < N - 1; i++) { markupModel.addRangeHighlighter(2 * i, 2 * i + 1, 0, null, HighlighterTargetArea.EXACT_RANGE); } markupModel.addRangeHighlighter( N / 2, N / 2 + 1, 0, null, HighlighterTargetArea.LINES_IN_RANGE); PlatformTestUtil.startPerformanceTest( "slow highlighters lookup", (int) (N * Math.log(N) / 1000), new ThrowableRunnable() { @Override public void run() { List<RangeHighlighterEx> list = new ArrayList<RangeHighlighterEx>(); CommonProcessors.CollectProcessor<RangeHighlighterEx> coll = new CommonProcessors.CollectProcessor<RangeHighlighterEx>(list); for (int i = 0; i < N - 1; i++) { list.clear(); markupModel.processRangeHighlightersOverlappingWith(2 * i, 2 * i + 1, coll); assertEquals(2, list.size()); // 1 line plus one exact range marker } } }) .assertTiming(); }
public static boolean processHighlightsOverlappingOutside( @NotNull Document document, @NotNull Project project, @Nullable("null means all") final HighlightSeverity minSeverity, final int startOffset, final int endOffset, @NotNull final Processor<HighlightInfo> processor) { LOG.assertTrue(ApplicationManager.getApplication().isReadAccessAllowed()); final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(project); MarkupModelEx model = (MarkupModelEx) DocumentMarkupModel.forDocument(document, project, true); return model.processRangeHighlightersOutside( startOffset, endOffset, new Processor<RangeHighlighterEx>() { public boolean process(RangeHighlighterEx marker) { Object tt = marker.getErrorStripeTooltip(); if (!(tt instanceof HighlightInfo)) return true; HighlightInfo info = (HighlightInfo) tt; return minSeverity != null && severityRegistrar.compare(info.getSeverity(), minSeverity) < 0 || info.highlighter == null || processor.process(info); } }); }
public void testRangeHighlighterIteratorOrder() throws Exception { Document document = EditorFactory.getInstance().createDocument("1234567890"); final MarkupModelEx markupModel = (MarkupModelEx) DocumentMarkupModel.forDocument(document, ourProject, true); RangeHighlighter exact = markupModel.addRangeHighlighter(3, 6, 0, null, HighlighterTargetArea.EXACT_RANGE); RangeHighlighter line = markupModel.addRangeHighlighter(4, 5, 0, null, HighlighterTargetArea.LINES_IN_RANGE); List<RangeHighlighter> list = new ArrayList<RangeHighlighter>(); markupModel.processRangeHighlightersOverlappingWith( 2, 9, new CommonProcessors.CollectProcessor<RangeHighlighter>(list)); assertEquals(Arrays.asList(line, exact), list); }
private static void clearLineMarkers(Editor editor) { final List<RangeHighlighter> oldHighlighters = editor.getUserData(TAG_TREE_HIGHLIGHTERS_IN_EDITOR_KEY); if (oldHighlighters != null) { final MarkupModelEx markupModel = (MarkupModelEx) editor.getMarkupModel(); for (RangeHighlighter highlighter : oldHighlighters) { if (markupModel.containsHighlighter(highlighter)) { highlighter.dispose(); } } editor.putUserData(TAG_TREE_HIGHLIGHTERS_IN_EDITOR_KEY, null); } }
private void paintBorderEffect( final Graphics2D g, final ClipDetector clipDetector, MarkupModelEx markupModel, int clipStartOffset, int clipEndOffset) { markupModel.processRangeHighlightersOverlappingWith( clipStartOffset, clipEndOffset, new Processor<RangeHighlighterEx>() { @Override public boolean process(RangeHighlighterEx rangeHighlighter) { if (rangeHighlighter.getEditorFilter().avaliableIn(myEditor)) { TextAttributes attributes = rangeHighlighter.getTextAttributes(); if (isBorder(attributes)) { paintBorderEffect( g, clipDetector, rangeHighlighter.getAffectedAreaStartOffset(), rangeHighlighter.getAffectedAreaEndOffset(), attributes); } } return true; } }); }
private RangeHighlighter doHightlightRange( final TextRange textRange, final TextAttributes attributes, Set<RangeHighlighter> highlighters) { HighlightManager highlightManager = HighlightManager.getInstance(mySearchResults.getProject()); MarkupModelEx markupModel = (MarkupModelEx) mySearchResults.getEditor().getMarkupModel(); final RangeHighlighter[] candidate = new RangeHighlighter[1]; boolean notFound = markupModel.processRangeHighlightersOverlappingWith( textRange.getStartOffset(), textRange.getEndOffset(), new Processor<RangeHighlighterEx>() { @Override public boolean process(RangeHighlighterEx highlighter) { TextAttributes textAttributes = highlighter.getTextAttributes(); if (highlighter.getUserData(SEARCH_MARKER) != null && textAttributes != null && textAttributes.equals(attributes) && highlighter.getStartOffset() == textRange.getStartOffset() && highlighter.getEndOffset() == textRange.getEndOffset()) { candidate[0] = highlighter; return false; } return true; } }); if (!notFound && highlighters.contains(candidate[0])) { return candidate[0]; } final ArrayList<RangeHighlighter> dummy = new ArrayList<RangeHighlighter>(); highlightManager.addRangeHighlight( mySearchResults.getEditor(), textRange.getStartOffset(), textRange.getEndOffset(), attributes, false, dummy); final RangeHighlighter h = dummy.get(0); highlighters.add(h); h.putUserData(SEARCH_MARKER, YES); return h; }
public void paintHighlighters(MarkupModelEx markupModel) { markupModel.processRangeHighlightersOverlappingWith( myStartOffset, myEndOffset, new Processor<RangeHighlighterEx>() { @Override public boolean process(RangeHighlighterEx rangeHighlighter) { TextAttributes textAttributes = rangeHighlighter.getTextAttributes(); if (isBorder(textAttributes)) { paintBorder(rangeHighlighter, textAttributes); } return true; } }); }
private void paintHighlightersAfterEndOfLine( final Graphics2D g, MarkupModelEx markupModel, final int startOffset, int endOffset) { markupModel.processRangeHighlightersOverlappingWith( startOffset, endOffset, new Processor<RangeHighlighterEx>() { @Override public boolean process(RangeHighlighterEx highlighter) { if (highlighter.getEditorFilter().avaliableIn(myEditor) && highlighter.getStartOffset() >= startOffset) { paintHighlighterAfterEndOfLine(g, highlighter); } return true; } }); }
private void getNearestHighlighters( MarkupModelEx markupModel, MouseEvent e, final double width, final Collection<RangeHighlighter> nearest) { if (0 > e.getX() || e.getX() >= width) return; int startOffset = yPositionToOffset(e.getY() - getMinHeight(), true); int endOffset = yPositionToOffset(e.getY() + getMinHeight(), false); markupModel.processHighlightsOverlappingWith( startOffset, endOffset, new Processor<RangeHighlighterEx>() { public boolean process(RangeHighlighterEx highlighter) { if (highlighter.getErrorStripeMarkColor() != null) nearest.add(highlighter); return true; } }); }
private void paintLineMarkersSeparators( final Graphics g, final Rectangle clip, MarkupModelEx markupModel, int startOffset, int endOffset) { markupModel.processRangeHighlightersOverlappingWith( startOffset, endOffset, new Processor<RangeHighlighterEx>() { @Override public boolean process(RangeHighlighterEx highlighter) { if (highlighter.getEditorFilter().avaliableIn(myEditor)) { paintLineMarkerSeparator(highlighter, clip, g); } return true; } }); }
private void drawMarkup( final Graphics g, final int width, int startOffset, int endOffset, MarkupModelEx markup) { final Queue<PositionedStripe> thinEnds = new PriorityQueue<PositionedStripe>( 5, new Comparator<PositionedStripe>() { public int compare(PositionedStripe o1, PositionedStripe o2) { return o1.yEnd - o2.yEnd; } }); final Queue<PositionedStripe> wideEnds = new PriorityQueue<PositionedStripe>( 5, new Comparator<PositionedStripe>() { public int compare(PositionedStripe o1, PositionedStripe o2) { return o1.yEnd - o2.yEnd; } }); // sorted by layer final List<PositionedStripe> thinStripes = new ArrayList<PositionedStripe>(); final List<PositionedStripe> wideStripes = new ArrayList<PositionedStripe>(); final int[] thinYStart = new int[1]; // in range 0..yStart all spots are drawn final int[] wideYStart = new int[1]; // in range 0..yStart all spots are drawn markup.processHighlightsOverlappingWith( startOffset, endOffset, new Processor<RangeHighlighterEx>() { public boolean process(RangeHighlighterEx highlighter) { Color color = highlighter.getErrorStripeMarkColor(); if (color == null) return true; boolean isThin = highlighter.isThinErrorStripeMark(); int[] yStart = isThin ? thinYStart : wideYStart; List<PositionedStripe> stripes = isThin ? thinStripes : wideStripes; Queue<PositionedStripe> ends = isThin ? thinEnds : wideEnds; ProperTextRange range = offsetToYPosition(highlighter.getStartOffset(), highlighter.getEndOffset()); final int ys = range.getStartOffset(); int ye = range.getEndOffset(); if (ye - ys < getMinHeight()) ye = ys + getMinHeight(); yStart[0] = drawStripesEndingBefore(ys, ends, stripes, g, width, yStart[0]); final int layer = highlighter.getLayer(); PositionedStripe stripe = null; int i; for (i = 0; i < stripes.size(); i++) { PositionedStripe s = stripes.get(i); if (s.layer == layer) { stripe = s; break; } if (s.layer < layer) { break; } } if (stripe == null) { // started new stripe, draw previous above if (yStart[0] != ys) { if (!stripes.isEmpty()) { PositionedStripe top = stripes.get(0); drawSpot(g, width, top.thin, yStart[0], ys, top.color, true, true); } yStart[0] = ys; } stripe = new PositionedStripe(color, ys, ye, isThin, layer); stripes.add(i, stripe); ends.offer(stripe); } else { // key changed, reinsert into queue if (stripe.yEnd != ye) { ends.remove(stripe); stripe.yEnd = ye; ends.offer(stripe); } } return true; } }); drawStripesEndingBefore(Integer.MAX_VALUE, thinEnds, thinStripes, g, width, thinYStart[0]); drawStripesEndingBefore(Integer.MAX_VALUE, wideEnds, wideStripes, g, width, wideYStart[0]); }