Skip to content

Instantly share code, notes, and snippets.

@oowekyala oowekyala/
Last active Mar 27, 2018

What would you like to do?
MWE RTFX style overlay
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import org.fxmisc.richtext.InlineCssTextArea;
import org.fxmisc.richtext.model.StyleSpans;
import org.fxmisc.richtext.model.StyleSpansBuilder;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class App extends Application {
private static final String BOXED_STYLE
= "-rtfx-border-stroke-width: .75pt;"
+ "-rtfx-border-stroke-type: outside;"
+ "-rtfx-border-stroke-color: darkgoldenrod;"
+ "-rtfx-background-color: antiquewhite;";
private static final String OTHER_STYLE
= "-fx-font-weight: bolder;"
+ "-fx-fill: blue;";
public void start(Stage primaryStage) {
CustomCodeArea codeArea = new CustomCodeArea();
codeArea.replaceText("Lorem ipsum dolor sit amet consectetuer adipiscing elit");
TextSpanCoordinates firstFiveWords = new TextSpanCoordinates(0, 0, 0, "Lorem ipsum dolor sit amet".length());
TextSpanCoordinates secondAndThirdWords = new TextSpanCoordinates(0, 0, 6, 16);
codeArea.setStyle("-fx-font-size: 12pt;");
codeArea.styleCss(firstFiveWords, BOXED_STYLE);
codeArea.styleCss(secondAndThirdWords, OTHER_STYLE);
AnchorPane pane = new AnchorPane();
primaryStage.setScene(new Scene(pane));;
public static void main(String[] args) {
static class TextSpanCoordinates {
final int beginLine;
final int endLine;
final int endColumn;
final int beginColumn;
TextSpanCoordinates(int beginLine, int endLine, int beginColumn, int endColumn) {
this.beginLine = beginLine;
this.endLine = endLine;
this.beginColumn = beginColumn;
this.endColumn = endColumn;
static class CustomCodeArea extends InlineCssTextArea {
private final Stack<StyleSpans<String>> layers = new Stack<>();
/** Registers a span to be styled. */
void styleCss(TextSpanCoordinates node, String css) {
int offset = getAbsolutePosition(node.beginLine, node.beginColumn);
int spanLength = getAbsolutePosition(node.endLine, node.endColumn) - offset;
StyleSpansBuilder<String> builder = new StyleSpansBuilder<>();
builder.add("", offset);
builder.add(css, spanLength);
builder.add("", getLength() - (offset + spanLength));
* Forcefully applies the possibly updated css classes.
void paintCss() {
this.setStyleSpans(0, overlayAll());
private StyleSpans<String> overlayAll() {
List<StyleSpans<String>> allSpans = new ArrayList<>(layers);
if (allSpans.isEmpty()) {
return new StyleSpansBuilder<String>()
.add("", getLength())
final StyleSpans<String> base = allSpans.get(0);
.filter(spans -> spans != base)
.filter(spans -> spans.length() <= getLength())
(accumulator, elt) -> accumulator.overlay(elt, (style1, style2) -> style1 + ";" + style2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.