From febb8eb49bf0047d00b7f5feb71bf678a52e9a46 Mon Sep 17 00:00:00 2001 From: VAUsoltsev Date: Thu, 20 Aug 2026 17:28:33 +0300 Subject: [PATCH] Implement moveCursorToPageUp/Down and bind PageUp/PageDown to them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both methods were empty stubs marked `// TODO`, and neither `PageUp` nor `PageDown` was bound to anything in the default activators — on any platform. Pressing either key did nothing at all. The page is measured from the viewport: as many lines as fit on screen, less one kept as an overlap so that the reader can connect what was on screen with what is there now. When nothing is laid out yet there is no page to measure, and the cursor moves by a single line instead of standing still. With word wrap on a wrapped line still counts as one, so the jump may be longer than a screen; moving by visual lines would need the target line to be laid out, which it is not once it leaves the viewport. --- lib/src/_code_line.dart | 30 ++++++++++++++++++++++++++++-- lib/src/code_shortcuts.dart | 12 ++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/lib/src/_code_line.dart b/lib/src/_code_line.dart index 1ad82d6..cba9c22 100644 --- a/lib/src/_code_line.dart +++ b/lib/src/_code_line.dart @@ -485,12 +485,38 @@ class _CodeLineEditingControllerImpl extends ValueNotifier @override void moveCursorToPageUp() { - // TODO + _moveCursorByPage(false); } @override void moveCursorToPageDown() { - // TODO + _moveCursorByPage(true); + } + + /// Moves the cursor a screen up or down. + /// + /// The page is measured from the viewport: as many lines as fit on screen, + /// less one kept as an overlap so that the reader can connect what was on + /// screen with what is there now. With word wrap on, a wrapped line still + /// counts as one, so the jump may be longer than a screen. + void _moveCursorByPage(bool forward) { + final _CodeFieldRender? render = _render; + if (render == null || !render.hasSize || render.lineHeight <= 0) { + // Nothing is laid out yet, so there is no page to measure. Moving by a + // single line is still better than standing still. + moveCursor(forward ? AxisDirection.down : AxisDirection.up); + return; + } + + final int page = max(1, (render.size.height / render.lineHeight).floor() - 1); + final CodeLinePosition current = selection.extent; + final int index = min(max(0, current.index + (forward ? page : -page)), codeLines.length - 1); + + selection = CodeLineSelection.collapsed( + index: index, + offset: min(codeLines[index].length, current.offset) + ); + makeCursorVisible(); } @override diff --git a/lib/src/code_shortcuts.dart b/lib/src/code_shortcuts.dart index 08315b2..6de04fb 100644 --- a/lib/src/code_shortcuts.dart +++ b/lib/src/code_shortcuts.dart @@ -345,6 +345,12 @@ const Map> _kDefaultMacCodeShortcutsAc SingleActivator(LogicalKeyboardKey.arrowDown, meta: true), SingleActivator(LogicalKeyboardKey.end, control: true) ], + CodeShortcutType.cursorMovePageUp: [ + SingleActivator(LogicalKeyboardKey.pageUp) + ], + CodeShortcutType.cursorMovePageDown: [ + SingleActivator(LogicalKeyboardKey.pageDown) + ], CodeShortcutType.cursorMoveWordBoundaryBackward: [ SingleActivator(LogicalKeyboardKey.arrowLeft, alt: true) ], @@ -535,6 +541,12 @@ const Map> _kDefaultCommonCodeShortcut // NumLockedSingleActivator(LogicalKeyboardKey.numpad1, shift: true, control: true), // NumUnlockedSingleActivator(LogicalKeyboardKey.numpad1, control: true), ], + CodeShortcutType.cursorMovePageUp: [ + SingleActivator(LogicalKeyboardKey.pageUp), + ], + CodeShortcutType.cursorMovePageDown: [ + SingleActivator(LogicalKeyboardKey.pageDown), + ], CodeShortcutType.cursorMoveWordBoundaryBackward: [ SingleActivator(LogicalKeyboardKey.arrowLeft, control: true), // NumLockedSingleActivator(LogicalKeyboardKey.numpad4, shift: true, control: true),