From e44242471be58004097b126375b6ada0be398f4e Mon Sep 17 00:00:00 2001
From: "mathias.chouet" <mathias.chouet@irstea.fr>
Date: Wed, 12 Jun 2019 12:27:50 +0200
Subject: [PATCH] Pab: interpolation

---
 .../dialog-edit-pab.component.ts              | 37 +++++-----
 .../pab-table/pab-table.component.html        |  2 +-
 .../pab-table/pab-table.component.scss        |  8 +++
 .../pab-table/pab-table.component.ts          | 69 +++++++++++++++++--
 4 files changed, 90 insertions(+), 26 deletions(-)

diff --git a/src/app/components/dialog-edit-pab/dialog-edit-pab.component.ts b/src/app/components/dialog-edit-pab/dialog-edit-pab.component.ts
index 7bb57443c..a2e4c57ae 100644
--- a/src/app/components/dialog-edit-pab/dialog-edit-pab.component.ts
+++ b/src/app/components/dialog-edit-pab/dialog-edit-pab.component.ts
@@ -58,15 +58,22 @@ export class DialogEditPabComponent {
     return this._variable;
   }
 
-  // preloads valueToSet depending on variable chosen
-  public set variable(v: string) {
-    this._variable = v;
-    // find variable details from key
+  // find available variable details from key
+  private findVariableDetails(variable: string): any {
+    let details: any;
     for (const av of this.availableVariables) {
-      if (av.value === this.variable) {
-        this.valueToSet = av.first;
+      if (av.value === variable) {
+        details = av;
       }
     }
+    return details;
+  }
+
+  // preloads valueToSet depending on variable chosen
+  public set variable(v: string) {
+    this._variable = v;
+    const av = this.findVariableDetails(v);
+    this.valueToSet = av.first;
   }
 
   /** closes dialog and tells parent to apply modifications */
@@ -75,7 +82,8 @@ export class DialogEditPabComponent {
       action: this.varAction,
       variable: this.variable,
       value: this.valueToSet,
-      delta: this.delta
+      delta: this.delta,
+      variableDetails: this.findVariableDetails(this.variable)
     });
   }
 
