From 548714cbea73cbbd44eae265e8f9b0efbe8ddcf1 Mon Sep 17 00:00:00 2001
From: rhenck <richard.henck@iqb.hu-berlin.de>
Date: Mon, 8 Nov 2021 19:09:21 +0100
Subject: [PATCH] Add onlyOneItem and orientation  property to DropList

Also improve conditional border style. The additional dragPreview is
needed so the dragged item does not have the border.
---
 .../compound-elements/drop-list.component.ts  | 22 +++++++++++++++----
 .../models/compound-elements/drop-list.ts     |  2 ++
 .../element-properties.component.html         | 18 +++++++++++++++
 projects/editor/src/assets/i18n/de.json       |  1 +
 4 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/projects/common/element-components/compound-elements/drop-list.component.ts b/projects/common/element-components/compound-elements/drop-list.component.ts
index a608e2d8c..01f33a58f 100644
--- a/projects/common/element-components/compound-elements/drop-list.component.ts
+++ b/projects/common/element-components/compound-elements/drop-list.component.ts
@@ -1,6 +1,6 @@
 import { Component } from '@angular/core';
 import { CdkDragDrop } from '@angular/cdk/drag-drop/drag-events';
-import { moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
+import { CdkDrag, CdkDropList, DragRef, DropListRef, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
 import { DropListElement } from '../../models/compound-elements/drop-list';
 import { FormElementComponent } from '../../form-element-component.directive';
 
@@ -18,20 +18,30 @@ import { FormElementComponent } from '../../form-element-component.directive';
          [style.font-style]="elementModel.italic ? 'italic' : ''"
          [style.text-decoration]="elementModel.underline ? 'underline' : ''"
          [style.backgroundColor]="elementModel.backgroundColor"
+         [style.display]="elementModel.orientation === 'horizontal' ? 'flex' : ''"
+         [style.flex-direction]="elementModel.orientation === 'horizontal' ? 'row' : ''"
          cdkDropList
          [id]="elementModel.id"
          [cdkDropListData]="this"
          [cdkDropListConnectedTo]="elementModel.connectedTo"
+         [cdkDropListOrientation]="elementModel.orientation"
+         [cdkDropListEnterPredicate]="onlyOneItemPredicate"
          (cdkDropListDropped)="drop($event)">
-      <div class="item" *ngFor="let option of elementModel.options" cdkDrag>
+      <div class="item" *ngFor="let option of elementModel.options; let i = index" cdkDrag
+           [ngClass]="{'vertical-item': elementModel.orientation === 'vertical' &&
+                                   i+1 < elementModel.options.length,
+                       'horizontal-item': elementModel.orientation === 'horizontal' &&
+                                   i+1 < elementModel.options.length}">
+        <div *cdkDragPreview>{{option}}</div>
         {{option}}
       </div>
     </div>
   `,
   styles: [
-    '.list {border: 1px solid; border-radius: 3px}',
+    '.list {border: 1px solid; border-radius: 3px;}',
     '.item {padding: 10px;}',
-    '.item:not(:last-child) {border-bottom: 1px solid;}'
+    '.vertical-item {border-bottom: 1px solid}',
+    '.horizontal-item {border-right: 1px solid}'
   ]
 })
 export class DropListComponent extends FormElementComponent {
@@ -51,4 +61,8 @@ export class DropListComponent extends FormElementComponent {
     }
     this.elementFormControl.setValue(event.container.data.elementModel.options);
   }
+
+  onlyOneItemPredicate(drag: CdkDrag, drop: CdkDropList): boolean {
+    return !drop.data.elementModel.onlyOneItem || drop.data.elementModel.options.length < 1;
+  }
 }
diff --git a/projects/common/models/compound-elements/drop-list.ts b/projects/common/models/compound-elements/drop-list.ts
index d4d43ad53..6fff65975 100644
--- a/projects/common/models/compound-elements/drop-list.ts
+++ b/projects/common/models/compound-elements/drop-list.ts
@@ -4,7 +4,9 @@ import { initFontElement, initSurfaceElement } from '../../util/unit-interface-i
 
 export class DropListElement extends InputElement implements FontElement, SurfaceUIElement {
   options: string[] = [];
+  onlyOneItem: boolean = false;
   connectedTo: string[] = [];
+  orientation: 'vertical' | 'horizontal' = 'vertical';
 
   fontColor: string = 'black';
   font: string = 'Roboto';
diff --git a/projects/editor/src/app/unit-view/page-view/properties-panel/element-properties.component.html b/projects/editor/src/app/unit-view/page-view/properties-panel/element-properties.component.html
index 9ea667a67..fbebdc6dd 100644
--- a/projects/editor/src/app/unit-view/page-view/properties-panel/element-properties.component.html
+++ b/projects/editor/src/app/unit-view/page-view/properties-panel/element-properties.component.html
@@ -407,6 +407,24 @@
           </div>
         </mat-form-field>
 
+        <mat-form-field *ngIf="combinedProperties.orientation !== undefined"
+                        appearance="fill">
+          <mat-label>{{'propertiesPanel.alignment' | translate }}</mat-label>
+          <mat-select [value]="combinedProperties.orientation"
+                      (selectionChange)="updateModel('orientation', $event.value)">
+            <mat-option *ngFor="let option of ['vertical', 'horizontal']"
+                        [value]="option">
+              {{ 'propertiesPanel.' + option | translate }}
+            </mat-option>
+          </mat-select>
+        </mat-form-field>
+
+        <mat-checkbox *ngIf="combinedProperties.onlyOneItem !== undefined"
+                      [checked]="$any(combinedProperties.onlyOneItem)"
+                      (change)="updateModel('onlyOneItem', $event.checked)">
+          {{'propertiesPanel.onlyOneItem' | translate }}
+        </mat-checkbox>
+
         <mat-divider></mat-divider>
 
         <button mat-raised-button class="element-button"
diff --git a/projects/editor/src/assets/i18n/de.json b/projects/editor/src/assets/i18n/de.json
index 3c639e0d5..e4402b7b8 100644
--- a/projects/editor/src/assets/i18n/de.json
+++ b/projects/editor/src/assets/i18n/de.json
@@ -105,6 +105,7 @@
     "magnifierSize": "Größe der Lupe",
     "magnifierZoom": "Vergrößerungsfaktor",
     "connectedDropList": "Verbundene Ablegelisten",
+    "onlyOneItem": "Nur ein erlaubtes Element",
     "duplicateElement": "Element duplizieren",
     "deleteElement": "Element löschen",
     "noElementSelected": "Kein Element ausgewählt"
-- 
GitLab