Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
*/
package org.eclipse.jface.text.source.inlined;

import java.util.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
Expand Down Expand Up @@ -43,6 +45,16 @@ class InlinedAnnotationDrawingStrategy implements IDrawingStrategy {

private final ITextViewer viewer;

private static final char ZW_SPACE= '\u200b';

private static final char ZW_NON_JOINER= '\u200c';

private static final char ZW_JOINER= '\u200d';

private static final char ZW_NO_BREAK_SPACE= '\ufeff';

private static final Set<Character> ZW_CHARACTERS= Set.of(ZW_SPACE, ZW_NON_JOINER, ZW_JOINER, ZW_NO_BREAK_SPACE);

public InlinedAnnotationDrawingStrategy(ITextViewer viewer) {
this.viewer = viewer;
}
Expand Down Expand Up @@ -436,13 +448,17 @@ protected static void drawAsLeftOf1stCharacter(LineContentAnnotation annotation,
// Get size of the character where GlyphMetrics width is added
Point charBounds= gc.stringExtent(hostCharacter);
int charWidth= charBounds.x;
if (charWidth == 0 && ("\r".equals(hostCharacter) || "\n".equals(hostCharacter))) { //$NON-NLS-1$ //$NON-NLS-2$
boolean isZeroWidthCharacter= false;
if (hostCharacter.length() == 1 && ZW_CHARACTERS.contains(hostCharacter.charAt(0))) {
isZeroWidthCharacter= true;
charWidth= 0;
} else if (charWidth == 0 && ("\r".equals(hostCharacter) || "\n".equals(hostCharacter))) { //$NON-NLS-1$ //$NON-NLS-2$
// charWidth is 0 for '\r' on font Consolas, but not on other fonts, why?
charWidth= gc.stringExtent(" ").x; //$NON-NLS-1$
}
// FIXME: remove this code when we need not redraw the character (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=531769)
// START TO REMOVE
annotation.setRedrawnCharacterWidth(charWidth);
annotation.setRedrawnCharacterWidth(charWidth, isZeroWidthCharacter);
// END TO REMOVE

// Annotation takes place, add GlyphMetrics width to the style
Expand Down Expand Up @@ -523,6 +539,11 @@ protected static void drawAsRightOfPreviousCharacter(LineContentAnnotation annot
char hostCharacter= textWidget.getText(widgetOffset - 1, widgetOffset - 1).charAt(0);
// use gc.stringExtent instead of gc.geCharWidth because of bug 548866
int redrawnCharacterWidth= hostCharacter != '\t' ? gc.stringExtent(Character.toString(hostCharacter)).x : textWidget.getTabs() * gc.stringExtent(" ").x; //$NON-NLS-1$
boolean isZeroWidthCharacter= false;
if (ZW_CHARACTERS.contains(hostCharacter)) {
redrawnCharacterWidth= 0;
isZeroWidthCharacter= true;
}
Rectangle charBounds= textWidget.getTextBounds(widgetOffset - 1, widgetOffset - 1);
Rectangle annotationBounds= new Rectangle(charBounds.x + redrawnCharacterWidth, charBounds.y, annotation.getWidth(), charBounds.height);

Expand All @@ -539,7 +560,7 @@ protected static void drawAsRightOfPreviousCharacter(LineContentAnnotation annot
if (width != 0) {
// FIXME: remove this code when we need not redraw the character (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=531769)
// START TO REMOVE
annotation.setRedrawnCharacterWidth(redrawnCharacterWidth);
annotation.setRedrawnCharacterWidth(redrawnCharacterWidth, isZeroWidthCharacter);
// END TO REMOVE

// Annotation takes place, add GlyphMetrics width to the style
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public class LineContentAnnotation extends AbstractInlinedAnnotation {

private int redrawnCharacterWidth;

private boolean isZeroWidthCharacter;

/**
* Line content annotation constructor.
*
Expand Down Expand Up @@ -113,8 +115,9 @@ int getRedrawnCharacterWidth() {
return redrawnCharacterWidth;
}

void setRedrawnCharacterWidth(int redrawnCharacterWidth) {
void setRedrawnCharacterWidth(int redrawnCharacterWidth, boolean isZeroWidthCharacter) {
this.redrawnCharacterWidth= redrawnCharacterWidth;
this.isZeroWidthCharacter= isZeroWidthCharacter;
}

@Override
Expand Down Expand Up @@ -151,7 +154,7 @@ StyleRange updateStyle(StyleRange style, FontMetrics fontMetrics, ITextViewer vi
if (!afterPosition) {
usePreviousChar= drawRightToPreviousChar(widgetPosition.getOffset(), textWidget);
}
if (width == 0 || getRedrawnCharacterWidth() == 0) {
if (isZeroWidthCharacter == false && (width == 0 || getRedrawnCharacterWidth() == 0)) {
return null;
}
int fullWidth= width + getRedrawnCharacterWidth();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.api.extension.TestWatcher;
Expand Down Expand Up @@ -512,6 +511,53 @@ protected boolean condition() {
}.waitForCondition(widget.getDisplay(), 1000), "Code mining is unexpectedly rendered below last line");
}

@Test
public void testCodeMiningOnZeroWitdhCharacterAfterPosition() {
codeMiningOnZeroWidthCharacter(true);
}

@Test
public void testCodeMiningOnZeroWidthCharacterBeforePosition() {
codeMiningOnZeroWidthCharacter(false);
}

private void codeMiningOnZeroWidthCharacter(boolean afterPosition) {
char ZW_SPACE= '\u200b';
String text= "a" + ZW_SPACE + "b";
fViewer.getDocument().set(text);
fViewer.setCodeMiningProviders(new ICodeMiningProvider[] {
new AbstractCodeMiningProvider() {
@Override
public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextViewer viewer, IProgressMonitor monitor) {
List<ICodeMining> result= new ArrayList<>();
result.add(new LineContentCodeMining(new Position(1, 1), afterPosition, this) {
@Override
public String getLabel() {
return "ZWSP";
}
});
return CompletableFuture.completedFuture(result);
}
}
});
fViewer.updateCodeMinings();
Assertions.assertTrue(new DisplayHelper() {
@Override
protected boolean condition() {
var tw= fViewer.getTextWidget();
int off= afterPosition ? 1 : 0;
StyleRange styleRange= tw.getStyleRangeAtOffset(off);
if (styleRange != null && styleRange.metrics != null) {
// code mining applied a style range with metrics at offset 1
return true;
} else {
tw.redraw();
}
return false;
}
}.waitForCondition(fViewer.getTextWidget().getDisplay(), 1000), "Line content code mining not rendered at zero width character");
}

@Test
public void testCodeMiningSwitchingBetweenInLineAndLineHeader() {
String ref= "REF-X";
Expand Down
Loading