Richtextfx: How to set default text color with word highlighting of CodeArea?

Created on 9 Feb 2017  路  20Comments  路  Source: FXMisc/RichTextFX

I want to color the words which have not yet been colored with word highlightning (patterns etc.)
I tried:

CodeArea codeArea = new CodeArea();
codeArea.setId("codearea");

and in .css file

#codearea .text {
    -fx-fill: whitesmoke;
}

but it colors all text in CodeArea
Any ideas or help ?
Sorry about my bad english :)
Thanks

question

All 20 comments

If I'm understanding you correctly, you want to do the following, right?

  1. Create a CodeArea
  2. Make all of that area's text styled to a "regular text" style at its starting state.
  3. As time goes on, calculate what text in the area (according some some pattern) should now be styled to "highlight text"
  4. As time goes on, any "highlight text"-styled text should not be restyled back to "regular text" style if it no longer adheres to some pattern.

So, first i create CodeArea object, set id (style from css file), then I add highlightning

        codeArea = new CodeArea();
        codeArea.setId("codearea");
        codeArea.richChanges()
                .filter(ch -> !ch.getInserted().equals(ch.getRemoved()))
                .subscribe(change -> {
                    codeArea.setStyleSpans(0, computeHighlighting(codeArea.getText().toLowerCase()));
                });

But still all text is colored :( Maybe Im doing something wrong

obraz

Here highlightning (without style & dark background):

obraz

I need to color rest of text, i dont have already any ideas how to do that :(
Thanks :)

What happens if you don't set the area's ID? Does the highlighting work then?

And what does your computeHighlighting method's innards look like?

What happens if you don't set the area's ID? Does the highlighting work then?

It works, but default text color is black and dark background need white text or something. (I need dark background so...)

computeHighlighting is method from here:
https://github.com/TomasMikula/RichTextFX/blob/master/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/JavaKeywords.java

private static StyleSpans<Collection<String>> computeHighlighting(String text) {
        Matcher matcher = PATTERN.matcher(text);
        int lastKwEnd = 0;
        StyleSpansBuilder<Collection<String>> spansBuilder
                = new StyleSpansBuilder<>();
        while(matcher.find()) {
            String styleClass =
                    matcher.group("KEYWORD") != null ? "keyword" :
                    matcher.group("PAREN") != null ? "paren" :
                    matcher.group("BRACE") != null ? "brace" :
                    matcher.group("BRACKET") != null ? "bracket" :
                    matcher.group("SEMICOLON") != null ? "semicolon" :
                    matcher.group("STRING") != null ? "string" :
                    matcher.group("COMMENT") != null ? "comment" :
                    null; /* never happens */ assert styleClass != null;
            spansBuilder.add(Collections.emptyList(), matcher.start() - lastKwEnd);
            spansBuilder.add(Collections.singleton(styleClass), matcher.end() - matcher.start());
            lastKwEnd = matcher.end();
        }
        spansBuilder.add(Collections.emptyList(), text.length() - lastKwEnd);
        return spansBuilder.create();
}

Wait, so you're using the computeHighlighting method from the JavaKeywords demo? Have you modified its implementation at all?

Only patterns for matcher:

private static StyleSpans<Collection<String>> computeHighlighting(String text) {
        Matcher matcher = PATTERN.matcher(text);
        int lastKwEnd = 0;
        StyleSpansBuilder<Collection<String>> spansBuilder
                = new StyleSpansBuilder<>();
        while(matcher.find()) {
            String styleClass =
                    matcher.group("MNEMONIC") != null ? "mnemonic" :
                    matcher.group("REGISTRY") != null ? "registry" :
                    matcher.group("DIRECTIVE") != null ? "directive" :
                    matcher.group("COMMENT") != null ? "comment" :
                    matcher.group("LABEL") != null ? "label_j" :
                             null; /* never happens */ assert styleClass != null;
            spansBuilder.add(Collections.emptyList(), matcher.start() - lastKwEnd);
            spansBuilder.add(Collections.singleton(styleClass), matcher.end() - matcher.start());
            lastKwEnd = matcher.end();
        }
        spansBuilder.add(Collections.emptyList(), text.length() - lastKwEnd);
        return spansBuilder.create();
    }

It doesn't seem like you're doing anything wrong. Have you debugged it via ScenicView yet? It does seem clear that the initial CSS overrides the highlighting CSS.

You will probably need to subclass StyledTextArea in the same way that StyleClassedTextArea does, but modify the applyStyle to account for ID-specific CSS.

Ok, thanks for help, I will try ;)

