diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/canvas-drag-overlay.component.ts b/projects/editor/src/app/components/unit-view/page-view/canvas/canvas-drag-overlay.component.ts deleted file mode 100644 index 6c8b00863df50849e2a566ff461189ac63b83a2a..0000000000000000000000000000000000000000 --- a/projects/editor/src/app/components/unit-view/page-view/canvas/canvas-drag-overlay.component.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { - Component, OnInit, OnDestroy, Input, Output, - EventEmitter, - ComponentFactoryResolver, ViewChild, ViewContainerRef, HostListener -} from '@angular/core'; -import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; -import { CdkDragMove } from '@angular/cdk/drag-drop'; -import { UnitUIElement } from '../../../../../../../common/unit'; -import * as ComponentUtils from '../../../../../../../common/component-utils'; -import { UnitService } from '../../../../unit.service'; -import { ValueChangeElement } from '../../../../../../../common/form'; -import { ElementComponent } from '../../../../../../../common/element-component.directive'; -import { FormElementComponent } from '../../../../../../../common/form-element-component.directive'; - -@Component({ - selector: 'app-canvas-drag-overlay', - template: ` - <!-- Needs extra div because styling can interfere with drag and drop--> - <div class="draggable-element" [class.draggable-element-selected]="selected" - cdkDrag [cdkDragData]="this.element" [cdkDragDisabled]="!selected" - (click)="click($event)" - (dblclick)="openEditDialog()"> - <div [style.position]="'absolute'" - [style.border]="selected ? '2px solid' : ''" - [style.width.px]="element.width" - [style.height.px]="element.height" - [style.left.px]="element.xPosition" - [style.top.px]="element.yPosition" - [style.z-index]="element.zIndex"> - <!-- Element only for resizing --> - <!-- Extra droplist is needed to keep parent component droplist from handling the drop event. --> - <!-- Also for cursor styling. --> - <div cdkDropList class="test" *ngIf="selected" - [style.width.%]="100" - [style.height.%]="100"> - <div class="resizeHandle" - cdkDrag (cdkDragStarted)="dragStart()" (cdkDragMoved)="resizeElement($event)" - [style.right.px]="-1" - [style.bottom.px]="-7" - [style.z-index]="5"> - <mat-icon>aspect_ratio</mat-icon> - <div *cdkDragPlaceholder></div> - </div> - </div> - <ng-template #elementContainer></ng-template> - </div> - </div> - `, - styles: [ - 'div {position: absolute}', - '.draggable-element-selected {cursor: grab}', - '.draggable-element-selected:active {cursor: grabbing}', - '.draggable-element-selected .resizeHandle {cursor: nwse-resize}', - '.test.cdk-drop-list-dragging {cursor: nwse-resize}' - ] -}) -export class CanvasDragOverlayComponent implements OnInit, OnDestroy { - @Input() element!: UnitUIElement; - @Output() elementSelected = new EventEmitter<{ - componentElement: CanvasDragOverlayComponent, - multiSelect: boolean }>(); - - @ViewChild('elementContainer', { read: ViewContainerRef, static: true }) private elementContainer!: ViewContainerRef; - - selected = false; - private oldX: number = 0; - private oldY: number = 0; - private childComponent!: ElementComponent; - private ngUnsubscribe = new Subject<void>(); - - constructor(private unitService: UnitService, - private componentFactoryResolver: ComponentFactoryResolver) { } - - ngOnInit(): void { - const componentFactory = ComponentUtils.getComponentFactory(this.element.type, this.componentFactoryResolver); - this.childComponent = this.elementContainer.createComponent(componentFactory).instance; - this.childComponent.elementModel = this.element; - if (this.childComponent instanceof FormElementComponent) { - this.childComponent.formValueChanged - .pipe(takeUntil(this.ngUnsubscribe)) - .subscribe((changeElement: ValueChangeElement) => { - this.unitService.updateElementProperty(this.element, 'value', changeElement.values[1]); - }); - - this.unitService.elementPropertyUpdated - .pipe(takeUntil(this.ngUnsubscribe)) - .subscribe(() => { - (this.childComponent as FormElementComponent).updateFormValue( - this.element.value as string | number | boolean | undefined - ); - }); - } - } - - @HostListener('window:keydown', ['$event']) - handleKeyDown(event: KeyboardEvent): void { - if (!(event.target as Element).tagName.includes('input'.toUpperCase()) && - !(event.target as Element).tagName.includes('textarea'.toUpperCase()) && - event.key === 'Delete') { - this.unitService.deleteElement(this.element); - } - } - - setSelected(newValue: boolean): void { - this.selected = newValue; - } - - click(event: MouseEvent): void { - if (event.shiftKey) { - this.elementSelected.emit({ - componentElement: this, multiSelect: true - }); - } else { - this.elementSelected.emit({ - componentElement: this, multiSelect: false - }); - } - } - - dragStart(): void { - this.oldX = this.element.width; - this.oldY = this.element.height; - } - - resizeElement(event: CdkDragMove): void { - this.unitService.updateElementProperty(this.element, 'width', Math.max(this.oldX + event.distance.x, 0)); - this.unitService.updateElementProperty(this.element, 'height', Math.max(this.oldY + event.distance.y, 0)); - } - - openEditDialog(): void { - this.unitService.showDefaultEditDialog(this.element); - } - - ngOnDestroy(): void { - this.ngUnsubscribe.next(); - this.ngUnsubscribe.complete(); - } -} diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/canvas-element-overlay.ts b/projects/editor/src/app/components/unit-view/page-view/canvas/canvas-element-overlay.ts new file mode 100644 index 0000000000000000000000000000000000000000..f602b8ecf1cceeb4d5c19caa5079d6c0d3eaae6b --- /dev/null +++ b/projects/editor/src/app/components/unit-view/page-view/canvas/canvas-element-overlay.ts @@ -0,0 +1,98 @@ +import { + ComponentFactoryResolver, ComponentRef, + Directive, + EventEmitter, + HostListener, + Input, + Output, + ViewChild, ViewContainerRef +} from '@angular/core'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { UnitUIElement } from '../../../../../../../common/unit'; +import { UnitService } from '../../../../unit.service'; +import * as ComponentUtils from '../../../../../../../common/component-utils'; +import { FormElementComponent } from '../../../../../../../common/form-element-component.directive'; +import { ValueChangeElement } from '../../../../../../../common/form'; +import { ElementComponent } from '../../../../../../../common/element-component.directive'; + +@Directive() +export abstract class CanvasElementOverlay { + @Input() element!: UnitUIElement; + @Output() elementSelected = new EventEmitter<{ + componentElement: CanvasElementOverlay, + multiSelect: boolean }>(); + @ViewChild('elementContainer', { read: ViewContainerRef, static: true }) private elementContainer!: ViewContainerRef; + + selected = false; + // protected childComponent!: ElementComponent; + protected childComponent!: ComponentRef<ElementComponent>; + private ngUnsubscribe = new Subject<void>(); + + constructor(protected unitService: UnitService, + private componentFactoryResolver: ComponentFactoryResolver, + protected viewContainerRef: ViewContainerRef) { } + + ngOnInit(): void { + const componentFactory = ComponentUtils.getComponentFactory(this.element.type, this.componentFactoryResolver); + // this.childComponent = this.elementContainer.createComponent(componentFactory).instance; + this.childComponent = this.elementContainer.createComponent(componentFactory); + this.childComponent.instance.elementModel = this.element; + + // console.log('t0', this.childComponent.location.nativeElement.firstChild); + // console.log('t1', this.childComponent.location.nativeElement.firstChild.style); + // this.childComponent.location.nativeElement.firstChild.style.width = '100%'; + // console.log('t2', this.childComponent.location.nativeElement.firstChild.style.width); + // console.log('t1', this.childComponent.nativeElement); + + if (this.childComponent.instance instanceof FormElementComponent) { + this.childComponent.instance.formValueChanged + .pipe(takeUntil(this.ngUnsubscribe)) + .subscribe((changeElement: ValueChangeElement) => { + this.unitService.updateElementProperty(this.element, 'value', changeElement.values[1]); + }); + + this.unitService.elementPropertyUpdated + .pipe(takeUntil(this.ngUnsubscribe)) + .subscribe(() => { + (this.childComponent.instance as FormElementComponent).updateFormValue( + this.element.value as string | number | boolean | undefined + ); + }); + } + } + + @HostListener('window:keydown', ['$event']) + handleKeyDown(event: KeyboardEvent): void { + if (!(event.target as Element).tagName.includes('input'.toUpperCase()) && + !(event.target as Element).tagName.includes('textarea'.toUpperCase()) && + event.key === 'Delete') { + this.unitService.deleteElement(this.element); + } + } + + setSelected(newValue: boolean): void { + this.selected = newValue; + } + + click(event: MouseEvent): void { + if (event.shiftKey) { + this.elementSelected.emit({ + componentElement: this, multiSelect: true + }); + } else { + this.elementSelected.emit({ + componentElement: this, multiSelect: false + }); + } + } + + openEditDialog(): void { + this.unitService.showDefaultEditDialog(this.element); + } + + ngOnDestroy(): void { + this.ngUnsubscribe.next(); + this.ngUnsubscribe.complete(); + } +} diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/dynamic-canvas-overlay.component.ts b/projects/editor/src/app/components/unit-view/page-view/canvas/dynamic-canvas-overlay.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..9317721419f6c503b4920814017ba08102be94f3 --- /dev/null +++ b/projects/editor/src/app/components/unit-view/page-view/canvas/dynamic-canvas-overlay.component.ts @@ -0,0 +1,18 @@ +import { Component, Input } from '@angular/core'; +import { CanvasElementOverlay } from './canvas-element-overlay'; + +@Component({ + selector: 'app-dynamic-canvas-overlay', + template: ` + <div class="draggable-element" [class.draggable-element-selected]="selected" + cdkDrag [cdkDragData]="this.element" [cdkDragDisabled]="!selected" + (click)="click($event)" + (dblclick)="openEditDialog()" + [style.height.%]="100"> + <ng-template #elementContainer></ng-template> + </div> + ` +}) +export class DynamicCanvasOverlayComponent extends CanvasElementOverlay { + @Input() dynamicPositioning!: boolean; +} diff --git a/projects/editor/src/app/components/unit-view/page-view/canvas/static-canvas-overlay.component.ts b/projects/editor/src/app/components/unit-view/page-view/canvas/static-canvas-overlay.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..0cf72d13ff17f3e2a37b2dec4a11f4386d51c09b --- /dev/null +++ b/projects/editor/src/app/components/unit-view/page-view/canvas/static-canvas-overlay.component.ts @@ -0,0 +1,61 @@ +import { Component } from '@angular/core'; +import { CdkDragMove } from '@angular/cdk/drag-drop'; +import { CanvasElementOverlay } from './canvas-element-overlay'; + +@Component({ + selector: 'app-static-canvas-overlay', + template: ` + <!-- Needs extra div because styling can interfere with drag and drop--> + <div class="draggable-element" [class.draggable-element-selected]="selected" + cdkDrag [cdkDragData]="this.element" [cdkDragDisabled]="!selected" + (click)="click($event)" + (dblclick)="openEditDialog()"> + <div [style.position]="'absolute'" + [style.border]="selected ? '2px solid' : ''" + [style.width.px]="element.width" + [style.height.px]="element.height" + [style.left.px]="element.xPosition" + [style.top.px]="element.yPosition" + [style.z-index]="element.zIndex"> + <!-- Element only for resizing --> + <!-- Extra droplist is needed to keep parent component droplist from handling the drop event. --> + <!-- Also for cursor styling. --> + <div *ngIf="selected" cdkDropList class="resize-droplist" + [style.width.%]="100" + [style.height.%]="100"> + <div class="resizeHandle" + cdkDrag (cdkDragStarted)="dragStart()" (cdkDragMoved)="resizeElement($event)" + [style.right.px]="-1" + [style.bottom.px]="-7" + [style.z-index]="5"> + <mat-icon>aspect_ratio</mat-icon> + <div *cdkDragPlaceholder></div> + </div> + </div> + <ng-template #elementContainer></ng-template> + </div> + </div> + `, + styles: [ + '.resizeHandle {position: absolute}', + '.resize-droplist {position: absolute}', + '.draggable-element-selected {cursor: grab}', + '.draggable-element-selected:active {cursor: grabbing}', + '.draggable-element-selected .resizeHandle {cursor: nwse-resize}', + '.resize-droplist.cdk-drop-list-dragging {cursor: nwse-resize}' + ] +}) +export class StaticCanvasOverlayComponent extends CanvasElementOverlay { + private oldX: number = 0; + private oldY: number = 0; + + dragStart(): void { + this.oldX = this.element.width; + this.oldY = this.element.height; + } + + resizeElement(event: CdkDragMove): void { + this.unitService.updateElementProperty(this.element, 'width', Math.max(this.oldX + event.distance.x, 0)); + this.unitService.updateElementProperty(this.element, 'height', Math.max(this.oldY + event.distance.y, 0)); + } +}