From 61669a6ee11faab48c1f07721a5375d49892383b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E8=B1=AA=E7=8F=A3?= <519367854@qq.com>
Date: Sun, 31 Mar 2024 21:53:01 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0selection=E7=BB=84?=
=?UTF-8?q?=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../widgets/aux-tool/aux-tool.widget.ts | 28 ++++-
.../widgets/aux-tool/selection.widget.ts | 115 ++++++++++++++++++
.../component-tree/component-tree.widget.ts | 22 +++-
3 files changed, 159 insertions(+), 6 deletions(-)
create mode 100644 src/app/components/widgets/aux-tool/selection.widget.ts
diff --git a/src/app/components/widgets/aux-tool/aux-tool.widget.ts b/src/app/components/widgets/aux-tool/aux-tool.widget.ts
index 5fd9d36..b299d0e 100644
--- a/src/app/components/widgets/aux-tool/aux-tool.widget.ts
+++ b/src/app/components/widgets/aux-tool/aux-tool.widget.ts
@@ -1,13 +1,35 @@
-import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, ViewChild } from '@angular/core';
import { usePrefix } from '@/app/utils';
+import { Engine } from '@/app/core/models';
+import { SelectionWidget } from './selection.widget';
@Component({
selector: 'app-aux-tool-widget',
- template: `
`,
+ template: `
+
+ `,
styleUrls: ['./styles.less'],
standalone: true,
+ imports: [SelectionWidget],
changeDetection: ChangeDetectionStrategy.OnPush
})
-export class AuxToolWidget {
+export class AuxToolWidget implements AfterViewInit {
prefix = usePrefix('auxtool');
+
+ @ViewChild('ref') ref: ElementRef;
+
+ constructor(private engine: Engine) {}
+
+ ngAfterViewInit(): void {
+ const element = this.ref.nativeElement;
+ const viewport = this.engine.workbench.currentWorkspace.viewport;
+
+ this.engine.subscribeWith('viewport:scroll', () => {
+ if (viewport.isIframe && element) {
+ element.style.transform = `perspective(1px) translate3d(${-viewport.scrollX}px,${-viewport.scrollY}px,0)`;
+ }
+ });
+ }
}
diff --git a/src/app/components/widgets/aux-tool/selection.widget.ts b/src/app/components/widgets/aux-tool/selection.widget.ts
new file mode 100644
index 0000000..a6ff57c
--- /dev/null
+++ b/src/app/components/widgets/aux-tool/selection.widget.ts
@@ -0,0 +1,115 @@
+import {
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ Component,
+ ElementRef,
+ Input,
+ OnChanges,
+ Renderer2,
+ SimpleChanges,
+ ViewChild
+} from '@angular/core';
+import { usePrefix } from '@/app/utils';
+import { Engine, TreeNode } from '@/app/core/models';
+import { Selection } from '@/app/core/models/selection';
+import { Cursor } from '@/app/core/models/cursor';
+import { MoveHelper } from '@/app/core/models/move-helper';
+import { Rect } from '@/app/shared/coordinate';
+
+@Component({
+ selector: 'app-selection-box-widget',
+ template: `
+
+ `,
+ standalone: true,
+ styleUrls: [`./styles.less`],
+ changeDetection: ChangeDetectionStrategy.Default
+})
+export class SelectionBoxWidget implements OnChanges {
+ @ViewChild('container') container: ElementRef;
+
+ @Input() node: TreeNode;
+
+ @Input() showHelpers: boolean;
+
+ prefix = usePrefix('aux-selection-box');
+
+ innerPrefix = usePrefix('aux-selection-box-inner');
+
+ nodeRect: Rect;
+
+ createSelectionStyle = () => {
+ const baseStyle = {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ boxSizing: 'border-box',
+ zIndex: 4
+ } as any;
+ if (this.nodeRect) {
+ baseStyle.transform = `perspective(1px) translate3d(${this.nodeRect.x}px,${this.nodeRect.y}px,0)`;
+ baseStyle.height = `${this.nodeRect.height}px`;
+ baseStyle.width = `${this.nodeRect.width}px`;
+ }
+ return baseStyle;
+ };
+
+ constructor(
+ private designer: Engine,
+ private renderer2: Renderer2,
+ private cdr: ChangeDetectorRef
+ ) {}
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes.node && changes.node.currentValue) {
+ setTimeout(() => {
+ this.nodeRect = this.designer.workbench.currentWorkspace.viewport.getValidNodeOffsetRect(this.node);
+
+ this.renderer2.setAttribute(
+ this.container.nativeElement,
+ `${this.designer.props?.nodeSelectionIdAttrName}`,
+ this.node.id
+ );
+ this.cdr.markForCheck();
+ });
+ }
+ }
+}
+
+@Component({
+ selector: 'app-selection-widget',
+ template: `
+ @if (cursor.status === 'NORMAL' || !viewportMoveHelper.touchNode) {
+ @for (id of selection.selected; track id) {
+ @if (tree.findById(id) && !tree.findById(id).hidden) {
+
+ }
+ }
+ }
+ `,
+ standalone: true,
+ imports: [SelectionBoxWidget],
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class SelectionWidget {
+ selection: Selection;
+
+ cursor: Cursor;
+
+ viewportMoveHelper: MoveHelper;
+
+ tree: TreeNode;
+
+ constructor(private designer: Engine) {
+ const operation = this.designer.workbench.currentWorkspace.operation;
+ this.selection = operation.selection;
+ this.viewportMoveHelper = operation.moveHelper;
+ this.tree = operation.tree;
+ this.cursor = this.designer.cursor;
+ }
+}
diff --git a/src/app/components/widgets/component-tree/component-tree.widget.ts b/src/app/components/widgets/component-tree/component-tree.widget.ts
index 63d6d34..25f9a3b 100644
--- a/src/app/components/widgets/component-tree/component-tree.widget.ts
+++ b/src/app/components/widgets/component-tree/component-tree.widget.ts
@@ -1,4 +1,14 @@
-import { AfterViewInit, ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core';
+import {
+ AfterViewInit,
+ ChangeDetectionStrategy,
+ Component,
+ ElementRef,
+ Input,
+ OnChanges,
+ Renderer2,
+ SimpleChanges,
+ ViewChild
+} from '@angular/core';
import { usePrefix } from '@/app/utils';
import { TreeNodeWidget } from '../tree-node/tree-node.widget';
import { IDesignerComponents } from '../../types';
@@ -9,7 +19,7 @@ import { Engine, TreeNode } from '@/app/core/models';
selector: 'app-component-tree-widget',
standalone: true,
template: `
-
+
`,
@@ -18,6 +28,8 @@ import { Engine, TreeNode } from '@/app/core/models';
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ComponentTreeWidget implements OnChanges, AfterViewInit {
+ @ViewChild('container') container: ElementRef;
+
prefix = usePrefix('component-tree');
@Input() components: IDesignerComponents;
@@ -28,7 +40,10 @@ export class ComponentTreeWidget implements OnChanges, AfterViewInit {
displayName = 'ComponentTreeWidget';
- constructor(private designer: Engine) {}
+ constructor(
+ private designer: Engine,
+ private renderer2: Renderer2
+ ) {}
ngOnChanges(changes: SimpleChanges): void {
if (changes.components && changes.components.currentValue) {
@@ -38,6 +53,7 @@ export class ComponentTreeWidget implements OnChanges, AfterViewInit {
ngAfterViewInit(): void {
this.tree = this.useTree();
+ this.renderer2.setAttribute(this.container.nativeElement, `${this.designer?.props?.nodeIdAttrName}`, this.tree.id);
}
registerDesignerBehaviors() {