From c8035f4b6939d5b7e85ae3ff0401b9538583677e Mon Sep 17 00:00:00 2001 From: Symeon94 Date: Mon, 5 Jan 2026 08:18:46 +0100 Subject: [PATCH 1/4] UT for test character hit --- .../org/fxmisc/richtext/CharacterHit.java | 1 - .../richtext/model/TwoLevelNavigator.java | 2 +- .../org/fxmisc/richtext/CharacterHitTest.java | 43 +++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 richtextfx/src/test/java/org/fxmisc/richtext/CharacterHitTest.java diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java b/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java index a9734c3bb..6345e6b51 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java @@ -32,7 +32,6 @@ public static CharacterHit trailingHalfOf(int charIdx) { return new CharacterHit(OptionalInt.of(charIdx), charIdx + 1); } - private final OptionalInt charIdx; private final int insertionIndex; diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/model/TwoLevelNavigator.java b/richtextfx/src/main/java/org/fxmisc/richtext/model/TwoLevelNavigator.java index 976c36b58..b93f9f37b 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/model/TwoLevelNavigator.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/model/TwoLevelNavigator.java @@ -7,7 +7,7 @@ /** * Default implementation of {@link TwoDimensional} that makes it trivial to calculate a position within a - * two dimensional object. + * two-dimensional object. */ public class TwoLevelNavigator implements TwoDimensional { diff --git a/richtextfx/src/test/java/org/fxmisc/richtext/CharacterHitTest.java b/richtextfx/src/test/java/org/fxmisc/richtext/CharacterHitTest.java new file mode 100644 index 000000000..242230847 --- /dev/null +++ b/richtextfx/src/test/java/org/fxmisc/richtext/CharacterHitTest.java @@ -0,0 +1,43 @@ +package org.fxmisc.richtext; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class CharacterHitTest { + private void checkHitAndNoCharIndex(CharacterHit hit, int insertion) { + assertEquals(insertion, hit.getInsertionIndex()); + assertTrue(hit.getCharacterIndex().isEmpty()); + } + + private void checkHit(CharacterHit hit, int insertion, int charIdx) { + assertEquals(insertion, hit.getInsertionIndex()); + assertEquals(charIdx, hit.getCharacterIndex().orElseThrow()); + } + + @Test + @DisplayName("Character hit insertion at a given position") + void insertionAt() { + CharacterHit hit = CharacterHit.insertionAt(2); + checkHitAndNoCharIndex(hit, 2); + checkHitAndNoCharIndex(hit.offset(12), 14); + } + + @Test + @DisplayName("Character hit leading half at a given position") + void leadingHalfOf() { + CharacterHit hit = CharacterHit.leadingHalfOf(2); + checkHit(hit, 2, 2); + checkHit(hit.offset(12), 14, 14); + } + + @Test + @DisplayName("Character hit trailing half at a given position") + void trailingHalfOf() { + CharacterHit hit = CharacterHit.trailingHalfOf(2); + checkHit(hit, 3, 2); + checkHit(hit.offset(12), 15, 14); + } +} From 84c86782606e79587f583082a7bdfa096fd61116 Mon Sep 17 00:00:00 2001 From: Symeon94 Date: Mon, 5 Jan 2026 08:28:10 +0100 Subject: [PATCH 2/4] More explanation --- .../org/fxmisc/richtext/CharacterHit.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java b/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java index 6345e6b51..5a0f91cdc 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java @@ -3,13 +3,16 @@ import java.util.OptionalInt; /** - * Object that stores information relating to the position in an area's content that corresponds to a given position - * in some visible entity (e.g. the area, a paragraph in the area, a line on a paragraph). + *

Object that stores information relating to the position in an area's content that corresponds to a given position + * in some visible entity (e.g. the area, a paragraph in the area, a line on a paragraph).

+ *

A character hit can either be before a given character (leading) or after a given character (trailing).

+ *

A special case is planned when the character hit happens outside the boundaries of some visible entity. In this case + * there is an insertion index but there isn't any actual character position in the content.

*/ public class CharacterHit { /** - * Returns a {@link CharacterHit} for cases where the insertion occurs outside the bounds of some visible entity + * @return a {@link CharacterHit} for cases where the insertion occurs outside the bounds of some visible entity * (e.g. the area, the paragraph in an area, the line in a paragraph) */ public static CharacterHit insertionAt(int insertionIndex) { @@ -17,7 +20,10 @@ public static CharacterHit insertionAt(int insertionIndex) { } /** - * Returns a {@link CharacterHit} for cases where the hit occurs inside the bounds of some visible entity + *

Represents a hit happening before a character at a given position (meaning the character is located forward).

+ *

Example: If you have a hit on {@code ALPHA} at position 1, it means before the character {@code L}. The character + * index would be 1 and the insertion would be at 1.

+ * @return a {@link CharacterHit} for cases where the hit occurs inside the bounds of some visible entity * (e.g. the area, the paragraph in an area, the line in a paragraph) and the character is leading. */ public static CharacterHit leadingHalfOf(int charIdx) { @@ -25,7 +31,10 @@ public static CharacterHit leadingHalfOf(int charIdx) { } /** - * Returns a {@link CharacterHit} for cases where the hit occurs inside the bounds of some visible entity + *

A hit that happens after the character at the given position (meaning the character is before).

+ *

Example: If you have a hit on {@code ALPHA} at position 1, it means after the character {@code L}. The character + * index would be 1 but the insertion would be at 2.

+ * @return a {@link CharacterHit} for cases where the hit occurs inside the bounds of some visible entity * (e.g. the area, the paragraph in an area, the line in a paragraph) and the character is trailing. */ public static CharacterHit trailingHalfOf(int charIdx) { From 22732b5b7e180c85e394de0f075fa8f539a2ff6a Mon Sep 17 00:00:00 2001 From: Symeon94 Date: Mon, 5 Jan 2026 08:33:12 +0100 Subject: [PATCH 3/4] Adding method to use a variable to generate the hit --- .../org/fxmisc/richtext/CharacterHit.java | 7 +++++++ .../org/fxmisc/richtext/CharacterHitTest.java | 19 ++++++++++--------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java b/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java index 5a0f91cdc..078ae408b 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java @@ -30,6 +30,13 @@ public static CharacterHit leadingHalfOf(int charIdx) { return new CharacterHit(OptionalInt.of(charIdx), charIdx); } + /** + * Same as {@link #leadingHalfOf(int)} if {@code leading} is set to true, else same as {@link #trailingHalfOf(int)} + */ + public static CharacterHit at(int charIdx, boolean leading) { + return leading ? leadingHalfOf(charIdx) : trailingHalfOf(charIdx); + } + /** *

A hit that happens after the character at the given position (meaning the character is before).

*

Example: If you have a hit on {@code ALPHA} at position 1, it means after the character {@code L}. The character diff --git a/richtextfx/src/test/java/org/fxmisc/richtext/CharacterHitTest.java b/richtextfx/src/test/java/org/fxmisc/richtext/CharacterHitTest.java index 242230847..1e777d690 100644 --- a/richtextfx/src/test/java/org/fxmisc/richtext/CharacterHitTest.java +++ b/richtextfx/src/test/java/org/fxmisc/richtext/CharacterHitTest.java @@ -20,24 +20,25 @@ private void checkHit(CharacterHit hit, int insertion, int charIdx) { @Test @DisplayName("Character hit insertion at a given position") void insertionAt() { - CharacterHit hit = CharacterHit.insertionAt(2); - checkHitAndNoCharIndex(hit, 2); - checkHitAndNoCharIndex(hit.offset(12), 14); + checkHitAndNoCharIndex(CharacterHit.insertionAt(2), 2); + checkHitAndNoCharIndex(CharacterHit.insertionAt(2).offset(12), 14); } @Test @DisplayName("Character hit leading half at a given position") void leadingHalfOf() { - CharacterHit hit = CharacterHit.leadingHalfOf(2); - checkHit(hit, 2, 2); - checkHit(hit.offset(12), 14, 14); + checkHit(CharacterHit.leadingHalfOf(2), 2, 2); + checkHit(CharacterHit.leadingHalfOf(2).offset(12), 14, 14); + checkHit(CharacterHit.at(2, true), 2, 2); + checkHit(CharacterHit.at(2, true).offset(12), 14, 14); } @Test @DisplayName("Character hit trailing half at a given position") void trailingHalfOf() { - CharacterHit hit = CharacterHit.trailingHalfOf(2); - checkHit(hit, 3, 2); - checkHit(hit.offset(12), 15, 14); + checkHit(CharacterHit.trailingHalfOf(2), 3, 2); + checkHit(CharacterHit.trailingHalfOf(2).offset(12), 15, 14); + checkHit(CharacterHit.at(2, false), 3, 2); + checkHit(CharacterHit.at(2, false).offset(12), 15, 14); } } From 5be7da1b7ef1fca04cc470432f28c2858edc907f Mon Sep 17 00:00:00 2001 From: Symeon94 Date: Mon, 5 Jan 2026 08:41:35 +0100 Subject: [PATCH 4/4] Cleanup --- .../src/main/java/org/fxmisc/richtext/CharacterHit.java | 7 ------- .../test/java/org/fxmisc/richtext/CharacterHitTest.java | 4 ---- 2 files changed, 11 deletions(-) diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java b/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java index 078ae408b..5a0f91cdc 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/CharacterHit.java @@ -30,13 +30,6 @@ public static CharacterHit leadingHalfOf(int charIdx) { return new CharacterHit(OptionalInt.of(charIdx), charIdx); } - /** - * Same as {@link #leadingHalfOf(int)} if {@code leading} is set to true, else same as {@link #trailingHalfOf(int)} - */ - public static CharacterHit at(int charIdx, boolean leading) { - return leading ? leadingHalfOf(charIdx) : trailingHalfOf(charIdx); - } - /** *

A hit that happens after the character at the given position (meaning the character is before).

*

Example: If you have a hit on {@code ALPHA} at position 1, it means after the character {@code L}. The character diff --git a/richtextfx/src/test/java/org/fxmisc/richtext/CharacterHitTest.java b/richtextfx/src/test/java/org/fxmisc/richtext/CharacterHitTest.java index 1e777d690..7723f1fc7 100644 --- a/richtextfx/src/test/java/org/fxmisc/richtext/CharacterHitTest.java +++ b/richtextfx/src/test/java/org/fxmisc/richtext/CharacterHitTest.java @@ -29,8 +29,6 @@ void insertionAt() { void leadingHalfOf() { checkHit(CharacterHit.leadingHalfOf(2), 2, 2); checkHit(CharacterHit.leadingHalfOf(2).offset(12), 14, 14); - checkHit(CharacterHit.at(2, true), 2, 2); - checkHit(CharacterHit.at(2, true).offset(12), 14, 14); } @Test @@ -38,7 +36,5 @@ void leadingHalfOf() { void trailingHalfOf() { checkHit(CharacterHit.trailingHalfOf(2), 3, 2); checkHit(CharacterHit.trailingHalfOf(2).offset(12), 15, 14); - checkHit(CharacterHit.at(2, false), 3, 2); - checkHit(CharacterHit.at(2, false).offset(12), 15, 14); } }