Rich-text area for JavaFX

Overview

RichTextFX

RichTextFX provides a memory-efficient text area for JavaFX that allows the developer to style ranges of text, display custom objects in-line (no more HTMLEditor), and override the default behavior only where necessary without overriding any other part of the behavior.

It does not follow the MVC paradigm as this prevented access to view-specific API (e.g., getting the bounds of the caret/selection/characters, scrolling by some amount, etc.).

It is intended as a base for rich-text editors and code editors with syntax highlighting. Since it is a base, a number of suggested features (specific syntax highlighters, search-and-replace, specific support for hyperlinks, etc.) will not be implemented directly in this project. Rather, developers can implement these on top of RichTextFX and submit their work as a PR to the richtextfx-demos package.

For a greater explanation of RichTextFX, its design principles, how it works, and how to style its areas via CSS, please see the wiki

Demos

Stand-alone Applications that demonstrate some of the features of RichTextFX have been moved to their own folder here

Table of Contents

Who uses RichTextFX?

If you use RichTextFX in an interesting project, I would like to know!

Features

  • Assign arbitrary styles to arbitrary ranges of text. A style can be an object, a CSS string, or a style class string.
  • Display line numbers or, more generally, any graphic in front of each paragraph. Can be used to show breakpoint toggles on each line of code.
  • Support for displaying other Nodes in-line
  • Positioning a popup window relative to the caret or selection. Useful e.g. to position an autocompletion box.
  • Getting the character index under the mouse when the mouse stays still over the text for a specified period of time. Useful for displaying tooltips depending on the word under the mouse.
  • Overriding the default behavior only where necessary without overriding any other part.

Flavors

The following explains the different rich text area classes. The first one is the base class from which all others extend: it needs further customization before it can be used but provides all aspects of the project's features. The later ones extend this base class in various ways to provide out-of-box functionality for specific use cases. Most will use one of these subclasses.

GenericStyledArea

GenericStyledArea allows one to inline custom objects into the area alongside of text. As such, it uses generics and functional programming to accomplish this task in a completely type-safe way.

It has three parameter types:

  • PS, the paragraph style. This can be used for text alignment or setting the background color for the entire paragraph. A paragraph is either one line when text wrap is off or a long text displayed over multiple lines in a narrow viewport when text wrap is on,
  • SEG, the segment object. This specifies what immutable object to store in the model part of the area: text, hyperlinks, images, emojis, or any combination thereof.
  • S, the segment style. This can be used for text and object styling. Usually, this will be a CSS style or CSS style class.

Functional programming via lambdas specify how to apply styles, how to create a Node for a given segment, and how to operate on a given segment (e.g., getting its length, combining it with another segment, etc.).

GenericStyledArea is used in the Rich-text demo.

See the wiki for a basic pattern that one must follow to implement custom objects correctly.

StyledTextArea

StyledTextArea<PS, S>, or one of its subclasses below, is the area you will most likely use if you don't need to display custom objects in your area.

It extends GenericStyledArea<PS, StyledText<S>, S>>. StyledText is simply a text (String) and a style object (S). A slightly-enhanced JavaFX Text node is used to display the StyledText<S>, so you can style it using its CSS properties and additional RichTextFX-specific CSS (see the wiki for more details).

It properly handles the aforementioned functional programming to properly display and operate on StyledText<S> objects.

The style object (S) can either be a CSS String (-fx-fill: red;), a CSS styleclass (.red { -fx-fill: red; }), or an object that handles this in a different way. Since most will use either the CSS String or CSS style class approach, there are two subclasses that already handle this correctly.

InlineCssTextArea

InlineCssTextArea uses the Node#setStyle(String cssStyle) method to style Text objects:

area.setStyle(from, to, "-fx-font-weight: bold;");

StyleClassedTextArea

StyleClassedTextArea uses the Node#setStyleClass(String styleClass) method to style Text` objects. You can define the style classes in your stylesheet.

example.css:

.red { -fx-fill: red; }

