mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-13 01:21:58 +00:00
refactor(style): fix code style for editor-core refactor(style): fix code style for editor-skeleton refactor(style): fix code style for react-simulator-renderer refactor(style): fix code style for rax-simulator-renderer
169 lines
3.5 KiB
TypeScript
169 lines
3.5 KiB
TypeScript
import { EventEmitter } from 'events';
|
|
import { obx } from '@ali/lowcode-editor-core';
|
|
import { Node, comparePosition, PositionNO } from './node/node';
|
|
import { DocumentModel } from './document-model';
|
|
|
|
export class Selection {
|
|
private emitter = new EventEmitter();
|
|
|
|
@obx.val private _selected: string[] = [];
|
|
|
|
constructor(readonly doc: DocumentModel) {}
|
|
|
|
/**
|
|
* 选中的节点 id
|
|
*/
|
|
get selected(): string[] {
|
|
return this._selected;
|
|
}
|
|
|
|
/**
|
|
* 选中
|
|
*/
|
|
select(id: string) {
|
|
if (this._selected.length === 1 && this._selected.indexOf(id) > -1) {
|
|
// avoid cause reaction
|
|
return;
|
|
}
|
|
|
|
this._selected = [id];
|
|
this.emitter.emit('selectionchange', this._selected);
|
|
}
|
|
|
|
/**
|
|
* 批量选中
|
|
*/
|
|
selectAll(ids: string[]) {
|
|
this._selected = ids;
|
|
this.emitter.emit('selectionchange', this._selected);
|
|
}
|
|
|
|
/**
|
|
* 清除选中
|
|
*/
|
|
clear() {
|
|
if (this._selected.length < 1) {
|
|
return;
|
|
}
|
|
this._selected = [];
|
|
this.emitter.emit('selectionchange', this._selected);
|
|
}
|
|
|
|
/**
|
|
* 整理选中
|
|
*/
|
|
dispose() {
|
|
const l = this._selected.length;
|
|
let i = l;
|
|
while (i-- > 0) {
|
|
const id = this._selected[i];
|
|
if (!this.doc.hasNode(id)) {
|
|
this._selected.splice(i, 1);
|
|
}
|
|
}
|
|
if (this._selected.length !== l) {
|
|
this.emitter.emit('selectionchange', this._selected);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 添加选中
|
|
*/
|
|
add(id: string) {
|
|
if (this._selected.indexOf(id) > -1) {
|
|
return;
|
|
}
|
|
|
|
this._selected.push(id);
|
|
this.emitter.emit('selectionchange', this._selected);
|
|
}
|
|
|
|
/**
|
|
* 是否选中
|
|
*/
|
|
has(id: string) {
|
|
return this._selected.indexOf(id) > -1;
|
|
}
|
|
|
|
/**
|
|
* 移除选中
|
|
*/
|
|
remove(id: string) {
|
|
const i = this._selected.indexOf(id);
|
|
if (i > -1) {
|
|
this._selected.splice(i, 1);
|
|
this.emitter.emit('selectionchange', this._selected);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 选区是否包含节点
|
|
*/
|
|
containsNode(node: Node, excludeRoot = false) {
|
|
for (const id of this._selected) {
|
|
const parent = this.doc.getNode(id);
|
|
if (excludeRoot && parent === this.doc.rootNode) {
|
|
continue;
|
|
}
|
|
if (parent?.contains(node)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 获取选中的节点
|
|
*/
|
|
getNodes() {
|
|
const nodes = [];
|
|
for (const id of this._selected) {
|
|
const node = this.doc.getNode(id);
|
|
if (node) {
|
|
nodes.push(node);
|
|
}
|
|
}
|
|
return nodes;
|
|
}
|
|
|
|
/**
|
|
* 获取顶层选区节点, 场景:拖拽时,建立蒙层,只蒙在最上层
|
|
*/
|
|
getTopNodes(includeRoot = false) {
|
|
const nodes = [];
|
|
for (const id of this._selected) {
|
|
const node = this.doc.getNode(id);
|
|
// 排除根节点
|
|
if (!node || (!includeRoot && node === this.doc.rootNode)) {
|
|
continue;
|
|
}
|
|
let i = nodes.length;
|
|
let isTop = true;
|
|
while (i-- > 0) {
|
|
const n = comparePosition(nodes[i], node);
|
|
// nodes[i] contains node
|
|
if (n === PositionNO.Contains || n === PositionNO.TheSame) {
|
|
isTop = false;
|
|
break;
|
|
}
|
|
// node contains nodes[i], delete nodes[i]
|
|
if (n === PositionNO.ContainedBy) {
|
|
nodes.splice(i, 1);
|
|
}
|
|
}
|
|
// node is top item, push to nodes
|
|
if (isTop) {
|
|
nodes.push(node);
|
|
}
|
|
}
|
|
return nodes;
|
|
}
|
|
|
|
onSelectionChange(fn: () => void): () => void {
|
|
this.emitter.on('selectionchange', fn);
|
|
return () => {
|
|
this.emitter.removeListener('selectionchange', fn);
|
|
};
|
|
}
|
|
}
|