Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMickael Istria2018-03-09 12:53:45 +0000
committerMickael Istria2018-03-14 14:06:55 +0000
commit2ef119e594da0ed9e93c88f3b32b03e82863870c (patch)
tree518b007ba254ea5fcb946e4d504914b627c17c3d
parent1c8a0ecfbe778d718be00e3b273a19d9c628f0be (diff)
downloadeclipse.platform.swt-2ef119e594da0ed9e93c88f3b32b03e82863870c.tar.gz
eclipse.platform.swt-2ef119e594da0ed9e93c88f3b32b03e82863870c.tar.xz
eclipse.platform.swt-2ef119e594da0ed9e93c88f3b32b03e82863870c.zip
Bug 532173 - [StyledText] Wrong caret bounds with variable height
Fix bug in getBoundsAtOffset to make it more reliable. Place caret to better location when it doesn't fit the whole line. May as well fix bug 118612 Change-Id: I942787c801090ff504c8ed37183a97b312f78e18 Signed-off-by: Mickael Istria <mistria@redhat.com> Also-By: Angelo Zerr <angelozerr@gmail.com>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java56
-rw-r--r--tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_StyledText.java39
2 files changed, 84 insertions, 11 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
index a05e0bf0a1..13249fe4a0 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/StyledText.java
@@ -3697,12 +3697,11 @@ Rectangle getBoundsAtOffset(int offset) {
if (line.length() != 0) {
TextLayout layout = renderer.getTextLayout(lineIndex);
int offsetInLine = Math.min (layout.getText().length(), Math.max (0, offset - lineOffset));
- if (caretAlignment == PREVIOUS_OFFSET_TRAILING && offsetInLine != 0) {
+ bounds = layout.getBounds(offsetInLine, offsetInLine);
+ if (getListeners(ST.LineGetSegments).length > 0 && caretAlignment == PREVIOUS_OFFSET_TRAILING && offsetInLine != 0) {
offsetInLine = layout.getPreviousOffset(offsetInLine, SWT.MOVEMENT_CLUSTER);
Point point = layout.getLocation(offsetInLine, true);
- bounds = new Rectangle (point.x, point.y, 0, renderer.getLineHeight());
- } else {
- bounds = layout.getBounds(offsetInLine, offsetInLine);
+ bounds = new Rectangle (point.x, point.y, 0, bounds.height);
}
renderer.disposeTextLayout(layout);
} else {
@@ -8632,18 +8631,53 @@ void setCaretLocation() {
Point newCaretPos = getPointAtOffset(caretOffset);
setCaretLocation(newCaretPos, getCaretDirection());
}
-void setCaretLocation(Point location, int direction) {
+void setCaretLocation(final Point location, int direction) {
Caret caret = getCaret();
if (caret != null) {
- boolean isDefaultCaret = caret == defaultCaret;
- int lineHeight = renderer.getLineHeight();
- int caretHeight = lineHeight;
- if (!isFixedLineHeight() && isDefaultCaret) {
- caretHeight = getBoundsAtOffset(caretOffset).height;
- if (caretHeight != lineHeight) {
+ final boolean isDefaultCaret = caret == defaultCaret;
+ final StyleRange styleAtOffset = content.getCharCount() > 0 ?
+ (caretOffset < content.getCharCount() ?
+ getStyleRangeAtOffset(caretOffset) :
+ getStyleRangeAtOffset(content.getCharCount() - 1)) : // caret after last char: use last char style
+ null;
+ final int caretLine = getCaretLine();
+
+ int graphicalLineHeight = getLineHeight();
+ final int lineStartOffset = getOffsetAtLine(caretLine);
+ int graphicalLineFirstOffset = lineStartOffset;
+ final int lineEndOffset = lineStartOffset + getLine(caretLine).length();
+ int graphicalLineLastOffset = lineEndOffset;
+ if (renderer.getLineHeight(caretLine) != getLineHeight()) { // word wrap, metrics, styles...
+ graphicalLineHeight = getLineHeight(caretOffset);
+ final Rectangle characterBounds = getBoundsAtOffset(caretOffset);
+ graphicalLineFirstOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y));
+ graphicalLineLastOffset = getOffsetAtPoint(new Point(leftMargin, characterBounds.y + graphicalLineHeight)) - 1;
+ if (graphicalLineLastOffset < graphicalLineFirstOffset) {
+ graphicalLineLastOffset = getCharCount();
+ }
+ }
+
+ int caretHeight = getLineHeight();
+ boolean isTextAlignedAtBottom = true;
+ for (StyleRange style : getStyleRanges(graphicalLineFirstOffset, graphicalLineLastOffset - graphicalLineFirstOffset)) {
+ isTextAlignedAtBottom &= (
+ (style.font == null || Objects.equals(style.font, getFont())) &&
+ style.rise >= 0 &&
+ (style.metrics == null || style.metrics.descent <= 0)
+ );
+ }
+ if (!isTextAlignedAtBottom || (styleAtOffset != null && styleAtOffset.isVariableHeight())) {
+ if (isDefaultCaret) {
direction = SWT.DEFAULT;
+ caretHeight = graphicalLineHeight;
+ } else {
+ caretHeight = caret.getSize().y;
}
}
+ if (isTextAlignedAtBottom && caretHeight < graphicalLineHeight) {
+ location.y += (graphicalLineHeight - caretHeight);
+ }
+
int imageDirection = direction;
if (isMirrored()) {
if (imageDirection == SWT.LEFT) {
diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_StyledText.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_StyledText.java
index c5fceeec25..7ed2c0c66c 100644
--- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_StyledText.java
+++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_custom_StyledText.java
@@ -48,6 +48,7 @@ import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.GlyphMetrics;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
@@ -4887,6 +4888,44 @@ public void test_clickUpdatesCaretPosition() {
}
@Test
+public void test_caretSizeAndPositionVariableGlyphMetrics() {
+ text.setText("abcd");
+ text.setMargins(2, 0, 0, 0); // keep leftMargin as it affects behavior
+ text.setLineSpacing(0);
+ StyleRange range = new StyleRange(2, 1, null, null);
+ range.metrics = new GlyphMetrics(100, 0, 10);
+ text.setStyleRange(range);
+ text.setCaretOffset(0);
+ assertEquals(text.getLineHeight(), text.getCaret().getSize().y);
+ // +5: caret takes 5 more pixels
+ assertEquals(text.getLineHeight(0) - text.getCaret().getSize().y, text.getCaret().getBounds().y);
+ text.setCaretOffset(1);
+ assertEquals(text.getLineHeight(), text.getCaret().getSize().y);
+ assertEquals(text.getLineHeight(0) - text.getCaret().getSize().y, text.getCaret().getBounds().y);
+ text.setCaretOffset(2);
+ assertEquals(text.getLineHeight(0), text.getCaret().getSize().y);
+ assertEquals(0, text.getCaret().getBounds().y);
+ text.setCaretOffset(3);
+ assertEquals(text.getLineHeight(), text.getCaret().getSize().y);
+ assertEquals(text.getLineHeight(0) - text.getCaret().getSize().y, text.getCaret().getBounds().y);
+ text.setCaretOffset(4);
+ assertEquals(text.getLineHeight(), text.getCaret().getSize().y);
+ assertEquals(text.getLineHeight(0) - text.getCaret().getSize().y, text.getCaret().getBounds().y);
+ text.setCaretOffset(3);
+ assertEquals(text.getLineHeight(), text.getCaret().getSize().y);
+ assertEquals(text.getLineHeight(0) - text.getCaret().getSize().y, text.getCaret().getBounds().y);
+ text.setCaretOffset(2);
+ assertEquals(text.getLineHeight(0), text.getCaret().getSize().y);
+ assertEquals(0, text.getCaret().getBounds().y);
+ text.setCaretOffset(1);
+ assertEquals(text.getLineHeight(), text.getCaret().getSize().y);
+ assertEquals(text.getLineHeight(0) - text.getCaret().getSize().y, text.getCaret().getBounds().y);
+ text.setCaretOffset(0);
+ assertEquals(text.getLineHeight(), text.getCaret().getSize().y);
+ assertEquals(text.getLineHeight(0) - text.getCaret().getSize().y, text.getCaret().getBounds().y);
+}
+
+@Test
public void test_doubleClickSelectsWord() {
text.setText("Test1 Test2");

Back to the top