Example.java:

area.setStyleClass(from, to, "red");

This renders the text in the range [from, to) in red.

CodeArea

CodeArea is a variant of StyleClassedTextArea that uses a fixed width font by default, making it a convenient base for source code editors. CodeArea is used in the Java Keywords demo.

Requirements

JDK8 is required, because TextFlow, introduced in JavaFX 8.0, is used to render each line. Also, there's a heavy use of lambdas, defender methods and the stream API in the code base.

Download

Stable release

Current stable release is 0.10.5 which is a multi-release JAR that is compatible with Java 9 and UP without the need for add-exports or add-opens JVM arguments.

Maven coordinates

Group ID Artifact ID Version
org.fxmisc.richtext richtextfx 0.10.5

Gradle example

dependencies {
    compile group: 'org.fxmisc.richtext', name: 'richtextfx', version: '0.10.5'
}

Sbt example

libraryDependencies += "org.fxmisc.richtext" % "richtextfx" % "0.10.5"

Manual download

Download the JAR file or the fat JAR file (including dependencies) and place it on your classpath.

Snapshot releases

Snapshot releases are deployed to Sonatype snapshot repository.

Maven coordinates

Group ID Artifact ID Version
org.fxmisc.richtext richtextfx 1.0.0-SNAPSHOT

Gradle example

repositories {
    maven {
        url 'https://oss.sonatype.org/content/repositories/snapshots/'
    }
}

dependencies {
    compile group: 'org.fxmisc.richtext', name: 'richtextfx', version: '1.0.0-SNAPSHOT'
}

Sbt example

resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"

libraryDependencies += "org.fxmisc.richtext" % "richtextfx" % "1.0.0-SNAPSHOT"

License

Dual-licensed under BSD 2-Clause License and GPLv2 with the Classpath Exception.

