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

org.fxmisc.richtext.CaretSelectionBind Maven / Gradle / Ivy

package org.fxmisc.richtext;

import javafx.beans.value.ObservableValue;
import javafx.scene.control.IndexRange;
import org.fxmisc.richtext.model.StyledDocument;

import java.text.BreakIterator;

/**
 * An object for encapsulating a caret and a selection in a given area where the caret and selection are bound
 * to one another.
 *
 * In other words, selecting some range in the area (via {@link #selectRangeExpl(int, int)},
 * {@link #selectRange(int, int, int, int)}) will move the caret in the same call, except if one uses
 * {@link #displaceSelection(int, int)}. Updating the selection via any method with an "update" prefix from
 * {@link Selection} will also move the caret if it has been {@link #displaceCaret(int) displaced} or the anchor is
 * not the boundary (i.e. the selection's the start or end position) that is being updated.
 *
 * Likewise, moving the caret via the "move" prefix methods from {@link Caret}
 * will clear the selection in the same call, except if one uses {@link #displaceCaret(int)}.
 *
 * 

* "Position" refers to the place in-between characters. In other words, every {@code "|"} in * {@code "|t|e|x|t|"} is a valid position. There are two kinds of positions used here:

*
    *
  1. * {@link #getStartPosition()}/{@link #getEndPosition()}, which refers to a position somewhere in the * entire area's content. It's bounds are {@code 0 <= x <= area.getLength()}. *
  2. *
  3. * {@link #getStartColumnPosition()}/{@link #getEndColumnPosition()}, which refers to a position * somewhere in the current paragraph. It's bounds are {@code 0 <= x <= area.getParagraphLength(index)}. *
  4. *
* * Note: when parameter names are "position" without the "column" prefix, they refer to the position in the entire area. * *

* The selection is typically made using the {@link #getAnchorPosition() anchor's position} and * the underlying {@link Caret#getPosition() caret's position}. Hence, {@link #selectRangeExpl(int, int)} * is the typical method to use, although {@link #selectRange(int, int)} can also be used. *

* *

* For type safety, {@link #getSelectedDocument()} requires the same generic types from {@link StyledDocument}. * This means that one must write a lot of boilerplate for the generics: * {@code CaretSelectionBind, StyledText>, Collection> selection}. * However, this is only necessary if one is using {@link #getSelectedDocument()} or * {@link #selectedDocumentProperty()}. If you are not going to use the "selectedDocument" getter or property, * then just write the much simpler {@code CaretSelectionBind selection}. *

* * @see Caret * @see Selection * * @param type for {@link StyledDocument}'s paragraph style; only necessary when using the "selectedDocument" * getter or property * @param type for {@link StyledDocument}'s segment type; only necessary when using the "selectedDocument" * getter or property * @param type for {@link StyledDocument}'s segment style; only necessary when using the "selectedDocument" * getter or property */ public interface CaretSelectionBind extends Selection, Caret { CaretNode getUnderlyingCaret(); Selection getUnderlyingSelection(); /* ********************************************************************** * * * * Observables * * * * Observables are "dynamic" (i.e. changing) characteristics of this * * control. They are not directly settable by the client code, but change * * in response to user input and/or API actions. * * * * ********************************************************************** */ int getAnchorPosition(); ObservableValue anchorPositionProperty(); int getAnchorParIndex(); ObservableValue anchorParIndexProperty(); int getAnchorColPosition(); ObservableValue anchorColPositionProperty(); /* ********************************************************************** * * * * Actions * * * * Actions change the state of this control. They typically cause a * * change of one or more observables and/or produce an event. * * * * ********************************************************************** */ // caret /** * Moves the caret to the given position in the text and clears any selection. */ @Override default void moveTo(int position) { moveTo(position, NavigationActions.SelectionPolicy.CLEAR); } /** * Moves the caret to the position returned from * {@link TextEditingArea#getAbsolutePosition(int, int)} * and clears any selection. */ @Override default void moveTo(int paragraphIndex, int columnPosition) { moveTo(paragraphIndex, columnPosition, NavigationActions.SelectionPolicy.CLEAR); } /** * Moves the caret to the beginning of the current paragraph and clears any selection */ @Override default void moveToParStart() { moveToParStart(NavigationActions.SelectionPolicy.CLEAR); } /** * Moves the caret to the end of the current paragraph and clears any selection */ @Override default void moveToParEnd() { moveToParEnd(NavigationActions.SelectionPolicy.CLEAR); } /** * Moves the caret to the beginning of the area and clears any selection */ @Override default void moveToAreaStart() { moveToAreaStart(NavigationActions.SelectionPolicy.CLEAR); } /** * Moves the caret to the end of the area and clears any selection */ @Override default void moveToAreaEnd() { moveToAreaEnd(NavigationActions.SelectionPolicy.CLEAR); } /** * Moves the caret backward one char in the text and clears any selection */ @Override default void moveToPrevChar() { moveToPrevChar(NavigationActions.SelectionPolicy.CLEAR); } /** * Moves the caret forward one char in the text and clears any selection */ @Override default void moveToNextChar() { moveToNextChar(NavigationActions.SelectionPolicy.CLEAR); } /** * Moves the caret forwards by the number of breaks and clears any selection */ @Override void moveBreaksForwards(int numOfBreaks, BreakIterator breakIterator); /** * Moves the caret backwards by the number of breaks and clears any selection */ @Override void moveBreaksBackwards(int numOfBreaks, BreakIterator breakIterator); // selection /** * Selects the given range and moves the caret to either the start of the new selection if the anchor was equal to * the original start or the end if the anchor was equal to the original end * *

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

*/ @Override void selectRange(int startParagraphIndex, int startColPosition, int endParagraphIndex, int endColPosition); /** * Selects the given range and moves the caret to either the start of the new selection if the anchor was equal to * the original start or the end if the anchor was equal to the original end */ @Override void selectRange(int startPosition, int endPosition); @Override void updateStartBy(int amount, Direction direction); @Override void updateEndBy(int amount, Direction direction); @Override void updateStartTo(int position); @Override void updateStartTo(int paragraphIndex, int columnPosition); @Override void updateStartByBreaksForward(int numOfBreaks, BreakIterator breakIterator); @Override void updateStartByBreaksBackward(int numOfBreaks, BreakIterator breakIterator); @Override void updateEndTo(int position); @Override void updateEndTo(int paragraphIndex, int columnPosition); @Override void updateEndByBreaksForward(int numOfBreaks, BreakIterator breakIterator); @Override void updateEndByBreaksBackward(int numOfBreaks, BreakIterator breakIterator); /** * Selects everything in the area and moves the caret to either the start of the new selection if the anchor was * equal to the original start or the end if the anchor was equal to the original end */ @Override void selectAll(); /** * Selects the given paragraph and moves the caret to either the start of the new selection if the anchor was * equal to the original start or the end if the anchor was equal to the original end */ @Override void selectParagraph(int paragraphIndex); /** * Selects the closest word to the given position in the area and moves the caret to either the start of the new * selection if the anchor was equal to the original start or the end if the anchor was equal to the original end */ @Override void selectWord(int wordPositionInArea); /** * Clears the selection while keeping the caret position the same. */ @Override void deselect(); // caret selection bind /** * Positions the anchor and caretPosition explicitly, * effectively creating a selection. */ void selectRangeExpl(int anchorParagraph, int anchorColumn, int caretParagraph, int caretColumn); /** * Positions the anchor and caretPosition explicitly, * effectively creating a selection. */ void selectRangeExpl(int anchorPosition, int caretPosition); /** * Moves the caret to the position indicated by {@code pos}. * Based on the selection policy, the selection is either cleared * (i.e. anchor is set to the same position as caret), adjusted * (i.e. anchor is not moved at all), or extended * (i.e. {@code pos} becomes the new caret and, if {@code pos} points * outside the current selection, the far end of the current selection * becomes the anchor. */ default void moveTo(int pos, NavigationActions.SelectionPolicy selectionPolicy) { switch(selectionPolicy) { case CLEAR: selectRange(pos, pos); break; case ADJUST: selectRange(getAnchorPosition(), pos); break; case EXTEND: IndexRange sel = getRange(); int anchor; if(pos <= sel.getStart()) anchor = sel.getEnd(); else if(pos >= sel.getEnd()) anchor = sel.getStart(); else anchor = getAnchorPosition(); selectRangeExpl(anchor, pos); break; } } /** * Moves the caret to the position returned from * {@link TextEditingArea#getAbsolutePosition(int, int)}. */ void moveTo(int paragraphIndex, int columnIndex, NavigationActions.SelectionPolicy selectionPolicy); /** * Moves the caret backward one char in the text. * Based on the given selection policy, anchor either moves with * the caret, stays put, or moves to the former caret position. */ void moveToPrevChar(NavigationActions.SelectionPolicy selectionPolicy); /** * Moves the caret forward one char in the text. * Based on the given selection policy, anchor either moves with * the caret, stays put, or moves to the former caret position. */ void moveToNextChar(NavigationActions.SelectionPolicy selectionPolicy); void moveToParStart(NavigationActions.SelectionPolicy selectionPolicy); void moveToParEnd(NavigationActions.SelectionPolicy selectionPolicy); void moveToAreaStart(NavigationActions.SelectionPolicy selectionPolicy); void moveToAreaEnd(NavigationActions.SelectionPolicy selectionPolicy); default void selectParagraph() { int parStartPosition = getPosition() - getColumnPosition(); int parEndPosition = parStartPosition + getArea().getParagraphLength(getParagraphIndex()); selectRange(parStartPosition, parEndPosition); } /** * Selects the word closest to the caret */ default void selectWord() { selectWord(getPosition()); }; /** * Displaces the caret from the selection by positioning only the caret to the new location without * also affecting the selection's {@link #getAnchorPosition()} anchor} or the {@link #getRange()} selection}. * Do not confuse this method with {@link #moveTo(int)}, which is the normal way of moving the caret. * This method can be used to achieve the special case of positioning the caret outside or inside the selection, * as opposed to always being at the boundary. Use with care. */ void displaceCaret(int position); /** * Displaces the caret from the selection by positioning only the selection to the new location without * also affecting the {@link #getPosition() caret's position}. * This method can be used to achieve the special case of selecting some range in the area without affecting the * caret's position. Use with care. */ void displaceSelection(int startPosition, int endPosition); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy