Skip to content

Commit c2361ff

Browse files
committed
Issue594: fixed review issues, added separate sub classes for various path types
1 parent b525dae commit c2361ff

8 files changed

Lines changed: 160 additions & 77 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package org.fxmisc.richtext;
2+
3+
import static org.junit.Assert.assertNotNull;
4+
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
8+
import org.fxmisc.flowless.Cell;
9+
import org.fxmisc.flowless.VirtualFlow;
10+
import org.fxmisc.richtext.UnderlinePath;
11+
12+
import javafx.scene.Node;
13+
import javafx.scene.layout.Region;
14+
import javafx.scene.shape.Path;
15+
import javafx.scene.text.Text;
16+
import javafx.scene.text.TextFlow;
17+
18+
/**
19+
* Contains inspection methods to analyze the scene graph which has been rendered by RichTextFX.
20+
* TestFX tests should subclass this if it needs to run tests on a simple area and needs to inspect
21+
* whether the scene graph has been properly created.
22+
*/
23+
public abstract class SceneGraphTests extends InlineCssTextAreaAppTest {
24+
25+
/**
26+
* @param index The index of the desired paragraph box
27+
* @return The paragraph box for the paragraph at the specified index
28+
*/
29+
protected Region getParagraphBox(int index) {
30+
@SuppressWarnings("unchecked")
31+
VirtualFlow<String, Cell<String, Node>> flow = (VirtualFlow<String, Cell<String, Node>>) area.getChildrenUnmodifiable().get(index);
32+
Cell<String, Node> gsa = flow.getCell(0);
33+
34+
// get the ParagraphBox (protected subclass of Region)
35+
return (Region) gsa.getNode();
36+
}
37+
38+
39+
/**
40+
* @param index The index of the desired paragraph box
41+
* @return The ParagraphText (protected subclass of TextFlow) for the paragraph at the specified index
42+
*/
43+
protected TextFlow getParagraphText(int index) {
44+
// get the ParagraphBox (protected subclass of Region)
45+
Region paragraphBox = getParagraphBox(index);
46+
47+
// get the ParagraphText (protected subclass of TextFlow)
48+
TextFlow tf = (TextFlow) paragraphBox.getChildrenUnmodifiable().stream().filter(n -> n instanceof TextFlow)
49+
.findFirst().orElse(null);
50+
assertNotNull("No TextFlow node found in rich text area", tf);
51+
52+
return tf;
53+
}
54+
55+
56+
/**
57+
* @param index The index of the desired paragraph box
58+
* @return A list of text nodes which render the text in the ParagraphBox
59+
* specified by the given index.
60+
*/
61+
protected List<Text> getTextNodes(int index) {
62+
TextFlow tf = getParagraphText(index);
63+
64+
List<Text> result = new ArrayList<>();
65+
tf.getChildrenUnmodifiable().filtered(n -> n instanceof Text).forEach(n -> result.add((Text) n));
66+
return result;
67+
}
68+
69+
70+
/**
71+
* @param index The index of the desired paragraph box
72+
* @return A list of nodes which render the underlines for the text in the ParagraphBox
73+
* specified by the given index.
74+
*/
75+
protected List<Path> getUnderlinePaths(int index) {
76+
TextFlow tf = getParagraphText(index);
77+
78+
List<Path> result = new ArrayList<>();
79+
tf.getChildrenUnmodifiable().filtered(n -> n instanceof UnderlinePath).forEach(n -> result.add((Path) n));
80+
return result;
81+
}
82+
}
Lines changed: 7 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,17 @@
11
package org.fxmisc.richtext.style;
22

33
import static org.junit.Assert.assertEquals;
4-
import static org.junit.Assert.assertNotNull;
54

6-
import java.util.ArrayList;
75
import java.util.List;
86

9-
import org.fxmisc.flowless.Cell;
10-
import org.fxmisc.flowless.VirtualFlow;
11-
import org.fxmisc.richtext.InlineCssTextAreaAppTest;
7+
import org.fxmisc.richtext.SceneGraphTests;
128
import org.junit.Test;
139

14-
import javafx.scene.Node;
15-
import javafx.scene.layout.Region;
1610
import javafx.scene.shape.Path;
1711
import javafx.scene.text.Text;
18-
import javafx.scene.text.TextFlow;
1912

2013

