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

IndexRange of style span #50

Closed
ghost opened this issue Apr 29, 2014 · 23 comments
Closed

IndexRange of style span #50

ghost opened this issue Apr 29, 2014 · 23 comments

Comments

@ghost
Copy link

ghost commented Apr 29, 2014

Hi Tomas, I have been testing this. it seems there is an issue.

In "word", if you make wo red, and detect the span index range, it will be correct,
"wo" is a range, and "rd" is a range.

but if you apply a color again to "or", so coloring should be like "w" "or" "d", and you click in "or", the span will only detect the O (from previously applied style.

Can you reproduce this?
I am using the richTextArea.getStyleRangeAtPosition(caretpos);

@TomasMikula
Copy link
Member

Hi Maher,

it's best if you post the code. I guess what is happening here is that when you get the style spans for "or", you get two style spans, each spanning 1 character. When you the call mapStyles, this switches the styles in the spans, but there are still two spans of length 1. The text area should probably merge them together, if they have the same style (in terms of equals). It is already merging adjacent ranges with the same style when you use setStyle.

@ghost
Copy link
Author

ghost commented Apr 29, 2014

Yes that is my guess too.

@TomasMikula
Copy link
Member

Please, try the new jar.

@ghost
Copy link
Author

ghost commented Apr 29, 2014

Hi Tomas, I tried it. It seems to works on the first and second attempts, but then starts missing characters on the both ends (before and after).
also, noticed that if I type, then apply style to the text. hit enter.. then type more, click in the new typed text (after hitting enter) and try to apply a style to the span at caret position (so new entered text), it applies style to the previous text (a couple of lines up).

I'll do more testing to try to narrow down the issue.

@ghost
Copy link
Author

ghost commented Apr 29, 2014

I did further testing, I think there is something to do with the line number somewhere
Because if I apply a style to a word (in span), it gets applied to the span relatively above it but in the line immediately above it.

@TomasMikula
Copy link
Member

Can you post a self-contained (runnable) code that demonstrates the problem?

On Wed, Apr 30, 2014 at 12:06 AM, melkhaldi [email protected]:

I did further testing, I think there is something to do with the line
number somewhere
Because if I apply a style to a word (in span), it gets applied to the
span relatively above it but in the line immediately above it.


Reply to this email directly or view it on GitHubhttps://github.com//issues/50#issuecomment-41738294
.

@ghost
Copy link
Author

ghost commented Apr 29, 2014

A runnable example will take me a long time to factor out. For now, these are the code bits I am using in the following steps:

-Type text:
-Apply style to selection in text. (do this a few times over different selections).
-Do more typing.. hit enter to start new lines, do more typing, etc.
-Here, anything typed uses the caret style, which is driven by the subscribe method. so the newly entered text has not been "chopped up".
-Click somewhere in the newly added text, and apply a new style to the span at caret position.
-styles gets applied but to a span that is in previous lines, and is not really to a full span as one would expect. It misses out on a couple of characters.

This is the code I am using to:

**Code to apply style to Selection (style coming as a cleaned up CSS string). Something like:
style = "-fx-font-family: Arial;-fx-font-size: 16;-fx-font-weight: normal;-fx-fill: rgb(153,204,255);-fx-font-style: normal;-fx-underline: false;"

public void applyNewStyleToSelection(TextEditorViewPort port, string style) {
    IndexRange range = port.richTextArea.getSelection();
    if (range.getEnd() > range.getStart()) {
        port.richTextArea.setStyle(range.getStart(), range.getEnd(),  style);
    }

}

**Code to apply style to a span (triggered by hitting a button).

 public void applyToSpanAtCaretCSS(String styleUpdate) {
    int pos = activePort.richTextArea.caretPositionProperty().get();
    int start = activePort.richTextArea.getStyleRangeAtPosition(pos).getStart();
    int end = activePort.richTextArea.getStyleRangeAtPosition(pos).getEnd();
    if (start < end) {
        activePort.richTextArea.setStyle(start, end, styleUpdate);
        System.out.println("Span is:" + activePort.richTextArea.getText(start, end));
        System.out.println("Style is is:" + styleUpdate);
    } else {
        System.out.println("Indices don't work");
    }
}

@TomasMikula
Copy link
Member

Can you narrow down which method is problematic? Is it getStyleRangeAtPosition or setStyle? Does getStyleRangeAtPosition return a range such that pos is not even between start and end?

@ghost
Copy link
Author

ghost commented Apr 30, 2014

I believe the issue is with the getStyleRangeAtPosition.

I also verified this by listening to caret change and printing text for the
detected style range using a getText(rangestart, rangeEnd). the printed
text string is not similar to what is being styled in the text area.

The setStyle works fine. I use it everywhere else and things work as
expected. including apply to selection and to paragraph.

On Tue, Apr 29, 2014 at 5:08 PM, TomasMikula [email protected]:

Can you narrow down which method is problematic? Is it
getStyleRangeAtPosition or setStyle? Does getStyleRangeAtPosition return
a range such that pos is not even between start and end?


Reply to this email directly or view it on GitHubhttps://github.com//issues/50#issuecomment-41747263
.

@ghost
Copy link
Author

ghost commented Apr 30, 2014

on another note, I just printed the style at caret using:
getStyleAtPosition, this is what I get (I only change colors):

END: Style At position is: -fx-font-family: Arial;-fx-font-size:
16;-fx-font-weight: normal;-fx-fill: rgb(0,0,0);-fx-font-style:
normal;-fx-underline: false;-fx-fill: rgb(0,0,0);-fx-fill:
rgb(0,51,51);-fx-fill: rgb(0,0,0);-fx-fill: rgb(0,102,102);-fx-fill:
rgb(0,0,0);-fx-fill: rgb(0,76,153);-fx-fill: rgb(0,0,0);-fx-fill:
rgb(0,102,204);-fx-fill: rgb(0,0,0);-fx-fill: rgb(0,128,255);-fx-fill:
rgb(0,0,0);-fx-fill: rgb(51,153,255);-fx-fill: rgb(0,0,0);-fx-fill:
rgb(102,178,235);-fx-fill: rgb(0,0,0);-fx-fill: rgb(153,204,255);-fx-fill:
rgb(0,0,0);-fx-fill: rgb(153,153,255);-fx-fill: rgb(0,0,0);-fx-fill:
rgb(204,204,255);-fx-fill: rgb(0,0,0);-fx-fill: rgb(153,153,255);-fx-fill:
rgb(0,0,0);-fx-fill: rgb(204,153,255);-fx-fill: rgb(0,0,0);-fx-fill:
rgb(255,153,255);-fx-fill: rgb(0,0,0);-fx-fill: rgb(255,102,255);-fx-fill:
rgb(0,0,0);-fx-fill: rgb(255,51,255);-fx-fill: rgb(255,51,255);-fx-fill:
rgb(255,51,255);-fx-fill: rgb(255,51,255);

something in the setStyle() probably cases the range detection to break.
The setStyle concatenates a new color value, so the string is actually not
the same. if the getStyleRangeAtPosition looks for string similarity, which
I guess it might be doing, this this is why?

On Tue, Apr 29, 2014 at 5:25 PM, Maher Elkhaldi [email protected]:

I believe the issue is with the getStyleRangeAtPosition.

I also verified this by listening to caret change and printing text for
the detected style range using a getText(rangestart, rangeEnd). the
printed text string is not similar to what is being styled in the text area.

The setStyle works fine. I use it everywhere else and things work as
expected. including apply to selection and to paragraph.

On Tue, Apr 29, 2014 at 5:08 PM, TomasMikula [email protected]:

Can you narrow down which method is problematic? Is it
getStyleRangeAtPosition or setStyle? Does getStyleRangeAtPosition return
a range such that pos is not even between start and end?


Reply to this email directly or view it on GitHubhttps://github.com//issues/50#issuecomment-41747263
.

@TomasMikula
Copy link
Member

In the code you posted before, can you add

if(pos < start || pos > end) {
    throw new AssertionError("style range [" + start + "," + end + "] does not contain caret position " + pos);
}

after

int pos = activePort.richTextArea.caretPositionProperty().get();
int start = activePort.richTextArea.getStyleRangeAtPosition(pos).getStart();
int end = activePort.richTextArea.getStyleRangeAtPosition(pos).getEnd();

and see if the exception gets thrown?

@ghost
Copy link
Author

ghost commented Apr 30, 2014

no exception is thrown.

On Tue, Apr 29, 2014 at 6:51 PM, TomasMikula [email protected]:

In the code you posted before, can you add

if(pos < start || pos > end) {
throw new AssertionError("style range [" + start + "," + end + "] does not contain caret position " + pos);}

after

int pos = activePort.richTextArea.caretPositionProperty().get();int start = activePort.richTextArea.getStyleRangeAtPosition(pos).getStart();int end = activePort.richTextArea.getStyleRangeAtPosition(pos).getEnd();

and see if the exception gets throws?


Reply to this email directly or view it on GitHubhttps://github.com//issues/50#issuecomment-41752896
.

@ghost
Copy link
Author

ghost commented Apr 30, 2014

so it must be in the setStyle(), right?

On Tue, Apr 29, 2014 at 6:59 PM, Maher Elkhaldi [email protected]:

no exception is thrown.

On Tue, Apr 29, 2014 at 6:51 PM, TomasMikula [email protected]:

In the code you posted before, can you add

if(pos < start || pos > end) {
throw new AssertionError("style range [" + start + "," + end + "] does not contain caret position " + pos);}

after

int pos = activePort.richTextArea.caretPositionProperty().get();int start = activePort.richTextArea.getStyleRangeAtPosition(pos).getStart();int end = activePort.richTextArea.getStyleRangeAtPosition(pos).getEnd();

and see if the exception gets throws?


Reply to this email directly or view it on GitHubhttps://github.com//issues/50#issuecomment-41752896
.

@TomasMikula
Copy link
Member

So it seems.

@ghost
Copy link
Author

ghost commented Apr 30, 2014

Is the set style method designed to concatenate styling information to the
existing string? Or replace it?

What I ended up doing for preparing for a file format is a method that gets
styles from the text and fetches last occurrence of a given styling
information then finally build a "lean" string.
On Apr 29, 2014 7:04 PM, "TomasMikula" [email protected] wrote:

So it seems.


Reply to this email directly or view it on GitHubhttps://github.com//issues/50#issuecomment-41753540
.

@TomasMikula
Copy link
Member

It replaces the style.

You wouldn't have to write such a method if you used InlineStyleTextArea with your custom style representation instead of InlineCssTextArea.

@ghost
Copy link
Author

ghost commented Apr 30, 2014

Yes I agree. I didn't really get the difference when I first started
working on the prototype. I am afraid to switch things now because the
whole code will probably break in multiple places. I realize now that I
ended up having to do the InlineStyle. Will keep going as I am done with a
big part of the work. I'll keep checking if you managed to find a fix. I'll
try to hack it from my end as well.
On Apr 29, 2014 8:05 PM, "TomasMikula" [email protected] wrote:

It replaces the style.

You wouldn't have to write such a method if you used InlineStyleTextAreawith your custom style representation instead of
InlineCssTextArea.


Reply to this email directly or view it on GitHubhttps://github.com//issues/50#issuecomment-41756285
.

@ghost
Copy link
Author

ghost commented Apr 30, 2014

Hi Tomas, I managed to get it to work this way:

This is the method to get an index range:

public static IndexRange getStyleRangeAtPosition(TextEditorViewPort port, int position) {
    int start = position;
    int end = position;
    start = findLeftEnd(port.richTextArea, position, start);
    end = findRightEnd(port.richTextArea, position, end);
    IndexRange range = new IndexRange(start, end);
    return range;
}

public static int findLeftEnd(InlineCssTextArea area, int pos, int start) {
    String style = getCleanedUpStyle(area.getStyleAtPosition(pos));
    start = pos;

    if (start == 0) {
        return 0;
    } else {
        while (getCleanedUpStyle(area.getStyleAtPosition(start)).equals(style)
                && start > 1) {
            start--;
        }
    }
    return start;
}

public static int findRightEnd(InlineCssTextArea area, int pos, int end) {
    String style = getCleanedUpStyle(area.getStyleAtPosition(pos));
    end = pos;
    if (end == area.getText().length()) {
        return end;
    } else {
        while (getCleanedUpStyle(area.getStyleAtPosition(end)).equals(style)
                && end < area.getText().length()) {
            end++;
        }
        if (end != area.getText().length()) {
            end--;
        }

    }
    return end;
}

this is the method that fetches the values from the style:

public static String getCleanedUpStyle(String roughStyle) {
    String lean = "";
    String[] splits = roughStyle.split(";");

    String colorSplit = "", nameSplit = "", sizeSplit = "", styleSplit = "", weightSplit = "", underlineSplit = "";
    for (String split : splits) {
        if (split.contains("family")) {
            nameSplit = split;
        } else if (split.contains("style")) {
            styleSplit = split;
        } else if (split.contains("size")) {
            sizeSplit = split;
        } else if (split.contains("weight")) {
            weightSplit = split;
        } else if (split.contains("underline")) {
            underlineSplit = split;
        } else if (split.contains("rgb")) {
            colorSplit = split;
        }
    }

    String colorCleaned = colorSplit.replace("-fx-fill: rgb(", "");
    colorCleaned = colorCleaned.replace(")", "");

    String nameCleaned = nameSplit.replace("-fx-font-family: ", "");
    nameCleaned = nameCleaned.replace(")", "");

    String weightCleaned = weightSplit.replace("-fx-font-weight: ", "");
    weightCleaned = weightCleaned.replace(")", "");

    String underLineCleaned = underlineSplit.replace("-fx-underline: ", "");
    underLineCleaned = underLineCleaned.replace(")", "");

    String styleCleaned = styleSplit.replace("-fx-font-style: ", "");
    styleCleaned = styleCleaned.replace(")", "");

    String sizeCleaned = sizeSplit.replace("-fx-font-size: ", "");
    sizeCleaned = sizeCleaned.replace(")", "");

    lean = colorCleaned + ";" + nameCleaned + ";" + weightCleaned + ";" + underLineCleaned + ";" + styleCleaned + ";" + sizeCleaned;

    return lean;
}

It seems to work fine so far.

@TomasMikula
Copy link
Member

Well, that is a lot of code that you wouldn't have to write if you used custom style representation instead of raw CSS string.

@ghost
Copy link
Author

ghost commented Apr 30, 2014

true :D
lol... someone told me once that my problem is that I don't mind working too much.

Were you able to confirm that the setStyle method (when working on raw CSS) generates extra styling information like the one I posted above?

@TomasMikula
Copy link
Member

There's no way setStyle generates extra style information. All the style information comes from you concatenating css strings (e.g. via mapStyles).

@ghost
Copy link
Author

ghost commented Apr 30, 2014

oh ok. so I can probably perform the style cleaning after I do the map
styles.

On Wed, Apr 30, 2014 at 8:59 AM, TomasMikula [email protected]:

There's no way setStyle generates extra style information. All the style
information comes from you concatenating css strings (e.g. via mapStyles).


Reply to this email directly or view it on GitHubhttps://github.com//issues/50#issuecomment-41814708
.

@TomasMikula
Copy link
Member

Yes, or rather in mapStyles. Instead of

mapStyles(s -> s + newStyle)

do

mapStyles(s -> getCleanedUpStyle(s + newStyle))

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

No branches or pull requests

1 participant