RichTextFX

repository·master·Indexed 23 days ago

https://github.com/fxmisc/richtextfx

A memory-efficient JavaFX library for building rich text and code editors. It provides a foundation for styling text ranges, displaying custom in-line objects, and implementing features like line numbers and syntax highlighting. Key components include GenericStyledArea, StyledTextArea, InlineCssTextArea, StyleClassedTextArea, and CodeArea. The library requires JDK 11 or higher, with version 0.11.7 required for JavaFX 25+.

Tokens
1.7K
Snippets
2
Records
12
Agent score
79%

What's inside RichTextFX

  1. Choose the right RichTextFX area class

    master

    RichTextFX provides several 'flavors' of text areas depending on whether you need to display custom objects (like images or emojis) or just styled text.

    1. GenericStyledArea: The base class. Use this if you need to inline custom objects (images, hyperlinks, etc.) alongside text. It uses generics for paragraph styles (PS), segment objects (SEG), and segment styles (S).
    2. StyledTextArea: The most common choice if you only need styled text. It extends GenericStyledArea using StyledText<S> (a combination of a String and a style object).
    3. InlineCssTextArea: A subclass of StyledTextArea that allows styling via inline CSS strings.
    4. StyleClassedTextArea: A subclass of StyledTextArea that allows styling via CSS style classes defined in an external stylesheet.
    5. CodeArea: A subclass of StyleClassedTextArea optimized for code editors, using a fixed-width font by default.
  2. Run RichTextFX demos via Gradle

    master

    To explore the capabilities of RichTextFX, you can run the included demonstration applications using Gradle.

    1. Clone the repository: git clone https://www.github.com/FXMisc/RichTextFX.git
    2. Checkout the latest release tag: git checkout <tagName> (use git tag to find the latest tag).
    3. List all available demos: ./gradlew demos
    4. Run a specific demo: ./gradlew [Demo Name]

    Note for Windows users: Use gradlew.bat instead of ./gradlew.

    git clone https://www.github.com/FXMisc/RichTextFX.git
    # ...
    ./gradlew demos
    ./gradlew [Demo Name]
  3. Install RichTextFX via Maven, Gradle, or Sbt

    master

    RichTextFX is available via Maven Central. Use the following coordinates for the current stable version (0.11.7).

    Requirements:

    • JDK 11 or higher.
    • For JavaFX 25+, you MUST use version 0.11.7 or higher to avoid method clashes.
  4. Implement custom tooltips based on text position

    master

    You can implement context-aware tooltips by detecting the character index under the mouse cursor. When the mouse pauses over the text area, you can retrieve the index of the character at that position and use it to determine the tooltip's content.

    Reference implementation: TooltipDemo.java.

  5. Implement Java keyword highlighting

    master

    RichTextFX supports syntax highlighting. For Java keywords, there are two approaches demonstrated in the codebase:

    • Synchronous highlighting: Computes highlighting on the JavaFX application thread using JavaKeywordsDemo.java.
    • Asynchronous highlighting: Computes highlighting on a background thread to prevent UI freezing, using JavaKeywordsAsyncDemo.java.

    These demos serve as a reference for implementing custom syntax highlighting logic within a GenericStyledArea or similar component.

  6. Understand GenericStyledArea type parameters

    master

    When extending GenericStyledArea to support custom in-line objects, you must define three generic types:

    • PS (Paragraph Style): Controls paragraph-level styling like text alignment or background color.
    • SEG (Segment): The immutable object stored in the model (e.g., text, hyperlinks, images, or emojis).
    • S (Segment Style): The style applied to segments (usually a CSS string or CSS class).
  7. Use TextOps for segment creation and composition

    master

    The TextOps<SEG, S> interface is used to manage text segments (SEG) and their associated styles (S). It extends SegmentOps by providing a way to transform raw String data into styled segments via the create(String text) method.

    Key capabilities include:

    • Segment Creation: Use create(String text) to map a string to a specific segment type.
    • Composition with either: You can compose two different sets of operations into a single TextOps that returns an Either<L, R> type. This allows the text model to handle multiple types of segments (e.g., plain text vs. syntax-highlighted tokens) within the same structure.

    Methods for composition:

    • _or(SegmentOps<R, S> rOps, BiFunction<S, S, Optional<S>> mergeStyle): Creates a new TextOps where the left side uses the current object's create method.
    • TextOps.eitherL(TextOps<L, S> lOps, SegmentOps<R, S> rOps, BiFunction<S, S, Optional<S>> mergeStyle): Static helper to create a combined operation where the left side is a TextOps.
    • TextOps.eitherR(SegmentOps<L, S> lOps, TextOps<R, S> rOps, BiFunction<S, S, Optional<S>> mergeStyle): Static helper to create a combined operation where the right side is a TextOps.
  8. Get shapes for text ranges and underlines

    master

    You can retrieve PathElement arrays to draw shapes (like highlights or underlines) over specific text ranges in a TextFlowExt instance.

    Range Shapes

    Use getRangeShape(IndexRange range) or getRangeShape(int from, int to) to get the geometric shape (typically a series of rectangles) surrounding the text from from to to.

    Underline Shapes

    The getUnderlineShape method allows for custom underline rendering, including wavy underlines.

    • getUnderlineShape(IndexRange range): Returns a standard underline shape for the given range.
    • getUnderlineShape(int from, int to, double offset, double waveRadius, double doubleGap):
      • from: Start index.
      • to: End index.
      • offset: Distance below the baseline.
      • waveRadius: If > 0, draws a wavy underline with arcs of this radius. If 0, draws a straight line.
      • doubleGap: If > 0, draws a double underline with this gap distance.
  9. Query line information from TextFlowExt

    master

    The TextFlowExt class provides methods to query the layout of text, specifically regarding line boundaries and counts. These are useful for implementing features like line numbering or cursor positioning.

    • getLineCount(): Returns the total number of lines in the text flow.
    • getLineOfCharacter(int charIdx): Returns the index of the line containing the character at the specified index.
    • getLineStartPosition(int charIdx): Returns the character index where the line containing charIdx begins.
    • getLineEndPosition(int charIdx): Returns the character index where the line containing charIdx ends.
  10. Perform hit testing on TextFlowExt

    master

    Use the hit methods to determine which character or insertion point corresponds to a specific (x, y) coordinate in the TextFlowExt.

    • hit(double x, double y): Finds the character hit at the given coordinates by first determining the correct line.
    • hit(double x, double y, int line): Performs a hit test specifically within the bounds of the provided line index.
    • hitLine(double x, int lineIndex): A convenience method that performs a hit test at the vertical midpoint of the specified line.