<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:"Yu Gothic";
panose-1:2 11 4 0 0 0 0 0 0 0;}
@font-face
{font-family:Aptos;
panose-1:2 11 0 4 2 2 2 2 2 4;}
@font-face
{font-family:"Iosevka Fixed SS16";
panose-1:2 0 5 9 3 0 0 0 0 4;}
@font-face
{font-family:"Times New Roman \(Body CS\)";
panose-1:2 11 6 4 2 2 2 2 2 4;}
@font-face
{font-family:"\@Yu Gothic";
panose-1:2 11 4 0 0 0 0 0 0 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
font-size:10.0pt;
font-family:"Aptos",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
span.EmailStyle200
{mso-style-type:personal-reply;
font-family:"Iosevka Fixed SS16";
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;
mso-ligatures:none;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style>
</head>
<body lang="EN-US" link="blue" vlink="purple" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">You *<b>do not*</b> want to update javaFX in a background thread.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">The idea is to compute the syntax in a background thread (provided the underlying model is properly synchronized and can serve the plain text paragraphs to multiple threads),
but the actual change must take effect in the FX application thread.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<div id="mail-editor-reference-message-container">
<div>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">openjfx-dev <openjfx-dev-retn@openjdk.org> on behalf of PavelTurk <pavelturk2000@gmail.com><br>
<b>Date: </b>Tuesday, April 29, 2025 at 10:54<br>
<b>To: </b>openjfx-dev@openjdk.org <openjfx-dev@openjdk.org><br>
<b>Subject: </b>Re: RichTextArea: How to return existing paragraphs from SyntaxDecorator?<o:p></o:p></span></p>
</div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:12.0pt">Thank you very much for such detailed answer!<o:p></o:p></span></p>
<div>
<p class="MsoNormal"><span style="font-size:12.0pt">On 4/29/25 20:15, Andy Goryachev wrote:<o:p></o:p></span></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">If you can guarantee that nothing in the paragraph has changed, the model can return a cached paragraph.</span><o:p></o:p></p>
</div>
</blockquote>
<p class="MsoNormal"><span style="font-size:12.0pt">The problem is it doesn't return. As I've said earlier the problem is in this line - </span><span style="font-size:11.0pt">However, it didn't work because of this line -
<a href="https://github.com/openjdk/jfx/blob/3fdd21386d6db96294fcecd80afc25d09732c067/modules/jfx.incubator.richtext/src/main/java/jfx/incubator/scene/control/richtext/model/CodeTextModel.java#L83">
https://github.com/openjdk/jfx/blob/3fdd21386d6db96294fcecd80afc25d09732c067/modules/jfx.incubator.richtext/src/main/java/jfx/incubator/scene/control/richtext/model/CodeTextModel.java#L83</a> and as a result -> StackOverflow.</span><span style="font-size:12.0pt"><br>
<br>
<br>
<o:p></o:p></span></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">But if the particular paragraph has changed in any way, it might impact other things like the scrollbars.</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">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.</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">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.</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">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.</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
</div>
</blockquote>
<p class="MsoNormal"><span style="font-size:12.0pt"><br>
Yes, I am working on highlighting now and I add highlighting in SyntaxDecorator on JavaFX thread:<br>
<br>
</span><span style="font-size:11.0pt"> @Override<br>
public RichParagraph createRichParagraph(CodeTextModel model, int index) {<br>
RichParagraph.Builder b = RichParagraph.builder();<br>
for (segment: segments) {<br>
b.addWithStyleNames(segment.getText(), segment.getStyles().toArray(String[]::new));</span><span style="font-size:12.0pt"><br>
</span><span style="font-size:11.0pt"> } <br>
return b.build();<br>
}<br>
}<br>
</span><span style="font-size:12.0pt"> <br>
Important! I use only style classes (no java, no inline style).<br>
<br>
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:<br>
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.<br>
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.
<br>
<br>
Best regards, Pavel<br>
<br>
<br>
<o:p></o:p></span></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<div id="mail-editor-reference-message-container">
<div>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">openjfx-dev <a href="mailto:openjfx-dev-retn@openjdk.org">
<openjfx-dev-retn@openjdk.org></a> on behalf of PavelTurk <a href="mailto:pavelturk2000@gmail.com">
<pavelturk2000@gmail.com></a><br>
<b>Date: </b>Tuesday, April 29, 2025 at 08:39<br>
<b>To: </b><a href="mailto:openjfx-dev@openjdk.org">openjfx-dev@openjdk.org</a> <a href="mailto:openjfx-dev@openjdk.org">
<openjfx-dev@openjdk.org></a><br>
<b>Subject: </b>Re: RichTextArea: How to return existing paragraphs from SyntaxDecorator?</span><o:p></o:p></p>
</div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:12.0pt">Andy, thank you for your reply</span><o:p></o:p></p>
<div>
<p class="MsoNormal"><span style="font-size:12.0pt">On 4/29/25 18:02, Andy Goryachev wrote:</span><o:p></o:p></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Multiple topics here.</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">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.</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">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.</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">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).</span><o:p></o:p></p>
</div>
</blockquote>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:12.0pt">Hm. I've read this line -
<a href="https://github.com/openjdk/jfx/blob/3fdd21386d6db96294fcecd80afc25d09732c067/modules/jfx.incubator.richtext/src/main/java/jfx/incubator/scene/control/richtext/model/RichParagraph.java#L42">
https://github.com/openjdk/jfx/blob/3fdd21386d6db96294fcecd80afc25d09732c067/modules/jfx.incubator.richtext/src/main/java/jfx/incubator/scene/control/richtext/model/RichParagraph.java#L42</a> 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<br>
and what not. I mean:<br>
<br>
public class ParagraphStyler implements Consumer<ListModification<? extends Paragraph<Collection<String>, String, Collection<String>>>> {<br>
<br>
@Override<br>
public void accept(ListModification<? extends Paragraph<Collection<String>, String, Collection<String>>> lm) { <br>
//here it is possible to update styles only for paragraphs which styles should be updated<br>
}<br>
}<br>
<br>
codeArea.getVisibleParagraphs().addModificationObserver(new ParagraphStyler()); //only for visible paragraphs!<br>
<br>
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.<br>
<br>
</span><o:p></o:p></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">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"?</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
</div>
</blockquote>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:12.0pt"><br>
Best regards, Pavel<br>
<br>
</span><o:p></o:p></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""> </span><o:p></o:p></p>
<div id="mail-editor-reference-message-container">
<div>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">openjfx-dev <a href="mailto:openjfx-dev-retn@openjdk.org">
<openjfx-dev-retn@openjdk.org></a> on behalf of PavelTurk <a href="mailto:pavelturk2000@gmail.com">
<pavelturk2000@gmail.com></a><br>
<b>Date: </b>Monday, April 28, 2025 at 16:54<br>
<b>To: </b><a href="mailto:openjfx-dev@openjdk.org">openjfx-dev@openjdk.org</a> <a href="mailto:openjfx-dev@openjdk.org">
<openjfx-dev@openjdk.org></a><br>
<b>Subject: </b>RichTextArea: How to return existing paragraphs from SyntaxDecorator?</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">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.<br>
<br>
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.<br>
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.<br>
<br>
Something like this:<br>
<br>
codeArea.setSyntaxDecorator(new SyntaxDecorator() {<br>
@Override<br>
public RichParagraph createRichParagraph(CodeTextModel model, int index) {<br>
if (paragraphStylesAreValid) {<br>
return codeArea.getModel().getParagraph(index);<br>
} else {<br>
RichParagraph.Builder b = RichParagraph.builder();<br>
...<br>
return b.build();<br>
}<br>
}<br>
<br>
@Override<br>
public void handleChange(CodeTextModel m, TextPos start, TextPos end, int charsTop,<br>
int linesAdded, int charsBottom) {<br>
<br>
}<br>
});<br>
<br>
However, it didn't work because of this line - <a href="https://github.com/openjdk/jfx/blob/3fdd21386d6db96294fcecd80afc25d09732c067/modules/jfx.incubator.richtext/src/main/java/jfx/incubator/scene/control/richtext/model/CodeTextModel.java#L83">
https://github.com/openjdk/jfx/blob/3fdd21386d6db96294fcecd80afc25d09732c067/modules/jfx.incubator.richtext/src/main/java/jfx/incubator/scene/control/richtext/model/CodeTextModel.java#L83</a><br>
<br>
As I result I get StackOverflowError. Could anyone say how to do it?<br>
<br>
Best regards, Pavel</span><o:p></o:p></p>
</div>
</div>
</div>
</div>
</div>
</blockquote>
<p class="MsoNormal"><span style="font-size:12.0pt"> </span><o:p></o:p></p>
</div>
</div>
</div>
</div>
</blockquote>
<p class="MsoNormal"><span style="font-size:12.0pt"><o:p> </o:p></span></p>
</div>
</div>
</div>
</div>
</body>
</html>