You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by rw...@apache.org on 2016/03/15 02:33:11 UTC
svn commit: r1735007 -
/pivot/trunk/wtk/src/org/apache/pivot/wtk/TextPane.java
Author: rwhitcomb
Date: Tue Mar 15 01:33:10 2016
New Revision: 1735007
URL: http://svn.apache.org/viewvc?rev=1735007&view=rev
Log:
Misc. TextPane improvements:
* Add some Javadoc, mostly pertaining to the offsets and whether they
are document-relative or block-relative.
* Notably add the "getText(start, end)" method so TextPane can (almost
completely) be used as a drop-in replacement with added functionality
for a TextArea control.
* Add some error messages to the IllegalStateExceptions that are thrown
everywhere.
Modified:
pivot/trunk/wtk/src/org/apache/pivot/wtk/TextPane.java
Modified: pivot/trunk/wtk/src/org/apache/pivot/wtk/TextPane.java
URL: http://svn.apache.org/viewvc/pivot/trunk/wtk/src/org/apache/pivot/wtk/TextPane.java?rev=1735007&r1=1735006&r2=1735007&view=diff
==============================================================================
--- pivot/trunk/wtk/src/org/apache/pivot/wtk/TextPane.java (original)
+++ pivot/trunk/wtk/src/org/apache/pivot/wtk/TextPane.java Tue Mar 15 01:33:10 2016
@@ -28,11 +28,14 @@ import org.apache.pivot.beans.DefaultPro
import org.apache.pivot.collections.LinkedList;
import org.apache.pivot.collections.Sequence;
import org.apache.pivot.util.ListenerList;
+import org.apache.pivot.wtk.Span;
import org.apache.pivot.wtk.media.Image;
+import org.apache.pivot.wtk.text.Block;
import org.apache.pivot.wtk.text.ComponentNode;
import org.apache.pivot.wtk.text.ComponentNodeListener;
import org.apache.pivot.wtk.text.Document;
import org.apache.pivot.wtk.text.Element;
+import org.apache.pivot.wtk.text.ImageNode;
import org.apache.pivot.wtk.text.Node;
import org.apache.pivot.wtk.text.NodeListener;
import org.apache.pivot.wtk.text.Paragraph;
@@ -178,6 +181,9 @@ public class TextPane extends Container
private static class TextPaneCharacterListenerList extends
WTKListenerList<TextPaneCharacterListener> implements TextPaneCharacterListener {
+ /**
+ * @param index Index into the whole document.
+ */
@Override
public void charactersInserted(TextPane textPane, int index, int count) {
for (TextPaneCharacterListener listener : this) {
@@ -185,6 +191,9 @@ public class TextPane extends Container
}
}
+ /**
+ * @param index Index into the whole document.
+ */
@Override
public void charactersRemoved(TextPane textPane, int index, int count) {
for (TextPaneCharacterListener listener : this) {
@@ -225,6 +234,9 @@ public class TextPane extends Container
};
private NodeListener documentListener = new NodeListener.Adapter() {
+ /**
+ * @param offset Offset into the document.
+ */
@Override
public void rangeInserted(Node node, int offset, int characterCount) {
if (selectionStart + selectionLength > offset) {
@@ -244,9 +256,11 @@ public class TextPane extends Container
}
}
+ /**
+ * @param offset Offset into the document.
+ */
@Override
public void nodesRemoved(Node node, Sequence<Node> removed, int offset) {
-
for (int i = 0; i < removed.getLength(); i++) {
Node descendant = removed.get(i);
if (descendant instanceof ComponentNode) {
@@ -261,6 +275,9 @@ public class TextPane extends Container
}
}
+ /**
+ * @param offset Offset into the document.
+ */
@Override
public void nodeInserted(Node node, int offset) {
Node descendant = document.getDescendantAt(offset);
@@ -271,6 +288,9 @@ public class TextPane extends Container
}
}
+ /**
+ * @param offset Offset into the document.
+ */
@Override
public void rangeRemoved(Node node, int offset, int characterCount) {
// if the end of the selection is in or after the range removed
@@ -425,7 +445,7 @@ public class TextPane extends Container
}
if (document == null) {
- throw new IllegalStateException();
+ throw new IllegalStateException("document is null.");
}
if (document.getCharacterCount() == 0) {
@@ -478,7 +498,44 @@ public class TextPane extends Container
}
if (document == null || document.getCharacterCount() == 0) {
- throw new IllegalStateException();
+ throw new IllegalStateException("document is null or empty.");
+ }
+
+ if (selectionLength > 0) {
+ removeDocumentRange(selectionStart, selectionLength);
+ }
+
+ // TODO If the caret is placed in the middle of a text node, split it;
+ // otherwise, insert an ImageNode immediately following the block
+ // containing the caret
+
+ // If the insertion is at the end of the document, then just add
+ if (selectionStart >= document.getCharacterCount() - 1) {
+ document.add(new ImageNode(image));
+ } else {
+ // Walk up the tree until we find a block
+ Node descendant = document.getDescendantAt(selectionStart);
+ while (!(descendant instanceof Block)) {
+ descendant = descendant.getParent();
+ }
+ Element parent = descendant.getParent();
+ if (parent != null) {
+ int index = parent.indexOf(descendant);
+ parent.insert(new ImageNode(image), index + 1);
+ }
+ }
+
+ // Set the selection start to the character following the insertion
+ setSelection(selectionStart + 1, selectionLength);
+ }
+
+ public void insertComponent(Component component) {
+ if (component == null) {
+ throw new IllegalArgumentException("component is null.");
+ }
+
+ if (document == null || document.getCharacterCount() == 0) {
+ throw new IllegalStateException("document is null or empty.");
}
if (selectionLength > 0) {
@@ -486,16 +543,32 @@ public class TextPane extends Container
}
// TODO If the caret is placed in the middle of a text node, split it;
- // otherwise, insert an ImageNode immediately following the node
+ // otherwise, insert a ComponentNode immediately following the block
// containing the caret
+ // If the insertion is at the end of the document, then just add
+ if (selectionStart >= document.getCharacterCount() - 1) {
+ document.add(new ComponentNode(component));
+ } else {
+ // Walk up the tree until we find a block
+ Node descendant = document.getDescendantAt(selectionStart);
+ while (!(descendant instanceof Block)) {
+ descendant = descendant.getParent();
+ }
+ Element parent = descendant.getParent();
+ if (parent != null) {
+ int index = parent.indexOf(descendant);
+ parent.insert(new ComponentNode(component), index + 1);
+ }
+ }
+
// Set the selection start to the character following the insertion
setSelection(selectionStart + 1, selectionLength);
}
public void insertParagraph() {
if (document == null || document.getCharacterCount() == 0) {
- throw new IllegalStateException();
+ throw new IllegalStateException("document is null or empty.");
}
if (selectionLength > 0) {
@@ -547,7 +620,7 @@ public class TextPane extends Container
public void removeText(int offset, int characterCount) {
if (document == null || document.getCharacterCount() == 0) {
- throw new IllegalStateException();
+ throw new IllegalStateException("document is null or empty.");
}
if (offset >= 0 && offset < document.getCharacterCount()) {
@@ -588,7 +661,7 @@ public class TextPane extends Container
public void cut() {
if (document == null || document.getCharacterCount() == 0) {
- throw new IllegalStateException();
+ throw new IllegalStateException("document is null or empty.");
}
if (selectionLength > 0) {
@@ -617,7 +690,7 @@ public class TextPane extends Container
public void copy() {
if (document == null || document.getCharacterCount() == 0) {
- throw new IllegalStateException();
+ throw new IllegalStateException("document is null or empty.");
}
String selectedText = getSelectedText();
@@ -631,7 +704,7 @@ public class TextPane extends Container
public void paste() {
if (document == null || document.getCharacterCount() == 0) {
- throw new IllegalStateException();
+ throw new IllegalStateException("document is null or empty.");
}
Manifest clipboardContent = Clipboard.getContent();
@@ -701,19 +774,42 @@ public class TextPane extends Container
// TODO
}
- private void addToText(StringBuilder text, Element element) {
- for (Node node : element) {
- if (node instanceof TextNode) {
- text.append(((TextNode) node).getCharacters());
- } else if (node instanceof ComponentNode) {
- text.append(((ComponentNode) node).getText());
- } else if (node instanceof Element) {
- addToText(text, (Element) node);
+ /**
+ * Add the text from the given element (and its children) to the given buffer,
+ * respecting the range of characters to be included.
+ * @param text The buffer we're building.
+ * @param element The current element in the document.
+ * @param includeSpan The range of text to be included (in document-relative
+ * coordinates).
+ */
+ private void addToText(StringBuilder text, Element element, Span includeSpan) {
+ Span elementSpan = element.getDocumentSpan();
+ Span elementIntersection = elementSpan.intersect(includeSpan);
+ if (elementIntersection != null) {
+ for (Node node : element) {
+ if (node instanceof Element) {
+ addToText(text, (Element) node, includeSpan);
+ }
+ else {
+ Span nodeSpan = node.getDocumentSpan();
+ Span nodeIntersection = nodeSpan.intersect(includeSpan);
+ if (nodeIntersection != null) {
+ Span currentSpan = nodeIntersection.offset(-nodeSpan.start);
+ if (node instanceof TextNode) {
+ text.append(((TextNode) node).getCharacters(currentSpan));
+ } else if (node instanceof ComponentNode) {
+ text.append(((ComponentNode) node).getCharacters(currentSpan));
+ }
+ // TODO: anything more that could/should be handled?
+ // lists for instance???
+ }
+ }
+ }
+ if (element instanceof Paragraph && elementIntersection.end == elementSpan.end) {
+ // TODO: unclear if this is included in the character count for a paragraph or not
+ // or what that means for the intersection range above
+ text.append('\n');
}
- // TODO: anything more that could/should be handled?
- }
- if (element instanceof Paragraph) {
- text.append('\n');
}
}
@@ -725,15 +821,45 @@ public class TextPane extends Container
*/
public String getText() {
Document doc = getDocument();
- if (doc != null && getCharacterCount() != 0) {
- StringBuilder text = new StringBuilder(getCharacterCount());
- addToText(text, doc);
+ int count;
+ if (doc != null && (count = getCharacterCount()) != 0) {
+ StringBuilder text = new StringBuilder(count);
+ addToText(text, doc, new Span(0, count - 1));
return text.toString();
}
return null;
}
/**
+ * Convenience method to get a portion of the document text into a single string.
+ *
+ * @param beginIndex The 0-based offset where to start retrieving text.
+ * @param endIndex The ending offset + 1 of the text to retrieve.
+ * @return The specified portion of the document text if there is any, or
+ * {@code null} if there is no document.
+ */
+ public String getText(int beginIndex, int endIndex) {
+ if (beginIndex > endIndex) {
+ throw new IllegalArgumentException();
+ }
+
+ if (beginIndex < 0 || endIndex > getCharacterCount()) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ int count = endIndex - beginIndex;
+ if (count == 0) {
+ return "";
+ }
+ Document doc = getDocument();
+ if (doc != null) {
+ StringBuilder text = new StringBuilder(count);
+ addToText(text, doc, new Span(beginIndex, endIndex - 1));
+ return text.toString();
+ }
+ return null;
+ }
+ /**
* Convenience method to create a text-only document consisting of one
* paragraph per line of the given text.
*
@@ -756,20 +882,14 @@ public class TextPane extends Container
throw new IllegalArgumentException();
}
- InputStream inputStream = null;
- try {
- inputStream = textURL.openStream();
+ try (InputStream inputStream = textURL.openStream()) {
setText(new InputStreamReader(inputStream));
- } finally {
- if (inputStream != null) {
- inputStream.close();
- }
}
}
public void setText(Reader textReader) throws IOException {
if (textReader == null) {
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException("Reader is null");
}
int tabPosition = 0;
@@ -849,7 +969,7 @@ public class TextPane extends Container
*/
public void setSelection(int selectionStart, int selectionLength) {
if (document == null || document.getCharacterCount() == 0) {
- throw new IllegalStateException();
+ throw new IllegalStateException("document is null or empty.");
}
if (selectionLength < 0) {
@@ -896,7 +1016,7 @@ public class TextPane extends Container
*/
public void selectAll() {
if (document == null) {
- throw new IllegalStateException();
+ throw new IllegalStateException("document is null.");
}
setSelection(0, document.getCharacterCount());