Comments
  • Custom object support

    Custom object support

    This is an enhanced proposal to support custom objects which can be rendered by user specific nodes.

    In the model layer, all occurrences of StyledTexthave been replaced by the new interface Segment. StyledTextis now just one flavor of segment types. CustomObjectis an abstract class which implements the Segmentinterface and which provides a base class for user defined objects. Out-of-the-box, RichTextFX would support images to be inserted into the document, but the user can define any other custom objects by registering a factory method for the JavaFX node and a decode method for deserializing the object through a Codec. See CustomObjectDemofor an example how to register and use custom objects.

    The code already supports copy&paste (if the selection contains a custom object, it is serialized when copying). Selecting one single custom object by clicking on it is not supported yet.

    Any feedback/comments are welcome - especially registering the decode method is very unclean yet, see the SegmentFactory class. Essentially, decoding must be delegated to the custom object implementation since only the custom object knows how to recreate itself from a DataInputStream, but the method in ReadOnlyStyledDocument which does the decoding is static which makes it difficult to access a delegate. I tried to make those methods non-static, but this looked like a huge bunch of refactoring is necessary then.

    opened by afester 82
  • Getting scroll position of CodeArea

    Getting scroll position of CodeArea

    Hi!

    I'm using this API for a project, and have added a CodeArea in a StackPane on top of a Canvas. I want to scroll the Canvas with the CodeArea. Is it possible to get the scroll position of the CodeArea to let me do this?

    Thanks!

    enhancement 
    opened by salmanarif 62
  • Starting a style at certain position in text (with having an index range)..

    Starting a style at certain position in text (with having an index range)..

    Hi Tomas, I could not find a way to assign a style at the caret location. Is there one? What is available now requires an range.

    For example, user clicks, then assigns a style. Then whatever is written afterward will inherit the new style.

    Since the current method requires a range, I currently get the caret position, then append a dummy white space (in case the caret is at the end), then use the position of the caret and increment by 1 (as a range) to assign style, then remove the white space.

    Thanks, Maher

    question 
    opened by ghost 41
  • CodeArea horizontal scrollbar not working

    CodeArea horizontal scrollbar not working

    Tomas, I am using a CodeArea in a Dialog. When there is no vertical scrollbar the horizontal scrollbar does not work. I modified JavaKeywordsAsync to demonstrate this. See the attached txt file (it wouldn't let me add a .java file) ScrollBarTest.txt

    Thanks, Mike

    bug has workaround 
    opened by msarmc 38
  • Refactor: create `Caret` class

    Refactor: create `Caret` class

    Coming from #417, it was proposed that we refactor the caret-related code into its own class. I've opened this issue to provide a place for discussing such a change's pros, cons, and implementation.

    opened by JordanMartinez 37
  • Code Formatting Support

    Code Formatting Support

    Is there anyway i can add code formatting support to codeArea? Similar to Alt+Shift+F format option in Netbeans And Ctrl+Shilft+F option in Eclipse. In this way i want to improve the representation of code in my code editor. :)

    opened by deepsidhu1313 32
  • Need new maintainer

    Need new maintainer

    Below is what was originally in #583, but that thread got bloated with discussion on another topic. Thus, I'm reposting it here:


    I've been talking to Tomas about this for a while. See the original thread here

    Hi everyone,

    since I don't work with JavaFX (or GUI applications, or that matter) anymore, it is hard for me to keep up with the maintenance of my JavaFX projects. I am therefore looking for new maintainers (and possibly new home) of my most active JavaFX project, RichTextFX ( https://github.com/TomasMikula/RichTextFX/), and its essential dependency, Flowless (https://github.com/TomasMikula/Flowless/).

    I want to thank Jordan Martinez, who has been doing the bulk of fixing bugs and reviewing pull requests for the past two years.

    I am hoping that either some bigger user of RichTextFX, or a UI framework for which RichTextFX would be an attractive addition to the portfolio, would step forward and take it up. Jordan and I are happy to help with the transfer.

    Best regards, Tomas


    I've been maintaining this (and other FXMisc projects) since Tomas stopped maintaining it (though I've contributed little in the past few months), but I've also decided to go a different route from here. Rather than continuing to use a JVM language and JavaFX to build my GUI program, I've decided to start using Purescript and Halogen instead.

    Due to the influence of Tomas' FP-style of coding and further investigating and agreeing with the FP paradigm, I had hoped to use more FP constructs using Scala and Scalaz. In workings towards a (at least, what I now understand to be) React-like framework for JavaFX (see JavaFXFunctional's Design Goals) and realizing that Scala was not a good language for FP, I thought it would be easier to learn web technologies and use Halogen rather than port that framework to Scala, Scalaz and JavaFX. The idea of Progressive Web Apps replacing Native apps and The Birth and Death of Javascript have further influenced me in that regard.

    As such, I will no longer be making any effort towards fixing bugs or responding to any questions regarding this project. Someone else will need to step up.

    enhancement has workaround meta 
    opened by JordanMartinez 30
  • RFE implementation for #653 / #655

    RFE implementation for #653 / #655

    RFE implementation for #655 The methods in ViewActions related to the following have been @Deprecated:

    onOutsideSelectionMousePress onInsideSelectionMousePress onNewSelectionDragEnd onSelectionDrop

    They have been replaced with FXML friendly equivalent (non default) interface methods:

    onOutsideSelectionMousePressed onInsideSelectionMousePressed onNewSelectionDragFinished onSelectionDropped

    Which have been implemented in GenericStyledArea. The references to the deprecated methods in GenericStyledAreaBehavior have been changed to the new ones.

    During this process it was found that the onNewSelectionDragEnd/Finished functionality hadn't been implemented in GenericStyledAreaBehavior and this was rectified as well.

    opened by Jugen 30
  • How To Add Padding Between StyledTextArea And Text Contents?

    How To Add Padding Between StyledTextArea And Text Contents?

    I have tried the obvious:

    styledTextArea.setPadding(new Insets(10, 10, 10, 10));

    but it doesn't seem to work. What is the correct way to add padding between a StyledTextArea and the textual content that it displays?

    opened by gbmhunter 30
  • Allow two or more StyledTextAreas (View) to share the same StyledDocument (Model)

    Allow two or more StyledTextAreas (View) to share the same StyledDocument (Model)

    I implemented the approach I described in #152 and for the most part it works. There are a few problems.

    • If the user types in the original area quickly or if the user types even one character in the second line in the original area, the original area making the modification throws a StringIndexOutOfBoundsException.
    opened by JordanMartinez 29
  • Refactor: ChangeType in TextChange

    Refactor: ChangeType in TextChange

    To address #322, I reimplemented the solution in #402 by using more readable code via ChangeType, which was through lazy evaluation initially. This caused regressions, as discovered in #472, and was later evaluated immediately in #470 to help find these regressions. Besides simplifying the logic, I used ChangeType because I thought developers would be able to use it in their code to quickly determine what kind of change the change was. By doing this, I realize now that I was solving the first problem and indirectly trying to solve another problem (adding convenience methods to TextChange that allows one to quickly determine what kind of change it was).

    And that is the issue: my solution to the second problem was not fully thought out because it was not the issue I was trying to solve. I didn't realize it then (but do realize it now because of the regressions, both known and yet unknown, that have appeared since 0.7-M3) that a RichTextChange can be a number of different changes (insertion, deletion, replacement, text style change, or a paragraph style change)--change tyes which ChangeType does not cover.

    So I see two options for addressing this bug:

    1. Refactor the code to always create a TextChange that can get exactly what kind of change type it is
    2. Change the way the code knows that a TextChange is an insertion or deletion type of change and thus whether to merge it with another TextChange.

    I'm against the former because it will be more invasive to the current API and using a TextChange does not always require knowing what kind of change it is. For example, sometimes one just needs to know how much to adjust the caret based on how much content was removed and inserted. I think the latter is best because it will immediately address all possible (known and currently unknown) regressions related to #458.

    To still maintain code readability, I don't think we should just implement methods like TextChange#isInsertion and TextChange#isDeletion. Rather, I think ChangeType (which I think needs to be better named since it doesn't address all the changes a TextChange could be and since it pollutes the namespace that developers might want to use later in their own code) should be as follows:

    // Enum needs a better name!
    public class ChangeType {
        INSERTION,
        DELETION,
        NEITHER // indicates it is neither an insertion/deletion
    

    And then the TextChange#mergeWith code would still read:

    // this is either a insertion/deletion
    if (this.getType() != ChangeType.NEITHER 
        // the two types match: both are insertion or both are deletion
        && this.getType() == that.getType()) { 
        // merge code
    }
    

    Unfortunately, I can't think of a better name to address the namespace pollution issue I raised above. Does anyone else have a better name?

    However, #472 did show that sometimes RTFX is inefficient because it tries to make an empty replacement. I wonder if there are others areas that could be further optimized so that replace always replaces something and ignores calls that ultimately do nothing. For example, ignoring "style change" calls that don't actually restyle the content because that content already has that style.

    opened by JordanMartinez 28
  • After updating from 0.10.9 to 0.11.0 ( i am using Java 19 ) i am having errors

    After updating from 0.10.9 to 0.11.0 ( i am using Java 19 ) i am having errors

    Hello i am using for many many years this library to my big JavaFX project XR3Player

    XR3Player is running on Java 19 .

    Today updating from 0.10.9 to 0.11.0 i am having errors ? Do i need to add something extra to module-info.java after updating to version 0.11.0 ? I had no problem with 0.10.9 .

    @Jugen :)

    question documentation 
    opened by goxr3plus 1
  • How can I implement some code folding between brackets?

    How can I implement some code folding between brackets?

    I just want to implement code folding just like other ide-s : intellij, eclipse, netbeans. I reviewed java keyboard sample. The folding is controlled from context menu. I want indicate fold unfold icon on the line indicator? How to do it with codearea? Can you give me some code hints? Thank you.

    opened by garawaa 5
  • CodeArea CaretBounds Bug

    CodeArea CaretBounds Bug

    I listener caretPositionProperty and print CaretBounds, but i found when caret change line, the bounds minY is always -1. How can i get right bounds?

    1657172328430

    opened by Lson-L 1
  • bug report: Chosen line highlighter color isn't used when there is only 1 line.

    bug report: Chosen line highlighter color isn't used when there is only 1 line.

    Expected Behavior

    The chosen color (hsb(0, 0, 1, 0.1)) should be used.

    Actual Behavior

    The default color (yellow) is used.

    Demo

    1th line, 3 lines total. image

    1th line, 1 lines total. image

    Environment info:

    • RichTextFX Version: 0.10.9
    • Operating System: Linux
    • Java version: 17
    opened by QazCetelic 1
  • Add support for terminal like caret

    Add support for terminal like caret

    RichTextFX is also used for building terminal emulator applications. At the same time, currently it is not possible to style caret to look like in terminals. This problem was also discussed in https://github.com/FXMisc/RichTextFX/issues/397 , but later the issue was closed without resolving.

    I suggest to support the following caret features:

    1. width
    2. height
    3. shape
    4. color
    5. inverse color (for example, the color of the letter that the caret is on)
    6. caret position (it is necessary to set caret over letter)
    enhancement 
    opened by PashaTurok 1
  • .styled-text-area .caret seems not to work

    .styled-text-area .caret seems not to work

    This is java code:

    public class JavaFxTest2 extends Application {
    
        private final InlineCssTextArea textArea = new InlineCssTextArea();
    
        private final VirtualizedScrollPane scrollPane = new VirtualizedScrollPane(textArea);
    
        public static void main(String[] args) {
            launch(args);
        }
    
        @Override
        public void start(Stage primaryStage) {
            textArea.setWrapText(true);
            textArea.setEditable(true);
            textArea.setParagraphGraphicFactory(LineNumberFactory.get(textArea));
            textArea.setPadding(new Insets(0, 0, 0, 0));
            var ss = "Some text here";
            VBox.setVgrow(scrollPane, Priority.ALWAYS);
            VBox root = new VBox();
    
            root.getChildren().addAll(scrollPane, new TextField());
            textArea.setWrapText(true);
            var css = this.getClass().getResource("console.css").toExternalForm();
            var scene = new Scene(root, 450, 450);
            scene.getStylesheets().add(css);
            primaryStage.setScene(scene);
            primaryStage.show();
            textArea.appendText(ss);
        }
    }
    

    This is css:

    .root {
        -fx-font-size: 20;
    }
    
    .styled-text-area .caret {
        -rtfx-blink-rate: 5000ms;
        -fx-stroke-width: 10.0;
    }
    

    Caret seems to blink with the same rate, and with one pixel width. Is this correct behavior?

    opened by PashaTurok 1
