org.fxmisc.richtext.model.StyledDocument Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of richtextfx Show documentation
Show all versions of richtextfx Show documentation
Rich-text area for JavaFX
The newest version!
package org.fxmisc.richtext.model;
import static org.fxmisc.richtext.model.TwoDimensional.Bias.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javafx.scene.control.IndexRange;
/**
* An object (document) that is a list of styleable {@link Paragraph} that each contain a list of styleable segments.
*
* @param The type of the paragraph style.
* @param The type of the segments in the paragraph (e.g. {@link String}).
* @param The type of the style of individual segments.
*/
public interface StyledDocument extends TwoDimensional {
int length();
String getText();
List> getParagraphs();
StyledDocument concat(StyledDocument that);
StyledDocument subSequence(int start, int end);
default String getText(IndexRange range) {
return getText(range.getStart(), range.getEnd());
}
default String getText(int start, int end) {
return subSequence(start, end).getText();
}
default String getText(int paragraphIndex) {
return getParagraph(paragraphIndex).getText();
}
default Paragraph getParagraph(int index) {
return getParagraphs().get(index);
}
default int getParagraphLength(int paragraphIndex) {
return getParagraph(paragraphIndex).length();
}
default StyledDocument subSequence(IndexRange range) {
return subSequence(range.getStart(), range.getEnd());
}
default StyledDocument subDocument(int paragraphIndex) {
return new ReadOnlyStyledDocument<>(Collections.singletonList(getParagraphs().get(paragraphIndex)));
}
default char charAt(int index) {
Position pos = offsetToPosition(index, Forward);
return getParagraphs().get(pos.getMajor()).charAt(pos.getMinor());
}
default S getStyleOfChar(int index) {
Position pos2D = offsetToPosition(index, Forward);
int paragraph = pos2D.getMajor();
int col = pos2D.getMinor();
return getParagraphs().get(paragraph).getStyleOfChar(col);
}
default S getStyleOfChar(int paragraph, int column) {
return getParagraphs().get(paragraph).getStyleOfChar(column);
}
default S getStyleAtPosition(int position) {
Position pos2D = offsetToPosition(position, Forward);
return getStyleAtPosition(pos2D.getMajor(), pos2D.getMinor());
}
default S getStyleAtPosition(int paragraph, int position) {
return getParagraphs().get(paragraph).getStyleAtPosition(position);
}
default PS getParagraphStyle(int paragraph) {
return getParagraphs().get(paragraph).getParagraphStyle();
}
default PS getParagraphStyleAtPosition(int position) {
Position pos = offsetToPosition(position, Forward);
return getParagraphStyle(pos.getMajor());
}
default IndexRange getStyleRangeAtPosition(int position) {
Position pos2D = offsetToPosition(position, Forward);
int paragraph = pos2D.getMajor();
int col = pos2D.getMinor();
return getParagraphs().get(paragraph).getStyleRangeAtPosition(col);
}
default IndexRange getStyleRangeAtPosition(int paragraph, int position) {
return getParagraphs().get(paragraph).getStyleRangeAtPosition(position);
}
default StyleSpans getStyleSpans(int from, int to) {
Position start = offsetToPosition(from, Forward);
Position end = to == from
? start
: start.offsetBy(to - from, Backward);
int startParIdx = start.getMajor();
int endParIdx = end.getMajor();
int affectedPars = endParIdx - startParIdx + 1;
List> subSpans = new ArrayList<>(affectedPars);
if(startParIdx == endParIdx) {
Paragraph par = getParagraphs().get(startParIdx);
subSpans.add(par.getStyleSpans(start.getMinor(), end.getMinor()));
} else {
Paragraph startPar = getParagraphs().get(startParIdx);
subSpans.add(startPar.getStyleSpans(start.getMinor(), startPar.length() + 1));
for(int i = startParIdx + 1; i < endParIdx; ++i) {
Paragraph par = getParagraphs().get(i);
subSpans.add(par.getStyleSpans(0, par.length() + 1));
}
Paragraph endPar = getParagraphs().get(endParIdx);
subSpans.add(endPar.getStyleSpans(0, end.getMinor()));
}
int n = subSpans.stream().mapToInt(StyleSpans::getSpanCount).sum();
StyleSpansBuilder builder = new StyleSpansBuilder<>(n);
for(StyleSpans spans: subSpans) {
for(StyleSpan span: spans) {
builder.add(span);
}
}
return builder.create();
}
default StyleSpans getStyleSpans(int paragraph) {
return getParagraphs().get(paragraph).getStyleSpans();
}
default StyleSpans getStyleSpans(int paragraph, int from, int to) {
return getParagraphs().get(paragraph).getStyleSpans(from, to);
}
/**
* Returns the absolute position (i.e. the spot in-between characters) of the given column position in the given
* paragraph.
*
* For example, given a text with only one line {@code "text"} and a {@code columnPosition} value of {@code 1},
* the value, {@code 1}, as in "position 1" would be returned:
*
* ┌ character index 0
* | ┌ character index 1
* | | ┌ character index 3
* | | |
* v v v
*
* |t|e|x|t|
*
* ^ ^ ^
* | | |
* | | └ position 4
* | └ position 1
* └ position 0
*
*
* Warning: Off-By-One errors can easily occur
* If the column index spans outside of the given paragraph's length, the returned value will
* pass on to the previous/next paragraph. In other words, given a document with two paragraphs
* (where the first paragraph's text is "some" and the second "thing"), then the following statements are true:
*
* getAbsolutePosition(0, "some".length()) == 4 == getAbsolutePosition(1, -1)
* getAbsolutePosition(0, "some".length() + 1) == 5 == getAbsolutePosition(1, 0)
*
*
* @param paragraphIndex The index of the paragraph from which to start.
* @param columnPosition If positive, the index going forward (the given paragraph's line or the next one(s)).
* If negative, the index going backward (the previous paragraph's line(s))
*/
default int getAbsolutePosition(int paragraphIndex, int columnPosition) {
int position = position(paragraphIndex, columnPosition).toOffset();
if (position < 0) {
throw new IndexOutOfBoundsException(String.format("Negative index! Out of bounds by %s.", 0 - position));
}
if (length() < position) {
throw new IndexOutOfBoundsException(String.format("Out of bounds by %s. Area Length: %s", position - length(), length()));
}
return position;
}
}