From 9f92b2abea87b35a3954ca59e02de08a32e6b4d3 Mon Sep 17 00:00:00 2001
From: Andrea Gottsponer <ago@attr.ch>
Date: Tue, 18 Feb 2020 19:25:26 +0100
Subject: [PATCH] - multi move - remove configmenu when moving

---
 .../elements/collections/FillCollection.ts    | 86 +++++++++++++++++--
 .../elements/collections/LegendCollection.ts  | 28 ++++--
 .../interactions/select/SelectElement.ts      | 81 +++++++++++++++--
 .../elements/positionings/PositionPoint.ts    | 12 ++-
 src/lib/elements/primitives/ArrowPrimitive.ts |  6 ++
 .../elements/primitives/EllipsePrimitive.ts   |  6 ++
 .../elements/primitives/RectanglePrimitive.ts |  6 ++
 src/lib/elements/primitives/TextPrimitive.ts  |  6 ++
 8 files changed, 211 insertions(+), 20 deletions(-)

diff --git a/src/lib/elements/collections/FillCollection.ts b/src/lib/elements/collections/FillCollection.ts
index b8a43183..df591b46 100644
--- a/src/lib/elements/collections/FillCollection.ts
+++ b/src/lib/elements/collections/FillCollection.ts
@@ -18,6 +18,8 @@ import {InteractiveGenerator} from "../../generators/InteractiveGenerator";
 import {LegendCollection} from "./LegendCollection";
 import {LegendColumnCollection} from "./LegendColumnCollection";
 import {NumberElement} from "../interactions/number/NumberElement";
+import {MoveInteraction} from "../../interactions/MoveInteraction";
+import * as Keyboard from "pixi.js-keyboard";
 
 /**
  * Fill collection
@@ -38,7 +40,8 @@ export class FillCollection extends BaseElementContainer<Models.FillCollection>
     /**
      * Interactions
      */
