From 00ea09f4f65543cc130ec9112c45781d5d92c5cd Mon Sep 17 00:00:00 2001 From: lukas-heiligenbrunner Date: Mon, 24 Oct 2022 02:02:35 +0200 Subject: [PATCH] add drawing area --- lib/canvas/document_types.dart | 20 +++++ lib/canvas/drawing_canvas.dart | 129 +++++++++++++++++++++++++++++++++ lib/canvas/my_painter.dart | 34 +++++++++ lib/main.dart | 34 +++++++-- pubspec.lock | 29 ++++++-- pubspec.yaml | 3 +- 6 files changed, 231 insertions(+), 18 deletions(-) create mode 100644 lib/canvas/document_types.dart create mode 100644 lib/canvas/drawing_canvas.dart create mode 100644 lib/canvas/my_painter.dart diff --git a/lib/canvas/document_types.dart b/lib/canvas/document_types.dart new file mode 100644 index 0000000..158b1c3 --- /dev/null +++ b/lib/canvas/document_types.dart @@ -0,0 +1,20 @@ +import 'dart:ui'; + +class Stroke { + List points = []; + + @override + String toString() { + return 'Stroke{points: $points}'; + } + + Stroke.fromPoints(this.points); + Stroke(); +} + +class Point { + final Offset point; + final double thickness; + + Point(this.point, this.thickness); +} diff --git a/lib/canvas/drawing_canvas.dart b/lib/canvas/drawing_canvas.dart new file mode 100644 index 0000000..f599d6e --- /dev/null +++ b/lib/canvas/drawing_canvas.dart @@ -0,0 +1,129 @@ +import 'dart:math'; +import 'dart:ui'; + +import 'package:equations/equations.dart'; +import 'package:flutter/material.dart'; +import 'package:notes/canvas/my_painter.dart'; + +import 'document_types.dart'; + +class DrawingCanvas extends StatefulWidget { + const DrawingCanvas({Key? key}) : super(key: key); + + @override + State createState() => _DrawingCanvasState(); +} + +class _DrawingCanvasState extends State { + List _strokes = []; + bool allowDrawWithFinger = false; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(backgroundColor: Colors.blueGrey), + body: _buildCanvas(), + ); + } + + double _calcTiltedWidth(double baseWidth, double tilt){ + return baseWidth * tilt; + } + + double _calcAngleDependentWidth(List pts, double basetickness){ + // todo do correct linear interpolation and extimate angle + final lininterpol = PolynomialInterpolation(nodes: pts.map((e) => InterpolationNode(x: e.point.dx, y: e.point.dy)).toList(growable: false)); + lininterpol.compute(1.0); + print(lininterpol.buildPolynomial().toString()); + + // double angle = atan((pt2.dy - pt1.dy)/(pt2.dx - pt1.dx)); + + final angle = 5 / (2 * pi); + // print("pt1: ${pt1}, pt2: ${pt2}, angle: ${angle}"); + + return basetickness * (angle / .5 + .5); + } + + Widget _buildCanvas() { + return Scaffold( + body: Listener( + onPointerMove: (event) { + // print(event.tilt); + final pos = event.localPosition; + final pts = _strokes.last.points; + + if(pts.last.point == pos) return; + + if (allowDrawWithFinger || event.kind != PointerDeviceKind.touch) { + double newWidth = _calcTiltedWidth(3.0, event.tilt); + + if(_strokes.last.points.length > 1){ + // todo current point not in list + newWidth = _calcAngleDependentWidth(pts.getRange(pts.length - 10 >= 0 ? pts.length -10 : 0, pts.length).toList(growable: false), event.tilt); + } + setState(() { + _strokes = List.from(_strokes, growable: false) + ..last.points.add(Point(pos, newWidth)); + }); + } + }, + onPointerDown: (event) { + if (allowDrawWithFinger || event.kind != PointerDeviceKind.touch) { + setState(() { + _strokes = List.from(_strokes) + ..add(Stroke.fromPoints([Point(event.localPosition, _calcTiltedWidth(3.0, event.tilt))])); + }); + } + }, + onPointerUp: (event) { + if (allowDrawWithFinger || event.kind != PointerDeviceKind.touch) { + if (_strokes.last.points.length <= 1) { + // if the line consists only of one point (point) add endpoint as the same to allow drawing a line + // todo maybe solve this in custompainter in future + setState(() { + _strokes = List.from(_strokes, growable: false) + ..last.points.add(_strokes.last.points.last); + }); + } else { + setState(() {}); + } + + print(_strokes.length); + print(_strokes.last.points.length); + } + }, + // child: GestureDetector( + // onPanUpdate: (DragUpdateDetails details) { + // setState(() { + // _strokes = List.from(_strokes,growable: false)..last.points.add(details.localPosition); + // }); + // }, + // onPanEnd: (DragEndDetails details) { + // if(_strokes.last.points.length <= 1){ + // // if the line consists only of one point (point) add endpoint as the same to allow drawing a line + // // todo maybe solve this in custompainter in future + // setState(() { + // _strokes = List.from(_strokes,growable: false)..last.points.add(_strokes.last.points.last); + // }); + // }else{ + // setState(() {}); + // } + // + // + // print(_strokes.length); + // print(_strokes.last.points.length); + // }, + // onPanStart: (details) { + // setState(() { + // _strokes = List.from(_strokes)..add(Stroke.fromPoints([details.localPosition])); + // }); + // }, + child: CustomPaint( + painter: MyPainter(strokes: _strokes), + size: Size.infinite, + // ), + ), + ), + ); + } +} diff --git a/lib/canvas/my_painter.dart b/lib/canvas/my_painter.dart new file mode 100644 index 0000000..635d3df --- /dev/null +++ b/lib/canvas/my_painter.dart @@ -0,0 +1,34 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +import 'document_types.dart'; + +class MyPainter extends CustomPainter { + List strokes = []; + + MyPainter({required this.strokes}); + + @override + void paint(Canvas canvas, Size size) { + var paint = Paint() + ..color = Colors.blue + ..strokeCap = StrokeCap.square; + // ..strokeWidth = 3.0; + + for(final stroke in strokes){ + for(int i = 0; i < stroke.points.length -1; i++){ + final pt1 = stroke.points[i].point; + final pt2 = stroke.points[i+1].point; + + // final strokewidth = _calcAngleDependentWidth(pt1, pt2, stroke.points[i].thickness); + canvas.drawLine(pt1, pt2, paint..strokeWidth = stroke.points[i].thickness); + } + } + } + + @override + bool shouldRepaint(MyPainter oldDelegate) { + return oldDelegate.strokes != strokes; + } +} diff --git a/lib/main.dart b/lib/main.dart index 82d5081..dc4583c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:notes/CollapseDrawer.dart'; import 'package:notes/all_notes_page.dart'; +import 'package:notes/canvas/drawing_canvas.dart'; void main() { runApp(const MyApp()); @@ -38,11 +39,7 @@ class _MyHomePageState extends State { @override Widget build(BuildContext context) { return Scaffold( - floatingActionButton: FloatingActionButton( - onPressed: () {}, - backgroundColor: const Color(0xff3f3f3f), - child: - const Icon(Icons.edit_calendar_outlined, color: Colors.orange)), + floatingActionButton: _fab(), body: Row( children: [ CollapseDrawer( @@ -60,23 +57,44 @@ class _MyHomePageState extends State { ); } + Widget _fab() { + switch (activePage) { + case View.all: + case View.folders: + return FloatingActionButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const DrawingCanvas(), + ), + ); + }, + backgroundColor: const Color(0xff3f3f3f), + child: const Icon(Icons.edit_calendar_outlined, color: Colors.orange), + ); + default: + return Container(); + } + } + Widget _buildPage() { switch (activePage) { case View.all: return const AllNotesPage(); case View.shared: return const Text( - 'Todo1', + 'shared notebooks WIP', style: TextStyle(color: Colors.white), ); case View.recycle: return const Text( - 'Todo', + 'recycle bin WIP', style: TextStyle(color: Colors.white), ); case View.folders: return const Text( - 'Todo', + 'Folders WIP', style: TextStyle(color: Colors.white), ); } diff --git a/pubspec.lock b/pubspec.lock index aa8a9bc..eef9558 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -29,13 +29,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.1" - collapsible_sidebar: - dependency: "direct main" - description: - name: collapsible_sidebar - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.3" collection: dependency: transitive description: @@ -50,6 +43,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.5" + equations: + dependency: "direct main" + description: + name: equations + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.0" fake_async: dependency: transitive description: @@ -74,6 +74,13 @@ packages: description: flutter source: sdk version: "0.0.0" + fraction: + dependency: transitive + description: + name: fraction + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.4" lints: dependency: transitive description: @@ -109,6 +116,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.2" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.0" sky_engine: dependency: transitive description: flutter @@ -165,4 +179,3 @@ packages: version: "2.1.2" sdks: dart: ">=2.18.2 <3.0.0" - flutter: ">=1.17.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1d2e138..e983850 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,12 +31,11 @@ environment: dependencies: flutter: sdk: flutter - collapsible_sidebar: ^2.0.3 - # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 + equations: ^4.1.0 dev_dependencies: flutter_test: