X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.ui%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fui%2Feditor2%2Fiterator%2FJavaWordIterator.java;fp=bundles%2Forg.simantics.scl.ui%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fui%2Feditor2%2Fiterator%2FJavaWordIterator.java;h=403cc9df320ebb2aefc9cea392a765bc3b05647a;hp=0000000000000000000000000000000000000000;hb=3286205a29ade556a0ac3e19c68ac6ebb3c8a62d;hpb=e81aaf01a022b7f9fd54924f843a8f8594682126 diff --git a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/editor2/iterator/JavaWordIterator.java b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/editor2/iterator/JavaWordIterator.java new file mode 100644 index 000000000..403cc9df3 --- /dev/null +++ b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/editor2/iterator/JavaWordIterator.java @@ -0,0 +1,224 @@ +package org.simantics.scl.ui.editor2.iterator; + +import java.text.CharacterIterator; + +import com.ibm.icu.text.BreakIterator; + +import org.eclipse.core.runtime.Assert; + + + +/** + * Breaks java text into word starts, also stops at line start and end. No + * direction dependency. + * + * @since 3.0 + */ +public class JavaWordIterator extends BreakIterator { + + /** + * The underlying java break iterator. It returns all breaks, including + * before and after every whitespace. + */ + private JavaBreakIterator fIterator; + /** The current index for the stateful operations. */ + private int fIndex; + + /** + * Creates a new word iterator. + */ + public JavaWordIterator() { + fIterator= new JavaBreakIterator(); + first(); + } + + /* + * @see java.text.BreakIterator#first() + */ + @Override + public int first() { + fIndex= fIterator.first(); + return fIndex; + } + + /* + * @see java.text.BreakIterator#last() + */ + @Override + public int last() { + fIndex= fIterator.last(); + return fIndex; + } + + /* + * @see java.text.BreakIterator#next(int) + */ + @Override + public int next(int n) { + int next= 0; + while (--n > 0 && next != DONE) { + next= next(); + } + return next; + } + + /* + * @see java.text.BreakIterator#next() + */ + @Override + public int next() { + fIndex= following(fIndex); + return fIndex; + } + + /* + * @see java.text.BreakIterator#previous() + */ + @Override + public int previous() { + fIndex= preceding(fIndex); + return fIndex; + } + + + /* + * @see java.text.BreakIterator#preceding(int) + */ + @Override + public int preceding(int offset) { + int first= fIterator.preceding(offset); + if (isWhitespace(first, offset)) { + int second= fIterator.preceding(first); + if (second != DONE && !isDelimiter(second, first)) + return second; + } + return first; + } + + /* + * @see java.text.BreakIterator#following(int) + */ + @Override + public int following(int offset) { + int first= fIterator.following(offset); + if (eatFollowingWhitespace(offset, first)) { + int second= fIterator.following(first); + if (isWhitespace(first, second)) + return second; + } + return first; + } + + private boolean eatFollowingWhitespace(int offset, int exclusiveEnd) { + if (exclusiveEnd == DONE || offset == DONE) + return false; + + if (isWhitespace(offset, exclusiveEnd)) + return false; + if (isDelimiter(offset, exclusiveEnd)) + return false; + + return true; + } + + /** + * Returns true if the given sequence into the underlying text + * represents a delimiter, false otherwise. + * + * @param offset the offset + * @param exclusiveEnd the end offset + * @return true if the given range is a delimiter + */ + private boolean isDelimiter(int offset, int exclusiveEnd) { + if (exclusiveEnd == DONE || offset == DONE) + return false; + + Assert.isTrue(offset >= 0); + Assert.isTrue(exclusiveEnd <= getText().getEndIndex()); + Assert.isTrue(exclusiveEnd > offset); + + CharSequence seq= fIterator.fText; + + while (offset < exclusiveEnd) { + char ch= seq.charAt(offset); + if (ch != '\n' && ch != '\r') + return false; + offset++; + } + + return true; + } + + /** + * Returns true if the given sequence into the underlying text + * represents whitespace, but not a delimiter, false otherwise. + * + * @param offset the offset + * @param exclusiveEnd the end offset + * @return true if the given range is whitespace + */ + private boolean isWhitespace(int offset, int exclusiveEnd) { + if (exclusiveEnd == DONE || offset == DONE) + return false; + + Assert.isTrue(offset >= 0); + Assert.isTrue(exclusiveEnd <= getText().getEndIndex()); + Assert.isTrue(exclusiveEnd > offset); + + CharSequence seq= fIterator.fText; + + while (offset < exclusiveEnd) { + char ch= seq.charAt(offset); + if (!Character.isWhitespace(ch)) + return false; + if (ch == '\n' || ch == '\r') + return false; + offset++; + } + + return true; + } + + /* + * @see java.text.BreakIterator#current() + */ + @Override + public int current() { + return fIndex; + } + + /* + * @see java.text.BreakIterator#getText() + */ + @Override + public CharacterIterator getText() { + return fIterator.getText(); + } + + /** + * Sets the text as CharSequence. + * @param newText the new text + */ + public void setText(CharSequence newText) { + fIterator.setText(newText); + first(); + } + + /* + * @see java.text.BreakIterator#setText(java.text.CharacterIterator) + */ + @Override + public void setText(CharacterIterator newText) { + fIterator.setText(newText); + first(); + } + + /* + * @see java.text.BreakIterator#setText(java.lang.String) + */ + @Override + public void setText(String newText) { + setText((CharSequence) newText); + } + +}