2 * Copyright (c) 2017 ZTE Corporation.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * and the Apache License 2.0 which both accompany this distribution,
6 * and are available at http://www.eclipse.org/legal/epl-v10.html
7 * and http://www.apache.org/licenses/LICENSE-2.0
10 * ZTE - initial API and implementation and/or initial documentation
13 import { AfterViewChecked, AfterViewInit, Component, ElementRef, HostListener, OnInit, OnDestroy, ViewChild } from '@angular/core';
15 import { SequenceFlow } from '../../model/workflow/sequence-flow';
16 import { WorkflowElement } from '../../model/workflow/workflow-element';
17 import { WorkflowNode } from '../../model/workflow/workflow-node';
18 import { BroadcastService } from '../../services/broadcast.service';
19 import { InterfaceService } from '../../services/interface.service';
20 import { JsPlumbService } from '../../services/jsplumb.service';
21 import { ModelService } from '../../services/model.service';
24 * main canvas, it contains two parts: canvas and node property component
25 * bpmn task nodes can be dropped into this canvas, and then the workflow can be edit
28 selector: 'wfm-container',
29 templateUrl: 'container.component.html',
30 styleUrls: ['./container.component.css']
32 export class ContainerComponent implements AfterViewChecked, AfterViewInit, OnInit, OnDestroy {
33 public allNotes: WorkflowNode[];
34 @ViewChild('nodeSelector') nodeSelector: ElementRef;
35 @ViewChild('mainContainer') mainContainer: ElementRef;
37 private isSelecting = false;
38 private selectedElements: WorkflowElement[] = [];
39 private showProperties = false;
40 private needInitSequence = false;
42 constructor(private broadcastService: BroadcastService, private jsPlumbService: JsPlumbService,
43 private interfaceService: InterfaceService, public modelService: ModelService) {
46 @HostListener('window:keyup.delete', ['$event']) ondelete(event: KeyboardEvent) {
47 if (this.showProperties || 0 >= this.selectedElements.length) {
50 this.selectedElements.forEach(element => {
51 if (this.modelService.isNode(element)) {
52 let selectNode = element as WorkflowNode;
53 const parentId = this.jsPlumbService.getParentNodeId(selectNode.id);
54 this.jsPlumbService.remove(selectNode);
55 this.modelService.deleteNode(parentId, selectNode.id);
57 let sequenceFlow = element as SequenceFlow;
58 this.modelService.deleteConnection(sequenceFlow.sourceRef, sequenceFlow.targetRef);
59 this.jsPlumbService.deleteConnect(sequenceFlow.sourceRef, sequenceFlow.targetRef);
62 this.selectedElements = [];
65 @HostListener('document:mouseup', ['$event']) onmouseup() {
66 if (this.isSelecting) {
67 this.nodeSelector.nativeElement.style.display = 'none';
68 this.mainContainer.nativeElement.onmousemove = null;
69 this.isSelecting = false;
70 this.broadcastService.broadcast(this.broadcastService.showProperty, null);
71 this.broadcastService.broadcast(this.broadcastService.selectedElement, this.selectedElements);
76 this.jsPlumbService.initJsPlumbInstance(this.modelService.rootNodeId);
77 this.broadcastService.initModel$.subscribe(() => {
78 this.needInitSequence = true;
80 this.broadcastService.showProperty$.subscribe(element=>{
81 this.showProperties = null !== element;
85 public ngAfterViewInit() {
86 this.jsPlumbService.canvasDroppable();
87 this.broadcastService.selectedElement$.subscribe(elements => {
89 this.selectedElements = elements;
91 this.selectedElements = [];
96 public ngAfterViewChecked() {
97 if (this.needInitSequence) {
98 this.needInitSequence = false;
100 this.jsPlumbService.connectChildrenNodes(this.modelService.rootNodeId);
104 public ngOnDestroy() {
105 if (this.mainContainer.nativeElement.onmousemove) {
106 this.mainContainer.nativeElement.document.onmousemove = null;
110 public canvasMouseDown(event) {
111 this.selectedElements = [];
112 this.isSelecting = true;
113 let posx = event.clientX + this.mainContainer.nativeElement.scrollLeft;
114 posx = 220 > posx ? 0 : posx - 220;
115 let posy = event.clientY + this.mainContainer.nativeElement.scrollTop;
116 posy = 60 > posy ? 0 : posy - 60;
117 let element = this.nodeSelector.nativeElement;
118 element.style.left = posx + "px";
119 element.style.top = posy + "px";
120 element.style.width = '0px';
121 element.style.height = '0px';
122 element.style.display = 'block';
124 this.mainContainer.nativeElement.onmousemove = function (moveEvent) {
125 let movePosx = moveEvent.clientX + curThis.mainContainer.nativeElement.scrollLeft;
126 movePosx = 220 > movePosx ? 0 : movePosx - 220;
127 let movePosy = moveEvent.clientY + curThis.mainContainer.nativeElement.scrollTop;
128 movePosy = 60 > movePosy ? 0 : movePosy - 60;
129 const left = Math.min(movePosx, posx);
130 const top = Math.min(movePosy, posy);
131 const width = Math.abs(posx - movePosx);
132 const height = Math.abs(posy - movePosy);
133 element.style.left = left + "px";
134 element.style.top = top + "px";
135 element.style.width = width + "px";
136 element.style.height = height + "px";
137 curThis.selectNodes(left, top, width, height);
141 private selectNodes(left: number, top: number, width: number, height: number) {
142 this.selectedElements = [];
143 const allNodes = this.modelService.getNodes();
144 allNodes.forEach(node => {
145 const np = node.position;
146 let selected = false;
147 if (left < np.left) {
148 if ((top < np.top && left + width > np.left && top + height > np.top)
149 || (top >= np.top && top < np.top + np.height && left + width > np.left)) {
152 } else if (left < np.left + np.width) {
153 if ((top < np.top && top + height > np.top)
154 || (top >= np.top && top < np.top + np.height)) {
159 this.selectedElements.push(node);
162 this.broadcastService.broadcast(this.broadcastService.selectedElement, this.selectedElements);