Skip to content

Commit 45589ef

Browse files
Merge pull request #587 from JordanMartinez/paragraphBounds
Add API to get paragraph bounds if visible
2 parents 78fcff1 + 793ddad commit 45589ef

1 file changed

Lines changed: 52 additions & 0 deletions

File tree

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,58 @@ private int getParagraphOffset(int parIdx) {
12661266
return position(parIdx, 0).toOffset();
12671267
}
12681268

1269+
/**
1270+
* Returns the bounds of the paragraph if it is visible or {@link Optional#empty()} if it's not.
1271+
*
1272+
* The returned bounds object will always be within the bounds of the area. In other words, it takes
1273+
* scrolling into account. Note: the bound's width will always equal the area's width, not necessarily
1274+
* the paragraph's real width (if it's short and doesn't take up all of the area's provided horizontal space
1275+
* or if it's long and spans outside of the area's width).
1276+
*
1277+
* @param visibleParagraphIndex the index in area's list of visible paragraphs.
1278+
*/
1279+
public Bounds getVisibleParagraphBoundsOnScreen(int visibleParagraphIndex) {
1280+
return getParagraphBoundsOnScreen(virtualFlow.visibleCells().get(visibleParagraphIndex));
1281+
}
1282+
1283+
/**
1284+
* Returns the bounds of the paragraph if it is visible or {@link Optional#empty()} if it's not.
1285+
*
1286+
* The returned bounds object will always be within the bounds of the area. In other words, it takes
1287+
* scrolling into account. Note: the bound's width will always equal the area's width, not necessarily
1288+
* the paragraph's real width (if it's short and doesn't take up all of the area's provided horizontal space
1289+
* or if it's long and spans outside of the area's width).
1290+
*
1291+
* @param paragraphIndex the index in area's list of paragraphs (visible and invisible).
1292+
*/
1293+
public Optional<Bounds> getParagraphBoundsOnScreen(int paragraphIndex) {
1294+
return virtualFlow.getCellIfVisible(paragraphIndex).map(this::getParagraphBoundsOnScreen);
1295+
}
1296+
1297+
private Bounds getParagraphBoundsOnScreen(Cell<Paragraph<PS, SEG, S>, ParagraphBox<PS, SEG, S>> cell) {
1298+
Bounds nodeLocal = cell.getNode().getBoundsInLocal();
1299+
Bounds nodeScreen = cell.getNode().localToScreen(nodeLocal);
1300+
Bounds areaLocal = getBoundsInLocal();
1301+
Bounds areaScreen = localToScreen(areaLocal);
1302+
1303+
// use area's minX if scrolled right and paragraph's left is not visible
1304+
double minX = nodeScreen.getMinX() < areaScreen.getMinX()
1305+
? areaScreen.getMinX()
1306+
: nodeScreen.getMinX();
1307+
// use area's minY if scrolled down vertically and paragraph's top is not visible
1308+
double minY = nodeScreen.getMinY() < areaScreen.getMinY()
1309+
? areaScreen.getMinY()
1310+
: nodeScreen.getMinY();
1311+
// use area's width whether paragraph spans outside of it or not
1312+
// so that short or long paragraph takes up the entire space
1313+
double width = areaScreen.getWidth();
1314+
// use area's maxY if scrolled up vertically and paragraph's bottom is not visible
1315+
double maxY = nodeScreen.getMaxY() < areaScreen.getMaxY()
1316+
? nodeScreen.getMaxY()
1317+
: areaScreen.getMaxY();
1318+
return new BoundingBox(minX, minY, width, maxY - minY);
1319+
}
1320+
12691321
private Optional<Bounds> getRangeBoundsOnScreen(int paragraphIndex, int from, int to) {
12701322
return virtualFlow.getCellIfVisible(paragraphIndex)
12711323
.map(c -> c.getNode().getRangeBoundsOnScreen(from, to));

0 commit comments

Comments
 (0)