Giter Club home page Giter Club logo

Comments (15)

Jugen avatar Jugen commented on June 24, 2024 1

Do the following three steps ....

  1. Declare private field:
private SuspendableYes suspendUndo = new SuspendableYes();
  1. Set undo manager when creating area:
textArea.setUndoManager( UndoUtils.richTextSuspendableUndoManager( textArea, suspendUndo ) );
  1. Use suspendUndo when required:
suspendUndo.suspendWhile( () -> textArea.setStyleSpans( position, ssb.create() ) );

from richtextfx.

Jugen avatar Jugen commented on June 24, 2024

Would codeArea.getStyleRangeAtPosition( pos ); maybe help ?

from richtextfx.

PavelTurk avatar PavelTurk commented on June 24, 2024

@Jugen Thank you for your answer. This is my code:

System.out.println("The position:" + position);
var range = this.textArea.getStyleRangeAtPosition(position - 1);
System.out.println("The range:" + range);

And this is output:

The position:304
The range:16, 20

Firstly I couldn't understand how it is possible. But it can be possible if returned range is considered in specific paragraph. But, what if my span takes two paragraphs? Then how can I take the multiparagraph span at position X? Or I misunderstand something.

from richtextfx.

Jugen avatar Jugen commented on June 24, 2024

Yeah, I'm surprised by that as well !? Looking at the code reveals that the returned IndexRange is relative to the paragraph as you guessed.
I'd say this is a bug but I'm not going to change it since it's been like that for how long and may break somebody's code ? I will however add a note to the JavaDoc for those methods.

I'd suggest using getStyleRangeAtPosition( par, col ) instead where it makes more sense that the returned IndexRange is relative to the paragraph.

For style spans over multiple paragraphs you could try the following based on what is done in Paragraph:

// Must use this method of getStyleSpans or the one with parameter IndexRange and not any other !
var spans = codeArea.getStyleSpans( 0, codeArea.getLength() );
var offset = spans.offsetToPosition( targetPos, Bias.Backward );
var styleStart = offset.getMinor();
var styleEnd = styleStart + spans.getStyleSpan( offset.getMajor() ).getLength();

from richtextfx.

PavelTurk avatar PavelTurk commented on June 24, 2024

@Jugen Thank you for your answer. I couldn't make it work:

My code:

    public IndexRange getRealStyleRangeAt(int position) {
        // Must use this method of getStyleSpans or the one with parameter IndexRange and not any other !
        var spans = this.getStyleSpans(0, this.getLength());
        var offset = spans.offsetToPosition(position, Bias.Backward);
        var styleStart = offset.getMinor();
        var styleEnd = styleStart + spans.getStyleSpan( offset.getMajor() ).getLength();
        return new IndexRange(styleStart, styleEnd);
    }

Usage:

    System.out.println("The position:" + position);
    var range = this.textArea.getRealStyleRangeAt(position - 1);
    System.out.println("The range:" + range);

Output:

The position:302
The range:2, 5

from richtextfx.

PavelTurk avatar PavelTurk commented on June 24, 2024

I can provide test code, if it's required. I think it is necessary to add to RichTextFX API something like this.

from richtextfx.

Jugen avatar Jugen commented on June 24, 2024

Please do provide test code, then I'll have go at it ....

from richtextfx.

PavelTurk avatar PavelTurk commented on June 24, 2024

This is code:

public class JavaFxTest7 extends Application {

    private final CodeArea codeArea = new CodeArea();

