mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-12 11:20:11 +00:00
185 lines
5.3 KiB
TypeScript
185 lines
5.3 KiB
TypeScript
import { isLocationChildrenDetail } from '@alilc/lowcode-utils';
|
|
import { IPublicModelPluginContext, IPublicTypeActiveTarget, IPublicModelNode, IPublicTypeDisposable, IPublicEnumPluginRegisterLevel } from '@alilc/lowcode-types';
|
|
import TreeNode from './tree-node';
|
|
import { Tree } from './tree';
|
|
import EventEmitter from 'events';
|
|
import { enUS, zhCN } from '../locale';
|
|
import { ReactNode } from 'react';
|
|
|
|
export interface ITreeBoard {
|
|
readonly at: string | symbol;
|
|
scrollToNode(treeNode: TreeNode, detail?: any): void;
|
|
}
|
|
|
|
enum EVENT_NAMES {
|
|
pluginContextChanged = 'pluginContextChanged',
|
|
}
|
|
|
|
export interface IOutlinePanelPluginContext extends IPublicModelPluginContext {
|
|
extraTitle?: string;
|
|
intlNode(id: string, params?: object): ReactNode;
|
|
intl(id: string, params?: object): string;
|
|
getLocale(): string;
|
|
}
|
|
|
|
export class TreeMaster {
|
|
pluginContext: IOutlinePanelPluginContext;
|
|
|
|
private boards = new Set<ITreeBoard>();
|
|
|
|
private treeMap = new Map<string, Tree>();
|
|
|
|
private disposeEvents: (IPublicTypeDisposable | undefined)[] = [];
|
|
|
|
event = new EventEmitter();
|
|
|
|
constructor(pluginContext: IPublicModelPluginContext, readonly options: {
|
|
extraTitle?: string;
|
|
}) {
|
|
this.setPluginContext(pluginContext);
|
|
const { workspace } = this.pluginContext;
|
|
this.initEvent();
|
|
if (pluginContext.registerLevel === IPublicEnumPluginRegisterLevel.Workspace) {
|
|
this.setPluginContext(workspace.window?.currentEditorView);
|
|
let dispose: IPublicTypeDisposable | undefined;
|
|
const windowViewTypeChangeEvent = () => {
|
|
dispose = workspace.window?.onChangeViewType(() => {
|
|
this.setPluginContext(workspace.window?.currentEditorView);
|
|
});
|
|
};
|
|
|
|
windowViewTypeChangeEvent();
|
|
|
|
workspace.onChangeActiveWindow(() => {
|
|
windowViewTypeChangeEvent();
|
|
this.setPluginContext(workspace.window?.currentEditorView);
|
|
dispose && dispose();
|
|
});
|
|
}
|
|
}
|
|
|
|
private setPluginContext(pluginContext: IPublicModelPluginContext | undefined | null) {
|
|
if (!pluginContext) {
|
|
return;
|
|
}
|
|
const { intl, intlNode, getLocale } = pluginContext.common.utils.createIntl({
|
|
'en-US': enUS,
|
|
'zh-CN': zhCN,
|
|
});
|
|
let _pluginContext: IOutlinePanelPluginContext = Object.assign(pluginContext, {
|
|
intl,
|
|
intlNode,
|
|
getLocale,
|
|
});
|
|
_pluginContext.extraTitle = this.options && this.options['extraTitle'];
|
|
this.pluginContext = _pluginContext;
|
|
this.disposeEvent();
|
|
this.initEvent();
|
|
this.emitPluginContextChange();
|
|
}
|
|
|
|
private disposeEvent() {
|
|
this.disposeEvents.forEach(d => {
|
|
d && d();
|
|
});
|
|
}
|
|
|
|
private initEvent() {
|
|
let startTime: any;
|
|
const { event, project, canvas } = this.pluginContext;
|
|
const setExpandByActiveTracker = (target: IPublicTypeActiveTarget) => {
|
|
const { node, detail } = target;
|
|
const tree = this.currentTree;
|
|
if (!tree/* || node.document !== tree.document */) {
|
|
return;
|
|
}
|
|
const treeNode = tree.getTreeNode(node);
|
|
if (detail && isLocationChildrenDetail(detail)) {
|
|
treeNode.expand(true);
|
|
} else {
|
|
treeNode.expandParents();
|
|
}
|
|
this.boards.forEach((board) => {
|
|
board.scrollToNode(treeNode, detail);
|
|
});
|
|
};
|
|
this.disposeEvents = [
|
|
canvas.dragon?.onDragstart(() => {
|
|
startTime = Date.now() / 1000;
|
|
// needs?
|
|
this.toVision();
|
|
}),
|
|
canvas.activeTracker?.onChange(setExpandByActiveTracker),
|
|
canvas.dragon?.onDragend(() => {
|
|
const endTime: any = Date.now() / 1000;
|
|
const nodes = project.currentDocument?.selection?.getNodes();
|
|
event.emit('outlinePane.dragend', {
|
|
selected: nodes
|
|
?.map((n) => {
|
|
if (!n) {
|
|
return;
|
|
}
|
|
const npm = n?.componentMeta?.npm;
|
|
return (
|
|
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') || n?.componentMeta?.componentName
|
|
);
|
|
})
|
|
.join('&'),
|
|
time: (endTime - startTime).toFixed(2),
|
|
});
|
|
}),
|
|
project.onRemoveDocument((data: {id: string}) => {
|
|
const { id } = data;
|
|
this.treeMap.delete(id);
|
|
}),
|
|
];
|
|
if (canvas.activeTracker?.target) {
|
|
setExpandByActiveTracker(canvas.activeTracker?.target);
|
|
}
|
|
}
|
|
|
|
private toVision() {
|
|
const tree = this.currentTree;
|
|
if (tree) {
|
|
const selection = this.pluginContext.project.getCurrentDocument()?.selection;
|
|
selection?.getTopNodes().forEach((node: IPublicModelNode) => {
|
|
tree.getTreeNode(node).setExpanded(false);
|
|
});
|
|
}
|
|
}
|
|
|
|
addBoard(board: ITreeBoard) {
|
|
this.boards.add(board);
|
|
}
|
|
|
|
removeBoard(board: ITreeBoard) {
|
|
this.boards.delete(board);
|
|
}
|
|
|
|
purge() {
|
|
// todo others purge
|
|
}
|
|
|
|
onPluginContextChange(fn: () => void) {
|
|
this.event.on(EVENT_NAMES.pluginContextChanged, fn);
|
|
}
|
|
|
|
emitPluginContextChange() {
|
|
this.event.emit(EVENT_NAMES.pluginContextChanged);
|
|
}
|
|
|
|
get currentTree(): Tree | null {
|
|
const doc = this.pluginContext.project.getCurrentDocument();
|
|
if (doc) {
|
|
const { id } = doc;
|
|
if (this.treeMap.has(id)) {
|
|
return this.treeMap.get(id)!;
|
|
}
|
|
const tree = new Tree(this);
|
|
this.treeMap.set(id, tree);
|
|
return tree;
|
|
}
|
|
return null;
|
|
}
|
|
}
|