diff --git a/lib/canvas/drawing_page.dart b/lib/canvas/drawing_page.dart index 5add434..e3883d3 100644 --- a/lib/canvas/drawing_page.dart +++ b/lib/canvas/drawing_page.dart @@ -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 { 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) { diff --git a/lib/canvas/my_painter.dart b/lib/canvas/my_painter.dart index da2096a..2e5ca9e 100644 --- a/lib/canvas/my_painter.dart +++ b/lib/canvas/my_painter.dart @@ -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; } } diff --git a/lib/canvas/paint_controller.dart b/lib/canvas/paint_controller.dart index 023cd10..660b2f5 100644 --- a/lib/canvas/paint_controller.dart +++ b/lib/canvas/paint_controller.dart @@ -18,6 +18,7 @@ class PaintController extends ChangeNotifier { Offset? _currentPointerPosition; Pen activePen = Pen.pen; List 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; } } diff --git a/lib/canvas/path/path_transform.dart b/lib/canvas/path/path_transform.dart new file mode 100644 index 0000000..b50adbe --- /dev/null +++ b/lib/canvas/path/path_transform.dart @@ -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; + } +} diff --git a/lib/canvas/path/ring_number_provider.dart b/lib/canvas/path/ring_number_provider.dart new file mode 100644 index 0000000..4ce0f10 --- /dev/null +++ b/lib/canvas/path/ring_number_provider.dart @@ -0,0 +1,13 @@ +class RingNumberProvider { + RingNumberProvider(this._vals); + + final List _vals; + int _idx = 0; + + double get next { + if (_idx >= _vals.length) { + _idx = 0; + } + return _vals[_idx++]; + } +}