Thank you very much for such detailed answer!
On 4/29/25 20:15, Andy Goryachev wrote:
If you can guarantee that nothing in the paragraph has changed, the model can
return a cached paragraph.
The problem is it doesn't return. As I've said earlier the problem is in this line
- However, it didn't work because of this line -
https://github.com/openjdk/jfx/blob/3fdd21386d6db96294fcecd80afc25d09732c067/modules/jfx.incubator.richtext/src/main/java/jfx/incubator/scene/control/richtext/model/CodeTextModel.java#L83
and as a result -> StackOverflow.
But if the particular paragraph has changed in any way, it might impact other
things like the scrollbars.
I suppose it is possible to implement certain optimizations if, for example,
the overall dimensions do not change - like, for example, if the style changes
only affect the text colors and nothing else.
One can also try to query the view for which paragraphs are visible and which
are not, but keep in mind that the same model can be visualized by different
views - you should be fine as long as your application can guarantee that there
is only one view.
Getting back to syntax highlighting of large models, I envisioned that the
background thread that computes the highlighting updates the model periodically
and in (large) blocks, to minimize the load, and to strike the balance between
quality and performance. Also, when dealing with large text that might contain
comments, the syntax highlighter may want to keep track of the nexus points
from which the syntax computation can be re-started instead of re-scanning the
file from the beginning. All this might get complicated rather quickly though.
Yes, I am working on highlighting now and I add highlighting in SyntaxDecorator
on JavaFX thread:
@Override
public RichParagraph createRichParagraph(CodeTextModel model, int
index) {
RichParagraph.Builder b = RichParagraph.builder();
for (segment: segments) {
b.addWithStyleNames(segment.getText(),
segment.getStyles().toArray(String[]::new));
}
return b.build();
}
}
Important! I use only style classes (no java, no inline style).
Segments - already ready model. Can such code create performance problems,
including scrolling? I mean, that as I understand there are TWO ways to add
styles:
1) on JavaFX thread 2) on background thread. I optimized my code model
(providing ready segments) to the maximum, and I think the code must work well
on JavaFX thread.
But it doesn't - I tested code with about 6 000 paragraphs. At the same time
the same approach works without performance problems in RTFX.
Best regards, Pavel
-andy
*From: *openjfx-dev <[email protected]> on behalf of PavelTurk
<[email protected]>
*Date: *Tuesday, April 29, 2025 at 08:39
*To: *[email protected] <[email protected]>
*Subject: *Re: RichTextArea: How to return existing paragraphs from
SyntaxDecorator?
Andy, thank you for your reply
On 4/29/25 18:02, Andy Goryachev wrote:
Multiple topics here.
1. The view does size 100 paragraphs (Params.SLIDING_WINDOW_EXTENT) to
ensure smooth scrolling when text wrap is on. Initially I thought we could
allow the application to control this parameter, but we decided against it, as
it exposes internal aspect of the implementation.
2. You probably should not cache the paragraphs in the model, or try to
optimize the styling in the way I understood you did. When the view asks for
the paragraph, the model needs to render it in all its glory, or things would
break.
It looks you are trying to implement the syntax highlighting, right? The
first question you might want to ask is determine whether the styles are known
at the time when the paragraph gets requested. If not - you probably want to
return a plain text paragraph, that is with no styling, and once the styling is
known, fire the model's style change event, which will cause the view to
request the (newly updated) paragraphs it needs. In other words, the code you
supplied won't work - the model should always build a new paragraph (or supply
a cached one only if you can guarantee that nothing in it changed, not event
line index).
Hm. I've read this line -
https://github.com/openjdk/jfx/blob/3fdd21386d6db96294fcecd80afc25d09732c067/modules/jfx.incubator.richtext/src/main/java/jfx/incubator/scene/control/richtext/model/RichParagraph.java#L42
saying that paragraph is IMMUTABLE and decided - why should I recreate it if
it hasn't changed. It seems that I was wrong. At the same time in RTFX you can
control what to update
and what not. I mean:
public class ParagraphStyler implements Consumer<ListModification<? extends
Paragraph<Collection<String>, String, Collection<String>>>> {
@Override
public void accept(ListModification<? extends Paragraph<Collection<String>, String,
Collection<String>>> lm) {
//here it is possible to update styles only for paragraphs which styles
should be updated
}
}
codeArea.getVisibleParagraphs().addModificationObserver(new ParagraphStyler());
//only for visible paragraphs!
In other words, JFX CodeArea forces paragraph styles to update whether it’s
necessary or not, whereas in RTFX we can optimize this process—at least, that’s
how I understand it.
3. Not sure about the scrolling, it seems to work on macOS as expected. Does it work
with a stock model that has none of the "optimizations"?
-andy
Best regards, Pavel
*From: *openjfx-dev <[email protected]>
<mailto:[email protected]> on behalf of PavelTurk <[email protected]>
<mailto:[email protected]>
*Date: *Monday, April 28, 2025 at 16:54
*To: *[email protected] <[email protected]>
<mailto:[email protected]>
*Subject: *RichTextArea: How to return existing paragraphs from
SyntaxDecorator?
I noticed that paragraphs in CodeArea are updated too aggressively. For
example, when I press a single key like '1', about 100 paragraphs get refreshed.
To improve performance, I decided to implement it this way: I store
information for each paragraph indicating whether its styles are up-to-date or
not.
From SyntaxDecorator, I return the existing paragraph from the model if
the styles are valid. If the styles are outdated, I build a new paragraph.
Something like this:
codeArea.setSyntaxDecorator(new SyntaxDecorator() {
@Override
public RichParagraph createRichParagraph(CodeTextModel model,
int index) {
if (paragraphStylesAreValid) {
return codeArea.getModel().getParagraph(index);
} else {
RichParagraph.Builder b = RichParagraph.builder();
...
return b.build();
}
}
@Override
public void handleChange(CodeTextModel m, TextPos start,
TextPos end, int charsTop,
int linesAdded, int charsBottom) {
}
});
However, it didn't work because of this line -
https://github.com/openjdk/jfx/blob/3fdd21386d6db96294fcecd80afc25d09732c067/modules/jfx.incubator.richtext/src/main/java/jfx/incubator/scene/control/richtext/model/CodeTextModel.java#L83
As I result I get StackOverflowError. Could anyone say how to do it?
Best regards, Pavel