Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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