From 8040c8061bdfbc6b1a5c38e39fde30711a7247c9 Mon Sep 17 00:00:00 2001 From: "jose.pereda" Date: Wed, 13 Nov 2024 20:01:36 +0100 Subject: [PATCH] Expose row and column position of caret --- .../com/gluonhq/richtextarea/RichTextArea.java | 15 +++++++++++++++ .../gluonhq/richtextarea/RichTextAreaSkin.java | 14 +++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/rta/src/main/java/com/gluonhq/richtextarea/RichTextArea.java b/rta/src/main/java/com/gluonhq/richtextarea/RichTextArea.java index 40ee183..bf28f5e 100644 --- a/rta/src/main/java/com/gluonhq/richtextarea/RichTextArea.java +++ b/rta/src/main/java/com/gluonhq/richtextarea/RichTextArea.java @@ -334,6 +334,21 @@ public final Point2D getCaretOrigin() { return caretOriginProperty.get(); } + /** + * A Point2D, with x for column and y for row, with integer values, for a given position of the caret. + * Column is defined by the number of characters from the beginning of the paragraph to the current position + * of the caret, starting in 0 (or -1 if the control has no text). + * Row is defined by the number of paragraph the caret is placed in, starting in 0 (or -1 if the control + * has no text). + */ + final ReadOnlyObjectWrapper caretRowColumnProperty = new ReadOnlyObjectWrapper<>(this, "caretRowColumn", Point2D.ZERO); + public final ReadOnlyObjectProperty caretRowColumnProperty() { + return caretRowColumnProperty.getReadOnlyProperty(); + } + public final Point2D getCaretRowColumn() { + return caretRowColumnProperty.get(); + } + /** * The current decoration at the caret. */ diff --git a/rta/src/main/java/com/gluonhq/richtextarea/RichTextAreaSkin.java b/rta/src/main/java/com/gluonhq/richtextarea/RichTextAreaSkin.java index c18f9f4..c7e68d4 100644 --- a/rta/src/main/java/com/gluonhq/richtextarea/RichTextAreaSkin.java +++ b/rta/src/main/java/com/gluonhq/richtextarea/RichTextAreaSkin.java @@ -392,6 +392,7 @@ protected void invalidated() { getSkinnable().decorationAtParagraph.bind(viewModel.decorationAtParagraphProperty()); caretPositionProperty.bind(viewModel.caretPositionProperty()); getSkinnable().caretOriginProperty.bind(caretOriginProperty); + getSkinnable().caretRowColumnProperty.bind(caretRowColumnProperty); promptNode.visibleProperty().bind(promptVisibleBinding); promptNode.fontProperty().bind(promptFontBinding); } else { @@ -404,6 +405,7 @@ protected void invalidated() { getSkinnable().decorationAtParagraph.unbind(); caretPositionProperty.unbind(); getSkinnable().caretOriginProperty.unbind(); + getSkinnable().caretRowColumnProperty.unbind(); promptNode.visibleProperty().unbind(); promptNode.fontProperty().unbind(); } @@ -425,7 +427,17 @@ protected void invalidated() { } }; - final ObjectProperty caretOriginProperty = new SimpleObjectProperty<>(this, "caretOrigin", DEFAULT_POINT_2D); + final ObjectProperty caretOriginProperty = new SimpleObjectProperty<>(this, "caretOrigin", DEFAULT_POINT_2D) { + @Override + protected void invalidated() { + viewModel.getParagraphWithCaret().ifPresentOrElse(p -> { + int row = viewModel.getParagraphList().indexOf(p); + int col = caretPositionProperty.get() - p.getStart(); + caretRowColumnProperty.set(new Point2D(col, row)); + }, () -> caretRowColumnProperty.set(DEFAULT_POINT_2D)); + } + }; + private final ObjectProperty caretRowColumnProperty = new SimpleObjectProperty<>(this, "caretRowColumn", DEFAULT_POINT_2D); private final ObjectBinding promptFontBinding = Bindings.createObjectBinding(this::getPromptNodeFont, viewModel.decorationAtCaretProperty(), viewModel.decorationAtParagraphProperty());