JDK-8115072 : Hittesting inside TextFlow fails
  • Type: Bug
  • Component: javafx
  • Sub-Component: graphics
  • Affected Version: 8
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2013-02-19
  • Updated: 2015-06-17
  • Resolved: 2013-08-14
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8Fixed
Related Reports
Relates :  
Description
Nesting Text elements inside a TextFlow makes the attached hit-test fail, the reason is that the correct Y-Coordinate is reported by the MouseEvent, when directly placing a Text-Node the Y-Coordinate is negative which I find strange.

The reason for the failing of the hit-test is that impl_hitTestChar always adds the YRendering() to the coordinate. To me it looks like Text-Node is providing wrong relative coordinates (negative ones) if placed into a container like HBox and to fix this YRendering was added.
Comments
Hi, I'm also wondering about how to do efficient hit testing. The current solutions are pretty bad. https://wiki.openjdk.java.net/display/OpenJFX/8u40 mentions an editor. Will this be a fully fledged editor (like notepad++ or sublime text) or just a simple edit control? Thanks.
04-10-2014

I strongly dislike that API, and my editor isn't an eclipse clone, it is more of sublime text clone with multiple cursors and selections, block selections, custom drawn selections and error overlays, etc. That was hell to get going on SWT/TextLayout, so I'm taking the javafx experiment as an opportunity to produce a nice API to handle those more advanced features as well. I am not going to base my editor on your code, nor Thomas' for those reasons and more. Sorry. Please realize I'm not an editor noob, I'm just an javafx noob but that will change fast enough.
30-07-2014

My control has the same API as StyledText - why don't you simply contribute what you miss? BTW on the none API layer you can implement something like TextLayout fairly ALL API is there - I know that because I started implementing TextLayout on SWTonJavaFX.
30-07-2014

1. getLayoutBounds#getHeight returns 0 while I am adding to vbox. 2. Oh, I absolutely tried Tom's control. It's promising, but didn't meet my goals in a number of ways. I know an editor is a fairly huge effort as I have developed one in SWT (which was made easier due to TextLayout et. al) In fact, I have a large amount of infrastructure in place, like nashorn-driven parsers for a wide variety of languages, debugger hooks, etc - so I am in the process of moving the frontend from SWT to JavaFX (where I'm still a noob).
30-07-2014

Good point by Tom. I would try that first before developing a text editor, which is a huge effort.
30-07-2014

did you try getLayoutBounds() ? Also note that ListView et. all. use a VirtualFlow container for virtualization.
30-07-2014

Use a ListView or a VirtualFlow - just take a look at http://git.eclipse.org/c/efxclipse/org.eclipse.efxclipse.git/tree/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/styledtext but this begs the question why do not simply using the available controls from myself or Tomas? Why reinventing the wheel? My StyledText is opensource (under EPL) and I have already support for the complete Eclipse Text Parsing infrastructure connected to it (http://git.eclipse.org/c/efxclipse/org.eclipse.efxclipse.git/tree/experimental/compensator) - OSGi is NOT needed at all!
30-07-2014

On a related note, I put a TextFlow per line into a VBox. However, I want to add only as many lines as needed that fits the windows height. How can I accomplish this? Can not seem to find a reliable way to query the height of the TextFlow (catering for wrapping, etc) while adding these to the VBox. I am probably missing something simple... I did try calling the protected method computePrefHeight via reflection, but it seems to ignore font size set in the css class. Ideas?
30-07-2014

About start work on an editor... will that be suitable for a code editor? I need the ability to show javadoc popups, error underlining, line numbers, breakpoints in the gutter, etc. That flexible? As for TextFlow performance, I��ll file a bug.
30-07-2014

mr. lang, about performance, if you have a specific test case that is slow please file a bug. Text and TextFlow use the very same code for rendering (at the lowest level), therefore I would expect the rendering performance to be similar. Also note that according to the page https://wiki.openjdk.java.net/display/OpenJFX/8u40 we should start working on editor in a few months.
28-07-2014

TextFlowHitTest.java - uses reflection to show how handle hit test on a TextFlow. Note: I do not suggest using this code for production. Note the offset to node mapping is a linear search O(n). In real text editor should have data structures able to do this mapping in O(logN) or better.
28-07-2014

