Skip to content

Commit 3da76ae

Browse files
authored
Merge pull request #28 from easyops-cn/zekun/diagram
feat(): 拓扑图支持快捷键shift快速选择和取消选择多个元素,原框选功能需要支持选中边
2 parents 3c328cf + 9b2b01b commit 3da76ae

File tree

12 files changed

+182
-61
lines changed

12 files changed

+182
-61
lines changed

bricks/diagram/src/draw-canvas/CellComponent.tsx

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
NodeBrickConf,
1414
NodeCell,
1515
EditableLine,
16+
BaseEdgeCell,
1617
} from "./interfaces";
1718
import {
1819
isContainerDecoratorCell,
@@ -51,6 +52,10 @@ export interface CellComponentProps {
5152
unrelatedCells: Cell[];
5253
dragNodeToContainerActive?: boolean;
5354
allowEdgeToArea?: boolean;
55+
curActiveEditableEdge?: BaseEdgeCell | null;
56+
updateCurActiveEditableEdge?: (
57+
activeEditableEdge: BaseEdgeCell | null
58+
) => void;
5459
onCellsMoving?(info: MoveCellPayload[]): void;
5560
onCellsMoved?(info: MoveCellPayload[]): void;
5661
onCellResizing?(info: ResizeCellPayload): void;
@@ -82,6 +87,8 @@ export function CellComponent({
8287
hoverCell,
8388
unrelatedCells,
8489
allowEdgeToArea,
90+
curActiveEditableEdge,
91+
updateCurActiveEditableEdge,
8592
onCellsMoving,
8693
onCellsMoved,
8794
onCellResizing,
@@ -96,7 +103,6 @@ export function CellComponent({
96103
onCellMouseLeave,
97104
}: CellComponentProps): JSX.Element | null {
98105
const {
99-
activeEditableEdge,
100106
lineEditorState,
101107
smartConnectLineState,
102108
setSmartConnectLineState,
@@ -109,7 +115,7 @@ export function CellComponent({
109115
() => unrelatedCells.some((item) => sameTarget(item, cell)),
110116
[cell, unrelatedCells]
111117
);
112-
// `containerRect` is undefined when it's an edge cell.
118+
113119
const containerRect = useMemo((): DecoratorView | undefined => {
114120
if (isContainerDecoratorCell(cell) && isNoManualLayout(layout)) {
115121
const containCells = cells.filter(
@@ -150,6 +156,7 @@ export function CellComponent({
150156
onCellsMoving,
151157
onCellsMoved,
152158
onSwitchActiveTarget,
159+
updateCurActiveEditableEdge,
153160
});
154161
}
155162
};
@@ -169,7 +176,6 @@ export function CellComponent({
169176
readOnly,
170177
transform.k,
171178
]);
172-
173179
// istanbul ignore next: experimental
174180
useEffect(() => {
175181
const g = gRef.current;
@@ -196,10 +202,10 @@ export function CellComponent({
196202
);
197203
}
198204
setSmartConnectLineState(null);
199-
} else if (activeEditableEdge && lineEditorState) {
205+
} else if (curActiveEditableEdge && lineEditorState) {
200206
const { type } = lineEditorState;
201-
const { source, target } = editableLineMap.get(activeEditableEdge)!;
202-
const { view } = activeEditableEdge;
207+
const { source, target } = editableLineMap.get(curActiveEditableEdge)!;
208+
const { view } = curActiveEditableEdge;
203209

204210
const isEntry = type === "entry";
205211
if ((isEntry ? target : source) === cell) {
@@ -225,7 +231,7 @@ export function CellComponent({
225231
g.removeEventListener("mouseup", onMouseUp);
226232
};
227233
}, [
228-
activeEditableEdge,
234+
curActiveEditableEdge,
229235
editableLineMap,
230236
allowEdgeToArea,
231237
cell,
@@ -235,6 +241,7 @@ export function CellComponent({
235241
setLineEditorState,
236242
setSmartConnectLineState,
237243
smartConnectLineState,
244+
updateCurActiveEditableEdge,
238245
]);
239246

240247
const handleContextMenu = useCallback(
@@ -276,7 +283,6 @@ export function CellComponent({
276283
}, [cell, onCellMouseLeave]);
277284

278285
const active = targetIsActive(cell, activeTarget);
279-
280286
return (
281287
<g
282288
className={classNames("cell", {

bricks/diagram/src/draw-canvas/EdgeComponent.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,18 @@ export function EdgeComponent({
139139
if (element) {
140140
// Jest does not support `SVGPathElement::getTotalLength`
141141
setPathLength(element.getTotalLength?.() ?? 100);
142+
const rect = element.getBBox?.();
143+
edge.view = {
144+
...edge.view,
145+
x: rect?.x,
146+
y: rect?.y,
147+
width: rect?.width,
148+
height: rect?.height,
149+
};
142150
}
143151
updateLabelPosition();
144152
},
145-
[updateLabelPosition]
153+
[updateLabelPosition, edge]
146154
);
147155

148156
const [labelElement, setLabelElement] = useState<HTMLElement | null>(null);

bricks/diagram/src/draw-canvas/EditingLineComponent.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,21 @@ export interface EditingLineComponentProps {
2626
editableLineMap: WeakMap<EdgeCell, EditableLine>;
2727
transform: TransformLiteral;
2828
options: ComputedLineConnecterConf;
29+
activeEditableEdge: EdgeCell | null;
2930
}
3031

3132
export function EditingLineComponent({
3233
cells,
3334
editableLineMap,
3435
transform,
3536
options,
37+
activeEditableEdge,
3638
}: EditingLineComponentProps): JSX.Element {
3739
const [connectLineTo, setConnectLineTo] = useState<PositionTuple | null>(
3840
null
3941
);
40-
const {
41-
activeEditableEdge,
42-
hoverState,
43-
lineEditorState,
44-
setLineEditorState,
45-
onChangeEdgeView,
46-
} = useHoverStateContext();
42+
const { hoverState, lineEditorState, setLineEditorState, onChangeEdgeView } =
43+
useHoverStateContext();
4744
const movedRef = useRef(false);
4845

4946
useEffect(() => {

bricks/diagram/src/draw-canvas/HoverStateContext.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const HoverStateContext = React.createContext<{
2323
smartConnectLineState: SmartConnectLineState | null;
2424
unsetHoverStateTimeoutRef: React.MutableRefObject<number | null>;
2525
hoverState: HoverState | null;
26-
activeEditableEdge: EdgeCell | null;
26+
activeEditableEdges: EdgeCell[];
2727
lineEditorState: LineEditorState | null;
2828
setLineEditorState: React.Dispatch<
2929
React.SetStateAction<LineEditorState | null>
@@ -48,7 +48,7 @@ export const HoverStateContext = React.createContext<{
4848
smartConnectLineState: null,
4949
unsetHoverStateTimeoutRef: { current: null },
5050
hoverState: null,
51-
activeEditableEdge: null,
51+
activeEditableEdges: [],
5252
lineEditorState: null,
5353
setLineEditorState: () => {},
5454
setHoverState: () => {},

bricks/diagram/src/draw-canvas/LineConnectorComponent.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,22 @@ export interface LineConnectorComponentProps {
2222
activeTarget: ActiveTarget | null;
2323
editableLineMap: WeakMap<EdgeCell, EditableLine>;
2424
scale: number;
25+
activeEditableEdge: EdgeCell | null;
2526
disabled?: boolean;
2627
}
2728

2829
export function LineConnectorComponent({
2930
activeTarget,
3031
editableLineMap,
3132
scale,
33+
activeEditableEdge,
3234
disabled,
3335
}: LineConnectorComponentProps): JSX.Element | null {
3436
const {
3537
unsetHoverStateTimeoutRef,
3638
hoverState,
3739
setHoverState,
3840
smartConnectLineState,
39-
activeEditableEdge,
4041
lineEditorState,
4142
} = useHoverStateContext();
4243

@@ -112,6 +113,7 @@ export function LineConnectorComponent({
112113
index={index}
113114
point={point}
114115
scale={scale}
116+
activeEditableEdge={activeEditableEdge}
115117
unsetActivePointIndex={unsetActivePointIndex}
116118
unsetTimeout={unsetTimeout}
117119
/>
@@ -127,6 +129,7 @@ interface ConnectPointComponentProps {
127129
index: number;
128130
point: NodePosition;
129131
scale: number;
132+
activeEditableEdge: EdgeCell | null;
130133
unsetTimeout: () => void;
131134
unsetActivePointIndex: () => void;
132135
}
@@ -136,6 +139,7 @@ function ConnectPointComponent({
136139
index,
137140
point,
138141
scale,
142+
activeEditableEdge,
139143
unsetTimeout,
140144
unsetActivePointIndex,
141145
}: ConnectPointComponentProps): JSX.Element {
@@ -146,7 +150,6 @@ function ConnectPointComponent({
146150
setHoverState,
147151
setSmartConnectLineState,
148152
onConnect,
149-
activeEditableEdge,
150153
lineEditorState,
151154
setLineEditorState,
152155
onChangeEdgeView,

bricks/diagram/src/draw-canvas/LineEditorComponent.tsx

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
import React, { useEffect, useMemo, useRef } from "react";
33
import type { NodePosition } from "../diagram/interfaces";
44
import { useHoverStateContext } from "./HoverStateContext";
5-
import type { ControlPoint, EdgeCell, EditableLine } from "./interfaces";
5+
import type {
6+
BaseEdgeCell,
7+
ControlPoint,
8+
EdgeCell,
9+
EditableLine,
10+
} from "./interfaces";
611
import { isStraightType } from "./processors/asserts";
712

813
const POINT_HELPER_IMAGE =
@@ -16,18 +21,22 @@ const POINT_HELPER_BG_SIZE = 22;
1621
export interface LineEditorComponentProps {
1722
scale: number;
1823
editableLineMap: WeakMap<EdgeCell, EditableLine>;
24+
activeEditableEdge: EdgeCell;
25+
updateCurActiveEditableEdge?: (
26+
activeEditableEdge: BaseEdgeCell | null
27+
) => void;
1928
}
2029

2130
export function LineEditorComponent({
2231
scale,
2332
editableLineMap,
33+
activeEditableEdge,
34+
updateCurActiveEditableEdge,
2435
}: LineEditorComponentProps): JSX.Element | null {
25-
const { rootRef, activeEditableEdge, setLineEditorState } =
26-
useHoverStateContext();
36+
const { rootRef, setLineEditorState } = useHoverStateContext();
2737
const exitRef = useRef<SVGImageElement>(null);
2838
const entryRef = useRef<SVGImageElement>(null);
2939
const controlPointsRef = useRef<(SVGImageElement | null)[]>([]);
30-
3140
useEffect(() => {
3241
const exit = exitRef.current;
3342
const entry = entryRef.current;
@@ -44,6 +53,7 @@ export function LineEditorComponent({
4453
from: [e.clientX, e.clientY],
4554
type,
4655
});
56+
updateCurActiveEditableEdge?.(activeEditableEdge);
4757
};
4858
};
4959
const handleStartMouseDown = handleMouseDownFactory("exit");
@@ -54,14 +64,18 @@ export function LineEditorComponent({
5464
exit.removeEventListener("mousedown", handleStartMouseDown);
5565
entry.removeEventListener("mousedown", handleEndMouseDown);
5666
};
57-
}, [activeEditableEdge, rootRef, setLineEditorState]);
67+
}, [
68+
activeEditableEdge,
69+
rootRef,
70+
setLineEditorState,
71+
updateCurActiveEditableEdge,
72+
]);
5873

5974
const controlPoints = useMemo(() => {
6075
return activeEditableEdge && !isStraightType(activeEditableEdge.view?.type)
6176
? getControlPoints(editableLineMap.get(activeEditableEdge)!.points!)
6277
: [];
6378
}, [activeEditableEdge, editableLineMap]);
64-
6579
useEffect(() => {
6680
if (!activeEditableEdge) {
6781
return;
@@ -71,6 +85,7 @@ export function LineEditorComponent({
7185
return (e: MouseEvent) => {
7286
e.stopPropagation();
7387
e.preventDefault();
88+
updateCurActiveEditableEdge?.(activeEditableEdge);
7489
const rect = rootRef.current!.getBoundingClientRect();
7590
setLineEditorState({
7691
offset: [rect.left, rect.top],
@@ -91,7 +106,13 @@ export function LineEditorComponent({
91106
el?.removeEventListener("mousedown", handlers[i]);
92107
});
93108
};
94-
}, [activeEditableEdge, controlPoints, rootRef, setLineEditorState]);
109+
}, [
110+
activeEditableEdge,
111+
controlPoints,
112+
rootRef,
113+
setLineEditorState,
114+
updateCurActiveEditableEdge,
115+
]);
95116

96117
const gRef = useRef<SVGGElement>(null);
97118
useEffect(() => {

0 commit comments

Comments
 (0)