|
|
@@ -4,12 +4,14 @@
|
|
|
*/
|
|
|
|
|
|
import { inject, injectable } from 'inversify';
|
|
|
+import { Rectangle } from '@flowgram.ai/utils';
|
|
|
import {
|
|
|
WorkflowDocument,
|
|
|
WorkflowLineEntity,
|
|
|
WorkflowNodeEntity,
|
|
|
WorkflowNodeLinesData,
|
|
|
} from '@flowgram.ai/free-layout-core';
|
|
|
+import { Playground } from '@flowgram.ai/core';
|
|
|
|
|
|
import { AutoLayoutOptions } from './type';
|
|
|
import { LayoutConfig, LayoutEdge, LayoutNode } from './layout/type';
|
|
|
@@ -18,6 +20,9 @@ import { DefaultLayoutConfig, Layout, type LayoutOptions } from './layout';
|
|
|
|
|
|
@injectable()
|
|
|
export class AutoLayoutService {
|
|
|
+ @inject(Playground)
|
|
|
+ private playground: Playground;
|
|
|
+
|
|
|
@inject(WorkflowDocument) private readonly document: WorkflowDocument;
|
|
|
|
|
|
private layoutConfig: LayoutConfig = DefaultLayoutConfig;
|
|
|
@@ -36,7 +41,18 @@ export class AutoLayoutService {
|
|
|
};
|
|
|
const root = this.createLayoutNode(this.document.root, options);
|
|
|
const layouts = await this.layoutNode(root, layoutOptions);
|
|
|
- await Promise.all(layouts.map((layout) => layout.position()));
|
|
|
+ const rect = this.getLayoutNodeRect(root);
|
|
|
+ const positionPromise = layouts.map((layout) => layout.position());
|
|
|
+ const fitViewPromise = this.fitView(layoutOptions, rect);
|
|
|
+ await Promise.all([...positionPromise, fitViewPromise]);
|
|
|
+ }
|
|
|
+
|
|
|
+ private async fitView(options: LayoutOptions, rect: Rectangle): Promise<void> {
|
|
|
+ if (options.disableFitView === true) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 留出 30 像素的边界
|
|
|
+ return this.playground.config.fitView(rect, options.enableAnimation, 30);
|
|
|
}
|
|
|
|
|
|
private async layoutNode(container: LayoutNode, options: LayoutOptions): Promise<Layout[]> {
|
|
|
@@ -51,8 +67,11 @@ export class AutoLayoutService {
|
|
|
const layout = new Layout(this.layoutConfig);
|
|
|
layout.init({ container, layoutNodes, layoutEdges }, options);
|
|
|
layout.layout();
|
|
|
- const { size } = layout;
|
|
|
- container.size = size;
|
|
|
+ const rect = this.getLayoutNodeRect(container);
|
|
|
+ container.size = {
|
|
|
+ width: rect.width,
|
|
|
+ height: rect.height,
|
|
|
+ };
|
|
|
return [...childrenLayouts, layout];
|
|
|
}
|
|
|
|
|
|
@@ -124,4 +143,22 @@ export class AutoLayoutService {
|
|
|
|
|
|
return lines;
|
|
|
}
|
|
|
+
|
|
|
+ private getLayoutNodeRect(layoutNode: LayoutNode): Rectangle {
|
|
|
+ const rects = layoutNode.layoutNodes.map((node) => this.layoutNodeRect(node));
|
|
|
+ const rect = Rectangle.enlarge(rects);
|
|
|
+ const { padding } = layoutNode.entity.transform;
|
|
|
+ const width = rect.width + padding.left + padding.right;
|
|
|
+ const height = rect.height + padding.top + padding.bottom;
|
|
|
+ const x = rect.x - padding.left;
|
|
|
+ const y = rect.y - padding.top;
|
|
|
+ return new Rectangle(x, y, width, height);
|
|
|
+ }
|
|
|
+
|
|
|
+ private layoutNodeRect(layoutNode: LayoutNode): Rectangle {
|
|
|
+ const { width, height } = layoutNode.size;
|
|
|
+ const x = layoutNode.position.x - width / 2;
|
|
|
+ const y = layoutNode.position.y - height / 2;
|
|
|
+ return new Rectangle(x, y, width, height);
|
|
|
+ }
|
|
|
}
|