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

Listening to the area.selectedTextProperty and then selecting the text beyond the end leads to exception #991

Closed
garybentley opened this issue Dec 20, 2020 · 4 comments · Fixed by #992

Comments

@garybentley
Copy link

This was tested using version 0.10.5.

For the following test code (the actual area instance used doesn't matter, this one was just convenient):

      InlineCssTextArea r = new InlineCssTextArea ();
       r.selectedTextProperty ().addListener ((pr, oldv, newv) -> {});
       Scene ss = new Scene (r);
       ss.getStylesheets ().add ("test.css");

       Stage st = new Stage ();
       st.setScene (ss);
       st.setWidth (500);
       st.setHeight (500);
       st.show ();

The test.css file contains:

.styled-text-area .paragraph-text
{
  -fx-padding: 0 0 30pt 0;
}

The size of the padding isn't important, it's just there to let the issue happen.

If you then click in the area and then drag towards the end of the line and/or below the line you get the following exception:

Position 1 is out of bounds
org.reactfx.util.FingerTree$NonEmptyFingerTree.locate(FingerTree.java:42)
org.fxmisc.richtext.model.ReadOnlyStyledDocument.split(ReadOnlyStyledDocument.java:275)
org.fxmisc.richtext.model.ReadOnlyStyledDocument.subSequence(ReadOnlyStyledDocument.java:315) 
org.fxmisc.richtext.model.GenericEditableStyledDocumentBase.subSequence(GenericEditableStyledDocumentBase.java:196) 
org.fxmisc.richtext.model.SimpleEditableStyledDocument.subSequence(SimpleEditableStyledDocument.java:10) 
org.fxmisc.richtext.GenericStyledArea.subDocument(GenericStyledArea.java:1011) 
org.fxmisc.richtext.TextEditingArea.subDocument(TextEditingArea.java:228) 
org.fxmisc.richtext.SelectionImpl.lambda$new$2(SelectionImpl.java:182) 
org.reactfx.value.Val$2.computeValue(Val.java:705) 
org.reactfx.value.ValBase.getValue(ValBase.java:17) 
org.reactfx.value.MappedVal.computeValue(MappedVal.java:22) 
org.reactfx.value.ValBase.getValue(ValBase.java:17) 
org.reactfx.value.SuspendableValWrapper.getValue(SuspendableValWrapper.java:23) 
org.reactfx.value.ChangeListenerWrapper.accept(Val.java:784) 
org.reactfx.util.AbstractReducingStreamNotifications.lambda$head$0(NotificationAccumulator.java:248) 
org.reactfx.ObservableBase.notifyObservers(ObservableBase.java:68) 
org.reactfx.SuspendableBase.resume(SuspendableBase.java:64) 
org.reactfx.CloseableOnceGuard.close(Guard.java:49) 
org.reactfx.MultiGuard.close(Guard.java:83) 
org.reactfx.Suspendable$1.resumeSource(Suspendable.java:118) 
org.reactfx.Suspendable$1.suspendSource(Suspendable.java:104) 
org.reactfx.util.NonAccumulativeStreamNotifications.lambda$head$0(NotificationAccumulator.java:134) 
org.reactfx.ObservableBase.notifyObservers(ObservableBase.java:68) 
org.reactfx.ObservableBase.notifyObservers(ObservableBase.java:57) 
org.reactfx.ProperEventStream.emit(ProperEventStream.java:18) 
org.reactfx.EventStreams$3.lambda$observeInputs$0(EventStreams.java:105) 
org.reactfx.value.ChangeListenerWrapper.accept(Val.java:786) 
org.reactfx.util.AbstractReducingStreamNotifications.lambda$head$0(NotificationAccumulator.java:248) 
org.reactfx.ObservableBase.notifyObservers(ObservableBase.java:68) 
org.reactfx.ObservableBase.notifyObservers(ObservableBase.java:57) 
org.reactfx.value.ValBase.invalidate(ValBase.java:32) 
org.reactfx.SuspendableBoolean.release(SuspendableBoolean.java:24) 
org.reactfx.CloseableOnceGuard.close(Guard.java:49) 
org.reactfx.MultiGuard.close(Guard.java:83) 
org.reactfx.Suspendable$1.resumeSource(Suspendable.java:118) 
org.reactfx.Suspendable$1.suspendSource(Suspendable.java:104) 
org.reactfx.util.NonAccumulativeStreamNotifications.lambda$head$0(NotificationAccumulator.java:134) 
org.reactfx.ObservableBase.notifyObservers(ObservableBase.java:68) 
org.reactfx.ObservableBase.notifyObservers(ObservableBase.java:57) 
org.reactfx.ProperEventStream.emit(ProperEventStream.java:18) 
org.reactfx.EventStreams$3.lambda$observeInputs$0(EventStreams.java:105) 
org.reactfx.value.ChangeListenerWrapper.accept(Val.java:786) 
org.reactfx.util.AbstractReducingStreamNotifications.lambda$head$0(NotificationAccumulator.java:248) 
org.reactfx.ObservableBase.notifyObservers(ObservableBase.java:68) 
org.reactfx.ObservableBase.notifyObservers(ObservableBase.java:57) 
org.reactfx.value.ValBase.invalidate(ValBase.java:32) 
org.reactfx.SuspendableBoolean.release(SuspendableBoolean.java:24) 
org.reactfx.CloseableOnceGuard.close(Guard.java:49) 
org.reactfx.Suspendable.suspendWhile(Suspendable.java:49) 
org.fxmisc.richtext.CaretSelectionBindImpl.doUpdate(CaretSelectionBindImpl.java:467) 
org.fxmisc.richtext.CaretSelectionBindImpl.doSelect(CaretSelectionBindImpl.java:456) 
org.fxmisc.richtext.CaretSelectionBindImpl.selectRangeExpl(CaretSelectionBindImpl.java:360) 
org.fxmisc.richtext.CaretSelectionBindImpl.moveTo(CaretSelectionBindImpl.java:373) 
org.fxmisc.richtext.NavigationActions.moveTo(NavigationActions.java:69) 
org.fxmisc.richtext.GenericStyledArea.lambda$new$2(GenericStyledArea.java:491) 
org.fxmisc.richtext.GenericStyledAreaBehavior.dragTo(GenericStyledAreaBehavior.java:553) 
org.fxmisc.richtext.GenericStyledAreaBehavior.processPrimaryOnlyMouseDragged(GenericStyledAreaBehavior.java:528) 
org.fxmisc.wellbehaved.event.template.PatternActionTemplate.lambda$null$1(InputMapTemplate.java:425) 
java.base/java.util.Optional.map(Optional.java:265) 
org.fxmisc.wellbehaved.event.template.PatternActionTemplate.lambda$getInputHandlerTemplateMap$2(InputMapTemplate.java:425) 
org.fxmisc.wellbehaved.event.template.InputHandlerTemplateMap.lambda$sequence$0(InputHandlerTemplateMap.java:24) 
org.fxmisc.wellbehaved.event.template.InputMapTemplate$HandlerTemplateConsumer$1.lambda$accept$0(InputMapTemplate.java:103) 
org.fxmisc.wellbehaved.event.InputHandler.handle(InputHandler.java:50) javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) 
javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) 
javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 
javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) 
javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) 
javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) 
javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) 
javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) 
javafx.base/javafx.event.Event.fireEvent(Event.java:198) 
javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3862) 
javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1849) 
javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2590) 
javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:409) 
javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:299) 
java.base/java.security.AccessController.doPrivileged(AccessController.java:389) 
javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:447) 
javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:411) 
javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:446) 
javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556) 
javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942) 
javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174) 
java.base/java.lang.Thread.run(Thread.java:835)