@@ -117,11 +125,8 @@ export class DialogEditPabComponent {
   }
 
   public variableLabel(v: string) {
-    for (const av of this.availableVariables) {
-      if (av.value === v) {
-        return av.label;
-      }
-    }
+    const av = this.findVariableDetails(v);
+    return av.label;
   }
 
   public get interpolationEnabled() {
@@ -134,13 +139,7 @@ export class DialogEditPabComponent {
   public get interpolationBounds() {
     let bounds = "";
     if (this.interpolationEnabled) {
-      // find variable details from key
-      let varDetails: any;
-      for (const v of this.availableVariables) {
-        if (v.value === this.variable) {
-          varDetails = v;
-        }
-      }
+      const varDetails = this.findVariableDetails(this.variable);
       if (varDetails) {
         bounds = sprintf(
           this.intlService.localizeText("INFO_DIALOG_EDIT_PAB_INTERPOLATION_BOUNDS"),
diff --git a/src/app/components/pab-table/pab-table.component.html b/src/app/components/pab-table/pab-table.component.html
index a045ed601..f1e7c5dda 100644
--- a/src/app/components/pab-table/pab-table.component.html
+++ b/src/app/components/pab-table/pab-table.component.html
@@ -78,7 +78,7 @@
                   [class.selectable-cell]="isSelectable(cell)" [class.selected-cell]="isSelected(cell) && ! isSelected(row)"
                   [attr.rowspan]="rowSpan(cell)" [attr.colspan]="colSpan(cell)">
 
-                    <input matInput *ngIf="isNumberInput(cell)" type="text" [(ngModel)]="cell.model.singleValue">
+                    <input matInput *ngIf="isNumberInput(cell)" type="number" [(ngModel)]="cell.model.singleValue">
 
                     <mat-select *ngIf="isSelect(cell)" [(value)]="cell.model">
                         <!-- <mat-option *ngFor="let opt of cell.options | keyvalue" [value]="l.key">
diff --git a/src/app/components/pab-table/pab-table.component.scss b/src/app/components/pab-table/pab-table.component.scss
index 45e4326af..487fca155 100644
--- a/src/app/components/pab-table/pab-table.component.scss
+++ b/src/app/components/pab-table/pab-table.component.scss
@@ -124,6 +124,14 @@ mat-card-content {
                         > mat-select.mat-select {
                             padding: 0 8px;
                         }
+
+                        > input[type="number"] {
+                            -moz-appearance: textfield;
+                        }
+                        /* input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button
+                            -webkit-appearance: none;
+                            margin: 0;
+                        } */
                     }
                 }
             }
diff --git a/src/app/components/pab-table/pab-table.component.ts b/src/app/components/pab-table/pab-table.component.ts
index 1397a59ce..f2949db1f 100644
--- a/src/app/components/pab-table/pab-table.component.ts
+++ b/src/app/components/pab-table/pab-table.component.ts
@@ -16,9 +16,10 @@ import {
  } from "jalhyd";
 
 import { I18nService } from "../../services/internationalisation/internationalisation.service";
+import { FormulaireService } from "../../services/formulaire/formulaire.service";
+import { ApplicationSetupService } from "../../services/app-setup/app-setup.service";
 import { PabTable } from "../../formulaire/pab-table";
 import { DialogEditPabComponent } from "../dialog-edit-pab/dialog-edit-pab.component";
-import { FormulaireService } from "../../services/formulaire/formulaire.service";
 
 /**
  * The big editable data grid for calculator type "Pab" (component)
@@ -62,7 +63,7 @@ export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit {
     public childrenToAdd = 1;
 
     /** items currently selected */
-    private selectedItems: any[];
+    private selectedItems: Nub[];
 
     /** used for shift+click implementation */
     private latestClickedCell: any;
@@ -70,7 +71,8 @@ export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit {
     public constructor(
         private i18nService: I18nService,
         private formService: FormulaireService,
-        private editPabDialog: MatDialog
+        private editPabDialog: MatDialog,
+        private appSetupService: ApplicationSetupService
     ) {
         this.selectedItems = [];
     }
@@ -780,7 +782,7 @@ export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit {
         if (this.selectedItems.length > 0) {
 
             // list variables eligible to modification
-            const availableVariables: any[] = [];
+            const availableVariables: { label: string, value: string, occurrences: number, first: number, last: number }[] = [];
             for (const c of this.selectedItems) {
                 for (const p of c.parameterIterator) { // deep one
                     if (
@@ -789,7 +791,10 @@ export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit {
                     ) {
                         availableVariables.push({
                             label: this.formService.expandVariableNameAndUnit(CalculatorType.Pab, p.symbol),
-                            value: p.symbol
+                            value: p.symbol,
+                            occurrences: 0,
+                            first: undefined,
+                            last: undefined
                         });
                     }
                 }
@@ -799,6 +804,7 @@ export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit {
                 for (const c of this.selectedItems) {
                     for (const p of c.parameterIterator) {
                         if (p.visible && p.symbol === av.value) {
+                            av.occurrences ++;
                             if (av.first === undefined) {
                                 av.first = p.singleValue;
                             }
@@ -858,15 +864,66 @@ export class PabTableComponent implements /* DoCheck, AfterViewInit, */ OnInit {
                     disableClose: true
                 }
             );
+
+            // apply modifications
             dialogRef.afterClosed().subscribe(result => {
                 if (result) {
-                    console.log("Apply values in parent !!", result.action, result.variable, result.value, result.delta);
+                    console.log("Apply values in parent !!", result.action, result.variable, result.value,
+                      result.delta, result.variableDetails);
                     switch (result.action) {
                         case "set-value":
+                            for (const s of this.selectedItems) {
+                                for (const p of s.parameterIterator) { // deep
+                                    if (p.symbol === result.variable) {
+                                        p.singleValue = result.value;
+                                    }
+                                }
+                            }
                             break;
+
                         case "delta":
+                            for (const s of this.selectedItems) {
+                                for (const p of s.parameterIterator) { // deep
+                                    if (p.symbol === result.variable) {
+                                        p.singleValue += result.delta;
+                                    }
+                                }
+                            }
                             break;
+
                         case "interpolate":
+                            if (result.variableDetails.occurrences > 1) {
+                                const nDigits = this.appSetupService.displayDigits;
+                                // build values list
+                                const interpolatedValues: number[] = [];
+                                const step = (
+                                    (result.variableDetails.last - result.variableDetails.first)
+                                    / (result.variableDetails.occurrences - 1)
+                                );
+                                console.log(">>>> step", step);
+                                interpolatedValues.push(result.variableDetails.first);
+                                let currentValue: number = result.variableDetails.first;
+                                for (let i = 0; i < result.variableDetails.occurrences - 2; i++) {
+                                    currentValue += step;
+                                    interpolatedValues.push(Number(currentValue.toFixed(nDigits)));
+                                }
+                                interpolatedValues.push(result.variableDetails.last);
+                                console.log(">>>> interp. values", interpolatedValues);
+                                // apply
+                                let idx = 0;
+                                for (const s of this.selectedItems) {
+                                    for (const p of s.parameterIterator) { // deep
+                                        if (p.symbol === result.variable) {
+                                            p.singleValue = interpolatedValues[idx];
+                                            idx ++;
+                                        }
+                                    }
+                                }
+                            } else {
+                                throw new Error(
+                                    `showEditPab() : cannot interpolate, too few occurrences (${result.variableDetails.occurrences})`
+                                );
+                            }
                             break;
                     }
                 }
-- 
GitLab