2323import java .util .function .IntFunction ;
2424
2525import org .checkerframework .checker .nullness .qual .NonNull ;
26+ import org .checkerframework .dataflow .qual .Pure ;
2627import org .fxmisc .richtext .LineNumberFactory ;
2728import org .fxmisc .richtext .event .MouseOverTextEvent ;
2829import org .reactfx .EventSource ;
4647import net .sourceforge .pmd .util .fxdesigner .model .testing .LiveViolationRecord ;
4748import net .sourceforge .pmd .util .fxdesigner .util .DataHolder ;
4849import net .sourceforge .pmd .util .fxdesigner .util .DesignerUtil ;
50+ import net .sourceforge .pmd .util .fxdesigner .util .RichRunnable ;
4951import net .sourceforge .pmd .util .fxdesigner .util .codearea .AvailableSyntaxHighlighters ;
5052import net .sourceforge .pmd .util .fxdesigner .util .codearea .HighlightLayerCodeArea ;
5153import net .sourceforge .pmd .util .fxdesigner .util .codearea .PmdCoordinatesSystem .TextPos2D ;
@@ -113,9 +115,9 @@ public NodeEditionCodeArea(@NamedArg("designerRoot") DesignerRoot root) {
113115
114116 setParagraphGraphicFactory (defaultLineNumberFactory ());
115117
116- currentRuleResultsProperty ().values ().subscribe (this ::highlightXPathResults );
117- currentErrorNodesProperty ().values ().subscribe (this ::highlightErrorNodes );
118- currentRelatedNodesProperty ().values ().subscribe (this ::highlightRelatedNodes );
118+ currentRuleResultsProperty ().values ().map (this ::highlightXPathResults ). subscribe ( this :: updateStyling );
119+ currentErrorNodesProperty ().values ().map (this ::highlightErrorNodes ). subscribe ( this :: updateStyling );
120+ currentRelatedNodesProperty ().values ().map (this ::highlightRelatedNodes ). subscribe ( this :: updateStyling );
119121
120122 initNodeSelectionHandling (designerRoot , selectionEvts , true );
121123
@@ -168,8 +170,8 @@ private void scrollToNode(Node node, boolean scrollToTop) {
168170 try {
169171 visibleLength = lastVisibleParToAllParIndex () - firstVisibleParToAllParIndex ();
170172 } catch (AssertionError e ) {
171- // may be thrown when many selection events occur in quick succession?
172- // Something like, the paragraphs
173+ // May be thrown when many selection events occur in quick succession?
174+ // The error is "dead code", probably a corner case in RichTextFX
173175 return ;
174176 }
175177
@@ -271,28 +273,40 @@ public Var<List<Node>> currentRelatedNodesProperty() {
271273 }
272274
273275
274- /** Highlights xpath results (xpath highlight). */
275- private void highlightXPathResults (Collection <? extends Node > nodes ) {
276- styleNodes (nodes , StyleLayerIds .XPATH_RESULT , true );
276+ /**
277+ * Highlights xpath results (xpath highlight).
278+ */
279+ @ Pure
280+ private RichRunnable highlightXPathResults (Collection <? extends Node > nodes ) {
281+ return styleNodesUpdate (nodes , StyleLayerIds .XPATH_RESULT , true );
277282 }
278283
279284
280- /** Highlights name occurrences (secondary highlight). */
281- private void highlightRelatedNodes (Collection <? extends Node > occs ) {
282- styleNodes (occs , StyleLayerIds .NAME_OCCURRENCE , true );
285+ /**
286+ * Highlights name occurrences (secondary highlight).
287+ */
288+ @ Pure
289+ private RichRunnable highlightRelatedNodes (Collection <? extends Node > occs ) {
290+ return styleNodesUpdate (occs , StyleLayerIds .NAME_OCCURRENCE , true );
283291 }
284292
285293
286- /** Highlights nodes that are in error (secondary highlight). */
287- private void highlightErrorNodes (Collection <? extends Node > nodes ) {
288- styleNodes (nodes , StyleLayerIds .ERROR , true );
294+ /**
295+ * Highlights nodes that are in error (secondary highlight).
296+ */
297+ @ Pure
298+ private RichRunnable highlightErrorNodes (Collection <? extends Node > nodes ) {
299+ RichRunnable r = styleNodesUpdate (nodes , StyleLayerIds .ERROR , true );
289300 if (!nodes .isEmpty ()) {
290- scrollToNode (nodes .iterator ().next (), true );
301+ r = r . andThen (() -> scrollToNode (nodes .iterator ().next (), true ) );
291302 }
303+ return r ;
292304 }
293305
294306
295- /** Moves the caret to a position and makes the view follow it. */
307+ /**
308+ * Moves the caret to a position and makes the view follow it.
309+ */
296310 public void moveCaret (int line , int column ) {
297311 moveTo (line , column );
298312 requestFollowCaret ();
@@ -301,32 +315,34 @@ public void moveCaret(int line, int column) {
301315
302316 @ Override
303317 public void setFocusNode (final Node node , DataHolder options ) {
318+ // editor must not be scrolled when finding a new selection in a
319+ // tree that is being edited
320+ if (node != null && !options .hasData (SELECTION_RECOVERY )) {
321+ // don't randomly jump to top of eg ClassOrInterfaceBody
322+ // when selecting from a caret position
323+ scrollToNode (node , !options .hasData (CARET_POSITION ));
324+ }
304325
305326
306- boolean changed = !Objects .equals (node , currentFocusNode .getValue ());
307- if (changed ) {
327+ RichRunnable update = () -> {};
328+ if (Objects .equals (node , currentFocusNode .getValue ())) {
329+ return ;
330+ }
308331
309- currentFocusNode .setValue (node );
332+ currentFocusNode .setValue (node );
310333
311- // editor is only restyled if the selection has changed
312- Platform . runLater (() -> styleNodes (
313- node == null ? emptyList () : singleton (node ), StyleLayerIds .FOCUS , true ));
334+ // editor is only restyled if the selection has changed
335+ update = update . andThen ( styleNodesUpdate (
336+ node == null ? emptyList () : singleton (node ), StyleLayerIds .FOCUS , true ));
314337
315- if (node == null ) {
316- highlightRelatedNodes (emptyList ());
317- } else {
318- Platform .runLater (() -> highlightRelatedNodes (relatedNodesSelector .getValue ().getHighlightedNodesWhenSelecting (node )));
319- }
338+ if (node == null ) {
339+ update = update .andThen (highlightRelatedNodes (emptyList ()));
340+ } else {
341+ update = update .andThen (highlightRelatedNodes (relatedNodesSelector .getValue ().getHighlightedNodesWhenSelecting (node )));
320342 }
321343
322- // editor must not be scrolled when finding a new selection in a
323- // tree that is being edited
324- // Editor must be scrolled after styling
325- if (node != null && !options .hasData (SELECTION_RECOVERY )) {
326- // don't randomly jump to top of eg ClassOrInterfaceBody
327- // when selecting from a caret position
328- Platform .runLater (() -> scrollToNode (node , !options .hasData (CARET_POSITION )));
329- }
344+ Runnable finalUpdate = update ;
345+ Platform .runLater (() -> updateStyling (finalUpdate ));
330346 }
331347
332348
0 commit comments