    @Override
    public void start(Stage stage) {
        var text = """
        <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
            <modelVersion>4.0.0</modelVersion>
            <groupId>com.foo</groupId>
            <artifactId>bar</artifactId>
            <version>1.0.0</version>
            <packaging>pom</packaging>
            <name>Foo</name>
        """;
        this.codeArea.appendText(text);
        VBox.setVgrow(codeArea, Priority.ALWAYS);
        StyleSpansBuilder<Collection<String>> ssb = new StyleSpansBuilder<>();
        ssb.add(Collections.singletonList("highlighted"), 3);
        codeArea.setStyleSpans(300, ssb.create());

        var button = new Button("Test");
        button.setOnAction((e) -> {
            var position = this.codeArea.getCaretPosition();
            System.out.println("The position:" + position);
            var range = this.getRealStyleRangeAt(position - 1);
            System.out.println("The range:" + range);
        });

        var css= this.getClass().getResource("test7.css").toExternalForm();
        Scene scene = new Scene(new VBox(codeArea, button), 600, 200);
        scene.getStylesheets().add(css);
        stage.setScene(scene);
        stage.show();
    }

    public IndexRange getRealStyleRangeAt(int position) {
        // Must use this method of getStyleSpans or the one with parameter IndexRange and not any other !
        var spans = this.codeArea.getStyleSpans(0, this.codeArea.getLength());
        var offset = spans.offsetToPosition(position, TwoDimensional.Bias.Backward);
        var styleStart = offset.getMinor();
        var styleEnd = styleStart + spans.getStyleSpan( offset.getMajor() ).getLength();
        return new IndexRange(styleStart, styleEnd);
    }

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

This is gif:
Peek 2024-05-28 18-24

from richtextfx.

Jugen avatar Jugen commented on June 24, 2024

Try updating getRealStyleRangeAt to the following:

    public IndexRange getRealStyleRangeAt( int position )
    {
        var length = 0;
        for ( var ss : codeArea.getStyleSpans( 0, codeArea.getLength() ) )
        {
            if ( (length += ss.getLength()) >= position )
            {
                var start = length - ss.getLength();
                return new IndexRange( start, length );
            }
        }

        return new IndexRange( 0,0 );
    }

from richtextfx.

PavelTurk avatar PavelTurk commented on June 24, 2024

@Jugen This is what I wanted to avoid. As I understand RichTextFX has its own model for style span ranges and I wanted to use it instead if iterating all style spans. Or there is no chance to get REAL range for concrete position?

from richtextfx.

Jugen avatar Jugen commented on June 24, 2024

Yeah, I don't like the iteration either but I don't know of another way as I haven't been able to find it in the model.
The StyleSpans interface extends TwoDimensional which only seems to be able to give us relative ranges and not absolute ones.
The API allows us to get a StyleSpan at a particular position and to tell us where in that StyleSpan the position is but it has no knowledge of it's own position and StyleSpans doesn't seem to know the absolute position either.

I can try and add a start field to StyleSpan which StyleSpansBuilder can update when creating StyleSpans. Then integrate getRealStyleRangeAt into StyleSpans which can then be reduced down to the following I think:

var offset = spans.offsetToPosition( position, Bias.Backward );
var span = spans.getStyleSpan( offset.getMajor() );
var spanStart = span.getStart();
return new IndexRange( spanStart, spanStart + span.getLength() );

from richtextfx.

PavelTurk avatar PavelTurk commented on June 24, 2024

@Jugen The only thing I can suggest is to distinguish relative ranges and absolute ones in API. Maybe something like this getAbsoluteStyleRangeAt(...).

from richtextfx.

Jugen avatar Jugen commented on June 24, 2024

Please see the PR that I've submitted to try and address this issue for you.

from richtextfx.

PavelTurk avatar PavelTurk commented on June 24, 2024

@Jugen I've checked. It seems to work. At least, all my tests finally passed. Only one question - when I do:
textArea.setStyleSpans(position, ssb.create()) then this modification is saved to undo list as a separate action. But this is not right as it is not an user action. Could you say, how I can exclude my style modification from undo actions? By other words undo manager must ignore my style operation.

from richtextfx.

PavelTurk avatar PavelTurk commented on June 24, 2024

@Jugen Yes, it helped. Thank you very much!

from richtextfx.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.