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

Button -- Or Obvious Clickable Link (Inside Text Area) #124

Closed
abigdreamer opened this issue Mar 6, 2015 · 7 comments
Closed

Button -- Or Obvious Clickable Link (Inside Text Area) #124

abigdreamer opened this issue Mar 6, 2015 · 7 comments
Labels

Comments

@abigdreamer
Copy link

Can we have a Wrapping Button or clickable Link inside a text area? -- Something like a button that is obvious to click on -- that would show a (VIDEO) or (PICTURE) but have formatted text.

Thanks

@ghost
Copy link

ghost commented Mar 6, 2015

I think this is similar to my request in #87 for adding support to insert arbitrary nodes.

@TomasMikula
Copy link
Member

Adding a button would indeed require #87. Clickable text does not, and you can do that with RichTextFX. You will not be able to use any of the specialized subclasses like CodeArea, InlineCssTextArea, InlineStyleTextArea or StyleClassedTextArea, because in those, "style" equals either inline CSS or CSS style class. But in StyledTextArea, style is literally anything, so it can be your custom object containing a URL to go to. You just need to provide a function how to apply your custom style to a Text node. (Those other classes just set "custom style" = "CSS string" and "apply function" = "Node.setStyle", or similar, for convenience.)

Here is a demo

package org.fxmisc.richtext.demo;

import javafx.application.Application;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.IndexRange;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;

import org.fxmisc.richtext.StyledTextArea;

public class InlineLink extends Application {

    static class MyStyleDef {
        static final MyStyleDef NO_LINK = new MyStyleDef();

        private final String url;

        private MyStyleDef() {
            this(null);
        }

        MyStyleDef(String url) {
            this.url = url;
        }

        void applyToText(Text text) {
            if(url != null) {
                text.setCursor(Cursor.HAND);
                text.setFill(Color.BLUE);
                text.setUnderline(true);
                text.setOnMouseClicked(click -> {
                    System.out.println("Go to " + url);
                });
            }
        }
    }

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        StyledTextArea<MyStyleDef> area = new StyledTextArea<MyStyleDef>(
                MyStyleDef.NO_LINK,
                (text, style) -> style.applyToText(text));

        Button addLink = new Button("Add link");
        addLink.setOnAction(ae -> {
            IndexRange range = area.getSelection();
            area.setStyle(
                    range.getStart(), range.getEnd(),
                    new MyStyleDef("https://github.com/TomasMikula/RichTextFX"));
        });

        VBox.setVgrow(area, Priority.ALWAYS);
        area.setWrapText(true);
        VBox vbox = new VBox(addLink, area);

        Scene scene = new Scene(vbox, 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

and the result:

richtextfx clickable link

@chrisf-london
Copy link
Contributor

chrisf-london commented Jul 19, 2021

Hi Tomas - I've recently started learning RichTextFX and I have been experimenting with this demo. I have noticed that single-clicking on the hyperlink does not consistently trigger the "Go to..." callback. About one in ten times, the click is ignored. I first observed this in my own app, but I can duplicate the issue with your demo code.

I'm almost certain it's connected with the behaviour of the flashing caret. If you happen to click the link at the exact location of the caret while the caret is visible, it seems that the MOUSE_CLICKED event is delivered to the ParagraphText node rather than the TextExt node (and TextExt doesn't get a chance to see it). The reason seems to be connected with the way that Java FX locates the target for the mouse event (see Scene:3551 ish) - I am fairly sure that the flashing of the caret is confusing this algorithm.

I've been trying to find a workaround but all my ideas have failed. I wondered if you had any insights please ? Btw thank you for creating such a powerful framework, it has saved me a huge amount of time and frustration !

@chrisf-london
Copy link
Contributor

chrisf-london commented Jul 19, 2021

btw, with reference to my earlier comment, here's a shot from the debugger during one of these "failed" clicks. Notice that the "pressedTargets" and "releasedTargets" are not identical, which means that FX selects the ParagraphText node as the one that receives the mouse event, rather than the TextExt. Like I say, I think this must be related to the flashing of the caret but I have no idea how to work around the problem. thanks again,

Image9

@chrisf-london
Copy link
Contributor

Ah I think I found a solution ! I went down the rabbit hole of trying to write my own "mouse pick" routine that would ignore certain types of node, but then I realised that every node has a "MouseTransparent" property. If I modify the source of CaretNode to set this to true, my problem goes away. Hooray !

Can anyone thing of a reason why you would ever want the caret to not be transparent ? I can't think of a valid case.

@Jugen
Copy link
Collaborator

Jugen commented Jul 20, 2021

Hi @chrisf-london thanks for chasing this down. Could you submit a PR please and I'll be happy to merge it.

chrisf-london added a commit to chrisf-london/RichTextFX that referenced this issue Jul 20, 2021
If you install a mouse handler on a TextExt area using setOnMouseClicked(), there's a small chance that your mouse click will be ignored (this happens approximately one time in ten in my experience).  The problem occurs when you click at the exact same position as the flashing caret while the caret is visible; this confuses the java FX mouse-picking algorithm, which causes the MouseEvent to be sent to the ParagraphText node rather than the TextExt. The fix is simply to make the caret transparent to mouse picking.

See this link for more evidence + screenshots : FXMisc#124
@chrisf-london
Copy link
Contributor

Hi Jugen - thanks, just did it. I hope the format is ok (my first time PR'ing to this repo)

Jugen pushed a commit that referenced this issue Jul 20, 2021
If you install a mouse handler on a TextExt area using setOnMouseClicked(), there's a small chance that your mouse click will be ignored (this happens approximately one time in ten in my experience).  The problem occurs when you click at the exact same position as the flashing caret while the caret is visible; this confuses the java FX mouse-picking algorithm, which causes the MouseEvent to be sent to the ParagraphText node rather than the TextExt. The fix is simply to make the caret transparent to mouse picking.

See this link for more evidence + screenshots : #124
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants