summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarsten Hiesserich2013-06-05 14:53:07 (EDT)
committer Florian Thienel2013-06-05 14:53:07 (EDT)
commit8cd6d1a64b27b676e2a5409d4d17dcf6390f6d7a (patch)
treeee86ed16f6ccec9686f988126a1c3bd58cdb0472
parentdaaf7a3029698ae9646e45df40db6347f7547519 (diff)
downloadorg.eclipse.mylyn.docs.vex-8cd6d1a64b27b676e2a5409d4d17dcf6390f6d7a.zip
org.eclipse.mylyn.docs.vex-8cd6d1a64b27b676e2a5409d4d17dcf6390f6d7a.tar.gz
org.eclipse.mylyn.docs.vex-8cd6d1a64b27b676e2a5409d4d17dcf6390f6d7a.tar.bz2
compress whitespace when inserting text through IVexWidget.insertText
into non-pre elements https://bugs.eclipse.org/bugs/show_bug.cgi?id=408453
-rw-r--r--org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java84
-rw-r--r--org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/VexWidgetImpl.java51
-rw-r--r--org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitBlockElementHandler.java7
3 files changed, 109 insertions, 33 deletions
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java
index 71bb480..0ac81bf 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SimpleEditingTest.java
@@ -21,11 +21,18 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import java.io.IOException;
+import java.util.List;
+
import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.internal.css.CssWhitespacePolicy;
import org.eclipse.vex.core.internal.css.StyleSheet;
import org.eclipse.vex.core.internal.css.StyleSheetReader;
import org.eclipse.vex.core.provisional.dom.IDocumentFragment;
import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.INode;
+import org.eclipse.vex.core.provisional.dom.IParent;
+import org.eclipse.vex.core.provisional.dom.IText;
import org.eclipse.vex.core.tests.TestResources;
import org.junit.Before;
import org.junit.Test;
@@ -269,9 +276,9 @@ public class L2SimpleEditingTest {
}
@Test
- public void hittingEnterInElement_shouldSplitElement() throws Exception {
- final StyleSheet styleSheet = new StyleSheetReader().read(TestResources.get("test.css"));
- widget.setDocument(createDocumentWithDTD(TEST_DTD, "section"), styleSheet);
+ public void givenNonPreElement_whenInsertingNewline_shouldSplitElement() throws Exception {
+ widget.setDocument(createDocumentWithDTD(TEST_DTD, "section"), readTestStyleSheet());
+ widget.setWhitespacePolicy(new CssWhitespacePolicy(widget.getStyleSheet()));
rootElement = widget.getDocument().getRootElement();
widget.insertElement(TITLE);
@@ -285,26 +292,77 @@ public class L2SimpleEditingTest {
}
@Test
- public void hittingEnterInPreformattedElement_shouldInsertNewline() throws Exception {
- final StyleSheet styleSheet = new StyleSheetReader().read(TestResources.get("test.css"));
- widget.setDocument(createDocumentWithDTD(TEST_DTD, "para"), styleSheet);
+ public void givenPreElement_whenInsertingNewline_shouldInsertNewline() throws Exception {
+ widget.setDocument(createDocumentWithDTD(TEST_DTD, "para"), readTestStyleSheet());
+ widget.setWhitespacePolicy(new CssWhitespacePolicy(widget.getStyleSheet()));
rootElement = widget.getDocument().getRootElement();
final IElement preElement = widget.insertElement(new QualifiedName(null, "pre"));
assertEquals(preElement.getEndOffset(), widget.getCaretOffset());
- widget.insertText("Line1");
+ widget.insertText("line1");
widget.insertText("\n");
assertEquals(1, rootElement.children().count());
- assertEquals("Line1\n", preElement.getText());
+ assertEquals("line1\n", preElement.getText());
}
@Test
- public void insertingTextWithNewlineToPreformattedElement_shouldInsertNewline() throws Exception {
- final StyleSheet styleSheet = new StyleSheetReader().read(TestResources.get("test.css"));
- widget.setDocument(createDocumentWithDTD(TEST_DTD, "para"), styleSheet);
+ public void givenPreElement_whenInsertingTextWithNewline_shouldInsertNewline() throws Exception {
+ widget.setDocument(createDocumentWithDTD(TEST_DTD, "para"), readTestStyleSheet());
+ widget.setWhitespacePolicy(new CssWhitespacePolicy(widget.getStyleSheet()));
final IElement preElement = widget.insertElement(new QualifiedName(null, "pre"));
assertEquals(preElement.getEndOffset(), widget.getCaretOffset());
- widget.insertText("Line1\nLine2");
- assertEquals("Line1\nLine2", preElement.getText());
+ widget.insertText("line1\nline2");
+ assertEquals("line1\nline2", preElement.getText());
+ }
+
+ @Test
+ public void givenPreElement_whenInsertingText_shouldKeepWhitespace() throws Exception {
+ widget.setDocument(createDocumentWithDTD(TEST_DTD, "para"), readTestStyleSheet());
+ widget.setWhitespacePolicy(new CssWhitespacePolicy(widget.getStyleSheet()));
+ final IElement preElement = widget.insertElement(new QualifiedName(null, "pre"));
+
+ widget.moveTo(preElement.getEndOffset());
+ widget.insertText("line1\nline2 end");
+
+ final List<? extends INode> children = preElement.children().asList();
+ assertTrue("Expecting IText", children.get(0) instanceof IText);
+ assertEquals("line1\nline2 end", children.get(0).getText());
+ }
+
+ @Test
+ public void givenNonPreElement_whenInsertingText_shouldCompressWhitespace() throws Exception {
+ widget.setDocument(createDocumentWithDTD(TEST_DTD, "section"), readTestStyleSheet());
+ widget.setWhitespacePolicy(new CssWhitespacePolicy(widget.getStyleSheet()));
+ final IElement para = widget.insertElement(PARA);
+ widget.moveTo(para.getEndOffset());
+ widget.insertText("line1\nline2 \t end");
+
+ final List<? extends INode> children = widget.getDocument().getRootElement().children().after(para.getStartOffset()).asList();
+ assertEquals("single para element", 2, children.size());
+ assertTrue("original para element", children.get(0) instanceof IParent);
+ assertTrue("splitted para element", children.get(1) instanceof IParent);
+ assertEquals("first line", "line1", children.get(0).getText());
+ assertEquals("second line with compressed whitespace", "line2 end", children.get(1).getText());
}
+
+ @Test
+ public void givenNonPreElement_whenInsertingText_shouldCompressNewlines() throws Exception {
+ widget.setDocument(createDocumentWithDTD(TEST_DTD, "section"), readTestStyleSheet());
+ widget.setWhitespacePolicy(new CssWhitespacePolicy(widget.getStyleSheet()));
+ final IElement para = widget.insertElement(PARA);
+ widget.moveTo(para.getEndOffset());
+ widget.insertText("line1\n\nline2");
+
+ final List<? extends INode> children = widget.getDocument().getRootElement().children().after(para.getStartOffset()).asList();
+ assertEquals("single para element", 2, children.size());
+ assertTrue("original para element", children.get(0) instanceof IParent);
+ assertTrue("splitted para element", children.get(1) instanceof IParent);
+ assertEquals("first line", "line1", children.get(0).getText());
+ assertEquals("second line", "line2", children.get(1).getText());
+ }
+
+ private static StyleSheet readTestStyleSheet() throws IOException {
+ return new StyleSheetReader().read(TestResources.get("test.css"));
+ }
+
}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/VexWidgetImpl.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/VexWidgetImpl.java
index 392379d..039b58b 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/VexWidgetImpl.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/VexWidgetImpl.java
@@ -28,17 +28,16 @@ import java.util.Set;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.vex.core.XML;
import org.eclipse.vex.core.internal.core.Caret;
import org.eclipse.vex.core.internal.core.Color;
import org.eclipse.vex.core.internal.core.ElementName;
import org.eclipse.vex.core.internal.core.Graphics;
import org.eclipse.vex.core.internal.core.QualifiedNameComparator;
import org.eclipse.vex.core.internal.core.Rectangle;
-import org.eclipse.vex.core.internal.css.CSS;
import org.eclipse.vex.core.internal.css.IWhitespacePolicy;
import org.eclipse.vex.core.internal.css.StyleSheet;
import org.eclipse.vex.core.internal.css.StyleSheetReader;
-import org.eclipse.vex.core.internal.css.Styles;
import org.eclipse.vex.core.internal.dom.Document;
import org.eclipse.vex.core.internal.dom.Node;
import org.eclipse.vex.core.internal.layout.BlockBox;
@@ -71,6 +70,7 @@ import org.eclipse.vex.core.provisional.dom.IDocumentFragment;
import org.eclipse.vex.core.provisional.dom.IDocumentListener;
import org.eclipse.vex.core.provisional.dom.IElement;
import org.eclipse.vex.core.provisional.dom.INode;
+import org.eclipse.vex.core.provisional.dom.IParent;
import org.eclipse.vex.core.provisional.dom.IPosition;
import org.eclipse.vex.core.provisional.dom.IText;
import org.eclipse.vex.core.provisional.dom.IValidator;
@@ -846,26 +846,36 @@ public class VexWidgetImpl implements IVexWidget {
deleteSelection();
}
+ final IElement element = getBlockForInsertionAt(getCaretOffset());
+ final boolean isPreformatted = whitespacePolicy.isPre(element);
+
+ String toInsert;
+ if (!isPreformatted) {
+ toInsert = XML.compressWhitespace(XML.normalizeNewlines(text), true, true, true);
+ } else {
+ toInsert = text;
+ }
+
boolean success = false;
try {
beginWork();
int i = 0;
for (;;) {
- final int nextLineBreak = text.indexOf('\n', i);
+ final int nextLineBreak = toInsert.indexOf('\n', i);
if (nextLineBreak == -1) {
break;
}
if (nextLineBreak - i > 0) {
- applyEdit(new InsertTextEdit(document, getCaretOffset(), text.substring(i, nextLineBreak)), getCaretOffset());
+ applyEdit(new InsertTextEdit(document, getCaretOffset(), toInsert.substring(i, nextLineBreak)), getCaretOffset());
}
this.moveTo(getCaretOffset() + nextLineBreak - i);
split();
i = nextLineBreak + 1;
}
- if (i < text.length()) {
- applyEdit(new InsertTextEdit(document, getCaretOffset(), text.substring(i)), getCaretOffset());
- this.moveTo(getCaretOffset() + text.length() - i);
+ if (i < toInsert.length()) {
+ applyEdit(new InsertTextEdit(document, getCaretOffset(), toInsert.substring(i)), getCaretOffset());
+ this.moveTo(getCaretOffset() + toInsert.length() - i);
}
success = true;
} finally {
@@ -873,6 +883,22 @@ public class VexWidgetImpl implements IVexWidget {
}
}
+ private IElement getBlockForInsertionAt(final int offset) {
+ final IElement element = getDocument().getElementForInsertionAt(offset);
+
+ if (whitespacePolicy.isBlock(element)) {
+ return element;
+ }
+
+ for (final IParent parent : element.ancestors().matching(Filters.elements())) {
+ if (whitespacePolicy.isBlock(parent)) {
+ return (IElement) parent;
+ }
+ }
+
+ return null;
+ }
+
public void insertChar(final char c) throws DocumentValidationException, ReadOnlyException {
if (readOnly) {
throw new ReadOnlyException("Cannot insert a character, because the editor is read-only.");
@@ -1377,18 +1403,13 @@ public class VexWidgetImpl implements IVexWidget {
final long start = System.currentTimeMillis();
- final IDocument doc = getDocument();
- IElement element = doc.getElementForInsertionAt(getCaretOffset());
- Styles styles = getStyleSheet().getStyles(element);
- while (!styles.isBlock()) {
- element = element.getParentElement();
- styles = getStyleSheet().getStyles(element);
- }
+ final IElement element = getBlockForInsertionAt(getCaretOffset());
+ final boolean isPreformatted = whitespacePolicy.isPre(element);
boolean success = false;
try {
beginWork();
- if (styles.getWhiteSpace().equals(CSS.PRE)) {
+ if (isPreformatted) {
applyEdit(new InsertTextEdit(document, getCaretOffset(), "\n"), getCaretOffset());
this.moveBy(1);
} else {
diff --git a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitBlockElementHandler.java b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitBlockElementHandler.java
index e1554fc..1f2712d 100644
--- a/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitBlockElementHandler.java
+++ b/org.eclipse.vex.ui/src/org/eclipse/vex/ui/internal/handlers/SplitBlockElementHandler.java
@@ -16,7 +16,6 @@ import java.util.List;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.vex.core.internal.VEXCorePlugin;
-import org.eclipse.vex.core.internal.css.CSS;
import org.eclipse.vex.core.internal.css.Styles;
import org.eclipse.vex.core.internal.dom.CopyOfElement;
import org.eclipse.vex.core.internal.widget.IVexWidget;
@@ -69,12 +68,10 @@ public class SplitBlockElementHandler extends AbstractVexWidgetHandler {
start = System.currentTimeMillis();
}
- final Styles styles = vexWidget.getStyleSheet().getStyles(node);
-
- if (styles.getWhiteSpace().equals(CSS.PRE)) {
+ final boolean isPreformatted = vexWidget.getWhitespacePolicy().isPre(node);
+ if (isPreformatted) {
vexWidget.insertText("\n");
} else {
-
// There may be a number of child elements below the given
// element. We cut out the tails of each of these elements
// and put them in a list of fragments to be reconstructed