implement simple in memory clipboard
Signed-off-by: Florian Thienel <florian@thienel.org>
diff --git a/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/InMemoryClipboardTest.java b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/InMemoryClipboardTest.java
new file mode 100644
index 0000000..c5a7e90
--- /dev/null
+++ b/org.eclipse.vex.core.tests/src/org/eclipse/vex/core/internal/widget/InMemoryClipboardTest.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2016 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.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+
+import org.eclipse.vex.core.internal.io.UniversalTestDocument;
+import org.eclipse.vex.core.provisional.dom.IElement;
+import org.eclipse.vex.core.provisional.dom.INode;
+import org.junit.Before;
+import org.junit.Test;
+
+public class InMemoryClipboardTest {
+
+ private UniversalTestDocument document;
+ private DocumentEditor editor;
+ private InMemoryClipboard clipboard;
+
+ @Before
+ public void setUp() throws Exception {
+ document = new UniversalTestDocument(1);
+ editor = new DocumentEditor(new FakeCursor(document.getDocument()));
+ editor.setDocument(document.getDocument());
+ clipboard = new InMemoryClipboard();
+ }
+
+ @Test
+ public void givenFirstParagraphSelected_cutSelection_shouldRemoveFirstParagraphFromDocument() throws Exception {
+ final IElement section = document.getSection(0);
+ final INode firstParagraph = section.children().first();
+
+ select(firstParagraph);
+ clipboard.cutSelection(editor);
+
+ assertNotSame(firstParagraph, section.children().first());
+ assertNull(firstParagraph.getDocument());
+ }
+
+ @Test
+ public void givenFirstParagraphSelected_cutAndPasteAfterSecondParagraph_shouldInsertFirstParagraphAfterSecondParagraph() throws Exception {
+ final IElement section = document.getSection(0);
+ final INode firstParagraph = section.children().first();
+ final INode secondParagraph = section.children().last();
+ final String firstParagraphContent = firstParagraph.getText();
+
+ select(firstParagraph);
+ clipboard.cutSelection(editor);
+ editor.moveTo(secondParagraph.getEndPosition().moveBy(1));
+ clipboard.paste(editor);
+
+ assertEquals(firstParagraphContent, section.children().last().getText());
+ assertEquals(2, section.children().count());
+ }
+
+ @Test
+ public void givenFirstParagraphSelected_copyAndPasteAfterSecondParagraph_shouldInsertFirstParagraphAgainAfterSecondParagraph() throws Exception {
+ final IElement section = document.getSection(0);
+ final INode firstParagraph = section.children().first();
+ final INode secondParagraph = section.children().last();
+ final String firstParagraphContent = firstParagraph.getText();
+
+ select(firstParagraph);
+ clipboard.copySelection(editor);
+ editor.moveTo(secondParagraph.getEndPosition().moveBy(1));
+ clipboard.paste(editor);
+
+ assertEquals(firstParagraphContent, section.children().last().getText());
+ assertEquals(3, section.children().count());
+ }
+
+ @Test
+ public void givenNothingSelected_cutSelection_shouldNotChangeClipboardContent() throws Exception {
+ final IElement section = document.getSection(0);
+ final INode firstParagraph = section.children().first();
+ final INode secondParagraph = section.children().last();
+ final String firstParagraphContent = firstParagraph.getText();
+
+ select(firstParagraph);
+ clipboard.copySelection(editor);
+ editor.moveTo(secondParagraph.getEndPosition().moveBy(1));
+ clipboard.cutSelection(editor);
+ clipboard.paste(editor);
+
+ assertEquals(firstParagraphContent, section.children().last().getText());
+ assertEquals(3, section.children().count());
+ }
+
+ @Test
+ public void givenNothingSelected_copySelection_shouldNotChangeClipboardContent() throws Exception {
+ final IElement section = document.getSection(0);
+ final INode firstParagraph = section.children().first();
+ final INode secondParagraph = section.children().last();
+ final String firstParagraphContent = firstParagraph.getText();
+
+ select(firstParagraph);
+ clipboard.copySelection(editor);
+ editor.moveTo(secondParagraph.getEndPosition().moveBy(1));
+ clipboard.copySelection(editor);
+ clipboard.paste(editor);
+
+ assertEquals(firstParagraphContent, section.children().last().getText());
+ assertEquals(3, section.children().count());
+ }
+
+ @Test
+ public void givenFirstParagraphSelected_copyAndPasteTextIntoSecondParagraph_shouldInsertTextOfFirstParagraphIntoSecondParagraph() throws Exception {
+ final IElement section = document.getSection(0);
+ final INode firstParagraph = section.children().first();
+ final INode secondParagraph = section.children().last();
+ final String firstParagraphContent = firstParagraph.getText();
+
+ select(firstParagraph);
+ clipboard.copySelection(editor);
+ editor.moveTo(secondParagraph.getEndPosition());
+ clipboard.pasteText(editor);
+
+ assertEquals(firstParagraphContent, section.children().last().getText());
+ assertEquals(2, section.children().count());
+ }
+
+ private void select(final INode node) {
+ editor.moveTo(node.getStartPosition());
+ editor.moveBy(1, true);
+ }
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/DocumentEditor.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/DocumentEditor.java
index 7bd765f..a750425 100644
--- a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/DocumentEditor.java
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/DocumentEditor.java
@@ -78,6 +78,7 @@
private final ICursor cursor;
private final EditStack editStack;
+ private final IClipboard clipboard;
private IDocument document;
private IWhitespacePolicy whitespacePolicy;
@@ -93,6 +94,7 @@
this.whitespacePolicy = whitespacePolicy;
editStack = new EditStack();
+ clipboard = new InMemoryClipboard();
}
/*
@@ -230,38 +232,41 @@
@Override
public void cutSelection() {
- // TODO Auto-generated method stub
-
+ if (isReadOnly()) {
+ throw new ReadOnlyException("Cannot cut selection, because the editor is read-only.");
+ }
+ clipboard.cutSelection(this);
}
@Override
public void copySelection() {
- // TODO Auto-generated method stub
-
+ clipboard.copySelection(this);
}
@Override
public boolean canPaste() {
- // TODO Auto-generated method stub
- return false;
+ return clipboard.hasContent();
}
@Override
public void paste() throws DocumentValidationException {
- // TODO Auto-generated method stub
-
+ if (isReadOnly()) {
+ throw new ReadOnlyException("Cannot paste, because the editor is read-only.");
+ }
+ clipboard.paste(this);
}
@Override
public boolean canPasteText() {
- // TODO Auto-generated method stub
- return false;
+ return clipboard.hasTextContent();
}
@Override
public void pasteText() throws DocumentValidationException {
- // TODO Auto-generated method stub
-
+ if (isReadOnly()) {
+ throw new ReadOnlyException("Cannot paste text, because the editor is read-only.");
+ }
+ clipboard.pasteText(this);
}
/*
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/IClipboard.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/IClipboard.java
new file mode 100644
index 0000000..56f5574
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/IClipboard.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2016 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 org.eclipse.vex.core.provisional.dom.DocumentValidationException;
+
+public interface IClipboard {
+
+ /**
+ * Cuts the current selection to the clipboard.
+ *
+ * @param editor
+ * TODO
+ */
+ void cutSelection(IDocumentEditor editor);
+
+ /**
+ * Copy the current selection to the clipboard.
+ *
+ * @param editor
+ * TODO
+ */
+ void copySelection(IDocumentEditor editor);
+
+ /**
+ * Returns true if the clipboard has content that can be pasted. Used to enable/disable the paste action of a
+ * containing application.
+ */
+ boolean hasContent();
+
+ /**
+ * Paste the current clipboard contents into the document at the current caret position.
+ *
+ * @param editor
+ * TODO
+ */
+ void paste(IDocumentEditor editor) throws DocumentValidationException;
+
+ /**
+ * Returns true if the clipboard has plain text content that can be pasted. Used to enable/disable the "paste text"
+ * action of a containing application.
+ */
+ boolean hasTextContent();
+
+ /**
+ * Paste the current clipboard contents as plain text into the document at the current caret position.
+ *
+ * @param editor
+ * TODO
+ */
+ void pasteText(IDocumentEditor editor) throws DocumentValidationException;
+
+}
diff --git a/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/InMemoryClipboard.java b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/InMemoryClipboard.java
new file mode 100644
index 0000000..61badb0
--- /dev/null
+++ b/org.eclipse.vex.core/src/org/eclipse/vex/core/internal/widget/InMemoryClipboard.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2016 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 org.eclipse.vex.core.provisional.dom.DocumentValidationException;
+import org.eclipse.vex.core.provisional.dom.IDocumentFragment;
+
+public class InMemoryClipboard implements IClipboard {
+
+ private IDocumentFragment content;
+
+ @Override
+ public void cutSelection(final IDocumentEditor editor) {
+ copySelection(editor);
+ editor.deleteSelection();
+ }
+
+ @Override
+ public void copySelection(final IDocumentEditor editor) {
+ if (!editor.hasSelection()) {
+ return;
+ }
+
+ content = editor.getSelectedFragment();
+ }
+
+ @Override
+ public boolean hasContent() {
+ if (content == null) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void paste(final IDocumentEditor editor) throws DocumentValidationException {
+ if (!hasContent()) {
+ return;
+ }
+
+ editor.insertFragment(content);
+ }
+
+ @Override
+ public boolean hasTextContent() {
+ if (content == null) {
+ return false;
+ }
+ final String text = content.getText();
+ if (text == null || "".equals(text)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void pasteText(final IDocumentEditor editor) throws DocumentValidationException {
+ if (!hasTextContent()) {
+ return;
+ }
+
+ editor.insertText(content.getText());
+ }
+
+}