diff --git a/flutter/lib/curve_painter.dart b/flutter/lib/curve_painter.dart index 6c2430b..6461e52 100644 --- a/flutter/lib/curve_painter.dart +++ b/flutter/lib/curve_painter.dart @@ -48,6 +48,15 @@ class CurvePainter extends CustomPainter { textDirection: TextDirection.ltr, textAlign: TextAlign.center); + void drawDotNames(Canvas canvas, Offset place, String s) { + var textPainter = _getTextPainter(s); + textPainter.layout(); + textPainter.paint( + canvas, + Offset((place.dx - textPainter.width), + (place.dy - textPainter.height) - aboveHeight)); + } + void drawAboveText(Canvas canvas, Offset size, String s) { var textPainter = _getTextPainter(s); textPainter.layout(); @@ -80,7 +89,7 @@ class CurvePainter extends CustomPainter { return off; } - void drawArrow(Canvas canvas, Offset from, Offset to, + void drawLowArrow(Canvas canvas, Size size, Offset from, Offset to, [bool doubleSided = false]) { Path path; @@ -93,15 +102,42 @@ class CurvePainter extends CustomPainter { ..strokeWidth = width - 1; /// Draw a single arrow. - path = Path(); + path = Path(); path.moveTo(from.dx, from.dy); - path.relativeCubicTo(0, 0, 0, 0, to.dx - from.dx, to.dy - from.dy); + path.relativeCubicTo( + 0, 0, size.width / 20, 50, to.dx - from.dx, to.dy - from.dy); path = ArrowPath.make(path: path, isDoubleSided: doubleSided, tipLength: 13); canvas.drawPath(path, paint); } - void drawConnections(Canvas canvas, List dots, Map off) { + void drawHighArrow(Canvas canvas, Size size, Offset from, Offset to, + [bool doubleSided = false]) { + Path path; + + // The arrows usually looks better with rounded caps. + Paint paint = Paint() + ..color = Colors.black + ..style = PaintingStyle.stroke + ..strokeCap = StrokeCap.round + ..strokeJoin = StrokeJoin.round + ..strokeWidth = width - 1; + + /// Draw a single arrow. + path = Path(); + path.moveTo(from.dx, from.dy); + path.relativeCubicTo( + 0, 0, -size.width / 25, -50, to.dx - from.dx, to.dy - from.dy); + path = ArrowPath.make( + path: path, + isDoubleSided: doubleSided, + tipLength: 13, + isAdjusted: false); + canvas.drawPath(path, paint); + } + + void drawConnections( + Canvas canvas, Size size, List dots, Map off) { for (var i in dots) { var list = i.getL(); var beg = off[i.num]; @@ -109,7 +145,35 @@ class CurvePainter extends CustomPainter { if (d == i.num) { drawSelfConnect(canvas, off[d]!); } else { - drawArrow(canvas, beg!, off[d]!, !gr.getDoubleSidedBool()); + if (gr.getDoubleSidedBool()) { + if (d > i.num) { + drawLowArrow(canvas, size, beg!, off[d]!, false); + if (gr.getUseLengthBool()) { + drawDotNames( + canvas, + Offset((off[d]!.dx + beg.dx) / 2 - 20, + (off[d]!.dy + beg.dy) / 2 - 20), + i.getL()[d].toString()); + } + } else { + drawHighArrow(canvas, size, beg!, off[d]!, false); + if (gr.getUseLengthBool()) { + drawDotNames( + canvas, + Offset((off[d]!.dx + beg.dx) / 2 + 25, + (off[d]!.dy + beg.dy) / 2 + 25), + i.getL()[d].toString()); + } + } + } else { + drawLine(canvas, beg!, off[d]!); + if (gr.getUseLengthBool()) { + drawDotNames( + canvas, + Offset((off[d]!.dx + beg.dx) / 2, (off[d]!.dy + beg.dy) / 2), + i.getL()[d].toString()); + } + } } } } @@ -128,12 +192,15 @@ class CurvePainter extends CustomPainter { //gr = getGraph(); var off = getDotPos(gr.getDotAmount(), size); - for (int i = 0; i < off.length; i++) { - drawDot(canvas, off[i + 1]!); - drawAboveText( - canvas, off[i + 1]!, "${gr.getDots()[i].getName()}:[${i + 1}]"); + for (int i in off.keys) { + drawDot(canvas, off[i]!); + drawDotNames(canvas, off[i]!, "${gr.getDots()[i - 1].getName()}:[${i}]"); } - drawConnections(canvas, gr.getDots(), off); + //var g = gr.getNoRepeatDots(); + //print(g); + var g = gr.getDots(); + drawConnections(canvas, size, g, off); + //pringArr(canvas, size); //drawArrow(canvas, Offset(size.width / 2, size.height / 2), // Offset(size.width / 2 + 50, size.height / 2 + 200)); } @@ -151,3 +218,140 @@ class CurvePainter extends CustomPainter { textPainter.paint(canvas, drawPosition); }*/ } + +void pringArr(Canvas canvas, Size size) { + TextSpan textSpan; + TextPainter textPainter; + Path path; + + // The arrows usually looks better with rounded caps. + Paint paint = Paint() + ..color = Colors.black + ..style = PaintingStyle.stroke + ..strokeCap = StrokeCap.round + ..strokeJoin = StrokeJoin.round + ..strokeWidth = 3.0; + + /// Draw a single arrow. + path = Path(); + path.moveTo(size.width * 0.25, size.height * 0.10); + path.relativeCubicTo(0, 0, size.width * 0.25, 50, size.width * 0.5, 0); + path = ArrowPath.make(path: path); + canvas.drawPath(path, paint..color = Colors.blue); + + textSpan = const TextSpan( + text: 'Single arrow', + style: TextStyle(color: Colors.blue), + ); + textPainter = TextPainter( + text: textSpan, + textAlign: TextAlign.center, + textDirection: TextDirection.ltr, + ); + textPainter.layout(minWidth: size.width); + textPainter.paint(canvas, Offset(0, size.height * 0.06)); +/* + /// Draw a double sided arrow. + path = Path(); + path.moveTo(size.width * 0.25, size.height * 0.2); + path.relativeCubicTo(0, 0, size.width * 0.25, 50, size.width * 0.5, 0); + path = ArrowPath.make(path: path, isDoubleSided: true); + canvas.drawPath(path, paint..color = Colors.cyan); + + textSpan = const TextSpan( + text: 'Double sided arrow', + style: TextStyle(color: Colors.cyan), + ); + textPainter = TextPainter( + text: textSpan, + textAlign: TextAlign.center, + textDirection: TextDirection.ltr, + ); + textPainter.layout(minWidth: size.width); + textPainter.paint(canvas, Offset(0, size.height * 0.16)); + + /// Use complex path. + path = Path(); + path.moveTo(size.width * 0.25, size.height * 0.3); + path.relativeCubicTo(0, 0, size.width * 0.25, 50, size.width * 0.5, 50); + path.relativeCubicTo(0, 0, -size.width * 0.25, 0, -size.width * 0.5, 50); + path.relativeCubicTo(0, 0, size.width * 0.125, 10, size.width * 0.25, -10); + path = ArrowPath.make(path: path, isDoubleSided: true); + canvas.drawPath(path, paint..color = Colors.blue); + + textSpan = const TextSpan( + text: 'Complex path', + style: TextStyle(color: Colors.blue), + ); + textPainter = TextPainter( + text: textSpan, + textAlign: TextAlign.center, + textDirection: TextDirection.ltr, + ); + textPainter.layout(minWidth: size.width); + textPainter.paint(canvas, Offset(0, size.height * 0.28)); + + /// Draw several arrows on the same path. + path = Path(); + path.moveTo(size.width * 0.25, size.height * 0.53); + path.relativeCubicTo(0, 0, size.width * 0.25, 50, size.width * 0.5, 50); + path = ArrowPath.make(path: path); + path.relativeCubicTo(0, 0, -size.width * 0.25, 0, -size.width * 0.5, 50); + path = ArrowPath.make(path: path); + Path subPath = Path(); + subPath.moveTo(size.width * 0.375, size.height * 0.53 + 100); + subPath.relativeCubicTo(0, 0, size.width * 0.125, 10, size.width * 0.25, -10); + subPath = ArrowPath.make(path: subPath, isDoubleSided: true); + path.addPath(subPath, Offset.zero); + canvas.drawPath(path, paint..color = Colors.cyan); + + textSpan = const TextSpan( + text: 'Several arrows on the same path', + style: TextStyle(color: Colors.cyan), + ); + textPainter = TextPainter( + text: textSpan, + textAlign: TextAlign.center, + textDirection: TextDirection.ltr, + ); + textPainter.layout(minWidth: size.width); + textPainter.paint(canvas, Offset(0, size.height * 0.49)); + + /// Adjusted + path = Path(); + path.moveTo(size.width * 0.1, size.height * 0.8); + path.relativeCubicTo(0, 0, size.width * 0.3, 50, size.width * 0.25, 75); + path = ArrowPath.make(path: path, isAdjusted: true); + canvas.drawPath(path, paint..color = Colors.blue); + + textSpan = const TextSpan( + text: 'Adjusted', + style: TextStyle(color: Colors.blue), + ); + textPainter = TextPainter( + text: textSpan, + textAlign: TextAlign.left, + textDirection: TextDirection.ltr, + ); + textPainter.layout(); + textPainter.paint(canvas, Offset(size.width * 0.2, size.height * 0.77)); + + /// Non adjusted. + path = Path(); + path.moveTo(size.width * 0.6, size.height * 0.8); + path.relativeCubicTo(0, 0, size.width * 0.3, 50, size.width * 0.25, 75); + path = ArrowPath.make(path: path, isAdjusted: false); + canvas.drawPath(path, paint..color = Colors.blue); + + textSpan = const TextSpan( + text: 'Non adjusted', + style: TextStyle(color: Colors.blue), + ); + textPainter = TextPainter( + text: textSpan, + textAlign: TextAlign.left, + textDirection: TextDirection.ltr, + ); + textPainter.layout(); + textPainter.paint(canvas, Offset(size.width * 0.65, size.height * 0.77));*/ +} diff --git a/flutter/lib/pages/drawing_page.dart b/flutter/lib/pages/drawing_page.dart index 9f426c5..91810ea 100644 --- a/flutter/lib/pages/drawing_page.dart +++ b/flutter/lib/pages/drawing_page.dart @@ -6,12 +6,12 @@ import 'package:flutter/material.dart'; Graphs getGraph() { List d = []; - d.add(Dot.fromTwoLists("1", [2, 3], [1, 1])); + d.add(Dot.fromTwoLists("1", [2, 3], [5, 1])); d.add(Dot.fromTwoLists("2", [1, 3], [1, 1])); - d.add(Dot.fromTwoLists("3", [1, 2], [1, 1])); + d.add(Dot.fromTwoLists("3", [1, 2], [1, 2])); d.add(Dot.fromTwoLists("Name1", [], [])); d.add(Dot.fromTwoLists("Name2", [], [])); - return Graphs.fromList("1", d, false, true); + return Graphs.fromList("1", d, true, false); } class DrawingPage extends StatefulWidget { @@ -301,9 +301,13 @@ class _DrawingPageState extends State { await FilePicker.platform.pickFiles(allowedExtensions: ["txt"]); setState(() { if (result != null) { - //print(result.files.single.path!); - String? res = data.replaceDataFromFile(result.files.single.path!); - if (res != null) showPopUp("Error", res); + if (!result.files.single.path!.endsWith(".txt")) { + showPopUp("Error", "Can open only \".txt\" files"); + } else { + //print(result.files.single.path!); + String? res = data.replaceDataFromFile(result.files.single.path!); + if (res != null) showPopUp("Error", res); + } } else { showPopUp("Error", "No file selected"); // User canceled the picker @@ -316,7 +320,6 @@ class _DrawingPageState extends State { dialogTitle: 'Please select an output file:', fileName: 'output-file.txt', allowedExtensions: ["txt"]); - if (outputFile == null) { showPopUp("Error", "Save cancelled"); // User canceled the picker diff --git a/flutter/lib/src/graph.dart b/flutter/lib/src/graph.dart index ba04eee..186bb3d 100644 --- a/flutter/lib/src/graph.dart +++ b/flutter/lib/src/graph.dart @@ -54,9 +54,9 @@ class Dot { } //******Constructor****** - Dot() { - _name = "Undefined"; - num = -1; + Dot([String name = "Undefined", int n = -1]) { + _name = name; + num = n; _ln = {}; } Dot.fromTwoLists(String name, List num0, List length, @@ -398,6 +398,23 @@ class Graphs { } return out; } + + /*List getNoRepeatDots() { + List ret = []; + for (int i = 0; i < _amount; i++) { + ret.add(Dot(_dots[i].getName(), _dots[i].num)); + } + for (int i = 0; i < _amount; i++) { + for (int j in _dots[i].getL().keys) { + if (!ret[j - 1].hasConnection(i + 1) && !ret[i].hasConnection(j) || + i == j) { + var len = _dots[i].getLength(j); + ret[i].addPath(j, len); + } + } + } + return ret; + }*/ //*****Getters******* //******Print******