void () { MarkupModel markupModel = myEditor.getMarkupModel(); if (myShowsPreviewHighlighters) { Rectangle visibleArea = myEditor.getScrollingModel().getVisibleArea(); VisualPosition visualStart = myEditor.xyToVisualPosition(visibleArea.getLocation()); VisualPosition visualEnd = myEditor.xyToVisualPosition(new Point(visibleArea.x + visibleArea.width, visibleArea.y + visibleArea.height)); // There is a possible case that viewport is located at its most bottom position and last document symbol // is located at the start of the line, hence, resulting visual end column has a small value and doesn't actually // indicates target visible rectangle. Hence, we need to correct that if necessary. int endColumnCandidate = visibleArea.width / EditorUtil.getSpaceWidth(Font.PLAIN, myEditor) + visualStart.column; if (endColumnCandidate > visualEnd.column) { visualEnd = new VisualPosition(visualEnd.line, endColumnCandidate); } int offsetToScroll = -1; CharSequence text = myEditor.getDocument().getCharsSequence(); TextAttributes backgroundAttributes = myEditor.getColorsScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES); TextAttributes borderAttributes = new TextAttributes( null, null, backgroundAttributes.getBackgroundColor(), EffectType.BOXED, Font.PLAIN ); boolean scrollToChange = true; for (TextRange range : myPreviewRangesToHighlight) { if (scrollToChange) { boolean rangeVisible = isWithinBounds(myEditor.offsetToVisualPosition(range.getStartOffset()), visualStart, visualEnd) || isWithinBounds(myEditor.offsetToVisualPosition(range.getEndOffset()), visualStart, visualEnd); scrollToChange = !rangeVisible; if (offsetToScroll < 0) { if (text.charAt(range.getStartOffset()) != '\n') { offsetToScroll = range.getStartOffset(); } else if (range.getEndOffset() > 0 && text.charAt(range.getEndOffset() - 1) != '\n') { offsetToScroll = range.getEndOffset() - 1; } } } TextAttributes attributesToUse = range.getLength() > 0 ? backgroundAttributes : borderAttributes; markupModel.addRangeHighlighter( range.getStartOffset(), range.getEndOffset(), HighlighterLayer.SELECTION, attributesToUse, HighlighterTargetArea.EXACT_RANGE ); } if (scrollToChange) { if (offsetToScroll < 0 && !myPreviewRangesToHighlight.isEmpty()) { offsetToScroll = myPreviewRangesToHighlight.get(0).getStartOffset(); } if (offsetToScroll >= 0 && offsetToScroll < text.length() - 1 && text.charAt(offsetToScroll) != '\n') { // There is a possible case that target offset is located too close to the right edge. However, our point is to show // highlighted region at target offset, hence, we need to scroll to the visual symbol end. Hence, we're trying to ensure // that by scrolling to the symbol's end over than its start. offsetToScroll++; } if (offsetToScroll >= 0 && offsetToScroll < myEditor.getDocument().getTextLength()) { myEditor.getScrollingModel().scrollTo( myEditor.offsetToLogicalPosition(offsetToScroll), ScrollType.RELATIVE ); } } } else { markupModel.removeAllHighlighters(); } myShowsPreviewHighlighters = !myShowsPreviewHighlighters; }