support drag muilt element 49/11949/2
authorLvbo163 <lv.bo163@zte.com.cn>
Tue, 12 Sep 2017 13:09:38 +0000 (21:09 +0800)
committerLvbo163 <lv.bo163@zte.com.cn>
Tue, 12 Sep 2017 13:29:24 +0000 (21:29 +0800)
support select multi element by mouse drag and drag multi element.

Issue-ID: SDC-316

Change-Id: I7111b705f2e490b84f030fc4832217808c3783dc
Signed-off-by: Lvbo163 <lv.bo163@zte.com.cn>
sdc-workflow-designer-ui/src/app/app.module.ts
sdc-workflow-designer-ui/src/app/components/canvas/canvas.component.html
sdc-workflow-designer-ui/src/app/directive/drag-select/drag-select.directive.ts [new file with mode: 0644]
sdc-workflow-designer-ui/src/app/services/data-access/in-memory-data.service.ts
sdc-workflow-designer-ui/src/styles.css

index 55b5795..b2bcb74 100644 (file)
@@ -46,11 +46,13 @@ import { WorkflowProcessService } from "./services/workflow-process.service";
 import { IntermediateCatchEventComponent } from "./components/property/intermediate-catch-event/intermediate-catch-event.component";
 import { SequenceFlowComponent } from "./components/sequence-flow/sequence-flow.component";
 import { ScriptTaskComponent } from "./components/property/script-task/script-task.component";
