allow zooming on desktop when holding ctrl and scrolling

add prototype of selection mode, span up dashed rectangle
This commit is contained in:
lukas-heiligenbrunner 2022-12-02 00:25:37 +01:00
parent 4899381510
commit 8e0cd05ded
5 changed files with 129 additions and 38 deletions

View File

@ -2,6 +2,7 @@ import 'dart:ui';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../context/file_change_notifier.dart'; import '../context/file_change_notifier.dart';
@ -151,8 +152,17 @@ class _DrawingPageState extends State<DrawingPage> {
debugPrint('got pointer signal: $pointerSignal'); debugPrint('got pointer signal: $pointerSignal');
if (pointerSignal is PointerScrollEvent) { if (pointerSignal is PointerScrollEvent) {
final bool ctrlPressed = RawKeyboard.instance.keysPressed
.contains(LogicalKeyboardKey.controlLeft);
final delta = pointerSignal.scrollDelta; 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) { onPointerDown: (d) {

View File

@ -3,6 +3,8 @@ import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'paint_controller.dart'; import 'paint_controller.dart';
import 'path/path_transform.dart';
import 'path/ring_number_provider.dart';
import 'screen_document_mapping.dart'; import 'screen_document_mapping.dart';
final Rect a4Page = final Rect a4Page =
@ -81,18 +83,37 @@ class MyPainter extends CustomPainter {
} }
} }
// active eraser outline // active pen hover effects
if (activePen == Pen.eraser) { switch (activePen) {
final pointerpos = controller.getPointerPosition(); case Pen.eraser:
if (pointerpos != null) { final pointerpos = controller.getPointerPosition();
final translatedPointerpos = _translatept(pointerpos, size); if (pointerpos != null) {
canvas.drawCircle( final translatedPointerpos = _translatept(pointerpos, size);
translatedPointerpos, canvas.drawCircle(
calcPageDependentScale(zoom, a4Page, canvasSize) * 2.0, translatedPointerpos,
paint calcPageDependentScale(zoom, a4Page, canvasSize) * 2.0,
..style = PaintingStyle.stroke paint
..color = Colors.grey); ..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;
} }
} }

View File

@ -18,6 +18,7 @@ class PaintController extends ChangeNotifier {
Offset? _currentPointerPosition; Offset? _currentPointerPosition;
Pen activePen = Pen.pen; Pen activePen = Pen.pen;
List<Stroke> strokes = []; List<Stroke> strokes = [];
Offset? _selectionStart;
PaintController(this.file); PaintController(this.file);
@ -37,38 +38,59 @@ class PaintController extends ChangeNotifier {
// todo line drawn on edge where line left page // todo line drawn on edge where line left page
if (!a4Page.contains(offset)) return; if (!a4Page.contains(offset)) return;
// todo handle other pens switch (activePen) {
if (activePen == Pen.eraser || activePen == Pen.selector) return; case Pen.pen:
case Pen.highlighter:
int strokeid = strokes.isNotEmpty ? strokes.last.id + 1 : 0; int strokeid = strokes.isNotEmpty ? strokes.last.id + 1 : 0;
final color = activePen == Pen.pen final color = activePen == Pen.pen
? const Color(0xFF444444) ? const Color(0xFF444444)
: Colors.yellow.withOpacity(.3); : Colors.yellow.withOpacity(.3);
strokes.add(Stroke.fromPoints( strokes.add(Stroke.fromPoints(
[Point(offset, _calcTiltedWidth(3.0, e.tilt))], strokeid, color)); [Point(offset, _calcTiltedWidth(3.0, e.tilt))], strokeid, color));
file.addStroke(strokeid, color); file.addStroke(strokeid, color);
notifyListeners(); 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) { void pointUpEvent(PointerUpEvent e) {
_currentPointerPosition = null; _currentPointerPosition = null;
notifyListeners(); notifyListeners();
if (activePen == Pen.eraser) return; switch (activePen) {
case Pen.pen:
// pointerupevent doesn't deliver correct event button case Pen.highlighter:
if (_allowedToDraw(e.kind, 1)) { // pointerupevent doesn't deliver correct event button
final lastStroke = strokes.last; if (_allowedToDraw(e.kind, 1)) {
if (lastStroke.points.length <= 1) { final lastStroke = strokes.last;
// if the line consists only of one point (point) add endpoint as the same to allow drawing a line if (lastStroke.points.length <= 1) {
lastStroke.points.add(lastStroke.points.last); // if the line consists only of one point (point) add endpoint as the same to allow drawing a line
file.addPoint(lastStroke.id, lastStroke.points.last); lastStroke.points.add(lastStroke.points.last);
notifyListeners(); file.addPoint(lastStroke.id, lastStroke.points.last);
} else { notifyListeners();
debugPrint('adding points to db'); } else {
file.addPoints(lastStroke.id, lastStroke.points); debugPrint('adding points to db');
} file.addPoints(lastStroke.id, lastStroke.points);
}
}
break;
case Pen.selector:
_selectionStart = null;
// todo highlight current selection
break;
default:
break;
} }
} }

View 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;
}
}

View 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++];
}
}