test simple selection operations
Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentTest.java
index 9db8e31..691d826 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/dom/DocumentTest.java
@@ -52,15 +52,6 @@
assertDocumentConnectedToRootElement(rootElement, document);
}
- private static void assertDocumentConnectedToRootElement(final Element rootElement, final Document document) {
- assertNotNull(document.getContent());
- assertTrue(document.isAssociated());
- assertTrue(rootElement.isAssociated());
- assertSame(document, rootElement.getParent());
- assertTrue(rootElement.getStartOffset() >= document.getStartOffset());
- assertTrue(rootElement.getEndOffset() <= document.getEndOffset());
- }
-
@Test
public void createFragmentWithTextAndChild() throws Exception {
final Document document = new Document(new Element("root"));
@@ -85,6 +76,17 @@
assertNodesEqual(document.getNodes(range), fragment.getNodes());
}
+ @Test
+ public void givenElementWithText_whenRangeBeginsFromStartOffset_shouldProvideParentAsCommenElement() throws Exception {
+ final Document document = new Document(new Element("root"));
+ final Element childElement = document.insertElement(1, new QualifiedName(null, "child"));
+ document.insertText(childElement.getEndOffset(), "Hello World");
+
+ final Element commonElement = document.findCommonElement(childElement.getStartOffset(), childElement.getEndOffset() - 5);
+
+ assertSame(document.getRootElement(), commonElement);
+ }
+
private static void assertNodesEqual(final List<? extends Node> expected, final List<? extends Node> actual) {
assertEquals(expected.size(), actual.size());
for (int i = 0; i < expected.size(); i++) {
@@ -99,4 +101,14 @@
assertNodesEqual(((Parent) expected).getChildNodes(), ((Parent) actual).getChildNodes());
}
}
+
+ private static void assertDocumentConnectedToRootElement(final Element rootElement, final Document document) {
+ assertNotNull(document.getContent());
+ assertTrue(document.isAssociated());
+ assertTrue(rootElement.isAssociated());
+ assertSame(document, rootElement.getParent());
+ assertTrue(rootElement.getStartOffset() >= document.getStartOffset());
+ assertTrue(rootElement.getEndOffset() <= document.getEndOffset());
+ }
+
}
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SelectionTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SelectionTest.java
new file mode 100644
index 0000000..269981a
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/L2SelectionTest.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Florian Thienel and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Florian Thienel - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.vex.core.internal.widget;
+
+import static org.eclipse.vex.core.internal.widget.VexWidgetTest.TITLE;
+import static org.eclipse.vex.core.internal.widget.VexWidgetTest.createDocumentWithDTD;
+import static org.eclipse.vex.core.tests.TestResources.TEST_DTD;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.vex.core.internal.css.StyleSheet;
+import org.eclipse.vex.core.internal.dom.Element;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Florian Thienel
+ */
+public class L2SelectionTest {
+
+ private VexWidgetImpl widget;
+ private Element rootElement;
+
+ @Before
+ public void setUp() throws Exception {
+ widget = new VexWidgetImpl(new MockHostComponent());
+ widget.setDocument(createDocumentWithDTD(TEST_DTD, "section"), StyleSheet.NULL);
+ rootElement = widget.getDocument().getRootElement();
+ }
+
+ @Test
+ public void givenCaretInElement_whenSelectionIncludesStartOffset_shouldExpandSelectionToEndOffset() throws Exception {
+ final Element titleElement = widget.insertElement(TITLE);
+ widget.moveBy(-1, true);
+ assertTrue(widget.hasSelection());
+ assertEquals(titleElement.getStartOffset(), widget.getSelectionStart());
+ assertEquals(titleElement.getEndOffset(), widget.getSelectionEnd());
+ }
+
+ @Test
+ public void givenCaretInElementWith_whenSelectionIncludesStartOffset_shouldExpandSelectionToEndOffset() throws Exception {
+ final Element titleElement = widget.insertElement(TITLE);
+ widget.insertText("Hello World");
+ widget.moveBy(-5, false);
+ widget.moveTo(titleElement.getStartOffset(), true);
+ assertTrue(widget.hasSelection());
+ assertEquals(titleElement.getStartOffset(), widget.getSelectionStart());
+ assertEquals(titleElement.getEndOffset(), widget.getSelectionEnd());
+ }
+
+ @Test
+ public void givenCaretInElementAtEndOffset_whenMovedByOneBehindEndOffset_shouldExpandSelectionToStartOffset() throws Exception {
+ final Element titleElement = widget.insertElement(TITLE);
+ widget.insertText("Hello World");
+ widget.moveBy(1, true);
+ assertTrue(widget.hasSelection());
+ assertEquals(titleElement.getStartOffset(), widget.getSelectionStart());
+ assertEquals(titleElement.getEndOffset() + 1, widget.getSelectionEnd());
+ }
+}
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 08569da..6f0d5dc 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
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.vex.core.internal.widget;
+import static org.eclipse.vex.core.internal.widget.VexWidgetTest.PARA;
+import static org.eclipse.vex.core.internal.widget.VexWidgetTest.TITLE;
import static org.eclipse.vex.core.internal.widget.VexWidgetTest.createDocumentWithDTD;
import static org.eclipse.vex.core.tests.TestResources.TEST_DTD;
import static org.junit.Assert.assertEquals;
@@ -17,11 +19,9 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
-import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.vex.core.internal.css.StyleSheet;
import org.eclipse.vex.core.internal.dom.Element;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
/**
@@ -29,9 +29,6 @@
*/
public class L2SimpleEditingTest {
- private static final QualifiedName TITLE = new QualifiedName(null, "title");
- private static final QualifiedName PARA = new QualifiedName(null, "para");
-
private VexWidgetImpl widget;
private Element rootElement;
@@ -82,7 +79,6 @@
}
@Test
- @Ignore("get moveTo working first")
public void givenAnEmptyElement_whenCaretBetweenStartAndEndTagAndHittingBackspace_shouldDeleteEmptyElement() throws Exception {
widget.insertElement(TITLE);
widget.moveBy(1);
@@ -94,7 +90,6 @@
}
@Test
- @Ignore("get moveTo working first")
public void givenAnEmptyElement_whenCaretBeforeStartOffsetAndHittingDelete_shouldDeleteEmptyElement() throws Exception {
widget.insertElement(TITLE);
widget.moveBy(1);
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/VexWidgetTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/VexWidgetTest.java
index 3a82c6c..c63bf0c 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/VexWidgetTest.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/VexWidgetTest.java
@@ -31,6 +31,9 @@
public class VexWidgetTest {
+ static final QualifiedName TITLE = new QualifiedName(null, "title");
+ static final QualifiedName PARA = new QualifiedName(null, "para");
+
@Test
public void provideOnlyAllowedElementsFromDtd() throws Exception {
final VexWidgetImpl widget = new VexWidgetImpl(new MockHostComponent());
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestSuite.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestSuite.java
index 79dad79..dcfacd7 100644
--- a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestSuite.java
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/tests/VEXCoreTestSuite.java
@@ -49,6 +49,7 @@
import org.eclipse.vex.core.internal.layout.TestBlocksInInlines;
import org.eclipse.vex.core.internal.layout.TestDocumentTextBox;
import org.eclipse.vex.core.internal.layout.TestStaticTextBox;
+import org.eclipse.vex.core.internal.widget.L2SelectionTest;
import org.eclipse.vex.core.internal.widget.L2SimpleEditingTest;
import org.eclipse.vex.core.internal.widget.VexWidgetTest;
@@ -95,5 +96,6 @@
addTestSuite(ListenerListTest.class);
addTest(new JUnit4TestAdapter(VexWidgetTest.class));
addTest(new JUnit4TestAdapter(L2SimpleEditingTest.class));
+ addTest(new JUnit4TestAdapter(L2SelectionTest.class));
}
}
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 97d7abd..345b4bf 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
@@ -397,7 +397,7 @@
final List<Element> children = element.getChildElements();
for (int i = 0; i < children.size(); i++) {
final Element child = children.get(i);
- if (child.containsOffset(offset1) && child.containsOffset(offset2)) {
+ if (isInsertionPointIn(child, offset1) && isInsertionPointIn(child, offset2)) {
element = child;
tryAgain = true;
break;
@@ -410,6 +410,10 @@
return element;
}
+ private static boolean isInsertionPointIn(final Node node, final int offset) {
+ return node.containsOffset(offset) && offset > node.getStartOffset();
+ }
+
private Node getNodeForInsertionAt(final int offset) {
final Node node = getChildNodeAt(offset);
if (offset == node.getStartOffset()) {
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 82c7be3..28b6169 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
@@ -846,8 +846,7 @@
selectionStart = Math.min(mark, caretOffset);
selectionEnd = Math.max(mark, caretOffset);
- // move selectionStart and selectionEnd to make sure we don't
- // select a partial element
+ // move selectionStart and selectionEnd to make sure we don't select a partial element
final Element commonElement = document.findCommonElement(selectionStart, selectionEnd);
Element element = document.getElementForInsertionAt(selectionStart);
@@ -858,8 +857,8 @@
element = document.getElementForInsertionAt(selectionEnd);
while (element != commonElement) {
- selectionEnd = element.getEndOffset() + 1;
- element = document.getElementForInsertionAt(selectionEnd);
+ selectionEnd = element.getEndOffset();
+ element = document.getElementForInsertionAt(selectionEnd + 1);
}
} else {