Same here i think, im trying to set the default text color, the highlighting works fine.
btw. im not even setting an id.
But the property: -fx-fill: white does not change anything, but it is working, trough if i set the property:
-fx-background-color: black just works fine.

After looking at this further, I wonder if the issue is the same thing arising from #303, part of which was fixed in #398.

Yeah, but not the text-color, is there maybe a work around for that issue?

@liz3 After looking at it a bit more, I got the default color to work by using the following CSS file:
css .styled-text-area { -fx-background-color: black; } .paragraph-box > .paragraph-text > .text { -fx-fill: white; }
Technically, the CSS should be .styled-text-area > .virtual-flow > .paragraph-box > .paragraph-text > .text { /* CSS */ } However, this doesn't work. Everything from paragraph-box forward works, so I'm not sure why the virtual-flow selector screws things up.

I've updated the CSS Reference Guide to properly demonstrate the three selector usage to style the default text.

Update: I found that if I replaced the > to denote immediate children with to denote within its children, then this CSS string works:
css .styled-text-area { -fx-background-color: black; } .styled-text-area .virtual-flow .paragraph-box .paragraph-text .text { -fx-fill: white; }
Thus, @KnightPL, you can achieve your goal without subclassing the area by using this CSS:
````css

codearea .virtual-flow .paragraph-box .paragraph-text .text {

-fx-fill: whitesmoke;

}
````

I've updated CSS Ref Guide to include the full selector string

Actually... #codeArea .text { /* CSS */ } does the same thing as the full string above... I remembered this issue being different from what it actually was.

Forget what I said in my previous comment, @KnightPL. Instead, I found that this will work:
Given a CSS file like:
````css
.styled-text-area {
-fx-background-color: black;
}

someArea .text {

-fx-fill: white;

}

someArea .red {

-fx-fill: red;

}
and an application like so: java
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.fxmisc.flowless.VirtualizedScrollPane;
import org.fxmisc.richtext.CodeArea;

import java.util.Collections;

public class CssBug extends Application {

@Override
public void start(Stage primaryStage) throws Exception {

    CodeArea area = new CodeArea("initial text");
    VirtualizedScrollPane<CodeArea> vsPane = new VirtualizedScrollPane<>(area);
    area.setId("someArea");
    area.setStyle(6, area.getLength(), Collections.singleton("red"));

    Scene scene = new Scene(vsPane, 500, 200);
    scene.getStylesheets().addAll(CssBug.class.getResource("css-bug.css").toExternalForm());


    primaryStage.setScene(scene);
    primaryStage.show();
}

public static void main(String[] args) {
        launch(args);
    }

}
``` I can override the defaultwhitesmokefill with ared` fill.

@KnightPL, is this issue resolved?

@JordanMartinez
I check out all above your answers, but sadly I didn't solve my problem in the end...

I run the XMLEditor Demo. Actually, I just want to do one thing :

make the background black and the non-highlight text white

So I modified the xml-highlighting.css like :

````
.text {
-fx-fill: white;
}

.tagmark {
-fx-fill: gray;
}
.anytag {
-fx-fill: orangered;
}
.paren {
-fx-fill: firebrick;
-fx-font-weight: bold;
}
.attribute {
-fx-fill: green;
}
.avalue {
-fx-fill: green;
}

.comment {
-fx-fill: mediumpurple;
}

.styled-text-area {
-fx-background-color: black;
}
````

It worked, BUT the line numbers became white, too
Now I cant see them because its background is grey
image

How can I solve this problem ? Thanks~

Add a lineno styleclass entry to your CSS file:
css .lineno { -fx-background-color: black; }
The CSS Reference Guide explains that one can style the LineNumberFactory's returning Node by using that styleclass.

@JordanMartinez
It works , thank you very much !
BTW, it's a wonderful JavaFX lib

Was this page helpful?
0 / 5 - 0 ratings