Skip to content

Commit af88538

Browse files
feat:update flow functions
1 parent 7f4f21c commit af88538

File tree

9 files changed

+579
-473
lines changed

9 files changed

+579
-473
lines changed

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,13 @@ Here are some of the key features of `flutter_easy_flow` in action:
1111
- **Real-time Data Rendering**: Automatically render flow diagrams based on real-time data.
1212
- **Real-time Data Viewing**: View the underlying data of flow diagrams in real-time.
1313

14-
<!-- ![Screen Recording](screen_recording.gif) -->
14+
![Screen Recording](screen_recording.gif)
1515

1616
## 🛠️ Installation
1717

1818
To get started with `flutter_easy_flow`, follow these steps:
1919

2020
1. Clone the repository:
21-
```bash
22-
git clone https://github.com/yourusername/flutter_easy_flow.git
23-
```
2421
2. Navigate to the project directory:
2522
```bash
2623
cd flutter_easy_flow
@@ -43,6 +40,17 @@ Welcome contributions from the community. If you would like to contribute, pleas
4340
3. Commit your changes and push the branch to your fork.
4441
4. Create a pull request with a detailed description of your changes.
4542

43+
### 📝 TODO
44+
45+
Here are some upcoming features that are planned for `flutter_easy_flow`:
46+
47+
1. **Collapsible Group Nodes**: Add support for collapsing and expanding group nodes to manage complex diagrams more efficiently.
48+
2. **Local Data Persistence**: Save canvas data locally and support data restoration to continue work seamlessly.
49+
3. **Animated JSON Data Panel**: Introduce an animated panel on the left side to expand or collapse JSON data for better data management.
50+
51+
## Stargazers over time
52+
[![Stargazers over time](https://starchart.cc/Jason-chen-coder/Flutter-EasyFlow.svg?)](https://starchart.cc/Jason-chen-coder/Flutter-EasyFlow)
53+
4654
### 📄 License
4755

4856
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.

lib/flow_chart/dashboard.dart

Lines changed: 67 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,26 @@ import './flow_chart_library.dart';
1515
import './ui/draw_arrow.dart';
1616
import './ui/segment_handler.dart';
1717

18+
/// 普通节点默认尺寸
19+
const Size defaultElementSize = Size(250, 60);
20+
21+
/// 组节点默认尺寸
22+
const Size defaultGroupElementSize = Size(320, 80);
23+
24+
/// 节点的padding
25+
const double elementPadding = 10;
26+
27+
/// 默认的锚点大小
28+
const double defaultHandlerSize = 20;
29+
1830
/// 组节点内子节点的间距
19-
const double groupElementSpacing = 20;
31+
const double groupElementSpacing = 10;
32+
33+
/// plus节点默认大小
34+
const double defaultPlusSize = 26;
2035

2136
/// 节点间默认距离
22-
const int defaultNodeDistance = 50;
37+
const int defaultNodeDistance = 35;
2338

2439
class GroupLayoutData {
2540
final String id;
@@ -281,13 +296,10 @@ class Dashboard extends ChangeNotifier {
281296
elements
282297
.where((element) => element.taskType == TaskType.group)
283298
.map((groupElement) {
284-
final childElements = elements
285-
.where((element) => element.parentId == groupElement.id)
286-
.toList();
287299
final groupLayoutData = GroupLayoutData(
288300
id: groupElement.id,
289301
columnsLayoutData: getGroupColumnLayoutData(groupElement.id),
290-
rowsLayoutData: getGroupRowLayoutData(childElements, groupElement.id),
302+
rowsLayoutData: getGroupRowLayoutData(groupElement.id),
291303
);
292304
_allGroupsLayoutData[groupElement.id] = groupLayoutData;
293305
}).toList();
@@ -749,8 +761,7 @@ class Dashboard extends ChangeNotifier {
749761
}
750762

751763
// 获取行布局数据
752-
List<List<FlowElement>> getGroupRowLayoutData(
753-
List<FlowElement> childElements, String groupId) {
764+
List<List<FlowElement>> getGroupRowLayoutData(String groupId) {
754765
FlowElement? groupElement = findElementById(groupId);
755766
List<List<FlowElement>> groupRowLayoutData = [];
756767
if (groupElement != null) {
@@ -1191,6 +1202,7 @@ class Dashboard extends ChangeNotifier {
11911202
// 删除组节点需要删除所有其子节点
11921203
if (removedElement.taskType == TaskType.group) {
11931204
elements.removeWhere((element) => element.parentId == removedElement.id);
1205+
allGroupsLayoutData.remove(removedElement.id);
11941206
}
11951207
// 移除当前节点所有的连接
11961208
for (final e in elements) {
@@ -1222,21 +1234,26 @@ class Dashboard extends ChangeNotifier {
12221234
.where((ele) => ele.parentId == removedElement.parentId)
12231235
.toList();
12241236
final groupElement = findElementById(removedElement.parentId)!;
1237+
final lastGroupColumnLayoutData =
1238+
getGroupColumnLayoutData(removedElement.parentId);
12251239
final removedElementColumnIndex = groupElement.colsElementIds
12261240
.indexWhere((elementIds) => elementIds.contains(removedElementId));
12271241
final removedElementRowIndex = groupElement.rowsElementIds
12281242
.indexWhere((elementIds) => elementIds.contains(removedElementId));
12291243
final lastColsLength = groupElement.colsElementIds.length;
12301244
final lastRowsLength = groupElement.rowsElementIds.length;
12311245
if (removedElementColumnIndex != -1 && removedElementRowIndex != -1) {
1232-
groupElement.colsElementIds[removedElementColumnIndex]
1233-
[removedElementRowIndex] = "";
1246+
if (removedEleNextEle != null) {
1247+
groupElement.colsElementIds[removedElementColumnIndex]
1248+
.removeAt(removedElementRowIndex);
1249+
groupElement.colsElementIds[removedElementColumnIndex].add("");
1250+
} else {
1251+
groupElement.colsElementIds[removedElementColumnIndex]
1252+
[removedElementRowIndex] = "";
1253+
}
12341254
groupElement.colsElementIds =
12351255
cleanLastEmptyItems(groupElement.colsElementIds);
1236-
groupElement.rowsElementIds[removedElementRowIndex]
1237-
[removedElementColumnIndex] = "";
1238-
groupElement.rowsElementIds =
1239-
cleanLastEmptyItems(groupElement.rowsElementIds);
1256+
groupElement.rowsElementIds = transpose(groupElement.colsElementIds);
12401257
}
12411258
final colsLength = groupElement.colsElementIds.length;
12421259
final rowsLength = groupElement.rowsElementIds.length;
@@ -1256,12 +1273,32 @@ class Dashboard extends ChangeNotifier {
12561273
decreaseWidth =
12571274
removedElement.size.width + currentGroupElementSpacing;
12581275
}
1276+
if (rowsLength == 0) {
1277+
decreaseHeight =
1278+
(defaultNodeDistance + defaultHandlerSize) * zoomFactor;
1279+
}
12591280
}
1281+
} else {
1282+
final sourceElementBottomHandlerPos =
1283+
sourceElement.getHandlerPosition(Alignment.bottomCenter);
1284+
final removedEleBottomHandlerPos =
1285+
removedElement.getHandlerPosition(Alignment.bottomCenter);
1286+
decreaseHeight =
1287+
removedEleBottomHandlerPos.dy - sourceElementBottomHandlerPos.dy;
12601288
}
1261-
final lastGroupColumnLayoutData =
1262-
getGroupColumnLayoutData(removedElement.parentId);
12631289

1264-
// 移除当前节点
1290+
List<FlowElement> bottomOfRemovedElements = [];
1291+
for (List<FlowElement> columnElements in lastGroupColumnLayoutData) {
1292+
if (columnElements.first.position.dx == removedElement.position.dx) {
1293+
bottomOfRemovedElements = columnElements.where((ele) {
1294+
return double.parse(ele.position.dy.toStringAsFixed(4)) >
1295+
double.parse(removedElement.position.dy.toStringAsFixed(4));
1296+
}).toList();
1297+
break;
1298+
}
1299+
}
1300+
1301+
/// 移除当前节点
12651302
elements.removeWhere((element) {
12661303
if (element.id == removedElementId) {
12671304
return true;
@@ -1270,52 +1307,32 @@ class Dashboard extends ChangeNotifier {
12701307
}
12711308
});
12721309

1273-
// 移除当前节点所有的连接
1310+
/// 移除当前节点所有的连接
12741311
for (final e in elements) {
12751312
e.next.removeWhere((handlerParams) {
12761313
return removedElementId.contains(handlerParams.destElementId);
12771314
});
12781315
}
12791316

1280-
List<FlowElement> bottomOfRemovedElements = [];
1281-
for (List<FlowElement> columnElements in lastGroupColumnLayoutData) {
1282-
if (columnElements.first.position.dx == removedElement.position.dx) {
1283-
bottomOfRemovedElements = columnElements.where((ele) {
1284-
return double.parse(ele.position.dy.toStringAsFixed(4)) >
1285-
double.parse(removedElement.position.dy.toStringAsFixed(4));
1286-
}).toList();
1287-
break;
1288-
}
1289-
}
1317+
/// 移除节点后,更新组内其他节点位置和连线
12901318
updateLayOutAfterDelElementInGroup(
12911319
removedElement, sourceElement, bottomOfRemovedElements, decreaseHeight);
12921320

1321+
/// 更新组节点大小和位置
12931322
List<FlowElement> childElements = elements
12941323
.where((ele) => ele.parentId == removedElement.parentId)
12951324
.toList();
1296-
final diffElementRows = rowsLength - lastRowsLength;
1325+
int diffElementRows = rowsLength - lastRowsLength;
12971326
final diffElementCols = colsLength - lastColsLength;
1298-
if (diffElementCols < 0) {
1327+
if (diffElementCols < 0 && colsLength > 0) {
12991328
decreaseWidth = removedElement.size.width + currentGroupElementSpacing;
13001329
}
1301-
if (sourceElement != null) {
1302-
final sourceElementBottomHandlerPos =
1303-
sourceElement.getHandlerPosition(Alignment.bottomCenter);
1304-
final removedEleBottomHandlerPos =
1305-
removedElement.getHandlerPosition(Alignment.bottomCenter);
1306-
decreaseHeight =
1307-
removedEleBottomHandlerPos.dy - sourceElementBottomHandlerPos.dy;
1308-
}
1309-
1310-
(defaultNodeDistance * 2 + defaultHandlerSize * 2) * zoomFactor;
13111330

1312-
/// 判断是否需要更新组节点的大小
1313-
/// 关于高度:如果删除的节点导致行数变少了,需要更新组节点的高度
13141331
final newGroupElementSize = Size(groupElement.size.width - decreaseWidth,
13151332
groupElement.size.height + decreaseHeight * diffElementRows);
13161333

1317-
///关于宽度:如果删除的节点导致列数变少了,需要更新组节点的宽度
13181334
groupElement.size = newGroupElementSize;
1335+
13191336
if (decreaseWidth != 0) {
13201337
// 更新组节点位置
13211338
groupElement.position = Offset(
@@ -1330,7 +1347,8 @@ class Dashboard extends ChangeNotifier {
13301347
element.position.dy));
13311348
}
13321349
}
1333-
// 如果行数减少了则追加调整组外后续节点的垂直位置
1350+
1351+
/// 如果行数减少了则追加调整组外后续节点的垂直位置
13341352
if (diffElementRows < 0) {
13351353
for (var element in elements) {
13361354
if (element.position.dy > removedElement.position.dy - decreaseHeight &&
@@ -1633,15 +1651,18 @@ class Dashboard extends ChangeNotifier {
16331651

16341652
List<List<String>> cleanLastEmptyItems(List<List<String>> matrix) {
16351653
if (matrix.isEmpty) return matrix;
1636-
16371654
// 如果所有子数组的最后一项都为空字符串,则移除最后一项
16381655
if (matrix.every((row) => row.isNotEmpty && row.last.isEmpty)) {
1639-
return matrix.map((row) => row.sublist(0, row.length - 1)).toList();
1656+
return matrix
1657+
.map((row) => row.sublist(0, row.length - 1))
1658+
.where((row) => row.isNotEmpty)
1659+
.toList();
16401660
}
16411661

16421662
// 否则,过滤掉空子数组并返回原始数组
16431663
return matrix
16441664
.where((row) => row.where((item) => item != "").isNotEmpty)
1665+
.where((row) => row.isNotEmpty)
16451666
.toList();
16461667
}
16471668
}

lib/flow_chart/elements/flow_element.dart

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ import 'package:uuid/uuid.dart';
88
import '../dashboard.dart';
99
import 'connection_params.dart';
1010

11-
const Size defaultElementSize = Size(310, 60);
12-
const Size defaultGoupElementSize = Size(400, 80);
13-
const Size defaultPlusElementSize = Size(36, 36);
14-
const double elementPadding = 10;
15-
const double defaultHandlerSize = 20;
1611

1712
enum TaskType { none, trigger, delay, timeout, grab, end, plus, group }
1813

0 commit comments

Comments
 (0)