mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-02-20 23:50:28 +00:00
143 lines
3.8 KiB
TypeScript
143 lines
3.8 KiB
TypeScript
import { Component, MouseEvent as ReactMouseEvent } from 'react';
|
|
import { observer } from '../../../globals';
|
|
import { Tree } from '../tree';
|
|
import TreeNodeView from './tree-node';
|
|
import { isRootNode } from '../../../designer/src/designer/document/node/root-node';
|
|
import Node from '../../../designer/src/designer/document/node/node';
|
|
import { DragObjectType, isShaken } from '../../../designer/src/designer/helper/dragon';
|
|
|
|
function getTreeNodeIdByEvent(e: ReactMouseEvent, stop: Element): null | string {
|
|
let target: Element | null = e.target as Element;
|
|
if (!target || !stop.contains(target)) {
|
|
return null;
|
|
}
|
|
target = target.closest('[data-id]');
|
|
if (!target || !stop.contains(target)) {
|
|
return null;
|
|
}
|
|
|
|
return (target as HTMLDivElement).dataset.id || null;
|
|
}
|
|
|
|
@observer
|
|
export default class TreeView extends Component<{ tree: Tree }> {
|
|
private shell: HTMLDivElement | null = null;
|
|
private hover(e: ReactMouseEvent) {
|
|
const { tree } = this.props;
|
|
|
|
const doc = tree.document;
|
|
const hovering = doc.designer.hovering;
|
|
if (!hovering.enable) {
|
|
return;
|
|
}
|
|
const node = this.getTreeNodeFromEvent(e)?.node;
|
|
hovering.hover(node || null);
|
|
}
|
|
|
|
private onClick = (e: ReactMouseEvent) => {
|
|
if (this.ignoreUpSelected) {
|
|
return;
|
|
}
|
|
if (this.boostEvent && isShaken(this.boostEvent, e.nativeEvent)) {
|
|
return;
|
|
}
|
|
const treeNode = this.getTreeNodeFromEvent(e);
|
|
if (!treeNode) {
|
|
return;
|
|
}
|
|
const { node } = treeNode;
|
|
const designer = treeNode.designer;
|
|
const doc = node.document;
|
|
const selection = doc.selection;
|
|
const id = node.id;
|
|
const isMulti = e.metaKey || e.ctrlKey;
|
|
designer.activeTracker.track(node);
|
|
if (isMulti && !isRootNode(node) && selection.has(id)) {
|
|
selection.remove(id);
|
|
} else {
|
|
selection.select(id);
|
|
}
|
|
};
|
|
|
|
private onMouseOver = (e: ReactMouseEvent) => {
|
|
this.hover(e);
|
|
};
|
|
|
|
private getTreeNodeFromEvent(e: ReactMouseEvent) {
|
|
if (!this.shell) {
|
|
return;
|
|
}
|
|
const id = getTreeNodeIdByEvent(e, this.shell);
|
|
if (!id) {
|
|
return;
|
|
}
|
|
|
|
const { tree } = this.props;
|
|
return tree.getTreeNodeById(id);
|
|
}
|
|
|
|
private ignoreUpSelected = false;
|
|
private boostEvent?: MouseEvent;
|
|
private onMouseDown = (e: ReactMouseEvent) => {
|
|
const treeNode = this.getTreeNodeFromEvent(e);
|
|
if (!treeNode) {
|
|
return;
|
|
}
|
|
|
|
const { node } = treeNode;
|
|
const designer = treeNode.designer;
|
|
const doc = node.document;
|
|
const selection = doc.selection;
|
|
|
|
const isMulti = e.metaKey || e.ctrlKey;
|
|
const isLeftButton = e.button === 0;
|
|
|
|
if (isLeftButton && !isRootNode(node)) {
|
|
let nodes: Node[] = [node];
|
|
this.ignoreUpSelected = false;
|
|
if (isMulti) {
|
|
// multi select mode, directily add
|
|
if (!selection.has(node.id)) {
|
|
designer.activeTracker.track(node);
|
|
selection.add(node.id);
|
|
this.ignoreUpSelected = true;
|
|
}
|
|
selection.remove(doc.rootNode.id);
|
|
// 获得顶层 nodes
|
|
nodes = selection.getTopNodes();
|
|
}
|
|
this.boostEvent = e.nativeEvent;
|
|
designer.dragon.boost(
|
|
{
|
|
type: DragObjectType.Node,
|
|
nodes,
|
|
},
|
|
this.boostEvent,
|
|
);
|
|
}
|
|
};
|
|
|
|
private onMouseLeave = () => {
|
|
const { tree } = this.props;
|
|
const doc = tree.document;
|
|
doc.designer.hovering.leave(doc);
|
|
};
|
|
|
|
render() {
|
|
const { tree } = this.props;
|
|
const root = tree.root;
|
|
return (
|
|
<div
|
|
className="lc-outline-tree"
|
|
ref={shell => (this.shell = shell)}
|
|
onMouseDown={this.onMouseDown}
|
|
onMouseOver={this.onMouseOver}
|
|
onClick={this.onClick}
|
|
onMouseLeave={this.onMouseLeave}
|
|
>
|
|
<TreeNodeView key={root.id} treeNode={root} />
|
|
</div>
|
|
);
|
|
}
|
|
}
|