Skip to content

Commit df26561

Browse files
committed
🧪 实验性的增加了xmind树形输入模式但还存在一些问题(反引号深入扩展、反斜杠广度扩展)
1 parent 04c9416 commit df26561

File tree

2 files changed

+108
-3
lines changed

2 files changed

+108
-3
lines changed

app/src/core/service/controlService/keyboardOnlyEngine/keyboardOnlyEngine.tsx

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ import { Vector } from "../../../dataStruct/Vector";
33
import { EdgeRenderer } from "../../../render/canvas2d/entityRenderer/edge/EdgeRenderer";
44
import { Camera } from "../../../stage/Camera";
55
import { Stage } from "../../../stage/Stage";
6+
import { GraphMethods } from "../../../stage/stageManager/basicMethods/GraphMethods";
7+
import { StageAutoAlignManager } from "../../../stage/stageManager/concreteMethods/StageAutoAlignManager";
68
import { StageNodeAdder } from "../../../stage/stageManager/concreteMethods/stageNodeAdder";
79
import { StageManager } from "../../../stage/stageManager/StageManager";
810
import { ConnectableEntity } from "../../../stage/stageObject/abstract/ConnectableEntity";
911
import { EntityDashTipEffect } from "../../feedbackService/effectEngine/concrete/EntityDashTipEffect";
1012
import { EntityShakeEffect } from "../../feedbackService/effectEngine/concrete/EntityShakeEffect";
1113
import { TextRiseEffect } from "../../feedbackService/effectEngine/concrete/TextRiseEffect";
1214
import { Settings } from "../../Settings";
13-
import { editTextNode } from "../controller/concrete/utilsControl";
15+
import { addTextNodeByLocation, editTextNode } from "../controller/concrete/utilsControl";
1416
import { KeyboardOnlyDirectionController } from "./keyboardOnlyDirectionController";
1517
import { NewTargetLocationSelector } from "./newTargetLocationSelector";
1618
import { SelectChangeEngine } from "./selectChangeEngine";
@@ -52,6 +54,11 @@ export namespace KeyboardOnlyEngine {
5254
*/
5355
function bindKeyEvents() {
5456
window.addEventListener("keydown", (event) => {
57+
if (event.key === "`") {
58+
onDeepGenerateNode();
59+
} else if (event.key === "\\") {
60+
onBroadGenerateNode();
61+
}
5562
if (event.key === "Tab") {
5663
// if (isEnableVirtualCreate()) {
5764
// createStart();
@@ -93,6 +100,66 @@ export namespace KeyboardOnlyEngine {
93100
// });
94101
}
95102

103+
function onDeepGenerateNode() {
104+
const rootNode = StageManager.getConnectableEntity().find((node) => node.isSelected);
105+
if (!rootNode) return;
106+
Camera.clearMoveCommander();
107+
Camera.speed = Vector.getZero();
108+
// 在自己的右下方创建一个节点
109+
const newLocation = rootNode.collisionBox.getRectangle().rightCenter.add(new Vector(100, 100));
110+
addTextNodeByLocation(newLocation, true, (newUUID) => {
111+
const newNode = StageManager.getTextNodeByUUID(newUUID);
112+
if (!newNode) return;
113+
// 连接到之前的节点
114+
StageManager.connectEntity(rootNode, newNode);
115+
// 重新排列树形节点
116+
const rootNodeParents = GraphMethods.getRoots(rootNode);
117+
if (rootNodeParents.length === 1) {
118+
const rootNodeParent = rootNodeParents[0];
119+
if (GraphMethods.isTree(rootNodeParent)) {
120+
StageAutoAlignManager.autoLayoutSelectedFastTreeModeRight(rootNodeParent);
121+
// 更新选择状态
122+
rootNodeParent.isSelected = false;
123+
newNode.isSelected = true;
124+
}
125+
}
126+
127+
Stage.effectMachine.addEffects(EdgeRenderer.getConnectedEffects(rootNode, newNode));
128+
});
129+
}
130+
131+
function onBroadGenerateNode() {
132+
const currentSelectNode = StageManager.getConnectableEntity().find((node) => node.isSelected);
133+
if (!currentSelectNode) return;
134+
Camera.clearMoveCommander();
135+
Camera.speed = Vector.getZero();
136+
// 找到自己的父节点
137+
const parents = GraphMethods.nodeParentArray(currentSelectNode);
138+
if (parents.length === 0) return;
139+
if (parents.length !== 1) return;
140+
const parent = parents[0];
141+
// 在自己的正下方创建一个节点
142+
const newLocation = parent.collisionBox.getRectangle().bottomCenter.add(new Vector(0, 100));
143+
addTextNodeByLocation(newLocation, true, (newUUID) => {
144+
const newNode = StageManager.getTextNodeByUUID(newUUID);
145+
if (!newNode) return;
146+
// 连接到之前的节点
147+
StageManager.connectEntity(parent, newNode);
148+
// 重新排列树形节点
149+
const rootNodeParents = GraphMethods.getRoots(parent);
150+
if (rootNodeParents.length === 1) {
151+
const rootNodeParent = rootNodeParents[0];
152+
if (GraphMethods.isTree(rootNodeParent)) {
153+
StageAutoAlignManager.autoLayoutSelectedFastTreeModeRight(rootNodeParent);
154+
// 更新选择状态
155+
rootNodeParent.isSelected = false;
156+
newNode.isSelected = true;
157+
}
158+
}
159+
Stage.effectMachine.addEffects(EdgeRenderer.getConnectedEffects(parent, newNode));
160+
});
161+
}
162+
96163
function addSuccessEffect() {
97164
const textNodes = StageManager.getTextNodes().filter((textNode) => textNode.isSelected);
98165
for (const textNode of textNodes) {

app/src/core/stage/stageManager/basicMethods/GraphMethods.tsx

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,57 @@ export namespace GraphMethods {
3232
}
3333

3434
/**
35-
* 获取一个节点的所有父亲节点,未排除自环
35+
* 获取一个节点的所有父亲节点,排除自环
3636
* 性能有待优化!!
3737
*/
3838
export function nodeParentArray(node: ConnectableEntity): ConnectableEntity[] {
3939
const res: ConnectableEntity[] = [];
4040
for (const edge of StageManager.getLineEdges()) {
41-
if (edge.target.uuid === node.uuid) {
41+
if (edge.target.uuid === node.uuid && edge.target.uuid !== edge.source.uuid) {
4242
res.push(edge.source);
4343
}
4444
}
4545
return res;
4646
}
4747

48+
/**
49+
* 获取反向边集
50+
* @param edges
51+
*/
52+
function getReversedEdgeDict(): Record<string, string> {
53+
const res: Record<string, string> = {};
54+
for (const edge of StageManager.getLineEdges()) {
55+
res[edge.target.uuid] = edge.source.uuid;
56+
}
57+
return res;
58+
}
59+
60+
/**
61+
* 获取自己的祖宗节点
62+
* @param node 节点
63+
*/
64+
export function getRoots(node: ConnectableEntity): ConnectableEntity[] {
65+
const reverseEdges = getReversedEdgeDict();
66+
let rootUUID = node.uuid;
67+
const visited: Set<string> = new Set(); // 用于记录已经访问过的节点,避免重复访问
68+
while (reverseEdges[rootUUID] && !visited.has(rootUUID)) {
69+
visited.add(rootUUID);
70+
const parentUUID = reverseEdges[rootUUID];
71+
const parent = StageManager.getConnectableEntityByUUID(parentUUID);
72+
if (parent) {
73+
rootUUID = parentUUID;
74+
} else {
75+
break;
76+
}
77+
}
78+
const root = StageManager.getConnectableEntityByUUID(rootUUID);
79+
if (root) {
80+
return [root];
81+
} else {
82+
return [];
83+
}
84+
}
85+
4886
export function isConnected(node: ConnectableEntity, target: ConnectableEntity): boolean {
4987
for (const edge of StageManager.getLineEdges()) {
5088
if (edge.source === node && edge.target === target) {

0 commit comments

Comments
 (0)