-    protected _selectInteraction: SelectInteraction;
+    private _selectInteraction: SelectInteraction;
+    private _moveInteraction: MoveInteraction;
 
     /**
      * Elements
@@ -149,6 +152,9 @@ export class FillCollection extends BaseElementContainer<Models.FillCollection>
         this.on("onSelectStart", this._onSelectStart, this);
         this.on("onInteractive", this._onInteractive, this); // TODO
 
+        this.moveInteraction = new MoveInteraction(this);
+        this.on("onMove", this._onMove, this);
+
         // Elements
         const buttonSize = this.canvasWidth / this._buttonSizeAspect;
 
@@ -408,6 +414,11 @@ export class FillCollection extends BaseElementContainer<Models.FillCollection>
             delete this.selectInteraction;
         }
 
+        if (this.moveInteraction) {
+            this.off("onMove", this._onMove, this);
+            delete this.moveInteraction;
+        }
+
         this._colorPicker.off("color", this._onColor, this);
         // TODO this._lineColorPicker.off("color", this._onLineColor, this);
         this._strokeWidthElement.off("number", this._onStrokeWidth, this);
@@ -659,9 +670,24 @@ export class FillCollection extends BaseElementContainer<Models.FillCollection>
         // Events
         this.interactive = true;
         this.on("pointerover", this.selectInteraction.onHover, this.selectInteraction);
-        this.on("pointerdown", this._onPointerDown, this);
-        this.on("pointerup", this._onPointerUp, this);
+        this.on("pointerover", this.moveInteraction.onMoveHover, this.moveInteraction);
+        this.on("pointerdown", this.moveInteraction.startMove, this.moveInteraction);
+        this.on("pointermove", this.moveInteraction.onMove, this.moveInteraction);
+        this.on("pointerup", this.moveInteraction.endMove, this.moveInteraction);
+        this.on("startMove", this._startMove, this);
+        this.on("endMove", this._endMove, this);
         this.on("onRelease", this._onRelease, this);
+
+        Keyboard.events.on("down_ArrowUp", "onLegendCollectionMoveUp", this.moveInteraction.moveUp.bind(this.moveInteraction));
+        Keyboard.events.on("down_ArrowRight", "onLegendCollectionMoveRight", this.moveInteraction.moveRight.bind(this.moveInteraction));
+        Keyboard.events.on("down_ArrowDown", "onLegendCollectionMoveDown", this.moveInteraction.moveDown.bind(this.moveInteraction));
+        Keyboard.events.on("down_ArrowLeft", "onLegendCollectionMoveLeft", this.moveInteraction.moveLeft.bind(this.moveInteraction));
+        Keyboard.events.on("released_ArrowUp", "onLegendCollectionMoveUpEnd", this.moveInteraction.moveRelease.bind(this.moveInteraction));
+        Keyboard.events.on("released_ArrowRight", "onLegendCollectionMoveRightEnd", this.moveInteraction.moveRelease.bind(this.moveInteraction));
+        Keyboard.events.on("released_ArrowDown", "onLegendCollectionMoveDownEnd", this.moveInteraction.moveRelease.bind(this.moveInteraction));
+        Keyboard.events.on("released_ArrowLeft", "onLegendCollectionMoveLeftEnd", this.moveInteraction.moveRelease.bind(this.moveInteraction));
+
+        this.emit("pointerover", new PIXI.interaction.InteractionEvent());
     }
 
     protected _removeModeSelect(): void {
@@ -670,9 +696,22 @@ export class FillCollection extends BaseElementContainer<Models.FillCollection>
         // Events
         this.interactive = false;
         this.off("pointerover", this.selectInteraction.onHover, this.selectInteraction);
-        this.off("pointerdown", this._onPointerDown, this);
-        this.off("pointerup", this._onPointerUp, this);
+        this.off("pointerover", this.moveInteraction.onMoveHover, this.moveInteraction);
+        this.off("pointerdown", this.moveInteraction.startMove, this.moveInteraction);
+        this.off("pointermove", this.moveInteraction.onMove, this.moveInteraction);
+        this.off("pointerup", this.moveInteraction.onMove, this.moveInteraction);
+        this.off("startMove", this._startMove, this);
+        this.off("endMove", this._endMove, this);
         this.off("onRelease", this._onRelease, this);
+
+        Keyboard.events.remove("down_ArrowUp", "onLegendCollectionMoveUp");
+        Keyboard.events.remove("down_ArrowRight", "onLegendCollectionMoveRight");
+        Keyboard.events.remove("down_ArrowDown", "onLegendCollectionMoveDown");
+        Keyboard.events.remove("down_ArrowLeft", "onLegendCollectionMoveLeft");
+        Keyboard.events.remove("released_ArrowUp", "onLegendCollectionMoveUpEnd");
+        Keyboard.events.remove("released_ArrowRight", "onLegendCollectionMoveRightEnd");
+        Keyboard.events.remove("released_ArrowDown", "onLegendCollectionMoveDownEnd");
+        Keyboard.events.remove("released_ArrowLeft", "onLegendCollectionMoveLeftEnd");
     }
 
     protected _modeBlocked(parent: ImageObject, element: ImageObject): void {
@@ -833,6 +872,35 @@ export class FillCollection extends BaseElementContainer<Models.FillCollection>
     //</editor-fold>
     //</editor-fold>
 
+    //<editor-fold desc="Move">
+    protected _startMove(): void {
+        this.removeChild(this._configurationElement);
+
+        // Events
+        this.off("pointerover", this.selectInteraction.onHover, this.selectInteraction);
+    }
+
+    protected _onMove(event: PIXI.interaction.InteractionEvent, dX: number, dY: number): void {
+        this.lines.forEach((line: Line) => {
+            if (line.graphicLine.direction === LineDirection.START_END) {
+                // @ts-ignore
+                line.graphicLine.start.emit("onMove", event, dX, dY);
+            } else {
+                // @ts-ignore
+                line.graphicLine.end.emit("onMove", event, dX, dY);
+            }
+        });
+    }
+
+    protected _endMove(event: PIXI.interaction.InteractionEvent): void {
+        this.addChild(this._configurationElement);
+
+        // Events
+        this.on("pointerover", this.selectInteraction.onHover, this.selectInteraction);
+        this.emit("pointerover", event);
+    }
+    //</editor-fold>
+
     //<editor-fold desc="Select">
     protected _onPointerDown(event: PIXI.interaction.InteractionEvent): void {
         event.stopPropagation();
@@ -1033,6 +1101,14 @@ export class FillCollection extends BaseElementContainer<Models.FillCollection>
         this._selectInteraction = value;
     }
 
+    public get moveInteraction(): MoveInteraction {
+        return this._moveInteraction;
+    }
+
+    public set moveInteraction(value: MoveInteraction) {
+        this._moveInteraction = value;
+    }
+
     public get isInteractive(): boolean {
         return this.model.isInteractive;
     }
diff --git a/src/lib/elements/collections/LegendCollection.ts b/src/lib/elements/collections/LegendCollection.ts
index 92758151..724135f4 100644
--- a/src/lib/elements/collections/LegendCollection.ts
+++ b/src/lib/elements/collections/LegendCollection.ts
@@ -302,12 +302,6 @@ export class LegendCollection extends BaseElementContainer<Models.LegendCollecti
             this.modeInteraction.off("remove-draw", this._removeModeDraw, this);
             this.modeInteraction.off("drawing", this._modeDrawing, this);
             this.modeInteraction.off("remove-drawing", this._removeModeDrawing, this);
-            /* TODO remove ???
-            this.modeInteraction.off("selftest_choosing", this._modeSelftestChoosing, this);
-            this.modeInteraction.off("remove-selftest_choosing", this._removeSelftestModeChoosing, this);
-            this.modeInteraction.off("fill_choosing", this._modeFillChoosing, this);
-            this.modeInteraction.off("remove-fill_choosing", this._removeFillModeChoosing, this);
-            */
             this.modeInteraction.off("delete", this._modeDelete, this);
             delete this.modeInteraction;
         }
