mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-183039 Invisible right margin
updated implementation as per discussion in ticket
This commit is contained in:
@@ -19,10 +19,12 @@ import com.intellij.openapi.editor.ex.FoldingModelEx;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
|
||||
import com.intellij.openapi.editor.impl.softwrap.SoftWrapHelper;
|
||||
import com.intellij.openapi.editor.impl.view.EditorPainter;
|
||||
import com.intellij.openapi.ide.CopyPasteManager;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.DocumentUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -509,16 +511,19 @@ public class CaretImpl extends UserDataHolderBase implements Caret, Dumpable {
|
||||
final EditorComponentImpl content = myEditor.getContentComponent();
|
||||
|
||||
int updateWidth = myEditor.getScrollPane().getHorizontalScrollBar().getValue() + visibleArea.width;
|
||||
int additionalRepaintHeight = this == myEditor.getCaretModel().getPrimaryCaret() && Registry.is("editor.adjust.right.margin") && EditorPainter.isMarginShown(myEditor) ? 1 : 0;
|
||||
if (Math.abs(myCaretInfo.y - oldCaretInfo.y) <= 2 * lineHeight) {
|
||||
int minY = Math.min(oldCaretInfo.y, myCaretInfo.y);
|
||||
int maxY = Math.max(oldCaretInfo.y + oldCaretInfo.height, myCaretInfo.y + myCaretInfo.height);
|
||||
content.repaintEditorComponent(0, minY, updateWidth, maxY - minY);
|
||||
content.repaintEditorComponent(0, minY - additionalRepaintHeight, updateWidth, maxY - minY + additionalRepaintHeight);
|
||||
gutter.repaint(0, minY, gutter.getWidth(), maxY - minY);
|
||||
}
|
||||
else {
|
||||
content.repaintEditorComponent(0, oldCaretInfo.y, updateWidth, oldCaretInfo.height + lineHeight);
|
||||
content.repaintEditorComponent(0, oldCaretInfo.y - additionalRepaintHeight,
|
||||
updateWidth, oldCaretInfo.height + lineHeight + additionalRepaintHeight);
|
||||
gutter.repaint(0, oldCaretInfo.y, updateWidth, oldCaretInfo.height + lineHeight);
|
||||
content.repaintEditorComponent(0, myCaretInfo.y, updateWidth, myCaretInfo.height + lineHeight);
|
||||
content.repaintEditorComponent(0, myCaretInfo.y - additionalRepaintHeight,
|
||||
updateWidth, myCaretInfo.height + lineHeight + additionalRepaintHeight);
|
||||
gutter.repaint(0, myCaretInfo.y, updateWidth, myCaretInfo.height + lineHeight);
|
||||
}
|
||||
}
|
||||
|
||||
+53
-50
@@ -13,7 +13,6 @@ import com.intellij.openapi.editor.impl.softwrap.SoftWrapDrawingType;
|
||||
import com.intellij.openapi.editor.markup.*;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.impl.IdeBackgroundUtil;
|
||||
@@ -40,7 +39,7 @@ import java.util.Map;
|
||||
/**
|
||||
* Renders editor contents.
|
||||
*/
|
||||
class EditorPainter implements TextDrawingCallback {
|
||||
public class EditorPainter implements TextDrawingCallback {
|
||||
private static final Color CARET_LIGHT = Gray._255;
|
||||
private static final Color CARET_DARK = Gray._0;
|
||||
private static final Stroke IME_COMPOSED_TEXT_UNDERLINE_STROKE = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0,
|
||||
@@ -87,8 +86,8 @@ class EditorPainter implements TextDrawingCallback {
|
||||
int yShift = -clip.y;
|
||||
g.translate(0, -yShift);
|
||||
|
||||
float[] marginShifts = paintBackground(g, clip, yShift, startLine, endLine, caretData);
|
||||
paintRightMargin(g, clip, yShift, startLine, endLine, marginShifts);
|
||||
float[] marginWidths = paintBackground(g, clip, yShift, startLine, endLine, caretData);
|
||||
paintRightMargin(g, clip, yShift, startLine, endLine, marginWidths);
|
||||
paintCustomRenderers(g, yShift, startOffset, endOffset);
|
||||
MarkupModelEx docMarkup = myEditor.getFilteredDocumentMarkupModel();
|
||||
paintLineMarkersSeparators(g, clip, yShift, docMarkup, startOffset, endOffset);
|
||||
@@ -143,19 +142,24 @@ class EditorPainter implements TextDrawingCallback {
|
||||
int yShift,
|
||||
int startVisualLine,
|
||||
int endVisualLine,
|
||||
float[] marginShifts) {
|
||||
float[] marginWidths) {
|
||||
if (!isMarginShown()) return;
|
||||
g.setColor(myEditor.getColorsScheme().getColor(EditorColors.RIGHT_MARGIN_COLOR));
|
||||
if (marginShifts == null) {
|
||||
int x = myCorrector.marginX();
|
||||
float baseMarginWidth = getBaseMarginWidth(myView);
|
||||
if (marginWidths == null) {
|
||||
int x = myCorrector.marginX(baseMarginWidth);
|
||||
UIUtil.drawLine(g, x, 0, x, clip.height);
|
||||
}
|
||||
else {
|
||||
int y = myView.visualLineToY(startVisualLine) + yShift;
|
||||
int lineHeight = myView.getLineHeight();
|
||||
for(int i = startVisualLine; i <= endVisualLine; i++) {
|
||||
int x = myCorrector.marginX(marginShifts[i - startVisualLine]);
|
||||
int nextX = myCorrector.marginX(marginShifts[i - startVisualLine + 1]);
|
||||
float width = marginWidths[i - startVisualLine];
|
||||
if (width == 0) width = baseMarginWidth;
|
||||
float nextWidth = marginWidths[i - startVisualLine + 1];
|
||||
if (nextWidth == 0) nextWidth = baseMarginWidth;
|
||||
int x = myCorrector.marginX(width);
|
||||
int nextX = myCorrector.marginX(nextWidth);
|
||||
g.fillRect(x, y, 1, lineHeight);
|
||||
if (nextX != x) g.fillRect(Math.min(x, nextX), y + lineHeight - 1, Math.abs(x - nextX) + 1, 1);
|
||||
y += lineHeight;
|
||||
@@ -170,11 +174,16 @@ class EditorPainter implements TextDrawingCallback {
|
||||
}
|
||||
}
|
||||
|
||||
private static float getBaseMarginWidth(EditorView view) {
|
||||
Editor editor = view.getEditor();
|
||||
return editor.getSettings().getRightMargin(editor.getProject()) * view.getPlainSpaceWidth();
|
||||
}
|
||||
|
||||
private boolean isMarginShown() {
|
||||
return isMarginShown(myEditor);
|
||||
}
|
||||
|
||||
private static boolean isMarginShown(@NotNull Editor editor) {
|
||||
public static boolean isMarginShown(@NotNull Editor editor) {
|
||||
return editor.getSettings().isRightMarginShown() &&
|
||||
editor.getColorsScheme().getColor(EditorColors.RIGHT_MARGIN_COLOR) != null &&
|
||||
(Registry.is("editor.show.right.margin.in.read.only.files") || editor.getDocument().isWritable());
|
||||
@@ -182,9 +191,9 @@ class EditorPainter implements TextDrawingCallback {
|
||||
|
||||
private float[] paintBackground(Graphics2D g, Rectangle clip, int yShift,
|
||||
int startVisualLine, int endVisualLine, IterationState.CaretData caretData) {
|
||||
Ref<float[]> marginShifts = new Ref<>();
|
||||
boolean calculateMarginShift = Registry.is("editor.adjust.right.margin") && isMarginShown();
|
||||
int maxVisualLine = endVisualLine + (calculateMarginShift ? 1 : 0);
|
||||
boolean calculateMarginWidths = Registry.is("editor.adjust.right.margin") && isMarginShown();
|
||||
float[] marginWidths = calculateMarginWidths ? new float[endVisualLine - startVisualLine + 2] : null;
|
||||
int maxVisualLine = endVisualLine + (calculateMarginWidths ? 1 : 0);
|
||||
int lineCount = myEditor.getVisibleLineCount();
|
||||
|
||||
final Map<Integer, Couple<Integer>> virtualSelectionMap = createVirtualSelectionMap(startVisualLine, endVisualLine);
|
||||
@@ -240,13 +249,11 @@ class EditorPainter implements TextDrawingCallback {
|
||||
primarySelectionStart, primarySelectionEnd);
|
||||
}
|
||||
}
|
||||
}, calculateMarginShift ? shift -> {
|
||||
if (marginShifts.isNull()) marginShifts.set(new float[endVisualLine - startVisualLine + 2]);
|
||||
marginShifts.get()[visualLine - startVisualLine] += shift;
|
||||
} : null);
|
||||
}, calculateMarginWidths && !visLinesIterator.endsWithSoftWrap() && !visLinesIterator.startsWithSoftWrap()
|
||||
? width -> marginWidths[visualLine - startVisualLine] = width : null);
|
||||
visLinesIterator.advance();
|
||||
}
|
||||
return marginShifts.get();
|
||||
return marginWidths;
|
||||
}
|
||||
|
||||
private void paintFoldingBackground(Graphics2D g, TextAttributes attributes, float x, int y, float width, FoldRegion foldRegion) {
|
||||
@@ -1017,12 +1024,12 @@ class EditorPainter implements TextDrawingCallback {
|
||||
}
|
||||
}
|
||||
|
||||
private interface MarginShiftConsumer {
|
||||
void process(float shift);
|
||||
private interface MarginWidthConsumer {
|
||||
void process(float width);
|
||||
}
|
||||
|
||||
private void paintLineFragments(Graphics2D g, Rectangle clip, VisualLinesIterator visLineIterator, IterationState.CaretData caretData,
|
||||
int y, LineFragmentPainter painter, MarginShiftConsumer marginShiftConsumer) {
|
||||
int y, LineFragmentPainter painter, MarginWidthConsumer marginWidthConsumer) {
|
||||
int visualLine = visLineIterator.getVisualLine();
|
||||
float x = myCorrector.startX(visualLine) + (visualLine == 0 ? myView.getPrefixTextWidthInPixels() : 0);
|
||||
int offset = visLineIterator.getVisualLineStartOffset();
|
||||
@@ -1031,6 +1038,9 @@ class EditorPainter implements TextDrawingCallback {
|
||||
int prevEndOffset = -1;
|
||||
boolean firstFragment = true;
|
||||
int maxColumn = 0;
|
||||
int marginColumns = myEditor.getSettings().getRightMargin(myEditor.getProject());
|
||||
int endLogicalLine = visLineIterator.getEndLogicalLine();
|
||||
boolean marginReached = false;
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, visLineIterator, null, true)) {
|
||||
int fragmentStartOffset = fragment.getStartOffset();
|
||||
int start = fragmentStartOffset;
|
||||
@@ -1054,11 +1064,10 @@ class EditorPainter implements TextDrawingCallback {
|
||||
}
|
||||
}
|
||||
}
|
||||
float marginShift = 0;
|
||||
FoldRegion foldRegion = fragment.getCurrentFoldRegion();
|
||||
if (foldRegion == null) {
|
||||
if (start != prevEndOffset) {
|
||||
it = new IterationState(myEditor, start, fragment.isRtl() ? offset : visualLineEndOffset,
|
||||
it = new IterationState(myEditor, start, fragment.isRtl() ? offset : visualLineEndOffset,
|
||||
caretData, false, false, false, fragment.isRtl());
|
||||
}
|
||||
prevEndOffset = end;
|
||||
@@ -1072,7 +1081,6 @@ class EditorPainter implements TextDrawingCallback {
|
||||
if (xNew >= clip.getMinX()) {
|
||||
painter.paint(g, fragment, 0, 0, attributes, x, xNew, y);
|
||||
}
|
||||
if (marginShiftConsumer != null) marginShift = xNew - x;
|
||||
x = xNew;
|
||||
}
|
||||
else {
|
||||
@@ -1093,6 +1101,11 @@ class EditorPainter implements TextDrawingCallback {
|
||||
x = xNew;
|
||||
start = curEnd;
|
||||
}
|
||||
if (marginWidthConsumer != null && fragment.getEndLogicalLine() == endLogicalLine &&
|
||||
fragment.getStartLogicalColumn() <= marginColumns && fragment.getEndLogicalColumn() > marginColumns) {
|
||||
marginWidthConsumer.process(fragment.visualColumnToX(fragment.logicalToVisualColumn(marginColumns)));
|
||||
marginReached = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1103,10 +1116,7 @@ class EditorPainter implements TextDrawingCallback {
|
||||
x = xNew;
|
||||
prevEndOffset = -1;
|
||||
it = null;
|
||||
if (marginShiftConsumer != null) marginShift = x - myCorrector.startX(visualLine)
|
||||
- fragment.getEndLogicalColumn() * myView.getPlainSpaceWidth();
|
||||
}
|
||||
if (marginShift != 0) marginShiftConsumer.process(marginShift);
|
||||
if (x > clip.getMaxX()) return;
|
||||
maxColumn = fragment.getEndVisualColumn();
|
||||
}
|
||||
@@ -1118,8 +1128,8 @@ class EditorPainter implements TextDrawingCallback {
|
||||
painter.paintBeforeLineStart(g, it.getBeforeLineStartBackgroundAttributes(), false, maxColumn, x, y);
|
||||
}
|
||||
if (it == null || it.getEndOffset() != visualLineEndOffset) {
|
||||
it = new IterationState(myEditor, visualLineEndOffset == offset ? visualLineEndOffset
|
||||
: DocumentUtil.getPreviousCodePointOffset(myDocument, visualLineEndOffset),
|
||||
it = new IterationState(myEditor, visualLineEndOffset == offset
|
||||
? visualLineEndOffset : DocumentUtil.getPreviousCodePointOffset(myDocument, visualLineEndOffset),
|
||||
visualLineEndOffset, caretData, false, false, false, false);
|
||||
}
|
||||
if (!it.atEnd()) {
|
||||
@@ -1127,6 +1137,13 @@ class EditorPainter implements TextDrawingCallback {
|
||||
}
|
||||
assert it.atEnd();
|
||||
painter.paintAfterLineEnd(g, clip, it, maxColumn, x, y);
|
||||
if (marginWidthConsumer != null && !marginReached &&
|
||||
(visualLine == myEditor.getCaretModel().getVisualPosition().line || x > marginColumns * myView.getPlainSpaceWidth())) {
|
||||
int endLogicalColumn = myView.offsetToLogicalPosition(visualLineEndOffset).column;
|
||||
if (endLogicalColumn < marginColumns) {
|
||||
marginWidthConsumer.process(x + (marginColumns - endLogicalColumn) * myView.getPlainSpaceWidth());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TextAttributes getFoldRegionAttributes(FoldRegion foldRegion) {
|
||||
@@ -1225,8 +1242,7 @@ class EditorPainter implements TextDrawingCallback {
|
||||
int lineSeparatorEnd(int maxX);
|
||||
float singleLineBorderStart(float x);
|
||||
float singleLineBorderEnd(float x);
|
||||
int marginX();
|
||||
int marginX(float shift);
|
||||
int marginX(float marginWidth);
|
||||
List<Integer> softMarginsX();
|
||||
|
||||
@NotNull
|
||||
@@ -1289,18 +1305,12 @@ class EditorPainter implements TextDrawingCallback {
|
||||
|
||||
@Override
|
||||
public int lineSeparatorEnd(int maxX) {
|
||||
return isMarginShown(myView.getEditor()) ? Math.min(marginX(), maxX) : maxX;
|
||||
return isMarginShown(myView.getEditor()) ? Math.min(marginX(getBaseMarginWidth(myView)), maxX) : maxX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int marginX() {
|
||||
EditorImpl editor = myView.getEditor();
|
||||
return (int) (myView.getInsets().left + editor.getSettings().getRightMargin(editor.getProject()) * myView.getPlainSpaceWidth());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int marginX(float shift) {
|
||||
return marginX() + (int)shift;
|
||||
public int marginX(float marginWidth) {
|
||||
return (int)(myView.getInsets().left + marginWidth);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1358,7 +1368,7 @@ class EditorPainter implements TextDrawingCallback {
|
||||
|
||||
@Override
|
||||
public int lineSeparatorStart(int minX) {
|
||||
return isMarginShown(myView.getEditor()) ? Math.max(marginX(), minX) : minX;
|
||||
return isMarginShown(myView.getEditor()) ? Math.max(marginX(getBaseMarginWidth(myView)), minX) : minX;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1367,15 +1377,8 @@ class EditorPainter implements TextDrawingCallback {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int marginX() {
|
||||
EditorImpl editor = myView.getEditor();
|
||||
return (int) (myView.getRightAlignmentMarginX() -
|
||||
editor.getSettings().getRightMargin(editor.getProject()) * myView.getPlainSpaceWidth());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int marginX(float shift) {
|
||||
return marginX() - (int)shift;
|
||||
public int marginX(float marginWidth) {
|
||||
return (int)(myView.getRightAlignmentMarginX() - marginWidth);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+33
-25
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.editor.impl.view;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
@@ -59,6 +45,13 @@ public class VisualLinesIterator {
|
||||
}
|
||||
}
|
||||
|
||||
private void setNextLocation() {
|
||||
if (myNextLocation == null) {
|
||||
myNextLocation = myLocation.clone();
|
||||
myNextLocation.advance();
|
||||
}
|
||||
}
|
||||
|
||||
public int getVisualLine() {
|
||||
checkEnd();
|
||||
return myLocation.visualLine;
|
||||
@@ -68,23 +61,27 @@ public class VisualLinesIterator {
|
||||
checkEnd();
|
||||
return myLocation.offset;
|
||||
}
|
||||
|
||||
|
||||
public int getVisualLineEndOffset() {
|
||||
checkEnd();
|
||||
if (myNextLocation == null) {
|
||||
myNextLocation = myLocation.clone();
|
||||
myNextLocation.advance();
|
||||
}
|
||||
return myNextLocation.atEnd() ? myDocument.getTextLength() :
|
||||
myNextLocation.softWrap == myLocation.softWrap ? myDocument.getLineEndOffset(myNextLocation.logicalLine - 2) :
|
||||
setNextLocation();
|
||||
return myNextLocation.atEnd() ? myDocument.getTextLength() :
|
||||
myNextLocation.softWrap == myLocation.softWrap ? myDocument.getLineEndOffset(myNextLocation.logicalLine - 2) :
|
||||
myNextLocation.offset;
|
||||
}
|
||||
|
||||
|
||||
public int getStartLogicalLine() {
|
||||
checkEnd();
|
||||
return myLocation.logicalLine - 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getEndLogicalLine() {
|
||||
checkEnd();
|
||||
setNextLocation();
|
||||
return myNextLocation.atEnd() ? myDocument.getLineCount() - 1
|
||||
: myNextLocation.logicalLine - (myNextLocation.softWrap == myLocation.softWrap ? 2 : 1);
|
||||
}
|
||||
|
||||
public int getStartOrPrevWrapIndex() {
|
||||
checkEnd();
|
||||
return myLocation.softWrap - 1;
|
||||
@@ -100,6 +97,17 @@ public class VisualLinesIterator {
|
||||
return myLocation.y;
|
||||
}
|
||||
|
||||
public boolean startsWithSoftWrap() {
|
||||
checkEnd();
|
||||
return myLocation.softWrap > 0 && myLocation.softWrap <= mySoftWraps.size() &&
|
||||
mySoftWraps.get(myLocation.softWrap - 1).getStart() == myLocation.offset;
|
||||
}
|
||||
|
||||
public boolean endsWithSoftWrap() {
|
||||
checkEnd();
|
||||
return myLocation.softWrap < mySoftWraps.size() && mySoftWraps.get(myLocation.softWrap).getStart() == getVisualLineEndOffset();
|
||||
}
|
||||
|
||||
private void checkEnd() {
|
||||
if (atEnd()) throw new IllegalStateException("Iteration finished");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user