@@ -1379,6 +1379,34 @@ else if ( lineHighlighter != null ) {
13791379 }
13801380 }
13811381
1382+ /**
1383+ * Scrolls the text one line UP while maintaining the caret's
1384+ * position on screen, so that it is now on the NEXT line.
1385+ * <i>Note: If the caret isn't visible then this is a noop.</i>
1386+ */
1387+ public void nextLine (SelectionPolicy selectionPolicy ) {
1388+ scrollLine ( +1 , selectionPolicy );
1389+ }
1390+
1391+ /**
1392+ * Scrolls the text one line DOWN while maintaining the caret's
1393+ * position on screen, so that it is now on the PREVIOUS line.
1394+ * <i>Note: If the caret isn't visible then this is a noop.</i>
1395+ */
1396+ public void prevLine (SelectionPolicy selectionPolicy ) {
1397+ scrollLine ( -1 , selectionPolicy );
1398+ }
1399+
1400+ /**
1401+ * Scrolls the text (direction*caretHeight) while maintaining the caret's current
1402+ * position on screen. <i>Note: If the caret isn't visible then this is a noop.</i>
1403+ */
1404+ private void scrollLine (int direction , SelectionPolicy selectionPolicy ) {
1405+ getCaretBoundsOnScreen ( getCaretSelectionBind ().getUnderlyingCaret () )
1406+ .map ( caretBounds -> (caretBounds .getHeight ()-2 ) * direction )
1407+ .ifPresent ( deltaY -> scrollText (deltaY , selectionPolicy ) );
1408+ }
1409+
13821410 @ Override
13831411 public void prevPage (SelectionPolicy selectionPolicy ) {
13841412 // Paging up and we're in the first frame then move/select to start.
@@ -1402,12 +1430,20 @@ public void nextPage(SelectionPolicy selectionPolicy) {
14021430 * <br>Negative numbers for paging up and positive for down.
14031431 */
14041432 private void page (int pgCount , SelectionPolicy selectionPolicy )
1433+ {
1434+ scrollText ( pgCount * getViewportHeight (), selectionPolicy );
1435+ }
1436+
1437+ /**
1438+ * Scrolls the text by deltaY while maintaining the caret's current position on screen.
1439+ */
1440+ private void scrollText (double deltaY , SelectionPolicy selectionPolicy )
14051441 {
14061442 // Use underlying caret to get the same behaviour as navigating up/down a line where the x position is sticky
14071443 Optional <Bounds > cb = caretSelectionBind .getUnderlyingCaret ().getCaretBounds ();
14081444
14091445 paging = true ; // Prevent scroll from reverting back to the current caret position
1410- scrollYBy ( pgCount * getViewportHeight ( ) );
1446+ suspendVisibleParsWhile ( () -> virtualFlow . scrollYBy ( deltaY ) );
14111447
14121448 cb .map ( this ::screenToLocal ) // Place caret near the same on screen position as before
14131449 .map ( b -> hit ( b .getMinX (), b .getMinY ()+b .getHeight ()/2.0 ).getInsertionIndex () )
0 commit comments