Last active
March 27, 2018 23:37
-
-
Save oowekyala/8319f98f7ed77042e2a4fa0e79116aad to your computer and use it in GitHub Desktop.
MWE RTFX style overlay
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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;"; | |
| @Override | |
| 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); | |
| codeArea.paintCss(); | |
| AnchorPane pane = new AnchorPane(); | |
| pane.setPrefWidth(400); | |
| pane.setPrefHeight(50); | |
| pane.getChildren().add(codeArea); | |
| codeArea.setPrefWidth(400); | |
| codeArea.setPrefHeight(50); | |
| primaryStage.setScene(new Scene(pane)); | |
| primaryStage.show(); | |
| } | |
| public static void main(String[] args) { | |
| launch(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)); | |
| layers.push(builder.create()); | |
| } | |
| /** | |
| * 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()) | |
| .create(); | |
| } | |
| final StyleSpans<String> base = allSpans.get(0); | |
| return allSpans.stream() | |
| .filter(spans -> spans != base) | |
| .filter(spans -> spans.length() <= getLength()) | |
| .reduce(allSpans.get(0), | |
| (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