Releases(v0.11.0)
Owner
null
Tray Icon implementation for JavaFX applications. Say goodbye to using AWT's SystemTray icon, instead use a JavaFX Tray Icon.

FXTrayIcon Library intended for use in JavaFX applications that makes adding a System Tray icon easier. The FXTrayIcon class handles all the messy AWT

Dustin Redmond 247 Dec 1, 2022
Lib-Tile is a multi Maven project written in JavaFX and NetBeans IDE 8 and provides the functionalities to use and handle easily Tiles in your JavaFX application.

Lib-Tile Intention Lib-Tile is a multi Maven project written in JavaFX and NetBeans IDE and provides the functionalities to use and handle easily Tile

Peter Rogge 13 Apr 13, 2022
DataFX - is a JavaFX frameworks that provides additional features to create MVC based applications in JavaFX by providing routing and a context for CDI.

What you’ve stumbled upon here is a project that intends to make retrieving, massaging, populating, viewing, and editing data in JavaFX UI controls ea

Guigarage 109 Nov 17, 2022
add one tag before or end text view

Tag Label Text Android Make a tag of text for android with custom background of tag Setup Coppy 2 class RoundBackgroundColorSpan.java and TagLabelText

Nguyễn Trọng Hải 15 Jan 24, 2022
Nightmare-text - This is a simple lib that help to create, titles, actionbars, hovers and click actions chat components.

