From eafdb8ae3faacf83c8027bcad493af37fc161dea Mon Sep 17 00:00:00 2001
From: rhenck <richard.henck@iqb.hu-berlin.de>
Date: Mon, 19 Jul 2021 16:40:38 +0200
Subject: [PATCH] [editor] Add drag resize functionality to canvas elements

Somewhat messy because of more nested droplists and a handler triggering
every pixel. But the best I can do for now. May revisit later.
---
 .../canvas/canvas-drag-overlay.component.ts   | 60 ++++++++++++++-----
 projects/editor/src/styles.css                |  3 +
 2 files changed, 47 insertions(+), 16 deletions(-)

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
index f3d93d8b1..9acbd36bb 100644
--- 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
@@ -1,32 +1,48 @@
 import {
   Component, OnInit, Input, Output, EventEmitter, ComponentFactoryResolver, ViewChild, ViewContainerRef
 } from '@angular/core';
+import { CdkDragMove } from '@angular/cdk/drag-drop';
 import { UnitUIElement } from '../../../../../../../common/unit';
-import { FormElementComponent } from '../../../../../../../common/form-element-component.directive';
 import * as ComponentUtils from '../../../../../../../common/component-utils';
+import { UnitService } from '../../../../unit.service';
 
 @Component({
   selector: 'app-canvas-drag-overlay',
   template: `
-<!--    Needs extra div because styling can interfere with drag and drop-->
-    <div cdkDrag [cdkDragData]="this.element"
-         [cdkDragDisabled]="!_selected"
+    <!--    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)">
-      <div [ngStyle]="style"
-           [style.position]="'absolute'"
-           [style.border]="_selected ? '2px solid' : ''"
+      <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">
-<!--        <button cdkDrag cdkDragHandle></button>-->
+        <!-- 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">
+            <mat-icon>aspect_ratio</mat-icon>
+            <div *cdkDragPlaceholder></div>
+          </div>
+        </div>
         <ng-template #elementContainer></ng-template>
       </div>
     </div>
-    `,
+  `,
   styles: [
-    'div {position: absolute}'
+    '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 {
@@ -36,16 +52,18 @@ export class CanvasDragOverlayComponent implements OnInit {
     multiSelect: boolean }>();
 
   @ViewChild('elementContainer', { read: ViewContainerRef, static: true }) private elementContainer!: ViewContainerRef;
-  private childComponent!: FormElementComponent;
-  _selected = false;
-  style: Record<string, string> = {};
 
-  constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
+  selected = false;
+  private oldX: number = 0;
+  private oldY: number = 0;
+
+  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;
+    const childComponent = this.elementContainer.createComponent(componentFactory);
+    childComponent.instance.elementModel = this.element;
+    childComponent.location.nativeElement.firstChild.style.cursor = 'inherit';
   }
 
   set selected(newValue: boolean) {
@@ -63,4 +81,14 @@ export class CanvasDragOverlayComponent implements OnInit {
       });
     }
   }
+
+  dragStart(): void {
+    this.oldX = this.element.width;
+    this.oldY = this.element.height;
+  }
+
+  resizeElement(event: CdkDragMove): void {
+    this.unitService.updateSelectedElementProperty('width', Math.max(this.oldX + event.distance.x, 0));
+    this.unitService.updateSelectedElementProperty('height', Math.max(this.oldY + event.distance.y, 0));
+  }
 }
diff --git a/projects/editor/src/styles.css b/projects/editor/src/styles.css
index 99d511720..49bf2fb7e 100644
--- a/projects/editor/src/styles.css
+++ b/projects/editor/src/styles.css
@@ -7,3 +7,6 @@ body {
 
 .snackbar-warning {border: 3px double #ff4d4d}
 .snackbar-error {background-color: #ff4d4d}
+
+
+.cdk-drop-list-dragging {cursor: grabbing}
-- 
GitLab