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,9 +152,18 @@ 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; | ||||
|           if (ctrlPressed) { | ||||
|             setState(() { | ||||
|               zoom = (zoom - delta.dy.sign * .1).clamp(0.25, 5.0); | ||||
|             }); | ||||
|           } else { | ||||
|             _calcNewPageOffset(-delta, size.width); | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|       onPointerDown: (d) { | ||||
|         Offset pos = d.localPosition; | ||||
|   | ||||
| @@ -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,8 +83,9 @@ class MyPainter extends CustomPainter { | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // active eraser outline | ||||
|     if (activePen == Pen.eraser) { | ||||
|     // active pen hover effects | ||||
|     switch (activePen) { | ||||
|       case Pen.eraser: | ||||
|         final pointerpos = controller.getPointerPosition(); | ||||
|         if (pointerpos != null) { | ||||
|           final translatedPointerpos = _translatept(pointerpos, size); | ||||
| @@ -93,6 +96,24 @@ class MyPainter extends CustomPainter { | ||||
|                 ..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,9 +38,9 @@ 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; | ||||
|  | ||||
|       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) | ||||
| @@ -48,15 +49,28 @@ class PaintController extends ChangeNotifier { | ||||
|               [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; | ||||
|  | ||||
|     switch (activePen) { | ||||
|       case Pen.pen: | ||||
|       case Pen.highlighter: | ||||
|         // pointerupevent doesn't deliver correct event button | ||||
|         if (_allowedToDraw(e.kind, 1)) { | ||||
|           final lastStroke = strokes.last; | ||||
| @@ -70,6 +84,14 @@ class PaintController extends ChangeNotifier { | ||||
|             file.addPoints(lastStroke.id, lastStroke.points); | ||||
|           } | ||||
|         } | ||||
|         break; | ||||
|       case Pen.selector: | ||||
|         _selectionStart = null; | ||||
|         // todo highlight current selection | ||||
|         break; | ||||
|       default: | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void pointMoveEvent(Offset offset, PointerMoveEvent event) { | ||||
|   | ||||
							
								
								
									
										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