render line breaks and tabs properly
Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/CharSequenceSplitter.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/CharSequenceSplitter.java
index d96f9d3..f66c0df 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/CharSequenceSplitter.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/CharSequenceSplitter.java
@@ -60,7 +60,7 @@
return properSplittingPosition + 1;
}
- public int findPositionAfter(final Graphics graphics, final int x, final int maxWidth) {
+ private int findPositionAfter(final Graphics graphics, final int x, final int maxWidth) {
if (x < 0) {
return 0;
}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/StaticText.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/StaticText.java
index 57ec691..15d9aee 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/StaticText.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/StaticText.java
@@ -103,11 +103,13 @@
}
public int getInvisibleGapLeft(final Graphics graphics) {
+ final String text = renderText(getText());
final int whitespaceCount = countWhitespaceAtStart(text);
return graphics.stringWidth(text.substring(0, whitespaceCount));
}
public int getInvisibleGapRight(final Graphics graphics) {
+ final String text = renderText(getText());
final int whitespaceCount = countWhitespaceAtEnd(text);
return graphics.stringWidth(text.substring(text.length() - whitespaceCount, text.length()));
}
@@ -156,7 +158,7 @@
}
applyFont(graphics);
- width = graphics.stringWidth(getText());
+ width = graphics.stringWidth(renderText(getText()));
final FontMetrics fontMetrics = graphics.getFontMetrics();
height = fontMetrics.getHeight();
@@ -165,6 +167,10 @@
layoutValid = true;
}
+ private static String renderText(final String rawText) {
+ return rawText.replaceAll("\n", " ").replaceAll("\t", " ");
+ }
+
@Override
public boolean reconcileLayout(final Graphics graphics) {
final int oldHeight = height;
@@ -180,7 +186,7 @@
public void paint(final Graphics graphics) {
applyFont(graphics);
graphics.setColor(graphics.getColor(color));
- graphics.drawString(getText(), 0, 0);
+ graphics.drawString(renderText(getText()), 0, 0);
}
private void applyFont(final Graphics graphics) {
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TextContent.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TextContent.java
index b829be3..068d8ad 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TextContent.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/boxes/TextContent.java
@@ -115,14 +115,18 @@
return content.getText(new ContentRange(startPosition.getOffset(), endPosition.getOffset()));
}
+ private static String renderText(final String rawText) {
+ return rawText.replaceAll("\n", " ").replaceAll("\t", " ");
+ }
+
public int getInvisibleGapLeft(final Graphics graphics) {
- final String text = getText();
+ final String text = renderText(getText());
final int whitespaceCount = countWhitespaceAtStart(text);
return graphics.stringWidth(text.substring(0, whitespaceCount));
}
public int getInvisibleGapRight(final Graphics graphics) {
- final String text = getText();
+ final String text = renderText(getText());
final int whitespaceCount = countWhitespaceAtEnd(text);
return graphics.stringWidth(text.substring(text.length() - whitespaceCount, text.length()));
}
@@ -183,7 +187,7 @@
}
applyFont(graphics);
- width = graphics.stringWidth(getText());
+ width = graphics.stringWidth(renderText(getText()));
final FontMetrics fontMetrics = graphics.getFontMetrics();
height = fontMetrics.getHeight();
@@ -207,7 +211,7 @@
public void paint(final Graphics graphics) {
applyFont(graphics);
graphics.setForeground(graphics.getColor(color));
- graphics.drawString(getText(), 0, 0);
+ graphics.drawString(renderText(getText()), 0, 0);
}
private void applyFont(final Graphics graphics) {
@@ -221,14 +225,15 @@
graphics.setBackground(graphics.getColor(background));
graphics.fillRect(getAbsoluteLeft(), getAbsoluteTop(), width, height);
applyFont(graphics);
- graphics.drawString(getText(), getAbsoluteLeft(), getAbsoluteTop());
+ graphics.drawString(renderText(getText()), getAbsoluteLeft(), getAbsoluteTop());
}
public void highlight(final Graphics graphics, final int startOffset, final int endOffset, final Color foreground, final Color background) {
final int highlightStartOffset = Math.max(getStartOffset(), Math.min(startOffset, getEndOffset())) - getStartOffset();
final int highlightEndOffset = Math.max(getStartOffset(), Math.min(endOffset, getEndOffset() + 1)) - getStartOffset();
- final String highlightPrefix = getText().substring(0, highlightStartOffset);
- final String highlightText = getText().substring(highlightStartOffset, highlightEndOffset);
+ final String text = getText();
+ final String highlightPrefix = renderText(text.substring(0, highlightStartOffset));
+ final String highlightText = renderText(text.substring(highlightStartOffset, highlightEndOffset));
applyFont(graphics);
final int widthBefore = graphics.stringWidth(highlightPrefix);
@@ -392,7 +397,7 @@
applyFont(graphics);
final char c = content.charAt(offset);
- final String head = content.subSequence(startPosition.getOffset(), offset).toString();
+ final String head = renderText(content.subSequence(startPosition.getOffset(), offset).toString());
final int left = graphics.stringWidth(head);
final int charWidth = graphics.stringWidth(Character.toString(c));
return new Rectangle(left, 0, charWidth, height);
@@ -400,9 +405,21 @@
@Override
public int getOffsetForCoordinates(final Graphics graphics, final int x, final int y) {
+ if (x < 0) {
+ return getStartOffset();
+ }
+ if (x > width) {
+ return getEndOffset();
+ }
+
applyFont(graphics);
- splitter.setContent(content, startPosition.getOffset(), endPosition.getOffset());
- final int offset = getStartOffset() + splitter.findPositionAfter(graphics, x, width);
+ final String text = getText();
+ int i = 0;
+ while (renderedWidth(graphics, text.substring(0, i)) < x && i < text.length()) {
+ i += 1;
+ }
+ final int offset = Math.max(getStartOffset(), getStartOffset() + i - 1);
+
final Rectangle area = getPositionArea(graphics, offset);
final int halfWidth = area.getWidth() / 2 + 1;
if (x < area.getX() + halfWidth) {
@@ -412,6 +429,10 @@
}
}
+ private static int renderedWidth(final Graphics graphics, final String text) {
+ return graphics.stringWidth(renderText(text));
+ }
+
@Override
public String toString() {
return "TextContent{ x: " + left + ", y: " + top + ", width: " + width + ", height: " + height + ", startOffset: " + startPosition + ", endOffset: " + endPosition + " }";
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java
index b6df88c..1affe93 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/dom/Document.java
@@ -340,10 +340,10 @@
});
}
- private String convertControlCharactersToSpaces(final String text) {
+ private static String convertControlCharactersToSpaces(final String text) {
final char[] characters = text.toCharArray();
for (int i = 0; i < characters.length; i++) {
- if (Character.isISOControl(characters[i]) && characters[i] != '\n') {
+ if (Character.isISOControl(characters[i]) && characters[i] != '\n' && characters[i] != '\t') {
characters[i] = ' ';
}
}