Nightmare text This is a simple lib that help to create, titles, actionbars, hovers and click actions chat components. Setup public final class Testin

Jonathan Narvaez 8 Mar 9, 2022
A beautiful and customizable text editor.✨

Tawfekh-Editor A beautiful and customizable text editor. ✨ Tawfekh Editor is simple and easy to use. You can Customize it as you want to get the best

Médoune Siby Georges Baldé 7 Oct 29, 2022
Collection of Binding helpers for JavaFX(8)

Advanced-Bindings for JavaFX (8) advanced-bindings is a collection of useful helpers and custom binding implementations to simplify the development of

Manuel Mauky 63 Nov 19, 2022
Docking framework for JavaFX platform

Docking framework for JavaFX platform AnchorFX is a gratis and open source library for JavaFX to create graphical interfaces with docking features Anc

Alessio Vinerbi 197 Oct 15, 2022
A library of +70 ready-to-use animations for JavaFX

AnimateFX A library of ready-to-use animations for JavaFX Features: Custom animations Custom interpolators Play/Stop animation Play an animation after

Loïc Sculier 355 Dec 1, 2022
BootstrapFX: Bootstrap for JavaFX

BootstrapFX BootstrapFX is a partial port of Twitter Bootstrap for JavaFX. It mainly provides a CSS stylesheet that closely resembles the original whi

