Skip to content

Commit 964f761

Browse files
update:优化组节点增删改查布局数据管理
1 parent e4b7d74 commit 964f761

File tree

4 files changed

+178
-97
lines changed

4 files changed

+178
-97
lines changed

lib/flow_chart/dashboard.dart

Lines changed: 157 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,8 @@ class Dashboard extends ChangeNotifier {
286286
.toList();
287287
final groupLayoutData = GroupLayoutData(
288288
id: groupElement.id,
289-
columnsLayoutData: getGroupColumnLayoutData(childElements),
290-
rowsLayoutData: getGroupRowLayoutData(childElements),
289+
columnsLayoutData: getGroupColumnLayoutData(groupElement.id),
290+
rowsLayoutData: getGroupRowLayoutData(childElements, groupElement.id),
291291
);
292292
_allGroupsLayoutData[groupElement.id] = groupLayoutData;
293293
}).toList();
@@ -447,12 +447,26 @@ class Dashboard extends ChangeNotifier {
447447
final groupElement = elements.firstWhere(
448448
(element) => element.id == sourceElement.parentId,
449449
);
450-
final lastChildElements =
451-
elements.where((el) => el.parentId == groupElement.id);
452-
final lastGroupRowLayoutData =
453-
getGroupRowLayoutData(lastChildElements.toList());
454450
// 新增节点
455451
addElement(orderElement);
452+
final lastRowNum = groupElement.rowsElementIds.length;
453+
454+
final sourceElementColumnIndex = groupElement.colsElementIds
455+
.indexWhere((elementIds) => elementIds.contains(sourceElement.id));
456+
final sourceElementRowIndex = groupElement.rowsElementIds
457+
.indexWhere((elementIds) => elementIds.contains(sourceElement.id));
458+
final columnNum = groupElement.colsElementIds.length;
459+
for (int i = 0; i < columnNum; i++) {
460+
if (i == sourceElementColumnIndex) {
461+
groupElement.colsElementIds[i]
462+
.insert(sourceElementRowIndex + 1, orderElement.id);
463+
} else {
464+
groupElement.colsElementIds[i].add("");
465+
}
466+
}
467+
groupElement.colsElementIds =
468+
cleanLastEmptyItems(groupElement.colsElementIds);
469+
groupElement.rowsElementIds = transpose(groupElement.colsElementIds);
456470

457471
// 选中当前节点
458472
setSelectedElement(orderElement.id);
@@ -480,8 +494,6 @@ class Dashboard extends ChangeNotifier {
480494

481495
/// 调整当前组当前节点所在的列后续节点的垂直位置
482496
final sourceDy = sourceElement.position.dy;
483-
final childElements =
484-
elements.where((el) => el.parentId == groupElement.id).toList();
485497
for (int i = 0; i < bottomOfSourceElementIds.length; i++) {
486498
final destElement = findElementById(bottomOfSourceElementIds[i])!;
487499
if ((destElement.position.dy > sourceDy.toDouble())) {
@@ -491,24 +503,22 @@ class Dashboard extends ChangeNotifier {
491503
}
492504

493505
/// 更新组节点大小
494-
final groupRowLayoutData = getGroupRowLayoutData(childElements.toList());
495-
final diffElementRows =
496-
groupRowLayoutData.length - lastGroupRowLayoutData.length;
506+
final diffElementRows = groupElement.rowsElementIds.length - lastRowNum;
497507
final newGroupElementSize = Size(groupElement.size.width,
498508
groupElement.size.height + addHeight * diffElementRows);
499509
final diffHeight = newGroupElementSize.height - groupElement.size.height;
500510

501511
/// 预留判断:
502512
/// 判断source的所在的列最后一个元素是否是整个组内的最后一行,最后一行才需要更新组节点大小
503513
/// 找到source所在列的最后一个元素
504-
FlowElement? sourceColumnLastElement =
505-
findElementById(bottomOfSourceElementIds.last);
506-
bool elementIsLastRow = sourceColumnLastElement == null
507-
? false
508-
: checkElementIsLastRow(sourceColumnLastElement, groupRowLayoutData);
509-
if (elementIsLastRow) {
510-
groupElement.size = newGroupElementSize;
511-
}
514+
// FlowElement? sourceColumnLastElement =
515+
// findElementById(bottomOfSourceElementIds.last);
516+
// bool elementIsLastRow = sourceColumnLastElement == null
517+
// ? false
518+
// : checkElementIsLastRow(sourceColumnLastElement, groupRowLayoutData);
519+
// if (elementIsLastRow) {
520+
groupElement.size = newGroupElementSize;
521+
// }
512522

513523
for (int i = 0; i < elements.length; i++) {
514524
if (elements[i].position.dy >= orderElement.position.dy &&
@@ -561,18 +571,6 @@ class Dashboard extends ChangeNotifier {
561571
return destElementIds;
562572
}
563573

564-
// 判断element是否是组内的最后一行
565-
bool checkElementIsLastRow(
566-
FlowElement element, List<List<FlowElement>> groupRowLayoutData) {
567-
// final lastRow = groupRowLayoutData.last;
568-
// 最后一行中y坐标最大的元素
569-
FlowElement maxDyElement = groupRowLayoutData.last.reduce((current, next) =>
570-
current.position.dy > next.position.dy ? current : next);
571-
572-
// 是否是lastRow最后一个元素
573-
return maxDyElement.position.dy == element.position.dy;
574-
}
575-
576574
// 判断element是否是组内的最后一列
577575
bool checkElementIsLastColumn(FlowElement element) {
578576
return false;
@@ -602,13 +600,28 @@ class Dashboard extends ChangeNotifier {
602600
(element) => element.id == sourceElement.parentId,
603601
);
604602

605-
final lastChildElements =
606-
elements.where((el) => el.parentId == groupElement.id);
607-
final lastGroupRowLayoutData =
608-
getGroupRowLayoutData(lastChildElements.toList());
609-
610603
/// 新增节点(节点先进画布,获取真实宽高)
611604
addElement(orderElement);
605+
// 通过sourceElementId找到他在groupElement.colsElementIds所在列
606+
final lastRowNum = groupElement.rowsElementIds.length;
607+
608+
final sourceElementColumnIndex = groupElement.colsElementIds
609+
.indexWhere((elementIds) => elementIds.contains(sourceElement.id));
610+
final sourceElementRowIndex = groupElement.rowsElementIds
611+
.indexWhere((elementIds) => elementIds.contains(sourceElement.id));
612+
final columnNum = groupElement.colsElementIds.length;
613+
for (int i = 0; i < columnNum; i++) {
614+
if (i == sourceElementColumnIndex) {
615+
groupElement.colsElementIds[i]
616+
.insert(sourceElementRowIndex + 1, orderElement.id);
617+
} else {
618+
groupElement.colsElementIds[i].add("");
619+
}
620+
}
621+
622+
groupElement.colsElementIds =
623+
cleanLastEmptyItems(groupElement.colsElementIds);
624+
groupElement.rowsElementIds = transpose(groupElement.colsElementIds);
612625

613626
///连接新节点
614627
addNextById(
@@ -621,13 +634,8 @@ class Dashboard extends ChangeNotifier {
621634
),
622635
);
623636
setSelectedElement(orderElement.id);
624-
final childElements =
625-
elements.where((el) => el.parentId == groupElement.id);
626-
627-
final groupRowLayoutData = getGroupRowLayoutData(childElements.toList());
628637

629-
final diffElementRows =
630-
groupRowLayoutData.length - lastGroupRowLayoutData.length;
638+
final diffElementRows = groupElement.rowsElementIds.length - lastRowNum;
631639

632640
/// 更新组节点大小
633641
final orderElementBottomHandlerPos =
@@ -667,6 +675,23 @@ class Dashboard extends ChangeNotifier {
667675

668676
/// 新增节点(节点先进画布,获取真实宽高)
669677
addElement(orderElement);
678+
groupElement.rowsElementIds = List.from(groupElement
679+
.rowsElementIds); // 第一行的最后一个元素为orderElement.id,其他行的最后一个元素是""
680+
if (groupElement.rowsElementIds.isNotEmpty) {
681+
for (int i = 0; i < groupElement.rowsElementIds.length; i++) {
682+
if (i == 0) {
683+
groupElement.rowsElementIds[i].add(orderElement.id);
684+
} else {
685+
groupElement.rowsElementIds[i].add("");
686+
}
687+
}
688+
} else {
689+
groupElement.rowsElementIds.add([orderElement.id]); // 新增节点在第一行
690+
}
691+
groupElement.rowsElementIds =
692+
cleanLastEmptyItems(groupElement.rowsElementIds);
693+
groupElement.colsElementIds = transpose(groupElement.rowsElementIds);
694+
670695
setSelectedElement(orderElement.id);
671696
final offsetWidth = (orderElement.size.width + currentGroupElementSpacing);
672697

@@ -687,9 +712,10 @@ class Dashboard extends ChangeNotifier {
687712
groupElement.position.dx - offsetWidth / 2, groupElement.position.dy);
688713

689714
/// 获取最右一列的坐标,并更新节点坐标
690-
List<FlowElement> lastRowsDx =
691-
getGroupColumnLayoutData(lastChildElements).last;
692-
final elementDx = lastRowsDx.first.position.dx +
715+
final elementDx = findElementById(groupElement.rowsElementIds
716+
.first[groupElement.rowsElementIds.first.length - 2])!
717+
.position
718+
.dx +
693719
(orderElement.size.width + currentGroupElementSpacing);
694720
orderElement.changePosition(Offset(elementDx, groupStartPosition.dy));
695721
List<FlowElement> childElements =
@@ -724,55 +750,39 @@ class Dashboard extends ChangeNotifier {
724750

725751
// 获取行布局数据
726752
List<List<FlowElement>> getGroupRowLayoutData(
727-
List<FlowElement> childElements) {
753+
List<FlowElement> childElements, String groupId) {
754+
FlowElement? groupElement = findElementById(groupId);
728755
List<List<FlowElement>> groupRowLayoutData = [];
729-
730-
/// 获取所有行数的Dy
731-
final subElementsOrderDy = childElements
732-
.map((childEle) => childEle.position.dy.toStringAsFixed(4))
733-
.toSet()
734-
.toList();
735-
subElementsOrderDy.sort();
736-
737-
List<List<FlowElement>> rows =
738-
List.generate(subElementsOrderDy.length, (_) => []);
739-
for (int i = 0; i < subElementsOrderDy.length; i++) {
740-
for (int j = 0; j < childElements.length; j++) {
741-
if (childElements[j].position.dy.toStringAsFixed(4) ==
742-
subElementsOrderDy[i]) {
743-
rows[i].add(childElements[j]);
756+
if (groupElement != null) {
757+
for (var rowElementIds in groupElement.rowsElementIds) {
758+
List<FlowElement> rowElements = [];
759+
for (var elementId in rowElementIds) {
760+
if (elementId != "") {
761+
FlowElement element = findElementById(elementId)!;
762+
rowElements.add(element);
763+
}
744764
}
765+
groupRowLayoutData.add(rowElements);
745766
}
746-
// 根据dx的值从小到大排序
747-
rows[i].sort((a, b) => a.position.dx.compareTo(b.position.dx));
748-
groupRowLayoutData.add(rows[i]);
749767
}
750768
return groupRowLayoutData;
751769
}
752770

753771
// 获取列布局数据
754-
List<List<FlowElement>> getGroupColumnLayoutData(
755-
List<FlowElement> childElements) {
772+
List<List<FlowElement>> getGroupColumnLayoutData(String groupId) {
773+
FlowElement? groupElement = findElementById(groupId);
756774
List<List<FlowElement>> groupColumnLayoutData = [];
757-
758-
/// 获取所有列数的Dx
759-
final subElementsOrderDx = childElements
760-
.map((childEle) => childEle.position.dx.toStringAsFixed(4))
761-
.toSet()
762-
.toList();
763-
subElementsOrderDx.sort();
764-
List<List<FlowElement>> columns =
765-
List.generate(subElementsOrderDx.length, (_) => []);
766-
for (int i = 0; i < subElementsOrderDx.length; i++) {
767-
for (int j = 0; j < childElements.length; j++) {
768-
if (childElements[j].position.dx.toStringAsFixed(4) ==
769-
subElementsOrderDx[i]) {
770-
columns[i].add(childElements[j]);
775+
if (groupElement != null) {
776+
for (var columnElementIds in groupElement.colsElementIds) {
777+
List<FlowElement> columnElements = [];
778+
for (var elementId in columnElementIds) {
779+
if (elementId != "") {
780+
FlowElement element = findElementById(elementId)!;
781+
columnElements.add(element);
782+
}
771783
}
784+
groupColumnLayoutData.add(columnElements);
772785
}
773-
// 根据dx的值从小到大排序
774-
columns[i].sort((a, b) => a.position.dy.compareTo(b.position.dy));
775-
groupColumnLayoutData.add(columns[i]);
776786
}
777787
return groupColumnLayoutData;
778788
}
@@ -1204,13 +1214,32 @@ class Dashboard extends ChangeNotifier {
12041214
FlowElement? sourceElement = findSrcElementByDestElement(removedElement);
12051215
double decreaseHeight = 0;
12061216
double decreaseWidth = 0;
1217+
final currentGroupElementSpacing = groupElementSpacing * zoomFactor;
12071218
FlowElement? removedEleNextEle = removedElement.next.isNotEmpty
12081219
? findElementById(removedElement.next.first.destElementId)
12091220
: null;
12101221
List<FlowElement> lastChildElements = elements
12111222
.where((ele) => ele.parentId == removedElement.parentId)
12121223
.toList();
12131224
final groupElement = findElementById(removedElement.parentId)!;
1225+
final removedElementColumnIndex = groupElement.colsElementIds
1226+
.indexWhere((elementIds) => elementIds.contains(removedElementId));
1227+
final removedElementRowIndex = groupElement.rowsElementIds
1228+
.indexWhere((elementIds) => elementIds.contains(removedElementId));
1229+
final lastColsLength = groupElement.colsElementIds.length;
1230+
final lastRowsLength = groupElement.rowsElementIds.length;
1231+
if (removedElementColumnIndex != -1 && removedElementRowIndex != -1) {
1232+
groupElement.colsElementIds[removedElementColumnIndex]
1233+
[removedElementRowIndex] = "";
1234+
groupElement.colsElementIds =
1235+
cleanLastEmptyItems(groupElement.colsElementIds);
1236+
groupElement.rowsElementIds[removedElementRowIndex]
1237+
[removedElementColumnIndex] = "";
1238+
groupElement.rowsElementIds =
1239+
cleanLastEmptyItems(groupElement.rowsElementIds);
1240+
}
1241+
final colsLength = groupElement.colsElementIds.length;
1242+
final rowsLength = groupElement.rowsElementIds.length;
12141243
if (sourceElement == null) {
12151244
//删除的是组内的第一行的节点
12161245
if (removedEleNextEle != null) {
@@ -1224,16 +1253,14 @@ class Dashboard extends ChangeNotifier {
12241253
} else {
12251254
//删除的节点下面没有其他节点,删除后组直接少一列
12261255
if (lastChildElements.length > 1) {
1227-
final currentGroupElementSpacing = groupElementSpacing * zoomFactor;
12281256
decreaseWidth =
12291257
removedElement.size.width + currentGroupElementSpacing;
12301258
}
12311259
}
12321260
}
1233-
final lastGroupRowLayoutData =
1234-
getGroupRowLayoutData(lastChildElements.toList());
12351261
final lastGroupColumnLayoutData =
1236-
getGroupColumnLayoutData(lastChildElements.toList());
1262+
getGroupColumnLayoutData(removedElement.parentId);
1263+
12371264
// 移除当前节点
12381265
elements.removeWhere((element) {
12391266
if (element.id == removedElementId) {
@@ -1249,6 +1276,7 @@ class Dashboard extends ChangeNotifier {
12491276
return removedElementId.contains(handlerParams.destElementId);
12501277
});
12511278
}
1279+
12521280
List<FlowElement> bottomOfRemovedElements = [];
12531281
for (List<FlowElement> columnElements in lastGroupColumnLayoutData) {
12541282
if (columnElements.first.position.dx == removedElement.position.dx) {
@@ -1265,9 +1293,11 @@ class Dashboard extends ChangeNotifier {
12651293
List<FlowElement> childElements = elements
12661294
.where((ele) => ele.parentId == removedElement.parentId)
12671295
.toList();
1268-
final groupRowLayoutData = getGroupRowLayoutData(childElements.toList());
1269-
final diffElementRows =
1270-
groupRowLayoutData.length - lastGroupRowLayoutData.length;
1296+
final diffElementRows = rowsLength - lastRowsLength;
1297+
final diffElementCols = colsLength - lastColsLength;
1298+
if (diffElementCols < 0) {
1299+
decreaseWidth = removedElement.size.width + currentGroupElementSpacing;
1300+
}
12711301
if (sourceElement != null) {
12721302
final sourceElementBottomHandlerPos =
12731303
sourceElement.getHandlerPosition(Alignment.bottomCenter);
@@ -1577,4 +1607,41 @@ class Dashboard extends ChangeNotifier {
15771607
updateAllGroupsLayoutData();
15781608
setFullView();
15791609
}
1610+
1611+
// 矩阵转置
1612+
List<List<T>> transpose<T>(List<List<T>> matrix) {
1613+
if (matrix.isEmpty || matrix[0].isEmpty) return [];
1614+
1615+
int rowCount = matrix.length;
1616+
int colCount = matrix[0].length;
1617+
1618+
// 创建一个新的二维数组
1619+
List<List<T>> result = List.generate(
1620+
colCount,
1621+
(_) => List<T>.filled(rowCount, matrix[0][0], growable: true),
1622+
);
1623+
1624+
// 填充转置后的数组
1625+
for (int i = 0; i < rowCount; i++) {
1626+
for (int j = 0; j < colCount; j++) {
1627+
result[j][i] = matrix[i][j];
1628+
}
1629+
}
1630+
1631+
return result;
1632+
}
1633+
1634+
List<List<String>> cleanLastEmptyItems(List<List<String>> matrix) {
1635+
if (matrix.isEmpty) return matrix;
1636+
1637+
// 如果所有子数组的最后一项都为空字符串,则移除最后一项
1638+
if (matrix.every((row) => row.isNotEmpty && row.last.isEmpty)) {
1639+
return matrix.map((row) => row.sublist(0, row.length - 1)).toList();
1640+
}
1641+
1642+
// 否则,过滤掉空子数组并返回原始数组
1643+
return matrix
1644+
.where((row) => row.where((item) => item != "").isNotEmpty)
1645+
.toList();
1646+
}
15801647
}

0 commit comments

Comments
 (0)