@@ -318,6 +312,22 @@ export class LegendCollection extends BaseElementContainer<Models.LegendCollecti
             delete this.selectInteraction;
         }
 
+        if (this.moveInteraction) {
+            this.off("onMove", this._onMove, this);
+            delete this.moveInteraction;
+        }
+
+        if (this.scaleInteraction) {
+            this.off("onScale", this._onScale, this);
+            delete this.scaleInteraction;
+        }
+
+        if (this.rotateInteraction) {
+            this.off("onRotate", this._onRotate, this);
+            this.off("lineRotate", this._lineRotate, this);
+            delete this.rotateInteraction;
+        }
+
         this._staticButton.off("button", this._onStaticButton, this);
         this._removeButton.off("button", this._onRemoveButton, this);
     }
@@ -793,6 +803,9 @@ export class LegendCollection extends BaseElementContainer<Models.LegendCollecti
 
     //<editor-fold desc="Move">
     protected _startMove(): void {
+        this.rotateContainer.removeChild(this._configurationElement);
+
+        // Events
         this.off("pointerover", this.selectInteraction.onHover, this.selectInteraction);
     }
 
@@ -809,6 +822,9 @@ export class LegendCollection extends BaseElementContainer<Models.LegendCollecti
     }
 
     protected _endMove(event: PIXI.interaction.InteractionEvent): void {
+        this.rotateContainer.addChild(this._configurationElement);
+
+        // Events
         this.on("pointerover", this.selectInteraction.onHover, this.selectInteraction);
         this.emit("pointerover", event);
     }
diff --git a/src/lib/elements/interactions/select/SelectElement.ts b/src/lib/elements/interactions/select/SelectElement.ts
index 1719ebaf..79d3726e 100644
--- a/src/lib/elements/interactions/select/SelectElement.ts
+++ b/src/lib/elements/interactions/select/SelectElement.ts
@@ -1,5 +1,6 @@
 import * as PIXI from "pixi.js-legacy";
 import {BaseContainer, ImageObject} from "../../../bases/BaseModul";