+import { DragSelectDirective } from "./directive/drag-select/drag-select.directive";
 
 @NgModule({
     declarations: [
         AppComponent,
         CanvasComponent,
+        DragSelectDirective,
         EditablePropertyComponent,
         IntermediateCatchEventComponent,
         MenuComponent,
index 97fe3a6..daf26bc 100644 (file)
@@ -11,6 +11,6 @@
  *     ZTE - initial API and implementation and/or initial documentation
  */
 -->
-<div id="canvas" class="canvas" (click)="canvasClick()">
+<div id="canvas" class="canvas" (click)="canvasClick()" b4tDragSelect>
     <b4t-node *ngFor="let node of getWorkflow()?.nodes; let last = last;" [node]="node" [last]="last"></b4t-node>
 </div>
diff --git a/sdc-workflow-designer-ui/src/app/directive/drag-select/drag-select.directive.ts b/sdc-workflow-designer-ui/src/app/directive/drag-select/drag-select.directive.ts
new file mode 100644 (file)
index 0000000..395cf04
--- /dev/null
@@ -0,0 +1,134 @@
+/**\r
+ * Copyright (c) 2017 ZTE Corporation.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * and the Apache License 2.0 which both accompany this distribution,\r
+ * and are available at http://www.eclipse.org/legal/epl-v10.html\r
+ * and http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Contributors:\r
+ *     ZTE - initial API and implementation and/or initial documentation\r
+ */\r
+\r
+import { AfterViewInit, Directive, ElementRef } from '@angular/core';\r
+import { JsPlumbService } from "../../services/jsplumb.service";\r
+\r
+@Directive({\r
+    selector: '[b4tDragSelect]'\r
+})\r
+export class DragSelectDirective implements AfterViewInit {\r
+    private selectBox: any;\r
+    public selecting = false;\r
+\r
+    public relatvieX: number;\r
+    public relatvieY: number;\r
+\r
+    public startX: number;\r
+    public startY: number;\r
+    public endX: number;\r
+    public endY: number;\r
+\r
+    public left: number = 0;\r
+    public top: number = 0;\r
+    public width: number = 0;\r
+    public height: number = 0;\r
+\r
+    constructor(private el: ElementRef, private jsPlumbService: JsPlumbService) { }\r
+\r
+    public ngAfterViewInit(): void {\r
+        this.selectBox = document.createElement('div');\r
+        const selectArea = this.el.nativeElement.appendChild(this.selectBox);\r
+        this.el.nativeElement.addEventListener("mousedown", (event: MouseEvent) => this.mouseDown(event));\r
+        this.el.nativeElement.addEventListener("mousemove", (event: MouseEvent) => this.mouseMove(event));\r
+        this.el.nativeElement.addEventListener("mouseup", (event: MouseEvent) => this.mouseUp(event));\r
+    }\r
+\r
+    public mouseDown(event: MouseEvent) {\r
+        this.relatvieX = event.clientX - event.offsetX;\r
+        this.relatvieY = event.clientY - event.offsetY;\r
+\r
+        this.width = 0;\r
+        this.height = 0;\r
+        this.startX = event.clientX;\r
+        this.startY = event.clientY;\r
+        this.endX = this.startX;\r
+        this.endY = this.startY;\r
+        this.selecting = true;\r
+        this.updateSelectArea();\r
+    }\r
+\r
+    public mouseMove(event: MouseEvent) {\r
+        this.endX = event.clientX;\r
+        this.endY = event.clientY;\r
+\r
+        this.updateSelectArea();\r
+    }\r
+\r
+    public mouseUp(event: MouseEvent) {\r
+        this.selecting = false;\r
+        this.updateSelectArea();\r
+    }\r
+\r
+    private updateSelectArea() {\r
+        if (this.selecting) {\r
+            this.selectBox.className = 'selecting';\r
+        } else {\r
+            this.selectBox.className = '';\r
+            return;\r
+        }\r
+\r
+        this.getAllSelectedNodes();\r
+\r
+        const leftTmp = this.startX >= this.endX ? this.endX : this.startX;\r
+        const topTmp = this.startY >= this.endY ? this.endY : this.startY;\r
+\r
+        this.left = leftTmp - this.relatvieX;\r
+        this.top = topTmp - this.relatvieY;\r
+\r
+        this.width = Math.abs(this.startX - this.endX);\r
+        this.height = Math.abs(this.endY - this.startY);\r
+\r
+        this.selectBox.style.top = this.top + 'px';\r
+        this.selectBox.style.left = this.left + 'px';\r
+        this.selectBox.style.width = this.width + 'px';\r
+        this.selectBox.style.height = this.height + 'px';\r
+    }\r
+\r
+    public getAllSelectedNodes() {\r
+        if(!this.selecting) {\r
+            return;\r
+        }\r
+        const selectedNodes = [];\r
+\r
+        const nodes = this.el.nativeElement.querySelectorAll('div.node');\r
+        nodes.forEach(node => {\r
+            if(this.checkNodeSelected(node)) {\r
+                selectedNodes.push(node);\r
+            }\r
+        });\r
+\r
+        this.jsPlumbService.jsplumbInstance.clearDragSelection();\r
+        this.jsPlumbService.jsplumbInstance.addToDragSelection(selectedNodes);\r
+\r
+    }\r
+\r
+    private checkNodeSelected(node: any): boolean {\r
+        const nodeLeft = node.offsetLeft;\r
+        const nodeTop = node.offsetTop;\r
+        const nodeRigth = nodeLeft + node.clientWidth;\r
+        const nodeBottom = nodeTop + node.clientHeight;\r
+\r
+        const selectedRight = this.left + this.width;\r
+        const selectedBottom = this.top + this.height;\r
+\r
+        return this.between(nodeLeft, this.left, selectedRight)\r
+            && this.between(nodeRigth, this.left, selectedRight)\r
+            && this.between(nodeTop, this.top, selectedBottom)\r
+            && this.between(nodeBottom, this.top, selectedBottom);\r
+    }\r
+\r
+    private between(value, min, max): boolean {\r
+        return min <= value && value <= max;\r
+    }\r
+\r
+}\r
index 0ad5fac..efc1e0b 100644 (file)
@@ -40,7 +40,8 @@ export class InMemoryDataService implements InMemoryDbService {
             configs: {\r
                 microservices: []\r
             }\r
-        }\r
+        },\r
+        {"id":"fjh","name":"fjh","nodes":[{"id":"node0","name":"startEvent","type":"startEvent","position":{"top":43,"left":80.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node0","targetRef":"node2"}],"parameters":[]},{"id":"node1","name":"endEvent","type":"endEvent","position":{"top":273,"left":488,"width":200,"height":100},"sequenceFlows":[]},{"id":"node2","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":6,"left":178,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node2","targetRef":"node3","condition":"未完成"},{"sourceRef":"node2","targetRef":"node4","condition":"创建完成"}]},{"id":"node3","name":"createVL","type":"restTask","position":{"top":13.5,"left":283.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node3","targetRef":"node11"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node4","name":"restTask","type":"restTask","position":{"top":110,"left":152,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node4","targetRef":"node5"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node5","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":27.5,"left":401.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node5","targetRef":"node6","condition":"未完成"},{"sourceRef":"node5","targetRef":"node12","condition":"创建完成"}]},{"id":"node6","name":"createVNF","type":"restTask","position":{"top":91,"left":389,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node6","targetRef":"node7"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node7","name":"intermediateCatchEvent","type":"intermediateCatchEvent","position":{"top":190.5,"left":398,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node7","targetRef":"node8"}],"timerEventDefinition":{"type":"timeDuration"}},{"id":"node8","name":"query_vnf nslcm","type":"restTask","position":{"top":240,"left":390,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node8","targetRef":"node9"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node9","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":316.5,"left":405.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node9","targetRef":"node7","condition":"未完成"},{"sourceRef":"node9","targetRef":"node10","condition":"已完成"}]},{"id":"node10","name":"scriptTask","type":"scriptTask","position":{"top":405.5,"left":404.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node10","targetRef":"node5"}]},{"id":"node11","name":"scriptTask","type":"scriptTask","position":{"top":181.5,"left":110.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node11","targetRef":"node2"}]},{"id":"node12","name":"restTask","type":"restTask","position":{"top":147.5,"left":364.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node12","targetRef":"node13"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node13","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":214.5,"left":397.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node13","targetRef":"node14","condition":"未结束"},{"sourceRef":"node13","targetRef":"node18","condition":"已结束"}]},{"id":"node14","name":"createSfc","type":"restTask","position":{"top":202,"left":290.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node14","targetRef":"node15"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node15","name":"intermediateCatchEvent","type":"intermediateCatchEvent","position":{"top":128,"left":145.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node15","targetRef":"node16"}],"timerEventDefinition":{"type":"timeDuration"}},{"id":"node16","name":"restTask","type":"restTask","position":{"top":330.5,"left":221,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node16","targetRef":"node17"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node17","name":"exclusiveGateway","type":"exclusiveGateway","position":{"top":402,"left":351.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node17","targetRef":"node15","condition":"未结束"},{"sourceRef":"node17","targetRef":"node19","condition":"已结束"}]},{"id":"node18","name":"restTask","type":"restTask","position":{"top":217.5,"left":194,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node18","targetRef":"node20"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node19","name":"scriptTask","type":"scriptTask","position":{"top":466,"left":389,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node19","targetRef":"node13"}]},{"id":"node20","name":"Assign_all_status","type":"scriptTask","position":{"top":306.5,"left":590.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node20","targetRef":"node21"}]},{"id":"node21","name":"post_do","type":"restTask","position":{"top":390,"left":612.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node21","targetRef":"node22"}],"produces":[],"consumes":[],"parameters":[],"responses":[]},{"id":"node22","name":"jobstatus","type":"restTask","position":{"top":426,"left":682.5,"width":200,"height":100},"sequenceFlows":[{"sourceRef":"node22","targetRef":"node1"}],"produces":[],"consumes":[],"parameters":[],"responses":[]}],"configs":{"microservices":[]}},\r
         ];\r
         return { workflows, swagger};\r
     }\r
index 6b32fc3..0a624d5 100644 (file)
@@ -57,3 +57,9 @@ textarea.form-control {
     margin: 0 !important;
     font-size: 12px !important;
 }
+
+.selecting {
+    border: 1px solid royalblue;
+    background-color: yellowgreen;
+    position: absolute;
+}