Quellcode durchsuchen

scroll finally works fine #6

xuty vor 4 Jahren
Ursprung
Commit
755d5bea62
1 geänderte Dateien mit 57 neuen und 50 gelöschten Zeilen
  1. 57 50
      lib/frontend/terminal_view.dart

+ 57 - 50
lib/frontend/terminal_view.dart

@@ -48,6 +48,7 @@ class TerminalView extends StatefulWidget {
 
   final InputBehavior inputBehavior;
 
+  // get the dimensions of a rendered character
   CellSize measureCellSize() {
     final testString = 'xxxxxxxxxx' * 1000;
 
@@ -87,6 +88,7 @@ class TerminalView extends StatefulWidget {
 }
 
 class _TerminalViewState extends State<TerminalView> {
+  /// blinking cursor and blinking character
   final oscillator = Oscillator.ms(600);
 
   bool get focused {
@@ -95,42 +97,41 @@ class _TerminalViewState extends State<TerminalView> {
 
   int? _lastTerminalWidth;
   int? _lastTerminalHeight;
-  late CellSize _cellSize;
-  late ViewportOffset _offset;
 
-  var _minScrollExtent = 0.0;
-  var _maxScrollExtent = 0.0;
+  late CellSize _cellSize;
 
   void onTerminalChange() {
-    // if (_offset != null) {
-    //   final currentScrollExtent =
-    //       _cellSize.cellHeight * widget.terminal.buffer.scrollOffsetFromTop;
+    final currentScrollExtent =
+        _cellSize.cellHeight * widget.terminal.buffer.scrollOffsetFromTop;
 
-    //   if (_offset.pixels != currentScrollExtent) {
-    //     _offset.correctBy(currentScrollExtent - _offset.pixels - 1);
-    //   }
-    // }
+    widget.scrollController.jumpTo(currentScrollExtent);
 
     if (mounted) {
       setState(() {});
     }
   }
 
-  void onTick() {
-    widget.terminal.refresh();
-  }
+  // listen to oscillator to update mouse blink etc.
+  // void onTick() {
+  //   widget.terminal.refresh();
+  // }
 
   @override
   void initState() {
     // oscillator.start();
     // oscillator.addListener(onTick);
+
+    // measureCellSize is expensive so we cache the result.
     _cellSize = widget.measureCellSize();
+
     widget.terminal.addListener(onTerminalChange);
+
     super.initState();
   }
 
   @override
   void didUpdateWidget(TerminalView oldWidget) {
+    oldWidget.terminal.removeListener(onTerminalChange);
     widget.terminal.addListener(onTerminalChange);
     super.didUpdateWidget(oldWidget);
   }
@@ -141,7 +142,6 @@ class _TerminalViewState extends State<TerminalView> {
     // oscillator.removeListener(onTick);
 
     widget.terminal.removeListener(onTerminalChange);
-
     super.dispose();
   }
 
@@ -160,29 +160,32 @@ class _TerminalViewState extends State<TerminalView> {
         cursor: SystemMouseCursors.text,
         child: LayoutBuilder(builder: (context, constraints) {
           onResize(constraints.maxWidth, constraints.maxHeight);
-          return Scrollable(
-            viewportBuilder: (context, offset) {
-              offset.applyViewportDimension(constraints.maxHeight);
-
-              _minScrollExtent = 0.0;
-
-              _maxScrollExtent = math.max(
-                  0.0,
-                  _cellSize.cellHeight * widget.terminal.buffer.height -
-                      constraints.maxHeight);
-
-              // final currentScrollExtent = _cellSize.cellHeight *
-              //     widget.terminal.buffer.scrollOffsetFromTop;
+          // use flutter's Scrollable to manage scrolling to better integrate
+          // with widgets such as Scrollbar.
+          return NotificationListener<UserScrollNotification>(
+            onNotification: (_) {
+              onScroll(_.metrics.pixels);
+              return false;
+            },
+            child: Scrollable(
+              controller: widget.scrollController,
+              viewportBuilder: (context, offset) {
+                // set viewport height.
+                offset.applyViewportDimension(constraints.maxHeight);
 
-              // offset.correctBy(currentScrollExtent - offset.pixels - 1);
+                final minScrollExtent = 0.0;
 
-              offset.applyContentDimensions(_minScrollExtent, _maxScrollExtent);
+                final maxScrollExtent = math.max(
+                    0.0,
+                    _cellSize.cellHeight * widget.terminal.buffer.height -
+                        constraints.maxHeight);
 
-              _offset = offset;
-              _offset.addListener(onScroll);
+                // set how much the terminal can scroll
+                offset.applyContentDimensions(minScrollExtent, maxScrollExtent);
 
-              return buildTerminal(context);
-            },
+                return buildTerminal(context);
+              },
+            ),
           );
         }),
       ),
@@ -272,7 +275,7 @@ class _TerminalViewState extends State<TerminalView> {
 
   void onKeyStroke(RawKeyEvent event) {
     widget.inputBehavior.onKeyStroke(event, widget.terminal);
-    _offset.moveTo(_maxScrollExtent);
+    widget.terminal.buffer.setScrollOffsetFromBottom(0);
   }
 
   void onFocus(bool focused) {
@@ -285,10 +288,14 @@ class _TerminalViewState extends State<TerminalView> {
     widget.inputBehavior.onAction(action, widget.terminal);
   }
 
-  void onScroll() {
-    final charOffset = (_offset.pixels / _cellSize.cellHeight).ceil();
-    final offset = widget.terminal.invisibleHeight - charOffset;
-    widget.terminal.buffer.setScrollOffsetFromBottom(offset);
+  // synchronize flutter scroll offset to terminal
+  void onScroll(double offset) {
+    final topOffset = (offset / _cellSize.cellHeight).ceil();
+    final bottomOffset = widget.terminal.invisibleHeight - topOffset;
+
+    setState(() {
+      widget.terminal.buffer.setScrollOffsetFromBottom(bottomOffset);
+    });
   }
 }
 
@@ -309,21 +316,21 @@ class TerminalPainter extends CustomPainter {
 
   @override
   void paint(Canvas canvas, Size size) {
-    paintBackground(canvas);
+    _paintBackground(canvas);
 
     // if (oscillator.value) {
     // }
 
     if (terminal.showCursor) {
-      paintCursor(canvas);
+      _paintCursor(canvas);
     }
 
-    paintText(canvas);
+    _paintText(canvas);
 
-    paintSelection(canvas);
+    _paintSelection(canvas);
   }
 
-  void paintBackground(Canvas canvas) {
+  void _paintBackground(Canvas canvas) {
     final lines = terminal.getVisibleLines();
 
     for (var i = 0; i < lines.length; i++) {
@@ -358,7 +365,7 @@ class TerminalPainter extends CustomPainter {
     }
   }
 
-  void paintSelection(Canvas canvas) {
+  void _paintSelection(Canvas canvas) {
     for (var y = 0; y < terminal.viewHeight; y++) {
       final offsetY = y * charSize.cellHeight;
       final absoluteY = terminal.buffer.convertViewLineToRawLine(y) -
@@ -392,7 +399,7 @@ class TerminalPainter extends CustomPainter {
     }
   }
 
-  void paintText(Canvas canvas) {
+  void _paintText(Canvas canvas) {
     final lines = terminal.getVisibleLines();
 
     for (var i = 0; i < lines.length; i++) {
@@ -408,12 +415,12 @@ class TerminalPainter extends CustomPainter {
         }
 
         final offsetX = i * charSize.cellWidth;
-        paintCell(canvas, cell, offsetX, offsetY);
+        _paintCell(canvas, cell, offsetX, offsetY);
       }
     }
   }
 
-  void paintCell(Canvas canvas, Cell cell, double offsetX, double offsetY) {
+  void _paintCell(Canvas canvas, Cell cell, double offsetX, double offsetY) {
     final attr = cell.attr!;
 
     if (cell.codePoint == null || attr.invisible) {
@@ -462,7 +469,7 @@ class TerminalPainter extends CustomPainter {
     tp.paint(canvas, Offset(offsetX, offsetY));
   }
 
-  void paintCursor(Canvas canvas) {
+  void _paintCursor(Canvas canvas) {
     final screenCursorY = terminal.cursorY + terminal.scrollOffset;
     if (screenCursorY < 0 || screenCursorY >= terminal.viewHeight) {
       return;
@@ -484,7 +491,7 @@ class TerminalPainter extends CustomPainter {
 
   @override
   bool shouldRepaint(CustomPainter oldDelegate) {
-    // print('shouldRepaint');
+    /// paint only when the terminal has changed since last paint.
     return terminal.dirty;
   }
 }