Author: rwhitcomb Date: Fri Feb 17 19:26:04 2017 New Revision: 1783453 URL: http://svn.apache.org/viewvc?rev=1783453&view=rev Log: PIVOT-992: Merge some ancillary changes (piecemeal) from "trunk" into "branches/2.0.x" that are needed to make the TextPane changes merged earlier to compile/work. Mostly these have to do with supporting text in ComponentNode, and using Span to access pieces of character data.
Modified: pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/Span.java pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/TextPane.java pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/ComponentNode.java pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/Node.java pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/TextNode.java Modified: pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/Span.java URL: http://svn.apache.org/viewvc/pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/Span.java?rev=1783453&r1=1783452&r2=1783453&view=diff ============================================================================== --- pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/Span.java (original) +++ pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/Span.java Fri Feb 17 19:26:04 2017 @@ -189,6 +189,20 @@ public final class Span { return new Span(Math.min(start, end), Math.max(start, end)); } + /** + * Returns a new {@link Span} with both values offset by the given value. + * <p> This is useful while moving through a {@link TextPane} document + * for instance, where you have to subtract off the starting offset for + * child nodes. + * + * @param offset The positive or negative amount by which to "move" this + * span (both start and end). + * @return A new {@link Span} with updated values. + */ + public Span offset(int offset) { + return new Span(this.start + offset, this.end + offset); + } + @Override public boolean equals(Object o) { boolean equal = false; Modified: pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/TextPane.java URL: http://svn.apache.org/viewvc/pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/TextPane.java?rev=1783453&r1=1783452&r2=1783453&view=diff ============================================================================== --- pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/TextPane.java (original) +++ pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/TextPane.java Fri Feb 17 19:26:04 2017 @@ -24,6 +24,7 @@ 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.ComponentNode; import org.apache.pivot.wtk.text.ComponentNodeListener; @@ -702,31 +703,92 @@ 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()); + /** + * 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??? + } + } } - else if (node instanceof Element) { - addToText(text, (Element)node); + 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'); } } /** - * Convenience method to get all the text from the current document - * into a single string. + * Convenience method to get all the text from the current document into a + * single string. + * + * @return The complete text of the document as a string. * @see #setText */ public String getText() { + int count; + Document doc = getDocument(); + 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("Beginning index " + beginIndex + + " is greater than ending index " + endIndex + "."); + } + + if (beginIndex < 0 || endIndex > getCharacterCount()) { + throw new IndexOutOfBoundsException("Beginning index = " + beginIndex + + ", ending index = " + endIndex + ", document.characterCount = " + + getCharacterCount() + "."); + } + + int count = endIndex - beginIndex; + if (count == 0) { + return ""; + } Document doc = getDocument(); - if (doc != null && getCharacterCount() != 0) { - StringBuilder text = new StringBuilder(getCharacterCount()); - addToText(text, doc); + if (doc != null) { + StringBuilder text = new StringBuilder(count); + addToText(text, doc, new Span(beginIndex, endIndex - 1)); return text.toString(); } return null; Modified: pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/ComponentNode.java URL: http://svn.apache.org/viewvc/pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/ComponentNode.java?rev=1783453&r1=1783452&r2=1783453&view=diff ============================================================================== --- pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/ComponentNode.java (original) +++ pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/ComponentNode.java Fri Feb 17 19:26:04 2017 @@ -17,7 +17,15 @@ package org.apache.pivot.wtk.text; import org.apache.pivot.util.ListenerList; +import org.apache.pivot.wtk.Button; import org.apache.pivot.wtk.Component; +import org.apache.pivot.wtk.Container; +import org.apache.pivot.wtk.Label; +import org.apache.pivot.wtk.Span; +import org.apache.pivot.wtk.TextArea; +import org.apache.pivot.wtk.TextInput; +import org.apache.pivot.wtk.TextPane; +import org.apache.pivot.wtk.content.ButtonData; /** * Node representing a live pivot component. @@ -62,14 +70,62 @@ public class ComponentNode extends Node } } + public String getText() { + return getText(this.component); + } + + private String getText(Component comp) { + if (comp instanceof TextInput) { + return ((TextInput)comp).getText(); + } else if (comp instanceof TextArea) { + return ((TextArea)comp).getText(); + } else if (comp instanceof TextPane) { + return ((TextPane)comp).getText(); + } else if (comp instanceof Label) { + return ((Label)comp).getText(); + } else if (comp instanceof Button) { + Object buttonData = ((Button)comp).getButtonData(); + if (buttonData instanceof ButtonData) { + return ((ButtonData)buttonData).getText(); + } else if (buttonData instanceof String) { + return (String)buttonData; + } else { + return buttonData.toString(); + } + } else if (comp instanceof Container) { + StringBuilder buf = new StringBuilder(); + for (Component child : (Container)comp) { + buf.append(getText(child)); + } + return buf.toString(); + } + return ""; + } + + public String getSubstring(Span range) { + return getText(this.component).substring(range.start, range.end + 1); + } + + public String getSubstring(int start, int end) { + return getText(this.component).substring(start, end); + } + + public CharSequence getCharacters(Span range) { + return getText(this.component).subSequence(range.start, range.end + 1); + } + + public CharSequence getCharacters(int start, int end) { + return getText(this.component).subSequence(start, end); + } + @Override public char getCharacterAt(int offset) { - return 0x00; + return getText(this.component).charAt(offset); } @Override public int getCharacterCount() { - return 1; + return getText(this.component).length(); } @Override @@ -84,7 +140,9 @@ public class ComponentNode extends Node @Override public Node getRange(int offset, int characterCount) { - if (offset < 0 || offset > 1) { + // Note: only supports getting the complete range of text + String componentText = getText(); + if (offset < 0 || offset >= componentText.length()) { throw new IndexOutOfBoundsException(); } Modified: pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/Node.java URL: http://svn.apache.org/viewvc/pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/Node.java?rev=1783453&r1=1783452&r2=1783453&view=diff ============================================================================== --- pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/Node.java (original) +++ pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/Node.java Fri Feb 17 19:26:04 2017 @@ -18,6 +18,7 @@ package org.apache.pivot.wtk.text; import org.apache.pivot.collections.Sequence; import org.apache.pivot.util.ListenerList; +import org.apache.pivot.wtk.Span; /** * Abstract base class for document nodes. @@ -120,6 +121,17 @@ public abstract class Node { } /** + * @return A {@link Span} that describes the content range of this node + * relative to the whole document. + */ + public Span getDocumentSpan() { + int docOffset = getDocumentOffset(); + int nodeLength = getCharacterCount(); + // The "end" of a Span is inclusive, so subtract one here + return new Span(docOffset, docOffset + nodeLength - 1); + } + + /** * Inserts a range into the node. Note that the contents of the range, * rather than the range itself, is added to the node. * Modified: pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/TextNode.java URL: http://svn.apache.org/viewvc/pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/TextNode.java?rev=1783453&r1=1783452&r2=1783453&view=diff ============================================================================== --- pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/TextNode.java (original) +++ pivot/branches/2.0.x/wtk/src/org/apache/pivot/wtk/text/TextNode.java Fri Feb 17 19:26:04 2017 @@ -17,6 +17,7 @@ package org.apache.pivot.wtk.text; import org.apache.pivot.util.ListenerList; +import org.apache.pivot.wtk.Span; /** * Node representing a sequence of characters. @@ -107,6 +108,10 @@ public final class TextNode extends Node } } + public String getSubstring(Span range) { + return characters.substring(range.start, range.end + 1); + } + public String getSubstring(int start, int end) { return characters.substring(start, end); } @@ -115,6 +120,14 @@ public final class TextNode extends Node return characters; } + public CharSequence getCharacters(int start, int end) { + return characters.subSequence(start, end); + } + + public CharSequence getCharacters(Span range) { + return characters.subSequence(range.start, range.end + 1); + } + @Override public char getCharacterAt(int index) { if (index < 0