allow zooming on desktop when holding ctrl and scrolling
add prototype of selection mode, span up dashed rectangle
This commit is contained in:
		@@ -2,6 +2,7 @@ import 'dart:ui';
 | 
			
		||||
 | 
			
		||||
import 'package:flutter/gestures.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:flutter/services.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
 | 
			
		||||
import '../context/file_change_notifier.dart';
 | 
			
		||||
@@ -151,8 +152,17 @@ class _DrawingPageState extends State<DrawingPage> {
 | 
			
		||||
        debugPrint('got pointer signal: $pointerSignal');
 | 
			
		||||
 | 
			
		||||
        if (pointerSignal is PointerScrollEvent) {
 | 
			
		||||
          final bool ctrlPressed = RawKeyboard.instance.keysPressed
 | 
			
		||||
              .contains(LogicalKeyboardKey.controlLeft);
 | 
			
		||||
 | 
			
		||||
          final delta = pointerSignal.scrollDelta;
 | 
			
		||||
          _calcNewPageOffset(-delta, size.width);
 | 
			
		||||
          if (ctrlPressed) {
 | 
			
		||||
            setState(() {
 | 
			
		||||
              zoom = (zoom - delta.dy.sign * .1).clamp(0.25, 5.0);
 | 
			
		||||
            });
 | 
			
		||||
          } else {
 | 
			
		||||
            _calcNewPageOffset(-delta, size.width);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      onPointerDown: (d) {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,8 @@ import 'dart:math';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
import 'paint_controller.dart';
 | 
			
		||||
import 'path/path_transform.dart';
 | 
			
		||||
import 'path/ring_number_provider.dart';
 | 
			
		||||
import 'screen_document_mapping.dart';
 | 
			
		||||
 | 
			
		||||
final Rect a4Page =
 | 
			
		||||
@@ -81,18 +83,37 @@ class MyPainter extends CustomPainter {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // active eraser outline
 | 
			
		||||
    if (activePen == Pen.eraser) {
 | 
			
		||||
      final pointerpos = controller.getPointerPosition();
 | 
			
		||||
      if (pointerpos != null) {
 | 
			
		||||
        final translatedPointerpos = _translatept(pointerpos, size);
 | 
			
		||||
        canvas.drawCircle(
 | 
			
		||||
            translatedPointerpos,
 | 
			
		||||
            calcPageDependentScale(zoom, a4Page, canvasSize) * 2.0,
 | 
			
		||||
            paint
 | 
			
		||||
              ..style = PaintingStyle.stroke
 | 
			
		||||
              ..color = Colors.grey);
 | 
			
		||||
      }
 | 
			
		||||
    // active pen hover effects
 | 
			
		||||
    switch (activePen) {
 | 
			
		||||
      case Pen.eraser:
 | 
			
		||||
        final pointerpos = controller.getPointerPosition();
 | 
			
		||||
        if (pointerpos != null) {
 | 
			
		||||
          final translatedPointerpos = _translatept(pointerpos, size);
 | 
			
		||||
          canvas.drawCircle(
 | 
			
		||||
              translatedPointerpos,
 | 
			
		||||
              calcPageDependentScale(zoom, a4Page, canvasSize) * 2.0,
 | 
			
		||||
              paint
 | 
			
		||||
                ..style = PaintingStyle.stroke
 | 
			
		||||
                ..color = Colors.grey);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case Pen.selector:
 | 
			
		||||
        final selection = controller.getSelection();
 | 
			
		||||
        if (selection != null) {
 | 
			
		||||
          final rectpath = (Path()
 | 
			
		||||
                ..addRect(Rect.fromPoints(_translatept(selection.topLeft, size),
 | 
			
		||||
                    _translatept(selection.bottomRight, size))))
 | 
			
		||||
              .dashPath(RingNumberProvider([3, 5]));
 | 
			
		||||
 | 
			
		||||
          canvas.drawPath(
 | 
			
		||||
              rectpath,
 | 
			
		||||
              paint
 | 
			
		||||
                ..style = PaintingStyle.stroke
 | 
			
		||||
                ..color = Colors.grey);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ class PaintController extends ChangeNotifier {
 | 
			
		||||
  Offset? _currentPointerPosition;
 | 
			
		||||
  Pen activePen = Pen.pen;
 | 
			
		||||
  List<Stroke> strokes = [];
 | 
			
		||||
  Offset? _selectionStart;
 | 
			
		||||
 | 
			
		||||
  PaintController(this.file);
 | 
			
		||||
 | 
			
		||||
@@ -37,38 +38,59 @@ class PaintController extends ChangeNotifier {
 | 
			
		||||
      // todo line drawn on edge where line left page
 | 
			
		||||
      if (!a4Page.contains(offset)) return;
 | 
			
		||||
 | 
			
		||||
      // todo handle other pens
 | 
			
		||||
      if (activePen == Pen.eraser || activePen == Pen.selector) return;
 | 
			
		||||
 | 
			
		||||
      int strokeid = strokes.isNotEmpty ? strokes.last.id + 1 : 0;
 | 
			
		||||
      final color = activePen == Pen.pen
 | 
			
		||||
          ? const Color(0xFF444444)
 | 
			
		||||
          : Colors.yellow.withOpacity(.3);
 | 
			
		||||
      strokes.add(Stroke.fromPoints(
 | 
			
		||||
          [Point(offset, _calcTiltedWidth(3.0, e.tilt))], strokeid, color));
 | 
			
		||||
      file.addStroke(strokeid, color);
 | 
			
		||||
      notifyListeners();
 | 
			
		||||
      switch (activePen) {
 | 
			
		||||
        case Pen.pen:
 | 
			
		||||
        case Pen.highlighter:
 | 
			
		||||
          int strokeid = strokes.isNotEmpty ? strokes.last.id + 1 : 0;
 | 
			
		||||
          final color = activePen == Pen.pen
 | 
			
		||||
              ? const Color(0xFF444444)
 | 
			
		||||
              : Colors.yellow.withOpacity(.3);
 | 
			
		||||
          strokes.add(Stroke.fromPoints(
 | 
			
		||||
              [Point(offset, _calcTiltedWidth(3.0, e.tilt))], strokeid, color));
 | 
			
		||||
          file.addStroke(strokeid, color);
 | 
			
		||||
          notifyListeners();
 | 
			
		||||
          break;
 | 
			
		||||
        case Pen.selector:
 | 
			
		||||
          _selectionStart = offset;
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Rect? getSelection() {
 | 
			
		||||
    if (_currentPointerPosition == null || _selectionStart == null) return null;
 | 
			
		||||
    return Rect.fromPoints(_selectionStart!, _currentPointerPosition!);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void pointUpEvent(PointerUpEvent e) {
 | 
			
		||||
    _currentPointerPosition = null;
 | 
			
		||||
    notifyListeners();
 | 
			
		||||
 | 
			
		||||
    if (activePen == Pen.eraser) return;
 | 
			
		||||
 | 
			
		||||
    // pointerupevent doesn't deliver correct event button
 | 
			
		||||
    if (_allowedToDraw(e.kind, 1)) {
 | 
			
		||||
      final lastStroke = strokes.last;
 | 
			
		||||
      if (lastStroke.points.length <= 1) {
 | 
			
		||||
        // if the line consists only of one point (point) add endpoint as the same to allow drawing a line
 | 
			
		||||
        lastStroke.points.add(lastStroke.points.last);
 | 
			
		||||
        file.addPoint(lastStroke.id, lastStroke.points.last);
 | 
			
		||||
        notifyListeners();
 | 
			
		||||
      } else {
 | 
			
		||||
        debugPrint('adding points to db');
 | 
			
		||||
        file.addPoints(lastStroke.id, lastStroke.points);
 | 
			
		||||
      }
 | 
			
		||||
    switch (activePen) {
 | 
			
		||||
      case Pen.pen:
 | 
			
		||||
      case Pen.highlighter:
 | 
			
		||||
        // pointerupevent doesn't deliver correct event button
 | 
			
		||||
        if (_allowedToDraw(e.kind, 1)) {
 | 
			
		||||
          final lastStroke = strokes.last;
 | 
			
		||||
          if (lastStroke.points.length <= 1) {
 | 
			
		||||
            // if the line consists only of one point (point) add endpoint as the same to allow drawing a line
 | 
			
		||||
            lastStroke.points.add(lastStroke.points.last);
 | 
			
		||||
            file.addPoint(lastStroke.id, lastStroke.points.last);
 | 
			
		||||
            notifyListeners();
 | 
			
		||||
          } else {
 | 
			
		||||
            debugPrint('adding points to db');
 | 
			
		||||
            file.addPoints(lastStroke.id, lastStroke.points);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      case Pen.selector:
 | 
			
		||||
        _selectionStart = null;
 | 
			
		||||
        // todo highlight current selection
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								lib/canvas/path/path_transform.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								lib/canvas/path/path_transform.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
import 'dart:ui';
 | 
			
		||||
 | 
			
		||||
import 'ring_number_provider.dart';
 | 
			
		||||
 | 
			
		||||
extension DashPath on Path {
 | 
			
		||||
  // creates a new dashed path with the given intervals
 | 
			
		||||
  Path dashPath(RingNumberProvider dashArray) {
 | 
			
		||||
    final Path dest = Path();
 | 
			
		||||
    for (final PathMetric metric in computeMetrics()) {
 | 
			
		||||
      double distance = .0;
 | 
			
		||||
      bool draw = true;
 | 
			
		||||
      while (distance < metric.length) {
 | 
			
		||||
        final double len = dashArray.next;
 | 
			
		||||
        if (draw) {
 | 
			
		||||
          dest.addPath(
 | 
			
		||||
              metric.extractPath(distance, distance + len), Offset.zero);
 | 
			
		||||
        }
 | 
			
		||||
        distance += len;
 | 
			
		||||
        draw = !draw;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return dest;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								lib/canvas/path/ring_number_provider.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								lib/canvas/path/ring_number_provider.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
class RingNumberProvider {
 | 
			
		||||
  RingNumberProvider(this._vals);
 | 
			
		||||
 | 
			
		||||
  final List<double> _vals;
 | 
			
		||||
  int _idx = 0;
 | 
			
		||||
 | 
			
		||||
  double get next {
 | 
			
		||||
    if (_idx >= _vals.length) {
 | 
			
		||||
      _idx = 0;
 | 
			
		||||
    }
 | 
			
		||||
    return _vals[_idx++];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user