Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug - Custom Styles and random scrolls #563

Closed
RodrigoSantiago opened this issue Aug 7, 2017 · 6 comments
Closed

Bug - Custom Styles and random scrolls #563

RodrigoSantiago opened this issue Aug 7, 2017 · 6 comments

Comments

@RodrigoSantiago
Copy link

RodrigoSantiago commented Aug 7, 2017

Simply create a StyledTextArea with a style type other than Collection<String> or String :

import java.util.*;
import java.util.regex.*;

import javafx.application.Application;
import javafx.scene.layout.StackPane;
import javafx.scene.Scene;
import javafx.stage.Stage;

import org.fxmisc.flowless.*;
import org.fxmisc.richtext.*;
import org.fxmisc.richtext.model.*;
import org.fxmisc.richtext.demo.*;

public class Test extends Application {

    public static class LinkStyle {
        public static final LinkStyle NO_STYLE = new LinkStyle("");
        public final String css;

        public LinkStyle(String css) {
            this.css = css;
        }
    }

    public class LinkArea extends StyledTextArea<Collection<String>, LinkStyle> {

        public LinkArea() {
            super(Collections.emptyList(), (paragraph, styleClasses) -> paragraph.getStyleClass().addAll(styleClasses),
                    LinkStyle.NO_STYLE, (text, style) -> text.getStyleClass().add(style.css), false);
            this.getStyleClass().add("code-area");
            this.getStylesheets().add(CodeArea.class.getResource("code-area.css").toExternalForm());
            this.setUseInitialStyleForInsertion(true);
        }
    }

    public class StringArea extends StyledTextArea<Collection<String>, Collection<String>> {

        public StringArea() {
            super(Collections.emptyList(), (paragraph, styleClasses) -> paragraph.getStyleClass().addAll(styleClasses),
                    Collections.emptyList(), (text, style) -> text.getStyleClass().addAll(style), false);
            this.getStyleClass().add("code-area");
            this.getStylesheets().add(CodeArea.class.getResource("code-area.css").toExternalForm());
            this.setUseInitialStyleForInsertion(true);
        }
    }

    private static final String[] KEYWORDS = new String[] {
            "abstract", "assert", "boolean", "break", "byte",
            "case", "catch", "char", "class", "const",
            "continue", "default", "do", "double", "else",
            "enum", "extends", "final", "finally", "float",
            "for", "goto", "if", "implements", "import",
            "instanceof", "int", "interface", "long", "native",
            "new", "package", "private", "protected", "public",
            "return", "short", "static", "strictfp", "super",
            "switch", "synchronized", "this", "throw", "throws",
            "transient", "try", "void", "volatile", "while"
    };

    private static final String KEYWORD_PATTERN = "\\b(" + String.join("|", KEYWORDS) + ")\\b";
    private static final String PAREN_PATTERN = "\\(|\\)";
    private static final String BRACE_PATTERN = "\\{|\\}";
    private static final String BRACKET_PATTERN = "\\[|\\]";
    private static final String SEMICOLON_PATTERN = "\\;";
    private static final String STRING_PATTERN = "\"([^\"\\\\]|\\\\.)*\"";
    private static final String COMMENT_PATTERN = "//[^\n]*" + "|" + "/\\*(.|\\R)*?\\*/";

    private static final Pattern PATTERN = Pattern.compile(
            "(?<KEYWORD>" + KEYWORD_PATTERN + ")"
                    + "|(?<PAREN>" + PAREN_PATTERN + ")"
                    + "|(?<BRACE>" + BRACE_PATTERN + ")"
                    + "|(?<BRACKET>" + BRACKET_PATTERN + ")"
                    + "|(?<SEMICOLON>" + SEMICOLON_PATTERN + ")"
                    + "|(?<STRING>" + STRING_PATTERN + ")"
                    + "|(?<COMMENT>" + COMMENT_PATTERN + ")"
    );

    private static final String sampleCode = String.join("\n", new String[] {
            "package com.example;",
            "",
            "public class Foo extends Bar implements Baz {",
            "    public static void main(String[] args) {",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "        System.out.println(\"Lorem ipsum\");",
            "    }",
            "",
            "}"
    });


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

    @Override
    public void start(Stage primaryStage) {
        LinkArea linkArea = new LinkArea();
        linkArea.setParagraphGraphicFactory(LineNumberFactory.get(linkArea));
        linkArea.richChanges()
                .filter(ch -> !ch.getInserted().getText().equals(ch.getRemoved().getText()))
                .subscribe(change -> {
                    linkArea.setStyleSpans(0, computeLinkHighlighting(linkArea.getText()));
                });
        linkArea.replaceText(0, 0, sampleCode);

        Scene scene = new Scene(new StackPane(new VirtualizedScrollPane<>(linkArea)), 600, 300);
        scene.getStylesheets().add(JavaKeywordsAsync.class.getResource("java-keywords.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.setTitle("LINK AREA");
        primaryStage.show();

        Stage secondaryStage = new Stage();
        StringArea stringArea = new StringArea();
        stringArea.setParagraphGraphicFactory(LineNumberFactory.get(stringArea));
        stringArea.richChanges()
                .filter(ch -> !ch.getInserted().getText().equals(ch.getRemoved().getText()))
                .subscribe(change -> {
                    stringArea.setStyleSpans(0, computeStringHighlighting(stringArea.getText()));
                });
        stringArea.replaceText(0, 0, sampleCode);

        Scene scene2 = new Scene(new StackPane(new VirtualizedScrollPane<>(stringArea)), 600, 300);
        scene2.getStylesheets().add(JavaKeywordsAsync.class.getResource("java-keywords.css").toExternalForm());
        secondaryStage.setScene(scene2);
        secondaryStage.setTitle("STRING AREA");
        secondaryStage.show();
    }

    private static StyleSpans<LinkStyle> computeLinkHighlighting(String text) {
        Matcher matcher = PATTERN.matcher(text);
        int lastKwEnd = 0;
        StyleSpansBuilder<LinkStyle> 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;
            spansBuilder.add(LinkStyle.NO_STYLE, matcher.start() - lastKwEnd);
            spansBuilder.add(new LinkStyle(styleClass), matcher.end() - matcher.start());
            lastKwEnd = matcher.end();
        }
        spansBuilder.add(LinkStyle.NO_STYLE, text.length() - lastKwEnd);
        return spansBuilder.create();
    }

    private static StyleSpans<Collection<String>> computeStringHighlighting(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;
            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();
    }
}
@JordanMartinez
Copy link
Contributor

I'm not entirely sure what your issue is. Is one area scrolling when the other isn't?

It seems to be a duplicate of #390.

@RodrigoSantiago
Copy link
Author

I thought this bug had already been fixed since I had never seen evidence of it

@JordanMartinez
Copy link
Contributor

Which version are you currently using? And which version were you using it when you first noticed it?

@RodrigoSantiago
Copy link
Author

I'm using the "07-M5"

I did other tests :
If the class has an equals overload, the error does not occur
If the equals return false when two have the same style classes, the error happens

@JordanMartinez
Copy link
Contributor

If the class has an equals overload, the error does not occur

That's interesting... I'm not sure why that would happen.

@JordanMartinez
Copy link
Contributor

I'm closing this since it's a duplicate. Let's continue discussion in the original issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants