All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fxmisc.richtext.model.TextEditingArea Maven / Gradle / Ivy

The newest version!
package org.fxmisc.richtext.model;

import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.scene.control.IndexRange;

import org.reactfx.EventStream;

/**
 * Interface for a text editing control.
 *
 * Defines the core methods. Other interfaces define default
 * higher-level methods implemented on top of the core methods.
 *
 * @param  type of style that can be applied to text.
 */
public interface TextEditingArea {

    /*******************
     *                 *
     *   Observables   *
     *                 *
     *******************/

    /**
     * The number of characters in this text-editing area.
     */
    int getLength();
    ObservableValue lengthProperty();

    /**
     * Text content of this text-editing area.
     */
    String getText();
    ObservableValue textProperty();

    /**
     * Rich-text content of this text-editing area.
     * The returned document is immutable, it does not reflect
     * subsequent edits of this text-editing area.
     */
    StyledDocument getDocument();

    /**
     * The current position of the caret, as a character offset in the text.
     *
     * Most of the time, caret is at the boundary of the selection (if there
     * is any selection). However, there are circumstances when the caret is
     * positioned inside or outside the selected text. For example, when the
     * user is dragging the selected text, the caret moves with the cursor
     * to point at the position where the selected text moves upon release.
     */
    int getCaretPosition();
    ObservableValue caretPositionProperty();

    /**
     * The anchor of the selection.
     * If there is no selection, this is the same as caret position.
     */
    int getAnchor();
    ObservableValue anchorProperty();

    /**
     * The selection range.
     *
     * One boundary is always equal to anchor, and the other one is most
     * of the time equal to caret position.
     */
    IndexRange getSelection();
    ObservableValue selectionProperty();

    /**
     * The selected text.
     */
    String getSelectedText();
    ObservableValue selectedTextProperty();

    /**
     * Index of the current paragraph, i.e. the paragraph with the caret.
     */
    int getCurrentParagraph();
    ObservableValue currentParagraphProperty();

    /**
     * The caret position within the current paragraph.
     */
    int getCaretColumn();
    ObservableValue caretColumnProperty();

    /**
     * Unmodifiable observable list of paragraphs in this text area.
     */
    ObservableList> getParagraphs();


    /*********************
     *                   *
     *   Event streams   *
     *                   *
     *********************/

    /**
     * Stream of text changes.
     */
    EventStream plainTextChanges();

    /**
     * Stream of rich text changes.
     */
    EventStream> richChanges();


    /***************
     *             *
     *   Queries   *
     *             *
     ***************/

    /**
     * Returns text content of the given paragraph.
     */
    String getText(int paragraphIndex);

    /**
     * Returns text content of the given character range.
     */
    String getText(int start, int end);

    /**
     * Returns text content of the given character range.
     *
     * 

Caution: see {@link #getAbsolutePosition(int, int)} to know how the column index argument * can affect the returned position.

*/ default String getText(int startParagraph, int startColumn, int endParagraph, int endColumn) { int start = getAbsolutePosition(startParagraph, startColumn); int end = getAbsolutePosition(endParagraph, endColumn); return getText(start, end); } /** * Returns rich-text content of the given paragraph. */ StyledDocument subDocument(int paragraphIndex); /** * Returns rich-text content of the given character range. */ StyledDocument subDocument(int start, int end); /** * Returns rich-text content of the given character range. * *

Caution: see {@link #getAbsolutePosition(int, int)} to know how the column index argument * can affect the returned position.

*/ default StyledDocument subDocument(int startParagraph, int startColumn, int endParagraph, int endColumn) { int start = getAbsolutePosition(startParagraph, startColumn); int end = getAbsolutePosition(endParagraph, endColumn); return subDocument(start, end); } /*************** * * * Actions * * * ***************/ /** * Positions the anchor and caretPosition explicitly, * effectively creating a selection. */ void selectRange(int anchor, int caretPosition); /** * Positions the anchor and caretPosition explicitly, * effectively creating a selection. * *

Caution: see {@link #getAbsolutePosition(int, int)} to know how the column index argument * can affect the returned position.

*/ default void selectRange(int anchorParagraph, int anchorColumn, int caretPositionParagraph, int caretPositionColumn) { int anchor = getAbsolutePosition(anchorParagraph, anchorColumn); int caretPosition = getAbsolutePosition(caretPositionParagraph, caretPositionColumn); selectRange(anchor, caretPosition); } /** * Replaces a range of characters with the given text. * * It must hold {@code 0 <= start <= end <= getLength()}. * * @param start Start index of the range to replace, inclusive. * @param end End index of the range to replace, exclusive. * @param text The text to put in place of the deleted range. * It must not be null. */ void replaceText(int start, int end, String text); /** * Replaces a range of characters with the given text. * * It must hold {@code 0 <= start <= end <= getLength()} where * {@code start = getAbsolutePosition(startParagraph, startColumn);} and is inclusive, and * {@code int end = getAbsolutePosition(endParagraph, endColumn);} and is exclusive. * *

Caution: see {@link #getAbsolutePosition(int, int)} to know how the column index argument * can affect the returned position.

* * @param text The text to put in place of the deleted range. * It must not be null. */ default void replaceText(int startParagraph, int startColumn, int endParagraph, int endColumn, String text) { int start = getAbsolutePosition(startParagraph, startColumn); int end = getAbsolutePosition(endParagraph, endColumn); replaceText(start, end, text); } /** * Replaces a range of characters with the given rich-text document. */ void replace(int start, int end, StyledDocument replacement); /** * Replaces a range of characters with the given rich-text document. * *

Caution: see {@link #getAbsolutePosition(int, int)} to know how the column index argument * can affect the returned position.

*/ default void replace(int startParagraph, int startColumn, int endParagraph, int endColumn, StyledDocument replacement) { int start = getAbsolutePosition(startParagraph, startColumn); int end = getAbsolutePosition(endParagraph, endColumn); replace(start, end, replacement); } /** * Replaces a range of characters with the given text. * * @param range The range to replace. It must not be null. * @param text The text to put in place of the deleted range. * It must not be null. * * @see #replaceText(int, int, String) */ default void replaceText(IndexRange range, String text) { replaceText(range.getStart(), range.getEnd(), text); } /** * Equivalent to * {@code replace(range.getStart(), range.getEnd(), replacement)}. */ default void replace(IndexRange range, StyledDocument replacement) { replace(range.getStart(), range.getEnd(), replacement); } /** * Returns the absolute position (i.e. the spot in-between characters) to the left of the given column in the given paragraph. * *

For example, given a text with only one line {@code "text"} and the columnIndex value of {@code 1}, "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 columnIndex 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) */ int getAbsolutePosition(int paragraphIndex, int columnIndex); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy