力皓 30bf21ca04 refactor(style): fix code style for designer
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
2020-09-10 21:05:43 +08:00

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);
};
}
}