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

Account for insets in layoutChildren() #510

Merged
merged 7 commits into from
Jun 6, 2017
Merged

Account for insets in layoutChildren() #510

merged 7 commits into from
Jun 6, 2017

Conversation

JordanMartinez
Copy link
Contributor

Fixes #507

@JordanMartinez
Copy link
Contributor Author

JordanMartinez commented May 28, 2017

I want to address #508 in this PR as well since they are of similar nature.

Edit: Since that's a bit more complicated, I'm not going to address it here.

@JordanMartinez
Copy link
Contributor Author

I'll also need to fix the implementation of firstLineOfArea() to use getCharacterBoundsOnScreen of the first letter.

@JordanMartinez
Copy link
Contributor Author

Adding these hit tests revealed a bug in the code. I believe the issue is caused by VirtualFlow#hit not accounting for the possibility of padding.

@JordanMartinez
Copy link
Contributor Author

Using this code:

import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
import org.fxmisc.wellbehaved.event.EventPattern;
import org.fxmisc.wellbehaved.event.InputHandler;
import org.fxmisc.wellbehaved.event.InputMap;
import org.fxmisc.wellbehaved.event.Nodes;

public class TestGUI extends Application {

    public Stage stage;
    public Scene scene;
    public InlineCssTextArea area;
    public ContextMenu menu;

    @Override
    public void start(Stage stage) throws Exception {
        area = new InlineCssTextArea();
        scene = new Scene(area);
        this.stage = stage;

        stage.setScene(scene);
        stage.setWidth(400);
        stage.setHeight(400);
        stage.show();

        area.requestFocus();

        String text = "abcdefghijklmnopqrstuvwxyz";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 19; i++) {
            sb.append("Paragraph #").append(i).append(": ").append(text).append("\n");
        }
        sb.append(text);
        
        String fullText = sb.toString();
        area.replaceText(fullText);
        
//        area.setPadding(new Insets(20));
        area.setStyle("-fx-font-family: monospace; -fx-font-size: 12pt;");

        Bounds local = area.getBoundsInLocal();
        Bounds screen = area.localToScreen(local);
        System.out.println("Area bounds = " + screen);
        
        int start = area.getAbsolutePosition(3, 8);
        area.selectRange(start, start + 1);
        Bounds b = area.getCharacterBoundsOnScreen(start, start + 1).get();
        System.out.println("Bounds: " + b);
        
        Nodes.addInputMap(area, InputMap.process(EventPattern.mousePressed(), (MouseEvent e) -> {
            System.out.println("Mouse pressed | x: " + e.getScreenX() + ", y: " + e.getScreenY());
            System.out.println("Mouse | x: " + e.getX() + ", y: " + e.getY());
            return InputHandler.Result.PROCEED;
        }));
    }

}

Here is the output for the non-padded area (I clicked manually)

Area bounds = BoundingBox [minX:760.0, minY:217.66667315363884, minZ:0.0, width:100.0, height:100.0, depth:0.0, maxX:860.0, maxY:317.66667315363884, maxZ:0.0]
Bounds: BoundingBox [minX:838.5625010728836, minY:277.16667303442955, minZ:0.0, width:10.63280999660492, height:21.000000834465027, depth:0.0, maxX:849.1953110694885, maxY:298.1666738688946, maxZ:0.0]
Mouse pressed | x: 859.0, y: 329.0
Mouse | x: 98.0, y: 88.0
GenericStyleArea#hit called with arguments:  x: 98.0, y: 88.0
VirtualFlow.getCellIndex = 4
VirtualFLowHit.getCell().getNode().getParagraph() = Par[; StyledText[text="Paragraph #4: abcdefghijklmnopqrstuvwxyz", style=]]
VirtualFlowHit.getCellOffset() = x: 98.0, y: 8.0
Cell.hit(cellOffset) = getInsertionIndex(): 10, getCharacterIndex(): OptionalInt[9]
CharacterHit.offset(parOffset [164]) = org.fxmisc.richtext.CharacterHit@180e75e8

Here is the output for the padded area (also clicked manually)

Area bounds = BoundingBox [minX:760.0, minY:217.66667315363884, minZ:0.0, width:100.0, height:100.0, depth:0.0, maxX:860.0, maxY:317.66667315363884, maxZ:0.0]
Bounds: BoundingBox [minX:838.5625010728836, minY:277.16667303442955, minZ:0.0, width:10.63280999660492, height:21.000000834465027, depth:0.0, maxX:849.1953110694885, maxY:298.1666738688946, maxZ:0.0]
Mouse pressed | x: 839.0, y: 310.0
Mouse | x: 78.0, y: 69.0
GenericStyleArea#hit called with arguments:  x: 78.0, y: 69.0
VirtualFlow.getCellIndex = 3
VirtualFLowHit.getCell().getNode().getParagraph() = Par[; StyledText[text="Paragraph #3: abcdefghijklmnopqrstuvwxyz", style=]]
VirtualFlowHit.getCellOffset() = x: 78.0, y: 9.0
Cell.hit(cellOffset) = getInsertionIndex(): 8, getCharacterIndex(): OptionalInt[7]
CharacterHit.offset(parOffset [123]) = org.fxmisc.richtext.CharacterHit@29ca9beb

@JordanMartinez
Copy link
Contributor Author

Aye, I can adjust cellOffset by subtracting the left insets so that the caret is immediately below the mouse, but the line index is still incorrect (^ = mouse; | = caret position after click).

abcd^efg
abcd|efg

That value, VirtualFlowHit#getCellIndex is calculated in VirtualFlow, not RTFX

@JordanMartinez
Copy link
Contributor Author

Looking into it more, one just needs to adjust the x/y values to account for the inset values before calling virtualFow.hit(x, y).

@JordanMartinez JordanMartinez merged commit 5fd39fe into FXMisc:master Jun 6, 2017
@JordanMartinez JordanMartinez deleted the fixPaddingIssues branch June 6, 2017 02:49
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 this pull request may close these issues.

1 participant