I obviously only render visible lines, which on my 4K monitor means 142 lines with normal font size. It's not super-slow, but it's not fast either. Also, not being able to set tab-size is sad (there's a jira for it now at least)
25-07-2014

My code editor has 0 performance problems rendering Java code > 10.000 line the trick is only to render the visible lines which are not more than 50. My biggest problem as of now is that if the text contains TAB controls the hit testing is invalid (i currently help my self by translating them to SPACE but that's is not the final solution) See the editor screenshots at https://twitter.com/tomsontom/status/489502913308655616/photo/1
25-07-2014

Felipe, I'm more than interested despite comment 7472, as there are promises of improvements. Please share the reflection code! :D My biggest worries now, as far as text editor impl goes, is that rendering with TextFlow is about 50% slower than laying out using AWT TextLayout and then render directly with Text.
25-07-2014

See RT-29077 for Hit-testing for TextFlow. Currently planned for 9. You can workaround this problem using a bit of reflection, I think I wrote this code once, if you like I can share it with you. You can also checkout what https://github.com/TomasMikula/RichTextFX did. That said, based on your last comment in RT-7472 I'm not sure if you are still interested.
22-07-2014

What's the status on hit-testing for text flows? Also, will there be public API's for this? What about finding the next/prev location of characters, considering bidi laid out text. That is, everything needed to use TextFlow as a text editor basis (like TextLayout in AWT)
08-07-2014

For a simple test case (the one from Tom) this line seems to fix it: diff -r 3095bcea30b4 modules/graphics/src/main/java/javafx/scene/text/Text.java --- a/modules/graphics/src/main/java/javafx/scene/text/Text.java Mon Jul 15 14:26:52 2013 -0700 +++ b/modules/graphics/src/main/java/javafx/scene/text/Text.java Mon Jul 15 19:15:35 2013 -0700 @@ -1076,6 +1076,8 @@ } private float getYRendering() { + if (isSpan()) return 0; + /* Always logical for rendering */ BaseBounds bounds = getLogicalBounds(); I test a bit better tomorrow and send out a review if it works
16-07-2013

I am seeing the exact thing in my FlowDown app. If a link is on anything other than the last line of a paragraph, no mouse events (even the cursor) is passed in. Here's two images I snapped. On one line I get mouseovers and clicks, on the second no such thing. So still a bug. https://docs.google.com/file/d/0B4W-6ALx-Sm5R3l1NXBIWXE5NE0/edit?usp=sharing https://docs.google.com/file/d/0B4W-6ALx-Sm5VzVlOHpLRzVTTDQ/edit?usp=sharing
30-03-2013

Hi Tom, Where you able to work this out ? (sorry, I completely forgot about this bug...) If you have a patch for the Text node I would be more than happy to released for you.
26-03-2013

I see, the problem is that all internal selection/hit test API were not made to work for TextFlow. I suspect that some might just work (the selection stuff), others (like impl_hitTestChar(), range) are completely broken. I can take a look if there is anything simple I can do to fix this. If you have the time, can you please try just adding getYRendering() only when isSpan() returns true. (note also that getX() and getY() are always zero if isSpan==false).
05-03-2013

My test case: package tests; import javafx.application.Application; import javafx.event.EventHandler; import javafx.geometry.Point2D; import javafx.scene.Scene; import javafx.scene.input.MouseEvent; import javafx.scene.layout.VBox; import javafx.scene.text.Text; import javafx.scene.text.TextFlow; import javafx.stage.Stage; import com.sun.javafx.scene.text.HitInfo; public class RT28485HitTesting extends Application { @Override public void start(Stage primaryStage) throws Exception { VBox box = new VBox(); box.getChildren().add(new TextFlow(createHitTest("TextFlow wrapped"))); box.getChildren().add(createHitTest("Plain text")); primaryStage.setScene(new Scene(box, 300, 300)); primaryStage.show(); } private Text createHitTest(String title) { final Text t = new Text(title); t.setOnMousePressed(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { Point2D p = new Point2D(event.getX(), event.getY()); System.err.println(p); HitInfo info = t.impl_hitTestChar(p); System.err.println(t.getText() + " => " + info.getCharIndex()); } }); return t; } /** * @param args */ public static void main(String[] args) { launch(args); } }
19-02-2013