private static void duplicateHighlighters( MarkupModel to, MarkupModel from, int offset, TextRange textRange) { for (RangeHighlighter rangeHighlighter : from.getAllHighlighters()) { if (!rangeHighlighter.isValid()) continue; Object tooltip = rangeHighlighter.getErrorStripeTooltip(); HighlightInfo highlightInfo = tooltip instanceof HighlightInfo ? (HighlightInfo) tooltip : null; if (highlightInfo != null) { if (highlightInfo.getSeverity() != HighlightSeverity.INFORMATION) continue; if (highlightInfo.type.getAttributesKey() == EditorColors.IDENTIFIER_UNDER_CARET_ATTRIBUTES) continue; } final int localOffset = textRange.getStartOffset(); final int start = Math.max(rangeHighlighter.getStartOffset(), localOffset) - localOffset; final int end = Math.min(rangeHighlighter.getEndOffset(), textRange.getEndOffset()) - localOffset; if (start > end) continue; final RangeHighlighter h = to.addRangeHighlighter( start + offset, end + offset, rangeHighlighter.getLayer(), rangeHighlighter.getTextAttributes(), rangeHighlighter.getTargetArea()); ((RangeHighlighterEx) h) .setAfterEndOfLine(((RangeHighlighterEx) rangeHighlighter).isAfterEndOfLine()); } }
@Override public void layoutContainer(final Container parent) { final int componentCount = parent.getComponentCount(); if (componentCount == 0) return; final EditorEx history = myHistoryViewer; final EditorEx editor = componentCount == 2 ? myConsoleEditor : null; if (editor == null) { parent.getComponent(0).setBounds(parent.getBounds()); return; } final Dimension panelSize = parent.getSize(); if (panelSize.getHeight() <= 0) return; final Dimension historySize = history.getContentSize(); final Dimension editorSize = editor.getContentSize(); final Dimension newEditorSize = new Dimension(); // deal with width final int width = Math.max(editorSize.width, historySize.width); newEditorSize.width = width + editor.getScrollPane().getHorizontalScrollBar().getHeight(); history.getSoftWrapModel().forceAdditionalColumnsUsage(); editor .getSettings() .setAdditionalColumnsCount( 2 + (width - editorSize.width) / EditorUtil.getSpaceWidth(Font.PLAIN, editor)); history .getSettings() .setAdditionalColumnsCount( 2 + (width - historySize.width) / EditorUtil.getSpaceWidth(Font.PLAIN, history)); // deal with height if (historySize.width == 0) historySize.height = 0; final int minHistorySize = historySize.height > 0 ? 2 * history.getLineHeight() + (myShowSeparatorLine ? SEPARATOR_THICKNESS : 0) : 0; final int minEditorSize = editor.isViewer() ? 0 : editor.getLineHeight(); final int editorPreferred = editor.isViewer() ? 0 : Math.max(minEditorSize, editorSize.height); final int historyPreferred = Math.max(minHistorySize, historySize.height); if (panelSize.height < minEditorSize) { newEditorSize.height = panelSize.height; } else if (panelSize.height < editorPreferred) { newEditorSize.height = panelSize.height - minHistorySize; } else if (panelSize.height < editorPreferred + historyPreferred) { newEditorSize.height = editorPreferred; } else { newEditorSize.height = editorPreferred == 0 ? 0 : panelSize.height - historyPreferred; } final Dimension newHistorySize = new Dimension(width, panelSize.height - newEditorSize.height); // apply editor .getComponent() .setBounds(0, newHistorySize.height, panelSize.width, newEditorSize.height); myForceScrollToEnd.compareAndSet(false, shouldScrollHistoryToEnd()); history.getComponent().setBounds(0, 0, panelSize.width, newHistorySize.height); }
private int wrapPositionForTabbedTextWithOptimization( @NotNull CharSequence text, int tabSize, int startLineOffset, int endLineOffset, int targetRangeEndOffset) { int width = 0; int symbolWidth; int result = Integer.MAX_VALUE; boolean wrapLine = false; for (int i = startLineOffset; i < Math.min(endLineOffset, targetRangeEndOffset); i++) { char c = text.charAt(i); switch (c) { case '\t': symbolWidth = tabSize - (width % tabSize); break; default: symbolWidth = 1; } if (width + symbolWidth + FormatConstants.RESERVED_LINE_WRAP_WIDTH_IN_COLUMNS >= mySettings.RIGHT_MARGIN && (Math.min(endLineOffset, targetRangeEndOffset) - i) >= FormatConstants.RESERVED_LINE_WRAP_WIDTH_IN_COLUMNS) { // Remember preferred position. result = i - 1; } if (width + symbolWidth >= mySettings.RIGHT_MARGIN) { wrapLine = true; break; } width += symbolWidth; } return wrapLine ? result : -1; }
private static void restoreBlockSelection( Editor editor, List<RangeMarker> caretsAfter, int caretLine) { int column = -1; int minLine = Integer.MAX_VALUE; int maxLine = -1; for (RangeMarker marker : caretsAfter) { if (marker.isValid()) { LogicalPosition lp = editor.offsetToLogicalPosition(marker.getStartOffset()); if (column == -1) { column = lp.column; } else if (column != lp.column) { return; } minLine = Math.min(minLine, lp.line); maxLine = Math.max(maxLine, lp.line); if (lp.line == caretLine) { editor.getCaretModel().moveToLogicalPosition(lp); } } } editor .getSelectionModel() .setBlockSelection( new LogicalPosition(minLine, column), new LogicalPosition(maxLine, column)); }
int getPreferredHeight() { int lineHeight = myView.getLineHeight(); if (myEditor.isOneLineMode()) return lineHeight; // Preferred height of less than a single line height doesn't make sense: // at least a single line with a blinking caret on it is to be displayed int size = Math.max(myEditor.getVisibleLineCount(), 1) * lineHeight; EditorSettings settings = myEditor.getSettings(); if (settings.isAdditionalPageAtBottom()) { int visibleAreaHeight = myEditor.getScrollingModel().getVisibleArea().height; // There is a possible case that user with 'show additional page at bottom' scrolls to that // virtual page; switched to another // editor (another tab); and then returns to the previously used editor (the one scrolled to // virtual page). We want to preserve // correct view size then because viewport position is set to the end of the original text // otherwise. if (visibleAreaHeight > 0 || myVirtualPageHeight <= 0) { myVirtualPageHeight = Math.max(visibleAreaHeight - 2 * lineHeight, lineHeight); } size += Math.max(myVirtualPageHeight, 0); } else { size += settings.getAdditionalLinesCount() * lineHeight; } Insets insets = myView.getInsets(); return size + insets.top + insets.bottom; }
/** * Returns a list of pairs of x coordinates for visual ranges representing given logical range. If * <code>startOffset == endOffset</code>, a pair of equal numbers is returned, corresponding to * target position. Target offsets are supposed to be located on the same visual line. */ private TFloatArrayList logicalRangeToVisualRanges(int startOffset, int endOffset) { assert startOffset <= endOffset; TFloatArrayList result = new TFloatArrayList(); for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, startOffset, false)) { int minOffset = fragment.getMinOffset(); int maxOffset = fragment.getMaxOffset(); if (startOffset == endOffset) { if (startOffset >= minOffset && startOffset <= maxOffset) { float x = fragment.offsetToX(startOffset); result.add(x); result.add(x); break; } } else if (startOffset < maxOffset && endOffset > minOffset) { float x1 = fragment.offsetToX(Math.max(minOffset, startOffset)); float x2 = fragment.offsetToX(Math.min(maxOffset, endOffset)); if (x1 > x2) { float tmp = x1; x1 = x2; x2 = tmp; } if (result.isEmpty() || x1 > result.get(result.size() - 1)) { result.add(x1); result.add(x2); } else { result.set(result.size() - 1, x2); } } } return result; }
@Override public void onFoldRegionStateChange(@NotNull FoldRegion region) { if (myDocument.isInBulkUpdate()) return; if (region.isValid()) { myFoldingChangeStartOffset = Math.min(myFoldingChangeStartOffset, region.getStartOffset()); myFoldingChangeEndOffset = Math.max(myFoldingChangeEndOffset, region.getEndOffset()); } }
public void documentChanged(DocumentEvent e) { finishUpdate(); DocumentEventImpl event = (DocumentEventImpl) e; final Document document = myEditor.getDocument(); boolean performSoftWrapAdjustment = e.getNewLength() > 0 // We want to put caret just after the last added symbol // There is a possible case that the user removes text just before the soft wrap. We // want to keep caret // on a visual line with soft wrap start then. || myEditor.getSoftWrapModel().getSoftWrap(e.getOffset()) != null; if (event.isWholeTextReplaced()) { int newLength = document.getTextLength(); if (myOffset == newLength - e.getNewLength() + e.getOldLength() || newLength == 0) { moveToOffset(newLength, performSoftWrapAdjustment); } else { final int line; try { line = event.translateLineViaDiff(myLogicalCaret.line); moveToLogicalPosition( new LogicalPosition(line, myLogicalCaret.column), performSoftWrapAdjustment); } catch (FilesTooBigForDiffException e1) { LOG.info(e1); moveToOffset(0); } } } else { if (document instanceof DocumentEx && ((DocumentEx) document).isInBulkUpdate()) return; int startOffset = e.getOffset(); int oldEndOffset = startOffset + e.getOldLength(); int newOffset = myOffset; if (myOffset > oldEndOffset || myOffset == oldEndOffset && needToShiftWhiteSpaces(e)) { newOffset += e.getNewLength() - e.getOldLength(); } else if (myOffset >= startOffset && myOffset <= oldEndOffset) { newOffset = Math.min(newOffset, startOffset + e.getNewLength()); } newOffset = Math.min(newOffset, document.getTextLength()); // if (newOffset != myOffset) { moveToOffset(newOffset, performSoftWrapAdjustment); // } // else { // moveToVisualPosition(oldPosition); // } } myVisualLineStart = myEditor.logicalPositionToOffset( myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line, 0))); myVisualLineEnd = myEditor.logicalPositionToOffset( myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line + 1, 0))); }
void invalidateRange(int startOffset, int endOffset) { if (myDocument.isInBulkUpdate()) return; if (myDocument.isInEventsHandling()) { myDocumentChangeStartOffset = Math.min(myDocumentChangeStartOffset, startOffset); myDocumentChangeEndOffset = Math.max(myDocumentChangeEndOffset, endOffset); } else if (myFoldingChangeEndOffset != Integer.MIN_VALUE) { // during batch folding processing we delay invalidation requests, as we cannot perform // coordinate conversions immediately myFoldingChangeStartOffset = Math.min(myFoldingChangeStartOffset, startOffset); myFoldingChangeEndOffset = Math.max(myFoldingChangeEndOffset, endOffset); } else { doInvalidateRange(startOffset, endOffset); } }
private boolean isWhiteSpaceOrComment(@NotNull PsiElement element, @NotNull TextRange range) { final TextRange textRange = element.getTextRange(); TextRange intersection = range.intersection(textRange); if (intersection == null) { return false; } intersection = TextRange.create( Math.max(intersection.getStartOffset() - textRange.getStartOffset(), 0), Math.min( intersection.getEndOffset() - textRange.getStartOffset(), textRange.getLength())); return isWhiteSpaceOrComment(element) || intersection.substring(element.getText()).trim().length() == 0; }
private VerticalInfo createVerticalInfo(LogicalPosition position) { Document document = myEditor.getDocument(); int logicalLine = position.line; if (logicalLine >= document.getLineCount()) { logicalLine = Math.max(0, document.getLineCount() - 1); } int startOffset = document.getLineStartOffset(logicalLine); int endOffset = document.getLineEndOffset(logicalLine); // There is a possible case that active logical line is represented on multiple lines due to // soft wraps processing. // We want to highlight those visual lines as 'active' then, so, we calculate 'y' position for // the logical line start // and height in accordance with the number of occupied visual lines. VisualPosition visualPosition = myEditor.offsetToVisualPosition(document.getLineStartOffset(logicalLine)); int y = myEditor.visualPositionToXY(visualPosition).y; int lineHeight = myEditor.getLineHeight(); int height = lineHeight; List<? extends SoftWrap> softWraps = myEditor.getSoftWrapModel().getSoftWrapsForRange(startOffset, endOffset); for (SoftWrap softWrap : softWraps) { height += StringUtil.countNewLines(softWrap.getText()) * lineHeight; } return new VerticalInfo(y, height); }
int getVisualLineWidth( VisualLinesIterator visualLinesIterator, @Nullable Runnable quickEvaluationListener) { assert !visualLinesIterator.atEnd(); int visualLine = visualLinesIterator.getVisualLine(); FoldRegion[] topLevelRegions = myEditor.getFoldingModel().fetchTopLevel(); if (quickEvaluationListener != null && (topLevelRegions == null || topLevelRegions.length == 0) && myEditor.getSoftWrapModel().getRegisteredSoftWraps().isEmpty() && !myView.getTextLayoutCache().hasCachedLayoutFor(visualLine)) { // fast path - speeds up editor opening quickEvaluationListener.run(); return myView .getLogicalPositionCache() .offsetToLogicalColumn( visualLine, myDocument.getLineEndOffset(visualLine) - myDocument.getLineStartOffset(visualLine)) * myView.getMaxCharWidth(); } float x = 0; int maxOffset = visualLinesIterator.getVisualLineStartOffset(); for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, visualLinesIterator, quickEvaluationListener)) { x = fragment.getEndX(); maxOffset = Math.max(maxOffset, fragment.getMaxOffset()); } if (myEditor.getSoftWrapModel().getSoftWrap(maxOffset) != null) { x += myEditor .getSoftWrapModel() .getMinDrawingWidthInPixels(SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED); } return (int) x; }
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(); }
@Override public int compare(IteratorWrapper o1, IteratorWrapper o2) { if (o1 == null) { return 1; } if (o2 == null) { return -1; } int startDiff = Math.max(o1.iterator.getRangeStart(), myCurrentEnd) - Math.max(o2.iterator.getRangeStart(), myCurrentEnd); if (startDiff != 0) { return startDiff; } return o2.order - o1.order; }
public boolean fillInCommonPrefix(boolean explicitlyInvoked) { if (explicitlyInvoked) { setFocusDegree(FocusDegree.FOCUSED); } if (explicitlyInvoked && myCalculating) return false; if (!explicitlyInvoked && mySelectionTouched) return false; ListModel listModel = getListModel(); if (listModel.getSize() <= 1) return false; if (listModel.getSize() == 0) return false; final LookupElement firstItem = (LookupElement) listModel.getElementAt(0); if (listModel.getSize() == 1 && firstItem instanceof EmptyLookupItem) return false; final PrefixMatcher firstItemMatcher = itemMatcher(firstItem); final String oldPrefix = firstItemMatcher.getPrefix(); final String presentPrefix = oldPrefix + getAdditionalPrefix(); String commonPrefix = getCaseCorrectedLookupString(firstItem); for (int i = 1; i < listModel.getSize(); i++) { LookupElement item = (LookupElement) listModel.getElementAt(i); if (item instanceof EmptyLookupItem) return false; if (!oldPrefix.equals(itemMatcher(item).getPrefix())) return false; final String lookupString = getCaseCorrectedLookupString(item); final int length = Math.min(commonPrefix.length(), lookupString.length()); if (length < commonPrefix.length()) { commonPrefix = commonPrefix.substring(0, length); } for (int j = 0; j < length; j++) { if (commonPrefix.charAt(j) != lookupString.charAt(j)) { commonPrefix = lookupString.substring(0, j); break; } } if (commonPrefix.length() == 0 || commonPrefix.length() < presentPrefix.length()) { return false; } } if (commonPrefix.equals(presentPrefix)) { return false; } for (int i = 0; i < listModel.getSize(); i++) { LookupElement item = (LookupElement) listModel.getElementAt(i); if (!itemMatcher(item).cloneWithPrefix(commonPrefix).prefixMatches(item)) { return false; } } myOffsets.setInitialPrefix(presentPrefix, explicitlyInvoked); replacePrefix(presentPrefix, commonPrefix); return true; }
private void paintVirtualSelectionIfNecessary( Graphics2D g, Map<Integer, Couple<Integer>> virtualSelectionMap, int columnStart, float xStart, float xEnd, int y) { int visualLine = myView.yToVisualLine(y); Couple<Integer> selectionRange = virtualSelectionMap.get(visualLine); if (selectionRange == null || selectionRange.second <= columnStart) return; float startX = selectionRange.first <= columnStart ? xStart : myView.visualPositionToXY(new VisualPosition(visualLine, selectionRange.first)).x; float endX = Math.min( xEnd, myView.visualPositionToXY(new VisualPosition(visualLine, selectionRange.second)).x); paintBackground( g, myEditor.getColorsScheme().getColor(EditorColors.SELECTION_BACKGROUND_COLOR), startX, y, endX - startX); }
@Override public void advance() { int max = overlappingRangesCount == 0 ? myIterators.length : overlappingRangesCount; for (int i = 0; i < max; i++) { IteratorWrapper wrapper = myIterators[i]; if (wrapper == null) { continue; } RangeIterator iterator = wrapper.iterator; if (overlappingRangesCount > 0 && iterator.getRangeEnd() > myCurrentEnd) { continue; } if (iterator.atEnd()) { iterator.dispose(); myIterators[i] = null; } else { iterator.advance(); } } Arrays.sort(myIterators, RANGE_SORTER); myCurrentStart = Math.max(myIterators[0].iterator.getRangeStart(), myCurrentEnd); myCurrentEnd = Integer.MAX_VALUE; //noinspection ForLoopReplaceableByForEach for (int i = 0; i < myIterators.length; i++) { IteratorWrapper wrapper = myIterators[i]; if (wrapper == null) { break; } RangeIterator iterator = wrapper.iterator; int nearestBound; if (iterator.getRangeStart() > myCurrentStart) { nearestBound = iterator.getRangeStart(); } else { nearestBound = iterator.getRangeEnd(); } myCurrentEnd = Math.min(myCurrentEnd, nearestBound); } myCurrentEnd = getRangeEnd(); for (overlappingRangesCount = 1; overlappingRangesCount < myIterators.length; overlappingRangesCount++) { IteratorWrapper wrapper = myIterators[overlappingRangesCount]; if (wrapper == null || wrapper.iterator.getRangeStart() > myCurrentStart) { break; } } }
private void onSoftWrapRecalculationEnd(IncrementalCacheUpdateEvent event) { if (myDocument.isInBulkUpdate()) return; boolean invalidate = true; if (myEditor.getFoldingModel().isInBatchFoldingOperation()) { myFoldingChangeStartOffset = Math.min(myFoldingChangeStartOffset, event.getStartOffset()); myFoldingChangeEndOffset = Math.max(myFoldingChangeEndOffset, event.getActualEndOffset()); invalidate = false; } if (myDocument.isInEventsHandling()) { myDocumentChangeStartOffset = Math.min(myDocumentChangeStartOffset, event.getStartOffset()); myDocumentChangeEndOffset = Math.max(myDocumentChangeEndOffset, event.getActualEndOffset()); invalidate = false; } if (invalidate) { doInvalidateRange(event.getStartOffset(), event.getActualEndOffset()); } }
private int getPreferredWidth() { if (myWidthInPixels < 0) { assert !myDocument.isInBulkUpdate(); myWidthInPixels = calculatePreferredWidth(); } validateMaxLineWithExtension(); return Math.max(myWidthInPixels, myMaxLineWithExtensionWidth); }
private void updateLookupWidth(LookupElement item, LookupElementPresentation presentation) { final Font customFont = myCellRenderer.getFontAbleToDisplay(presentation); if (customFont != null) { myCustomFonts.put(item, customFont); } int maxWidth = myCellRenderer.updateMaximumWidth(presentation, item); myLookupTextWidth = Math.max(maxWidth, myLookupTextWidth); }
private void findNextSuitableRange() { myNextAttributes = null; while (myIterator.hasNext()) { RangeHighlighterEx highlighter = myIterator.next(); if (highlighter == null || !highlighter.isValid() || !isInterestedInLayer(highlighter.getLayer())) { continue; } // LINES_IN_RANGE highlighters are not supported currently myNextStart = Math.max(highlighter.getStartOffset(), myStartOffset); myNextEnd = Math.min(highlighter.getEndOffset(), myEndOffset); if (myNextStart >= myEndOffset) { break; } if (myNextStart < myCurrentEnd) { continue; // overlapping ranges withing document markup model are not supported currently } TextAttributes attributes = null; Object tooltip = highlighter.getErrorStripeTooltip(); if (tooltip instanceof HighlightInfo) { HighlightInfo info = (HighlightInfo) tooltip; TextAttributesKey key = info.forcedTextAttributesKey; if (key == null) { HighlightInfoType type = info.type; key = type.getAttributesKey(); } if (key != null) { attributes = myColorsScheme.getAttributes(key); } } if (attributes == null) { continue; } Color foreground = attributes.getForegroundColor(); Color background = attributes.getBackgroundColor(); if ((foreground == null || myDefaultForeground.equals(foreground)) && (background == null || myDefaultBackground.equals(background)) && attributes.getFontType() == Font.PLAIN) { continue; } myNextAttributes = attributes; break; } }
private void paintCaret(Graphics2D g_) { EditorImpl.CaretRectangle[] locations = myEditor.getCaretLocations(true); if (locations == null) return; Graphics2D g = IdeBackgroundUtil.getOriginalGraphics(g_); int lineHeight = myView.getLineHeight(); EditorSettings settings = myEditor.getSettings(); Color caretColor = myEditor.getColorsScheme().getColor(EditorColors.CARET_COLOR); if (caretColor == null) caretColor = new JBColor(CARET_DARK, CARET_LIGHT); g.setColor(caretColor); for (EditorImpl.CaretRectangle location : locations) { int x = location.myPoint.x; int y = location.myPoint.y; Caret caret = location.myCaret; boolean isRtl = location.myIsRtl; if (myEditor.isInsertMode() != settings.isBlockCursor()) { int lineWidth = JBUI.scale(settings.getLineCursorWidth()); g.fillRect(x, y, lineWidth, lineHeight); if (myDocument.getTextLength() > 0 && caret != null && !myView.getLineLayout(caret.getLogicalPosition().line).isLtr()) { g.fillPolygon( new int[] { isRtl ? x + lineWidth : x, isRtl ? x + lineWidth - CARET_DIRECTION_MARK_SIZE : x + CARET_DIRECTION_MARK_SIZE, isRtl ? x + lineWidth : x }, new int[] {y, y, y + CARET_DIRECTION_MARK_SIZE}, 3); } } else { int width = location.myWidth; int startX = Math.max(0, isRtl ? x - width : x); g.fillRect(startX, y, width, lineHeight - 1); if (myDocument.getTextLength() > 0 && caret != null) { int targetVisualColumn = caret.getVisualPosition().column; for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, caret.getVisualLineStart(), false)) { int startVisualColumn = fragment.getStartVisualColumn(); int endVisualColumn = fragment.getEndVisualColumn(); if (startVisualColumn < targetVisualColumn && endVisualColumn > targetVisualColumn || startVisualColumn == targetVisualColumn && !isRtl || endVisualColumn == targetVisualColumn && isRtl) { g.setColor(ColorUtil.isDark(caretColor) ? CARET_LIGHT : CARET_DARK); fragment.draw( g, startX, y + myView.getAscent(), targetVisualColumn - startVisualColumn - (isRtl ? 1 : 0), targetVisualColumn - startVisualColumn + (isRtl ? 0 : 1)); break; } } } } } }
private int wrapPositionForTextWithoutTabs( int startLineOffset, int endLineOffset, int targetRangeEndOffset) { if (Math.min(endLineOffset, targetRangeEndOffset) - startLineOffset > mySettings.RIGHT_MARGIN) { return startLineOffset + mySettings.RIGHT_MARGIN - FormatConstants.RESERVED_LINE_WRAP_WIDTH_IN_COLUMNS; } return -1; }
private boolean isLineEmpty(final int line) { final CharSequence chars = myDocument.getCharsSequence(); int start = myDocument.getLineStartOffset(line); int end = Math.min(myDocument.getLineEndOffset(line), myDocument.getTextLength() - 1); for (int i = start; i <= end; i++) { if (!Character.isWhitespace(chars.charAt(i))) return false; } return true; }
public int getEndOffset(@NotNull FoldingGroup group) { final List<FoldRegion> regions = getGroupedRegions(group); int endOffset = 0; for (FoldRegion region : regions) { if (region.isValid()) { endOffset = Math.max(endOffset, region.getEndOffset()); } } return endOffset; }
private void paintComposedTextDecoration(Graphics2D g) { TextRange composedTextRange = myEditor.getComposedTextRange(); if (composedTextRange != null) { Point p1 = myView.offsetToXY( Math.min(composedTextRange.getStartOffset(), myDocument.getTextLength()), true, false); Point p2 = myView.offsetToXY( Math.min(composedTextRange.getEndOffset(), myDocument.getTextLength()), false, true); int y = p1.y + myView.getAscent() + 1; g.setStroke(IME_COMPOSED_TEXT_UNDERLINE_STROKE); g.setColor(myEditor.getColorsScheme().getDefaultForeground()); UIUtil.drawLine(g, p1.x, y, p2.x, y); } }
private int wrapPositionForTabbedTextWithoutOptimization( @NotNull Editor editor, @NotNull CharSequence text, int spaceSize, int startLineOffset, int endLineOffset, int targetRangeEndOffset) { int width = 0; int x = 0; int newX; int symbolWidth; int result = Integer.MAX_VALUE; boolean wrapLine = false; for (int i = startLineOffset; i < Math.min(endLineOffset, targetRangeEndOffset); i++) { char c = text.charAt(i); switch (c) { case '\t': newX = EditorUtil.nextTabStop(x, editor); int diffInPixels = newX - x; symbolWidth = diffInPixels / spaceSize; if (diffInPixels % spaceSize > 0) { symbolWidth++; } break; default: newX = x + EditorUtil.charWidth(c, Font.PLAIN, editor); symbolWidth = 1; } if (width + symbolWidth + FormatConstants.RESERVED_LINE_WRAP_WIDTH_IN_COLUMNS >= mySettings.RIGHT_MARGIN && (Math.min(endLineOffset, targetRangeEndOffset) - i) >= FormatConstants.RESERVED_LINE_WRAP_WIDTH_IN_COLUMNS) { result = i - 1; } if (width + symbolWidth >= mySettings.RIGHT_MARGIN) { wrapLine = true; break; } x = newX; width += symbolWidth; } return wrapLine ? result : -1; }
private int calculatePreferredWidth() { if (checkDirty()) return 1; assertValidState(); VisualLinesIterator iterator = new VisualLinesIterator(myView, 0); int maxWidth = 0; while (!iterator.atEnd()) { int visualLine = iterator.getVisualLine(); int width = myLineWidths.get(visualLine); if (width == UNKNOWN_WIDTH) { final Ref<Boolean> approximateValue = new Ref<Boolean>(Boolean.FALSE); width = getVisualLineWidth(iterator, () -> approximateValue.set(Boolean.TRUE)); if (approximateValue.get()) width = -width; myLineWidths.set(visualLine, width); } maxWidth = Math.max(maxWidth, Math.abs(width)); iterator.advance(); } return maxWidth; }
private void updateListHeight(ListModel model) { myList.setFixedCellHeight( myCellRenderer .getListCellRendererComponent(myList, model.getElementAt(0), 0, false, false) .getPreferredSize() .height); myList.setVisibleRowCount( Math.min(model.getSize(), UISettings.getInstance().MAX_LOOKUP_LIST_HEIGHT)); }
void repaintCarets() { EditorImpl.CaretRectangle[] locations = myEditor.getCaretLocations(false); if (locations == null) return; int lineHeight = myView.getLineHeight(); for (EditorImpl.CaretRectangle location : locations) { int x = location.myPoint.x; int y = location.myPoint.y; int width = Math.max(location.myWidth, CARET_DIRECTION_MARK_SIZE); myEditor.getContentComponent().repaintEditorComponent(x - width, y, width * 2, lineHeight); } }