21-
abstract class RenderingTests extends InlineCssTextAreaAppTest {
22-
23-
/**
24-
*
25-
* @param index The index of the desired paragraph box
26-
* @return The paragraph box for the paragraph at the specified index
27-
*/
28-
protected Region getParagraphBox(int index) {
29-
@SuppressWarnings("unchecked")
30-
VirtualFlow<String, Cell<String, Node>> flow = (VirtualFlow<String, Cell<String, Node>>) area.getChildrenUnmodifiable().get(index);
31-
Cell<String, Node> gsa = flow.getCell(0);
32-
33-
// get the ParagraphBox (protected subclass of Region)
34-
return (Region) gsa.getNode();
35-
}
36-
37-
38-
/**
39-
* @return A list of text nodes which render the current text.
40-
*/
41-
protected List<Text> getTextNodes() {
42-
// get the ParagraphBox (protected subclass of Region)
43-
Region paragraphBox = getParagraphBox(0);
44-
45-
// get the ParagraphText (protected subclass of TextFlow)
46-
TextFlow tf = (TextFlow) paragraphBox.getChildrenUnmodifiable().stream().filter(n -> n instanceof TextFlow)
47-
.findFirst().orElse(null);
48-
assertNotNull("No TextFlow node found in rich text area", tf);
49-
50-
List<Text> result = new ArrayList<>();
51-
tf.getChildrenUnmodifiable().filtered(n -> n instanceof Text).forEach(n -> result.add((Text) n));
52-
return result;
53-
}
54-
55-
/**
56-
* @return A list of nodes which render the underlines for the current text.
57-
*/
58-
protected List<Path> getUnderlinePaths() {
59-
// get the ParagraphBox (protected subclass of Region)
60-
Region paragraphBox = getParagraphBox(0);
61-
62-
// get the ParagraphText (protected subclass of TextFlow)
63-
TextFlow tf = (TextFlow) paragraphBox.getChildrenUnmodifiable().get(0);
64-
65-
List<Path> result = new ArrayList<>();
66-
tf.getChildrenUnmodifiable().filtered(n -> n instanceof Path).forEach(n -> result.add((Path) n));
67-
68-
result.forEach(n -> System.err.println(n.getClass()));
69-
70-
return result.subList(2, result.size());
71-
}
72-
}
73-
74-
75-
public class StylingTests extends RenderingTests {
14+
public class StylingTests extends SceneGraphTests {
7615

7716
private final static String HELLO = "Hello ";
7817
private final static String WORLD = "World";
@@ -88,15 +27,15 @@ public void simpleStyling() {
8827
});
8928

9029
// expected: one text node which contains the complete text
91-
List<Text> textNodes = getTextNodes();
30+
List<Text> textNodes = getTextNodes(0);
9231
assertEquals(1, textNodes.size());
9332

9433
interact(() -> {
9534
area.setStyle(HELLO.length(), HELLO.length() + WORLD.length(), "-fx-font-weight: bold;");
9635
});
9736

9837
// expected: three text nodes
99-
textNodes = getTextNodes();
38+
textNodes = getTextNodes(0);
10039
assertEquals(3, textNodes.size());
10140

10241
Text first = textNodes.get(0);
@@ -124,7 +63,7 @@ public void underlineStyling() {
12463
});
12564

12665
// expected: one text node which contains the complete text
127-
List<Text> textNodes = getTextNodes();
66+
List<Text> textNodes = getTextNodes(0);
12867
assertEquals(1, textNodes.size());
12968
assertEquals(HELLO + WORLD + AND_ALSO_THE + SUN + AND_MOON,
13069
textNodes.get(0).getText());
@@ -140,7 +79,7 @@ public void underlineStyling() {
14079
});
14180

14281
// expected: five text nodes
143-
textNodes = getTextNodes();
82+
textNodes = getTextNodes(0);
14483
assertEquals(5, textNodes.size());
14584

