Немного разделения цветов

This commit is contained in:
Морозов Андрей 2021-11-08 20:50:43 +04:00
parent 5e872804ac
commit 4cc9ab073d
3 changed files with 157 additions and 100 deletions

View File

@ -6,40 +6,42 @@ import 'dart:math';
class CurvePainter extends CustomPainter { class CurvePainter extends CustomPainter {
CurvePainter({ CurvePainter({
Key? key, Key? key,
required this.gr, required this.graphData,
required this.bfsPath,
}); });
Graphs gr; List<int>? bfsPath;
final double rad = 7; Graphs graphData;
final double width = 4; final double dotRad = 6;
final Color col = Colors.black; final double lineWidth = 2;
final Color lineColor = Colors.black;
final double aboveHeight = 5; final double aboveHeight = 5;
double circleRad = 100; double circleRad = 100;
final TextStyle textStyle = const TextStyle( final TextStyle textStyle = TextStyle(
color: Colors.black, color: Colors.green.shade900,
fontSize: 21, fontSize: 20,
); );
void drawLine(Canvas canvas, Offset p1, Offset p2) { void drawLine(Canvas canvas, Offset p1, Offset p2) {
Paint p = Paint(); Paint p = Paint();
p.color = col; p.color = lineColor;
p.strokeWidth = width - 2; p.strokeWidth = lineWidth;
canvas.drawLine(p1, p2, p); canvas.drawLine(p1, p2, p);
} }
void drawDot(Canvas canvas, Offset p1) { void drawDot(Canvas canvas, Offset p1) {
var p = Paint(); var p = Paint();
p.color = Colors.yellow.shade900; p.color = Colors.yellow.shade900;
p.strokeWidth = width; p.strokeWidth = lineWidth + 2;
canvas.drawCircle(p1, rad, p); canvas.drawCircle(p1, dotRad, p);
} }
void drawSelfConnect(Canvas canvas, Offset p1) { void drawSelfConnect(Canvas canvas, Offset p1) {
var p = Paint(); var p = Paint();
p.color = col; p.color = lineColor;
p.strokeWidth = width - 2; p.strokeWidth = lineWidth;
p.style = PaintingStyle.stroke; p.style = PaintingStyle.stroke;
canvas.drawCircle(Offset(p1.dx + rad + 20, p1.dy), rad + 20, p); canvas.drawCircle(Offset(p1.dx + dotRad + 20, p1.dy), dotRad + 20, p);
} }
TextSpan _getTextSpan(String s) => TextSpan(text: s, style: textStyle); TextSpan _getTextSpan(String s) => TextSpan(text: s, style: textStyle);
@ -66,27 +68,14 @@ class CurvePainter extends CustomPainter {
(size.dy - textPainter.height) - aboveHeight)); (size.dy - textPainter.height) - aboveHeight));
} }
Graphs getGraph() {
List<Dot> d = <Dot>[];
d.add(Dot.fromTwoLists("1", [2, 3], [1, 1]));
d.add(Dot.fromTwoLists("2", [1, 3], [1, 1]));
d.add(Dot.fromTwoLists("3", [1, 2], [1, 1]));
d.add(Dot.fromTwoLists("Name1", [], []));
d.add(Dot.fromTwoLists("Name2", [], []));
return Graphs.fromList("1", d, false, false);
}
int getHighInputConnections() { int getHighInputConnections() {
if (gr.getDots().length <= 3) return -1; if (graphData.getDots().length != 1 && graphData.getDots().length <= 3) {
return -1;
}
int higest = -1; int higest = -1;
for (var i in gr.getDots()) { for (var i in graphData.getDots()) {
if (i.getL().length > higest) higest = i.num; if (i.getL().length > higest) higest = i.num;
} }
/*gr.getDots().forEach((element) {
if (element.getL().length > higest) {
higest = element.num;
}
});*/
return higest; return higest;
} }
@ -110,14 +99,14 @@ class CurvePainter extends CustomPainter {
} else { } else {
print("GetDotPos error"); print("GetDotPos error");
} }
print(off.length); //print(off.length);
} }
//print(off); //print(off);
return off; return off;
} }
void drawLowArrow(Canvas canvas, Size size, Offset from, Offset to, void drawHArrow(Canvas canvas, Size size, Offset from, Offset to,
[bool doubleSided = false]) { [bool doubleSided = false]) {
Path path; Path path;
@ -127,7 +116,7 @@ class CurvePainter extends CustomPainter {
..style = PaintingStyle.stroke ..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round ..strokeCap = StrokeCap.round
..strokeJoin = StrokeJoin.round ..strokeJoin = StrokeJoin.round
..strokeWidth = width - 1; ..strokeWidth = lineWidth;
var length = sqrt((to.dx - from.dx) * (to.dx - from.dx) + var length = sqrt((to.dx - from.dx) * (to.dx - from.dx) +
(to.dy - from.dy) * (to.dy - from.dy)); (to.dy - from.dy) * (to.dy - from.dy));
@ -135,8 +124,13 @@ class CurvePainter extends CustomPainter {
/// Draw a single arrow. /// Draw a single arrow.
path = Path(); path = Path();
path.moveTo(from.dx, from.dy); path.moveTo(from.dx, from.dy);
path.relativeCubicTo(0, 0, -(from.dx + to.dx) / length * 2 - 40, path.relativeCubicTo(
-(from.dy + to.dy) / length * 2 - 40, to.dx - from.dx, to.dy - from.dy); 0,
0,
-(from.dx + to.dx) / (length * 2) - 40,
-(from.dy + to.dy) / (length * 2) - 40,
to.dx - from.dx,
to.dy - from.dy);
path = path =
ArrowPath.make(path: path, isDoubleSided: doubleSided, tipLength: 16); ArrowPath.make(path: path, isDoubleSided: doubleSided, tipLength: 16);
canvas.drawPath(path, paint); canvas.drawPath(path, paint);
@ -152,7 +146,7 @@ class CurvePainter extends CustomPainter {
..style = PaintingStyle.stroke ..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round ..strokeCap = StrokeCap.round
..strokeJoin = StrokeJoin.round ..strokeJoin = StrokeJoin.round
..strokeWidth = width - 1; ..strokeWidth = lineWidth;
var length = sqrt((to.dx - from.dx) * (to.dx - from.dx) + var length = sqrt((to.dx - from.dx) * (to.dx - from.dx) +
(to.dy - from.dy) * (to.dy - from.dy)); (to.dy - from.dy) * (to.dy - from.dy));
@ -160,8 +154,13 @@ class CurvePainter extends CustomPainter {
/// Draw a single arrow. /// Draw a single arrow.
path = Path(); path = Path();
path.moveTo(from.dx, from.dy); path.moveTo(from.dx, from.dy);
path.relativeCubicTo(0, 0, (from.dx + to.dx) / length + 60, path.relativeCubicTo(
(from.dy + to.dy) / length + 0, to.dx - from.dx, to.dy - from.dy); 0,
0,
(from.dx + to.dx) / (length * 3) + 40,
(from.dy + to.dy) / (length * 2) + 40,
to.dx - from.dx,
to.dy - from.dy);
path = ArrowPath.make( path = ArrowPath.make(
path: path, path: path,
isDoubleSided: doubleSided, isDoubleSided: doubleSided,
@ -179,10 +178,10 @@ class CurvePainter extends CustomPainter {
if (d == i.num) { if (d == i.num) {
drawSelfConnect(canvas, off[d]!); drawSelfConnect(canvas, off[d]!);
} else { } else {
if (gr.getDoubleSidedBool()) { if (graphData.getDoubleSidedBool()) {
if (d > i.num) { if (d > i.num) {
drawLowArrow(canvas, size, beg!, off[d]!, false); drawHArrow(canvas, size, beg!, off[d]!, false);
if (gr.getUseLengthBool()) { if (graphData.getUseLengthBool()) {
drawDotNames( drawDotNames(
canvas, canvas,
Offset((off[d]!.dx + beg.dx) / 2 - 18, Offset((off[d]!.dx + beg.dx) / 2 - 18,
@ -191,7 +190,7 @@ class CurvePainter extends CustomPainter {
} }
} else { } else {
drawHighArrow(canvas, size, beg!, off[d]!, false); drawHighArrow(canvas, size, beg!, off[d]!, false);
if (gr.getUseLengthBool()) { if (graphData.getUseLengthBool()) {
drawDotNames( drawDotNames(
canvas, canvas,
Offset((off[d]!.dx + beg.dx) / 2 + 30, Offset((off[d]!.dx + beg.dx) / 2 + 30,
@ -201,7 +200,7 @@ class CurvePainter extends CustomPainter {
} }
} else { } else {
drawLine(canvas, beg!, off[d]!); drawLine(canvas, beg!, off[d]!);
if (gr.getUseLengthBool()) { if (graphData.getUseLengthBool()) {
drawDotNames( drawDotNames(
canvas, canvas,
Offset((off[d]!.dx + beg.dx) / 2, (off[d]!.dy + beg.dy) / 2), Offset((off[d]!.dx + beg.dx) / 2, (off[d]!.dy + beg.dy) / 2),
@ -227,15 +226,16 @@ class CurvePainter extends CustomPainter {
//gr = getGraph(); //gr = getGraph();
//int higest = getHighConnections(); //int higest = getHighConnections();
//if (higest > -1) { //if (higest > -1) {
var off = getDotPos(gr.getDotAmount(), size); //, higest); var off = getDotPos(graphData.getDotAmount(), size); //, higest);
//off[higest] = Offset(size.width / 2, size.height / 2); //off[higest] = Offset(size.width / 2, size.height / 2);
for (int i in off.keys) { for (int i in off.keys) {
drawDot(canvas, off[i]!); drawDot(canvas, off[i]!);
drawDotNames(canvas, off[i]!, "${gr.getDots()[i - 1].getName()}:[${i}]"); drawDotNames(
canvas, off[i]!, "${graphData.getDots()[i - 1].getName()}:[$i]");
} }
//var g = gr.getNoRepeatDots(); //var g = gr.getNoRepeatDots();
//print(g); //print(g);
var g = gr.getDots(); var g = graphData.getDots();
drawConnections(canvas, size, g, off); drawConnections(canvas, size, g, off);
//pringArr(canvas, size); //pringArr(canvas, size);
//drawArrow(canvas, Offset(size.width / 2, size.height / 2), //drawArrow(canvas, Offset(size.width / 2, size.height / 2),

View File

@ -23,7 +23,8 @@ class DrawingPage extends StatefulWidget {
class _DrawingPageState extends State<DrawingPage> { class _DrawingPageState extends State<DrawingPage> {
double screenSize = 0; double screenSize = 0;
Graphs data = getGraph(); Graphs graphData = getGraph();
List<int>? bfsPath;
final _textNameController = TextEditingController(); final _textNameController = TextEditingController();
final _textNumbController = TextEditingController(); final _textNumbController = TextEditingController();
@ -41,7 +42,7 @@ class _DrawingPageState extends State<DrawingPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
screenSize = MediaQuery.of(context).size.width; screenSize = MediaQuery.of(context).size.width;
_textGrNmController.text = data.getName(); _textGrNmController.text = graphData.getName();
return MaterialApp( return MaterialApp(
home: Scaffold( home: Scaffold(
appBar: AppBar( appBar: AppBar(
@ -58,23 +59,24 @@ class _DrawingPageState extends State<DrawingPage> {
child: Column(children: <Widget>[ child: Column(children: <Widget>[
const SizedBox(height: 5), const SizedBox(height: 5),
Row(children: [ Row(children: [
addSpaceW(screenSize / 8 + 21), addSpaceW(screenSize / 8 + 19),
createButton("\nAdd dot\n", addDotPushed), createButton("\nAdd dot\n", addDotPushed),
createInputBox("Dot name", screenSize / 4 - 25, Icons.label, createInputBox("Dot name", screenSize / 4 - 25, Icons.label,
_textNameController), _textNameController),
addSpaceW(18), addSpaceW(8),
createButton("\nDel dot \n", delDotPushed),
createInputBox("Dot number", screenSize / 4 - 25,
Icons.fiber_manual_record, _textNumbController),
]),
addSpaceH(3),
Row(children: [
createInputBox(
"Name", screenSize / 8 - 25, null, _textGrNmController),
//addSpaceW(screenSize / 8 - 4),
createButton("\nAdd path\n", addPathPushed), createButton("\nAdd path\n", addPathPushed),
createInputBox("Input length", screenSize / 4 - 25, createInputBox("Input length", screenSize / 4 - 25,
Icons.arrow_right_alt_outlined, _textLnthController), Icons.arrow_right_alt_outlined, _textLnthController),
]),
addSpaceH(3),
Row(children: [
addSpaceW(5),
createInputBox(
"Name", screenSize / 8 - 25, null, _textGrNmController),
//addSpaceW(screenSize / 8 - 4),
createButton("\nDel dot \n", delDotPushed),
createInputBox("Dot number", screenSize / 4 - 25,
Icons.fiber_manual_record, _textNumbController),
addSpaceW(13), addSpaceW(13),
createButton("\nDel path\n", delPathPushed), createButton("\nDel path\n", delPathPushed),
createInputBox("Destination number", screenSize / 4 - 25, createInputBox("Destination number", screenSize / 4 - 25,
@ -90,21 +92,45 @@ class _DrawingPageState extends State<DrawingPage> {
), ),
]), ]),
body: CustomPaint( body: CustomPaint(
painter: CurvePainter(gr: data), painter: CurvePainter(graphData: graphData, bfsPath: bfsPath),
child: Align( child: Align(
alignment: Alignment.topRight, alignment: Alignment.topRight,
child: ButtonBar( child: ButtonBar(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
createButton("Bfs", () {}), createButton("Bfs", bfsPushed),
createButton("Dfs", () {}), createButton("Dfs", () {}),
createButton(data.getUseLengthStr(), changeLength), createButton("Clear dfs or bfs", () => bfsPath = null),
createButton(data.getDoubleSidedStr(), changeOriented), createButton(graphData.getUseLengthStr(), changeLength),
createButton(graphData.getDoubleSidedStr(), changeOriented),
/*Text(_textGrNmController.text, /*Text(_textGrNmController.text,
style: style:
TextStyle(fontSize: 15, color: Colors.blueGrey.shade900)),*/ TextStyle(fontSize: 15, color: Colors.blueGrey.shade900)),*/
createButton("Save to file", fileSaver), createButton("Save to file", fileSaver),
createButton("Load from file", fileOpener), createButton("Load from file", fileOpener),
createButton("Help", () {
String out =
" В поле \"Graph name\" можно сменить имя графу.\n";
out +=
" Для добавления точки необходимо ввести имя в \"Dot name\" и нажать на \"Add dot\".\n";
out +=
" Для удаления точки необходимо ввести номер в \"Dot number\" и нажать на \"Del dot\".\n";
out +=
" Для добавления пути необходимо ввести: номер выходной вершины в \"Dot number\", номер входной вершины в \"Destination number\" ";
out +=
"и, если граф взвешенный, то ввести длину пути в \"Input length\". Затем нажать \"Add path\".\n";
out +=
" Для удаления пути необходимо ввести номер выходной вершины в \"Dot number\" и номер входной вершины в \"Destination number\". Затем нажать \"Del path\".\n\n";
out +=
" Кнопки \"Bfs\" и \"Dfs\" нумеруют точки в зависимости от послежовательности, в которой они будут пройдены.\n";
out +=
" Кнопки \"Взвешенный\" и \"Ориентированный\" позволяют сменить эти значения перед построением графа (т.е. для их работы граф должен быть пустым).\n";
out +=
" Кнопки \"Save to file\" и \"Load from file\" позволяют вывести информацию в файл и загрузить информацию из файла соответственно.\n";
out +=
" Кнопка \"Help\" описывает работу с интерфейсом программы.";
showPopUp("Help:", out);
})
], ],
), ),
), ),
@ -135,7 +161,7 @@ class _DrawingPageState extends State<DrawingPage> {
child: TextField( child: TextField(
controller: controller, controller: controller,
textAlign: TextAlign.center, textAlign: TextAlign.center,
onChanged: (name) => data.setName(name), onChanged: (name) => graphData.setName(name),
decoration: InputDecoration( decoration: InputDecoration(
contentPadding: contentPadding:
const EdgeInsets.symmetric(vertical: 10, horizontal: 10), const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
@ -176,6 +202,21 @@ class _DrawingPageState extends State<DrawingPage> {
return SizedBox(width: w); return SizedBox(width: w);
} }
void showPopUp(String alertTitle, String err) => showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: Text(alertTitle),
content: Text(err),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
),
);
//*********ButtonsFunctions*********
void addDotPushed() { void addDotPushed() {
//showPopUp("Test", "Test message"); //showPopUp("Test", "Test message");
//var inp = int.tryParse(_textNameController.text); //var inp = int.tryParse(_textNameController.text);
@ -183,7 +224,7 @@ class _DrawingPageState extends State<DrawingPage> {
if (_textNameController.text == "") { if (_textNameController.text == "") {
showPopUp("Error", "No name in \"Dot name\" box"); showPopUp("Error", "No name in \"Dot name\" box");
} else { } else {
String? res = data.addIsolated(_textNameController.text); String? res = graphData.addIsolated(_textNameController.text);
if (res != null) { if (res != null) {
showPopUp("Error", res); showPopUp("Error", res);
} }
@ -197,8 +238,9 @@ class _DrawingPageState extends State<DrawingPage> {
if (_textNumbController.text == "") { if (_textNumbController.text == "") {
showPopUp("Error", "No number in \"Dot number\" box"); showPopUp("Error", "No number in \"Dot number\" box");
} else if (_textDestController.text == "") { } else if (_textDestController.text == "") {
showPopUp("Error", "No name in \"Dot name\" box"); showPopUp("Error", "No name in \"Destination number\" box");
} else if (_textLnthController.text == "" && data.getUseLengthBool()) { } else if (_textLnthController.text == "" &&
graphData.getUseLengthBool()) {
showPopUp("Error", "No length in \"Input length\" box"); showPopUp("Error", "No length in \"Input length\" box");
} else { } else {
int? from = int.tryParse(_textNumbController.text); int? from = int.tryParse(_textNumbController.text);
@ -206,12 +248,12 @@ class _DrawingPageState extends State<DrawingPage> {
int? len = int.tryParse(_textLnthController.text); int? len = int.tryParse(_textLnthController.text);
if (from == null || if (from == null ||
to == null || to == null ||
(len == null && data.getUseLengthBool())) { (len == null && graphData.getUseLengthBool())) {
showPopUp("Error", showPopUp("Error",
"Can't parse input.\nInts only allowed in \"Dot number\", \"Destination number\" and \"Input length\""); "Can't parse input.\nInts only allowed in \"Dot number\", \"Destination number\" and \"Input length\"");
} else { } else {
if (data.getUseLengthBool() && len == null) len = 0; len ??= 0;
String? res = data.addPath(from, to, len!); String? res = graphData.addPath(from, to, len);
if (res != null) { if (res != null) {
showPopUp("Error", res); showPopUp("Error", res);
} }
@ -221,23 +263,16 @@ class _DrawingPageState extends State<DrawingPage> {
}); });
} }
void addLenPushed() {
//data.delDot()
print(
"${_textNumbController.text} -> ${_textDestController.text} = ${_textLnthController.text}");
clearTextControllers();
}
void changeOriented() { void changeOriented() {
setState(() { setState(() {
String? res = data.flipUseOrientation(); String? res = graphData.flipUseOrientation();
if (res != null) showPopUp("Error", res); if (res != null) showPopUp("Error", res);
}); });
} }
void changeLength() { void changeLength() {
setState(() { setState(() {
String? res = data.flipUseLength(); String? res = graphData.flipUseLength();
if (res != null) showPopUp("Error", res); if (res != null) showPopUp("Error", res);
}); });
} }
@ -255,7 +290,7 @@ class _DrawingPageState extends State<DrawingPage> {
showPopUp("Error", showPopUp("Error",
"Can't parse input.\nInts only allowed in \"Dot number\" and \"Destination number\""); "Can't parse input.\nInts only allowed in \"Dot number\" and \"Destination number\"");
} else { } else {
String? res = data.delPath(from, to); String? res = graphData.delPath(from, to);
if (res != null) { if (res != null) {
showPopUp("Error", res); showPopUp("Error", res);
} }
@ -274,7 +309,7 @@ class _DrawingPageState extends State<DrawingPage> {
if (dot == null) { if (dot == null) {
showPopUp("Error", "Can't parse input.\nInts only allowed"); showPopUp("Error", "Can't parse input.\nInts only allowed");
} else { } else {
String? res = data.delDot(dot); String? res = graphData.delDot(dot);
if (res != null) { if (res != null) {
showPopUp("Error", res); showPopUp("Error", res);
} }
@ -284,20 +319,6 @@ class _DrawingPageState extends State<DrawingPage> {
}); });
} }
void showPopUp(String alertTitle, String err) => showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: Text(alertTitle),
content: Text(err),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
),
);
void fileOpener() async { void fileOpener() async {
FilePickerResult? result = FilePickerResult? result =
await FilePicker.platform.pickFiles(allowedExtensions: ["txt"]); await FilePicker.platform.pickFiles(allowedExtensions: ["txt"]);
@ -307,7 +328,8 @@ class _DrawingPageState extends State<DrawingPage> {
showPopUp("Error", "Can open only \".txt\" files"); showPopUp("Error", "Can open only \".txt\" files");
} else { } else {
//print(result.files.single.path!); //print(result.files.single.path!);
String? res = data.replaceDataFromFile(result.files.single.path!); String? res =
graphData.replaceDataFromFile(result.files.single.path!);
if (res != null) showPopUp("Error", res); if (res != null) showPopUp("Error", res);
} }
} else { } else {
@ -329,9 +351,34 @@ class _DrawingPageState extends State<DrawingPage> {
if (!outputFile.endsWith(".txt")) { if (!outputFile.endsWith(".txt")) {
outputFile += ".txt"; outputFile += ".txt";
} }
data.printToFile(outputFile); graphData.printToFile(outputFile);
} }
} }
void clearScreen() => data.flushData(); void bfsPushed() {
setState(() {
if (_textNumbController.text == "") {
showPopUp("Error", "No number in \"Dot number\" box");
} else if (_textDestController.text == "") {
showPopUp("Error", "No name in \"Destination number\" box");
} else {
int? from = int.tryParse(_textNumbController.text);
int? to = int.tryParse(_textDestController.text);
if (from == null || to == null) {
showPopUp("Error",
"Can't parse input.\nInts only allowed in \"Dot number\" and \"Destination number\"");
} else {
bfsPath = graphData.bfsPath(from, to);
if (bfsPath == null) {
showPopUp("Info", "There is no path");
}
print(bfsPath);
}
}
clearTextControllers();
});
}
void clearScreen() => graphData.flushData();
//*********ButtonsFunctions*********
} }

10
flutter/star.txt Normal file
View File

@ -0,0 +1,10 @@
star
Ориентированный
НеВзвешенный
1: 2|0
2: 4|0
3: 5|0
4: 6|0
5: 2|0
6: 3|0
END