+import {MoveInteraction} from "../../../interactions/MoveInteraction";
 
 /**
  * Select element
@@ -9,10 +10,16 @@ export class SelectElement extends BaseContainer {
      * Members
      */
     private _groupImageObjects: string[];
+    private _groupImageObjectRefs: ImageObject[];
     protected _rectangle: PIXI.Rectangle;
     protected _lineColor: number;
     protected _fillColor: number;
 
+    /**
+     * Interactions
+     */
+    private _moveInteraction: MoveInteraction;
+
     /**
      * Elements
      */
@@ -42,9 +49,24 @@ export class SelectElement extends BaseContainer {
         // Setup
         this.zIndex = 50;
         this._groupImageObjects = groupImageObjects;
+        this._groupImageObjectRefs = [];
         this._lineColor = this._lineColorNormal;
         this._fillColor = this._fillColorNormal;
 
+        // Events
+        this.interactive = true;
+
+        this.moveInteraction = new MoveInteraction(this);
+        this.on("pointerover", this.moveInteraction.onMoveHover, this.moveInteraction);
+        this.on("pointerdown", this.moveInteraction.startMove, this.moveInteraction);
+        this.on("pointermove", this.moveInteraction.onMove, this.moveInteraction);
+        this.on("pointerup", this.moveInteraction.endMove, this.moveInteraction);
+        this.on("pointerupoutside", this.moveInteraction.endMove, this.moveInteraction);
+
+        this.on("startMoveStart", this._onPointerDown, this);
+        this.on("onMove", this._onMove, this);
+        this.on("rightup", this._onRightUp, this);
+
         // Elements
         this._topLineElement = new PIXI.Graphics();
         this.addChild(this._topLineElement);
@@ -91,6 +113,23 @@ export class SelectElement extends BaseContainer {
 
         this.hitArea = this._rectangle;
     }
+
+    public cleanUp(): void {
+        this.off("pointerover", this.moveInteraction.onMoveHover, this.moveInteraction);
+        this.off("pointerdown", this.moveInteraction.startMove, this.moveInteraction);
+        this.off("pointermove", this.moveInteraction.onMove, this.moveInteraction);
+        this.off("pointerup", this.moveInteraction.endMove, this.moveInteraction);
+        this.off("pointerupoutside", this.moveInteraction.endMove, this.moveInteraction);
+
+        this.off("startMoveStart", this._onPointerDown, this);
+        this.off("onMove", this._onMove, this);
+        this.off("rightup", this._onRightUp, this);
+    }
+
+    public destroy(options?: { children?: boolean; texture?: boolean; baseTexture?: boolean }): void {
+        this.cleanUp();
+        super.destroy(options);
+    }
     //</editor-fold>
 
     //<editor-fold desc="Private functions">
@@ -153,6 +192,17 @@ export class SelectElement extends BaseContainer {
 
         this.getImage().allItemReleased(event);
     }
+
+    protected _onMove(event: PIXI.interaction.InteractionEvent, dX: number, dY: number): void {
+        this._groupImageObjectRefs.forEach((element: ImageObject) => {
+            element.emit("onMove", event, dX, dY);
+        });
+    }
+
+    protected _onItemMove(): void {
+        this._calculateRectangle();
+        this.draw();
+    }
     //</editor-fold>
 
     //<editor-fold desc="BaseContainer">
@@ -165,8 +215,6 @@ export class SelectElement extends BaseContainer {
 
         // Events
         this.interactive = true;
-        this.on("pointerdown", this._onPointerDown, this);
-        this.on("rightup", this._onRightUp, this);
     }
 
     public hideItem(): void {
@@ -174,21 +222,42 @@ export class SelectElement extends BaseContainer {
 
         // Events
         this.interactive = false;
-        this.off("pointerdown", this._onPointerDown, this);
-        this.off("rightup", this._onRightUp, this);
     }
     //</editor-fold>
 
     //<editor-fold desc="Getter and Setter">
+    public get moveInteraction(): MoveInteraction {
+        return this._moveInteraction;
+    }
+
+    public set moveInteraction(value: MoveInteraction) {
+        this._moveInteraction = value;
+    }
+
     public get groupImageObjects(): string[] {
         return this._groupImageObjects;
     }
 
     public set groupImageObjects(value: string[]) {
+        // Remove old references
+        this._groupImageObjectRefs.forEach((element: ImageObject) => {
+            element.off("onMove", this._onItemMove, this);
+        });
+        this._groupImageObjectRefs = [];
+
+        // Setup new values
         this._groupImageObjects = value;
+
         if (this._groupImageObjects.length > 0) {
-            this._calculateRectangle();
-            this.draw();
+            // Add events
+            this.groupImageObjects.forEach((id: string) => {
+                const element = this.getImage().getChildByName(id) as ImageObject;
+                element.on("onMove", this._onItemMove, this);
+                this._groupImageObjectRefs.push(element);
+            });
+
+            // Show selection
+            this._onItemMove();
         }
     }
     //</editor-fold>
diff --git a/src/lib/elements/positionings/PositionPoint.ts b/src/lib/elements/positionings/PositionPoint.ts
index d6619b17..e2b1a7e6 100644
--- a/src/lib/elements/positionings/PositionPoint.ts
+++ b/src/lib/elements/positionings/PositionPoint.ts
@@ -632,9 +632,12 @@ export class PositionPoint extends BaseElementContainer<Models.PositionPoint> {
 
     //<editor-fold desc="Move">
     protected _startMove(): void {
-        this.off("pointerover", this.selectInteraction.onHover, this.selectInteraction);
         this._circle.radius += MOVE_HITTEST_EXTENSION;
         this._positionPointElement.hitArea = this._circle;
+        this.removeChild(this._configurationElement);
+
+        // Events
+        this.off("pointerover", this.selectInteraction.onHover, this.selectInteraction);
     }
 
     protected _onMove(event: PIXI.interaction.InteractionEvent, dX: number, dY: number) {
@@ -645,10 +648,13 @@ export class PositionPoint extends BaseElementContainer<Models.PositionPoint> {
     }
 
     protected _endMove(event: PIXI.interaction.InteractionEvent): void {
-        this.on("pointerover", this.selectInteraction.onHover, this.selectInteraction);
-        this.emit("pointerover", event);
         this._circle.radius -= MOVE_HITTEST_EXTENSION;
         this._positionPointElement.hitArea = this._circle;
+        this.addChild(this._configurationElement);
+
+        // Events
+        this.on("pointerover", this.selectInteraction.onHover, this.selectInteraction);
+        this.emit("pointerover", event);
     }
     //</editor-fold>
 
diff --git a/src/lib/elements/primitives/ArrowPrimitive.ts b/src/lib/elements/primitives/ArrowPrimitive.ts
index 816612ad..a810088a 100644
--- a/src/lib/elements/primitives/ArrowPrimitive.ts
+++ b/src/lib/elements/primitives/ArrowPrimitive.ts
@@ -753,6 +753,9 @@ export class ArrowPrimitive extends BaseElementContainer<Models.ArrowPrimitive>
 
     //<editor-fold desc="Move">
     protected _startMove(): void {
+        this._rotateContainer.removeChild(this._configurationElement);
+
+        // Events
         this.off("pointerover", this.selectInteraction.onHover, this.selectInteraction);
         /* TODO check if needed
         this._rectangle.pad(MOVE_HITTEST_EXTENSION, MOVE_HITTEST_EXTENSION);
@@ -785,6 +788,9 @@ export class ArrowPrimitive extends BaseElementContainer<Models.ArrowPrimitive>
     }
 
     protected _endMove(event: PIXI.interaction.InteractionEvent): void {
+        this._rotateContainer.addChild(this._configurationElement);
+
+        // Events
         this.on("pointerover", this.selectInteraction.onHover, this.selectInteraction);
         this.emit("pointerover", event);
         /* TODO check if needed
diff --git a/src/lib/elements/primitives/EllipsePrimitive.ts b/src/lib/elements/primitives/EllipsePrimitive.ts
index dbc2d8d5..05a90889 100644
--- a/src/lib/elements/primitives/EllipsePrimitive.ts
+++ b/src/lib/elements/primitives/EllipsePrimitive.ts
@@ -727,6 +727,9 @@ export class EllipsePrimitive extends BaseElementContainer<Models.EllipsePrimiti
 
     //<editor-fold desc="Move">
     protected _startMove(): void {
+        this._rotateContainer.removeChild(this._configurationElement);
+
+        // Events
         this.off("pointerover", this.selectInteraction.onHover, this.selectInteraction);
         /* TODO check if needed
         this._rectangle.pad(MOVE_HITTEST_EXTENSION, MOVE_HITTEST_EXTENSION);
@@ -746,6 +749,9 @@ export class EllipsePrimitive extends BaseElementContainer<Models.EllipsePrimiti
     }
 
     protected _endMove(event: PIXI.interaction.InteractionEvent): void {
+        this._rotateContainer.addChild(this._configurationElement);
+
+        // Events
         this.on("pointerover", this.selectInteraction.onHover, this.selectInteraction);
         this.emit("pointerover", event);
         /* TODO check if needed
diff --git a/src/lib/elements/primitives/RectanglePrimitive.ts b/src/lib/elements/primitives/RectanglePrimitive.ts
index ef4bbe6d..dde27b60 100644
--- a/src/lib/elements/primitives/RectanglePrimitive.ts
+++ b/src/lib/elements/primitives/RectanglePrimitive.ts
@@ -727,6 +727,9 @@ export class RectanglePrimitive extends BaseElementContainer<Models.RectanglePri
 
     //<editor-fold desc="Move">
     protected _startMove(): void {
+        this._rotateContainer.removeChild(this._configurationElement);
+
+        // Events
         this.off("pointerover", this.selectInteraction.onHover, this.selectInteraction);
         /* TODO check if needed
         this._rectangle.pad(MOVE_HITTEST_EXTENSION, MOVE_HITTEST_EXTENSION);
@@ -746,6 +749,9 @@ export class RectanglePrimitive extends BaseElementContainer<Models.RectanglePri
     }
 
     protected _endMove(event: PIXI.interaction.InteractionEvent): void {
+        this._rotateContainer.addChild(this._configurationElement);
+
+        // Events
         this.on("pointerover", this.selectInteraction.onHover, this.selectInteraction);
         this.emit("pointerover", event);
         /* TODO check if needed
diff --git a/src/lib/elements/primitives/TextPrimitive.ts b/src/lib/elements/primitives/TextPrimitive.ts
index 1d36c0dc..9d2cc7c3 100644
--- a/src/lib/elements/primitives/TextPrimitive.ts
+++ b/src/lib/elements/primitives/TextPrimitive.ts
@@ -868,6 +868,9 @@ export class TextPrimitive extends BaseElementContainer<Models.TextPrimitive> {
 
     //<editor-fold desc="Move">
     protected _startMove(): void {
+        this._rotateContainer.removeChild(this._configurationElement);
+
+        // Events
         this.off("pointerover", this.selectInteraction.onHover, this.selectInteraction);
         /* TODO check if needed
         this._rectangle.pad(MOVE_HITTEST_EXTENSION, MOVE_HITTEST_EXTENSION);
@@ -887,6 +890,9 @@ export class TextPrimitive extends BaseElementContainer<Models.TextPrimitive> {
     }
 
     protected _endMove(event: PIXI.interaction.InteractionEvent): void {
+        this._rotateContainer.addChild(this._configurationElement);
+
+        // Events
         this.on("pointerover", this.selectInteraction.onHover, this.selectInteraction);
         this.emit("pointerover", event);
         /* TODO check if needed
-- 
GitLab