14685
Text first = textNodes.get(0);
@@ -155,7 +94,7 @@ public void underlineStyling() {
15594
assertEquals(AND_MOON, fifth.getText());
15695

15796
// determine the underline paths - need to be two of them!
158-
List<Path> underlineNodes = getUnderlinePaths();
97+
List<Path> underlineNodes = getUnderlinePaths(0);
15998
assertEquals(2, underlineNodes.size());
16099
}
161100
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.fxmisc.richtext;
2+
3+
import javafx.scene.shape.Path;
4+
5+
/**
6+
* A path which describes a background shape in the Scene graph.
7+
*
8+
*/
9+
public class BackgroundPath extends Path {
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.fxmisc.richtext;
2+
3+
import javafx.scene.shape.Path;
4+
5+
/**
6+
* A path which describes a border in the Scene graph.
7+
*
8+
*/
9+
public class BorderPath extends Path {
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.fxmisc.richtext;
2+
3+
import javafx.scene.shape.Path;
4+
5+
/**
6+
* A path which describes a selection shape in the Scene graph.
7+
*
8+
*/
9+
public class CaretPath extends Path {
10+
}

richtextfx/src/main/java/org/fxmisc/richtext/ParagraphText.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ public ObjectProperty<Paint> highlightTextFillProperty() {
5656

5757
private final Paragraph<PS, SEG, S> paragraph;
5858

59-
private final Path caretShape = new Path();
60-
private final Path selectionShape = new Path();
59+
private final Path caretShape = new CaretPath();
60+
private final Path selectionShape = new SelectionPath();
6161

6262
private final CustomCssShapeHelper<Paint> backgroundShapeHelper;
6363
private final CustomCssShapeHelper<BorderAttributes> borderShapeHelper;
@@ -71,9 +71,6 @@ public ObjectProperty<Paint> highlightTextFillProperty() {
7171
caretShape.visibleProperty().bind(caretVisible);
7272
}
7373

74-
private final class UnderlinePath extends Path{
75-
}
76-
7774
ParagraphText(Paragraph<PS, SEG, S> par, Function<StyledSegment<SEG, S>, Node> nodeFactory) {
7875
this.paragraph = par;
7976

@@ -118,18 +115,33 @@ private final class UnderlinePath extends Path{
118115
par.getStyledSegments().stream().map(nodeFactory).forEach(getChildren()::add);
119116

120117
// set up custom css shape helpers
121-
Supplier<Path> createShape = () -> {
118+
Supplier<Path> createBackgroundShape = () -> {
119+
Path shape = new BackgroundPath();
120+
shape.setManaged(false);
121+
shape.layoutXProperty().bind(leftInset);
122+
shape.layoutYProperty().bind(topInset);
123+
return shape;
124+
};
125+
Supplier<Path> createBorderShape = () -> {
126+
Path shape = new BorderPath();
127+
shape.setManaged(false);
128+
shape.layoutXProperty().bind(leftInset);
129+
shape.layoutYProperty().bind(topInset);
130+
return shape;
131+
};
132+
Supplier<Path> createUnderlineShape = () -> {
122133
Path shape = new UnderlinePath();
123134
shape.setManaged(false);
124135
shape.layoutXProperty().bind(leftInset);
125136
shape.layoutYProperty().bind(topInset);
126137
return shape;
127138
};
139+
128140
Consumer<Collection<Path>> clearUnusedShapes = paths -> getChildren().removeAll(paths);
129141
Consumer<Path> addToBackground = path -> getChildren().add(0, path);
130142
Consumer<Path> addToForeground = path -> getChildren().add(path);
131143
backgroundShapeHelper = new CustomCssShapeHelper<>(
132-
createShape,
144+
createBackgroundShape,
133145
(backgroundShape, tuple) -> {
134146
backgroundShape.setStrokeWidth(0);
135147
backgroundShape.setFill(tuple._1);
@@ -139,7 +151,7 @@ private final class UnderlinePath extends Path{
139151
clearUnusedShapes
140152
);
141153
borderShapeHelper = new CustomCssShapeHelper<>(
142-
createShape,
154+
createBorderShape,
143155
(borderShape, tuple) -> {
144156
BorderAttributes attributes = tuple._1;
145157
borderShape.setStrokeWidth(attributes.width);
@@ -156,7 +168,7 @@ private final class UnderlinePath extends Path{
156168
clearUnusedShapes
157169
);
158170
underlineShapeHelper = new CustomCssShapeHelper<>(
159-
createShape,
171+
createUnderlineShape,
160172
(underlineShape, tuple) -> {
161173
UnderlineAttributes attributes = tuple._1;
162174
underlineShape.setStroke(attributes.color);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.fxmisc.richtext;
2+
3+
import javafx.scene.shape.Path;
4+
5+
/**
6+
* A path which describes a selection shape in the Scene graph.
7+
*
8+
*/
9+
public class SelectionPath extends Path {
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.fxmisc.richtext;
2+
3+
import javafx.scene.shape.Path;
4+
5+
/**
6+
* A path which describes an underline in the Scene graph.
7+
*
8+
*/
9+
public class UnderlinePath extends Path {
10+
}

0 commit comments

Comments
 (0)