mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
paint caret directionality mark
This commit is contained in:
@@ -4607,10 +4607,11 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
private void setCursorPosition() {
|
||||
final List<CaretRectangle> caretPoints = new ArrayList<CaretRectangle>();
|
||||
for (Caret caret : getCaretModel().getAllCarets()) {
|
||||
boolean isRtl = myUseNewRendering && myView.isRtlLocation(caret.getOffset());
|
||||
VisualPosition caretPosition = caret.getVisualPosition();
|
||||
Point pos1 = visualPositionToXY(caretPosition);
|
||||
Point pos2 = visualPositionToXY(new VisualPosition(caretPosition.line, caretPosition.column + 1));
|
||||
caretPoints.add(new CaretRectangle(pos1, pos2.x - pos1.x, caret));
|
||||
Point pos2 = visualPositionToXY(new VisualPosition(caretPosition.line, Math.max(0, caretPosition.column + (isRtl ? -1 : 1))));
|
||||
caretPoints.add(new CaretRectangle(pos1, Math.abs(pos2.x - pos1.x), caret, isRtl));
|
||||
}
|
||||
myCaretCursor.setPositions(caretPoints.toArray(new CaretRectangle[caretPoints.size()]));
|
||||
}
|
||||
@@ -4681,11 +4682,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
public final Point myPoint;
|
||||
public final int myWidth;
|
||||
public final Caret myCaret;
|
||||
public final boolean myIsRtl;
|
||||
|
||||
private CaretRectangle(Point point, int width, Caret caret) {
|
||||
private CaretRectangle(Point point, int width, Caret caret, boolean isRtl) {
|
||||
myPoint = point;
|
||||
myWidth = Math.max(width, 2);
|
||||
myCaret = caret;
|
||||
myIsRtl = isRtl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4698,7 +4701,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
private long myStartTime = 0;
|
||||
|
||||
private CaretCursor() {
|
||||
myLocations = new CaretRectangle[] {new CaretRectangle(new Point(0, 0), 0, null)};
|
||||
myLocations = new CaretRectangle[] {new CaretRectangle(new Point(0, 0), 0, null, false)};
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
@@ -4743,8 +4746,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
|
||||
private void repaint() {
|
||||
for (CaretRectangle location : myLocations) {
|
||||
myEditorComponent.repaintEditorComponent(location.myPoint.x, location.myPoint.y, location.myWidth, getLineHeight());
|
||||
if (myUseNewRendering) {
|
||||
myView.repaintCarets();
|
||||
}
|
||||
else {
|
||||
for (CaretRectangle location : myLocations) {
|
||||
myEditorComponent.repaintEditorComponent(location.myPoint.x, location.myPoint.y, location.myWidth, getLineHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+50
-26
@@ -52,6 +52,7 @@ class EditorPainter {
|
||||
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,
|
||||
new float[]{0, 2, 0, 2}, 0);
|
||||
private static final int CARET_DIRECTION_MARK_SIZE = 5;
|
||||
|
||||
private final EditorView myView;
|
||||
private final EditorImpl myEditor;
|
||||
@@ -636,46 +637,69 @@ class EditorPainter {
|
||||
}
|
||||
}
|
||||
|
||||
private void paintCaret(Graphics2D g) {
|
||||
private void paintCaret(Graphics2D g_) {
|
||||
EditorImpl.CaretRectangle[] locations = myEditor.getCaretLocations();
|
||||
if (locations == null) return;
|
||||
for (EditorImpl.CaretRectangle location : locations) {
|
||||
paintCaretAt(g, location.myPoint.x, location.myPoint.y, location.myWidth, location.myCaret);
|
||||
}
|
||||
}
|
||||
|
||||
private void paintCaretAt(Graphics2D g_, int x, int y, int width, Caret caret) {
|
||||
|
||||
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);
|
||||
|
||||
if (myEditor.isInsertMode() != settings.isBlockCursor()) {
|
||||
if (UIUtil.isRetina()) {
|
||||
g.fillRect(x, y, settings.getLineCursorWidth(), lineHeight);
|
||||
} else {
|
||||
for (int i = 0; i < settings.getLineCursorWidth(); i++) {
|
||||
UIUtil.drawLine(g, x + i, y, x + i, y + lineHeight - 1);
|
||||
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 = 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 - 1 : x,
|
||||
isRtl ? x + lineWidth - 1 - CARET_DIRECTION_MARK_SIZE : x + CARET_DIRECTION_MARK_SIZE,
|
||||
isRtl ? x + lineWidth - 1 : x
|
||||
},
|
||||
new int[]{y, y, y + CARET_DIRECTION_MARK_SIZE}, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
g.fillRect(Math.min(x, x + width), y, Math.abs(width), lineHeight - 1);
|
||||
int targetVisualColumn = caret.getVisualPosition().column;
|
||||
for (VisualLineFragmentsIterator.Fragment fragment : VisualLineFragmentsIterator.create(myView, caret.getVisualLineStart())) {
|
||||
int startVisualColumn = fragment.getStartVisualColumn();
|
||||
int endVisualColumn = fragment.getEndVisualColumn();
|
||||
if (startVisualColumn <= targetVisualColumn && endVisualColumn > targetVisualColumn) {
|
||||
g.setColor(ColorUtil.isDark(caretColor) ? CARET_LIGHT : CARET_DARK);
|
||||
fragment.draw(g, x, y + myView.getAscent(), targetVisualColumn - startVisualColumn, targetVisualColumn - startVisualColumn + 1);
|
||||
break;
|
||||
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())) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void repaintCarets() {
|
||||
EditorImpl.CaretRectangle[] locations = myEditor.getCaretLocations();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void paintLineFragments(Graphics2D g, Rectangle clip, int visualLine, int y, LineFragmentPainter painter) {
|
||||
float x = visualLine == 0 ? myView.getPrefixTextWidthInPixels() : 0;
|
||||
LogicalPosition logicalPosition = myView.visualToLogicalPosition(new VisualPosition(visualLine, 0), false);
|
||||
|
||||
@@ -198,6 +198,11 @@ public class EditorView implements Disposable {
|
||||
myPainter.paint(g);
|
||||
}
|
||||
|
||||
public void repaintCarets() {
|
||||
assertIsDispatchThread();
|
||||
myPainter.repaintCarets();
|
||||
}
|
||||
|
||||
public Dimension getPreferredSize() {
|
||||
assertIsDispatchThread();
|
||||
return mySizeManager.getPreferredSize();
|
||||
@@ -254,6 +259,13 @@ public class EditorView implements Disposable {
|
||||
mySizeManager.reset();
|
||||
myTextLayoutCache.resetToDocumentSize();
|
||||
}
|
||||
|
||||
public boolean isRtlLocation(int offset) {
|
||||
if (myDocument.getTextLength() == 0) return false;
|
||||
int line = myDocument.getLineNumber(offset);
|
||||
LineLayout layout = getLineLayout(line);
|
||||
return layout.isRtlLocation(offset - myDocument.getLineStartOffset(line));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
LineLayout getLineLayout(int line) {
|
||||
|
||||
@@ -200,6 +200,17 @@ class LineLayout {
|
||||
};
|
||||
}
|
||||
|
||||
boolean isLtr() {
|
||||
return myBidiRunsInLogicalOrder.length == 0 || myBidiRunsInLogicalOrder.length == 1 && !myBidiRunsInLogicalOrder[0].isRtl();
|
||||
}
|
||||
|
||||
boolean isRtlLocation(int offset) {
|
||||
for (BidiRun run : myBidiRunsInLogicalOrder) {
|
||||
if (offset < run.endOffset) return run.isRtl();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class BidiRun {
|
||||
private final byte level;
|
||||
private final int startOffset;
|
||||
|
||||
Reference in New Issue
Block a user