The important things here are that the selectedTextProperty has a listener, there is padding around the paragraph-text and you try and select outside of the available text.

@Jugen
Copy link
Collaborator

Jugen commented Dec 21, 2020

Hi Gary, thanks for the bug report, minimal example, and stacktrace.

I get a similar error by just clicking inside the padded area of the last line.
It seems the exception only arises with the last line and only if there's a bottom padding greater than zero.

Currently I think that the issue arises in Flowless, specifically I believe hit.isAfterCells() should be returning true but isn't.
This is called from GenericStyledArea.hit( x, y ):

VirtualFlowHit<Cell<Paragraph<PS,SEG,S>, ParagraphBox<PS,SEG,S>>> hit = virtualFlow.hit(adjustedX, adjustedY);
if(hit.isBeforeCells()) {
    return CharacterHit.insertionAt(0);
} else if(hit.isAfterCells()) {              //  is FALSE but should be TRUE ?

Strangely this exception doesn't happen with JDK 1.8, only 1.9 and up ?
I'll probably have to debug step through each and see where they differ .... so maybe the problem is elsewhere ?

@garybentley
Copy link
Author

Yes I found it was only the last line and if it had padding.

It might be the JDK version or more likely it could be the JavaFX version. I'm using JavaFX version 12 on JDK 12 at the moment because the text rendering is a little wonky on JavaFX 12+ versions, so it could be that. Doesn't the hit call eventually call TextFlow.hitTest? Maybe the issue lies there.

I was thinking about trying to get rid of the padding to prevent the issue happening but I'm having trouble styling the ParagraphBox instance, it's not taking notice of any padding I set in the stylesheet. I haven't exactly nailed down whether I'm at fault there though so I haven't reported it.

@Jugen
Copy link
Collaborator

Jugen commented Dec 21, 2020

Okay so after going down the rabbit hole I've found the problem and submitted a PR.

You were close with the TextFlow.hitTest suggestion, it turned out to be TextFlowExt.hit( x, y )

Which was the reason it only happens in JDK 9+ because this is the Java 9+ version that had some missing code from the original JDK 8 code.

@garybentley
Copy link
Author

Thanks, that PR seems to fix the issue.

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

Successfully merging a pull request may close this issue.

2 participants