Kordamp 799 Nov 20, 2022
A Java framework for creating sophisticated calendar views (JavaFX 8, 9, 10, and 11)

CalendarFX A Java framework for creating sophisticated calendar views based on JavaFX. A detailed developer manual can be found online: CalendarFX 8 D

DLSC Software & Consulting GmbH 655 Dec 4, 2022
Allow runtime modification of JavaFX CSS

cssfx ⚠ WARNING ⚠ In version 11.3.0 we have relocated & refactored the project. maven groupId has been changed to fr.brouillard.oss java module name h

Matthieu Brouillard 133 Nov 18, 2022
A JavaFX UI framework to create fully customized undecorated windows

CustomStage A JavaFX undecorated stage which can fully be customized Donations If this project is helpful to you and love my work and feel like showin

Oshan Mendis 185 Nov 25, 2022
MDI components for JavaFX

DesktopPaneFX DesktopPaneFX is a JavaFX version of Swing’s JDesktopPane which can be used as a container for individual "child" similar to JInternalFr

Kordamp 58 Sep 23, 2022
Efficient VirtualFlow for JavaFX

Flowless Efficient VirtualFlow for JavaFX. VirtualFlow is a layout container that lays out cells in a vertical or horizontal flow. The main feature of

null 163 Nov 24, 2022
A framework for easily creating forms for a JavaFX UI.

FormsFX Forms for business application made easy. Creating forms in Java has never been this easy! Maven To use this framework as part of your Maven b

DLSC Software & Consulting GmbH 532 Dec 6, 2022
:icecream: iOS frosty/translucent effect to JavaFX

FroXty is JavaFX library which replicates the famous iOS translucent effect with ease. Set-up FroXty can be imported into your project either by downl

Giorgio Garofalo 32 Sep 9, 2022
💠 Undecorated JavaFX Scene with implemented move, resize, minimise, maximise, close and Windows Aero Snap controls.

Support me joining PI Network app with invitation code AlexKent FX-BorderlessScene ( Library ) ?? Undecorated JavaFX Scene with implemented move, resi

Alexander Kentros 123 Nov 29, 2022
Dynamic JavaFX form generation

FXForm 2 Stop coding forms: FXForm 2 can do it for you! About FXForm2 is a library providing automatic JavaFX form generation. How does it work? Write

dooApp 210 Oct 19, 2022