| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- /**
- * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
- * SPDX-License-Identifier: MIT
- */
- import { debounce } from 'lodash-es';
- import { inject, injectable } from 'inversify';
- import { domUtils } from '@flowgram.ai/utils';
- import { Disposable } from '@flowgram.ai/utils';
- import {
- WorkflowHoverService,
- WorkflowNodeEntity,
- WorkflowSelectService,
- } from '@flowgram.ai/free-layout-core';
- import { WorkflowLineEntity } from '@flowgram.ai/free-layout-core';
- import { WorkflowDocument } from '@flowgram.ai/free-layout-core';
- import { FlowNodeRenderData } from '@flowgram.ai/document';
- import { EntityManager, PipelineRegistry, PipelineRenderer } from '@flowgram.ai/core';
- import type { StackContextManagerOptions, StackingContext } from './type';
- import { StackingComputing } from './stacking-computing';
- import { BASE_Z_INDEX } from './constant';
- @injectable()
- export class StackingContextManager {
- @inject(WorkflowDocument) private readonly document: WorkflowDocument;
- @inject(EntityManager) private readonly entityManager: EntityManager;
- @inject(PipelineRenderer)
- private readonly pipelineRenderer: PipelineRenderer;
- @inject(PipelineRegistry)
- private readonly pipelineRegistry: PipelineRegistry;
- @inject(WorkflowHoverService)
- private readonly hoverService: WorkflowHoverService;
- @inject(WorkflowSelectService)
- private readonly selectService: WorkflowSelectService;
- public readonly node = domUtils.createDivWithClass(
- 'gedit-playground-layer gedit-flow-render-layer'
- );
- private options: StackContextManagerOptions = {
- sortNodes: (nodes: WorkflowNodeEntity[]) => nodes,
- };
- private disposers: Disposable[] = [];
- constructor() {}
- public init(options: Partial<StackContextManagerOptions> = {}): void {
- this.options = { ...this.options, ...options };
- this.pipelineRenderer.node.appendChild(this.node);
- this.mountListener();
- }
- public ready(): void {
- this.compute();
- }
- public dispose(): void {
- this.disposers.forEach((disposer) => disposer.dispose());
- }
- /**
- * 触发计算
- * 10ms内仅计算一次
- */
- private compute = debounce(this._compute, 10);
- private _compute(): void {
- const context = this.context;
- const stackingComputing = new StackingComputing();
- const { nodeLevel, lineLevel } = stackingComputing.compute({
- root: this.document.root,
- nodes: this.nodes,
- context,
- });
- this.nodes.forEach((node) => {
- const level = nodeLevel.get(node.id);
- const nodeRenderData = node.getData<FlowNodeRenderData>(FlowNodeRenderData);
- const element = nodeRenderData.node;
- element.style.position = 'absolute';
- if (level === undefined) {
- nodeRenderData.stackIndex = 0;
- element.style.zIndex = 'auto';
- return;
- }
- nodeRenderData.stackIndex = level;
- const zIndex = BASE_Z_INDEX + level;
- element.style.zIndex = String(zIndex);
- });
- this.lines.forEach((line) => {
- const level = lineLevel.get(line.id);
- const element = line.node;
- element.style.position = 'absolute';
- if (level === undefined) {
- line.stackIndex = 0;
- element.style.zIndex = 'auto';
- return;
- }
- line.stackIndex = level;
- const zIndex = BASE_Z_INDEX + level;
- element.style.zIndex = String(zIndex);
- });
- }
- private get nodes(): WorkflowNodeEntity[] {
- return this.entityManager.getEntities<WorkflowNodeEntity>(WorkflowNodeEntity);
- }
- private get lines(): WorkflowLineEntity[] {
- return this.entityManager.getEntities<WorkflowLineEntity>(WorkflowLineEntity);
- }
- private get context(): StackingContext {
- return {
- hoveredEntityID: this.hoverService.someHovered?.id,
- selectedNodes: this.selectService.selectedNodes,
- selectedIDs: new Set(this.selectService.selection.map((entity) => entity.id)),
- sortNodes: this.options.sortNodes,
- };
- }
- private mountListener(): void {
- const entityChangeDisposer = this.onEntityChange();
- const zoomDisposer = this.onZoom();
- const hoverDisposer = this.onHover();
- const selectDisposer = this.onSelect();
- this.disposers = [entityChangeDisposer, zoomDisposer, hoverDisposer, selectDisposer];
- }
- private onZoom(): Disposable {
- return this.pipelineRegistry.onZoom((scale: number) => {
- this.node.style.transform = `scale(${scale})`;
- });
- }
- private onHover(): Disposable {
- return this.hoverService.onHoveredChange(() => {
- this.compute();
- });
- }
- private onEntityChange(): Disposable {
- return this.entityManager.onEntityChange(() => {
- this.compute();
- });
- }
- private onSelect(): Disposable {
- return this.selectService.onSelectionChanged(() => {
- this.compute();
- });
- }
- }
|