diff --git a/src/app/cartography/cartography.module.ts b/src/app/cartography/cartography.module.ts index 99582470..99b15b66 100644 --- a/src/app/cartography/cartography.module.ts +++ b/src/app/cartography/cartography.module.ts @@ -10,7 +10,7 @@ import { LayersManager } from './managers/layers-manager'; import { MapChangeDetectorRef } from './services/map-change-detector-ref'; import { GraphLayout } from './widgets/graph-layout'; import { LinksWidget } from './widgets/links'; -import { NodesWidget } from './widgets/nodes'; +import { NodesWidget, NodeEvent } from './widgets/nodes'; import { DrawingsWidget } from './widgets/drawings'; import { DrawingLineWidget } from './widgets/drawing-line'; import { SelectionTool } from './tools/selection-tool'; diff --git a/src/app/cartography/components/map/map.component.ts b/src/app/cartography/components/map/map.component.ts index fc891679..fc89076d 100644 --- a/src/app/cartography/components/map/map.component.ts +++ b/src/app/cartography/components/map/map.component.ts @@ -1,8 +1,8 @@ import { - Component, ElementRef, HostListener, Input, OnChanges, OnDestroy, OnInit, SimpleChange + Component, ElementRef, HostListener, Input, OnChanges, OnDestroy, OnInit, SimpleChange, EventEmitter } from '@angular/core'; import { D3, D3Service } from 'd3-ng2-service'; -import { select, Selection } from 'd3-selection'; +import { Selection } from 'd3-selection'; import { Node } from "../../models/node"; import { Link } from "../../../models/link"; @@ -11,6 +11,8 @@ import { Context } from "../../models/context"; import { Size } from "../../models/size"; import { Drawing } from "../../models/drawing"; import { Symbol } from '../../../models/symbol'; +import { NodeEvent } from '../../widgets/nodes'; +import { Subscription } from 'rxjs'; @Component({ @@ -32,6 +34,8 @@ export class MapComponent implements OnInit, OnChanges, OnDestroy { private svg: Selection; private graphContext: Context; + private onNodeDraggingSubscription: Subscription; + // public graphLayout: GraphLayout; protected settings = { @@ -78,6 +82,7 @@ export class MapComponent implements OnInit, OnChanges, OnDestroy { ngOnDestroy() { this.graphLayout.disconnect(this.svg); + this.onNodeDraggingSubscription.unsubscribe(); } ngOnInit() { @@ -96,13 +101,12 @@ export class MapComponent implements OnInit, OnChanges, OnDestroy { this.graphContext.size = this.getSize(); - // this.graphLayout = new GraphLayout(); this.graphLayout.connect(this.svg, this.graphContext); - this.graphLayout.getNodesWidget().addOnNodeDraggingCallback((event: any, n: Node) => { + this.onNodeDraggingSubscription = this.graphLayout.getNodesWidget().onNodeDragging.subscribe((eventNode: NodeEvent) => { const linksWidget = this.graphLayout.getLinksWidget(); - const links = this.links.filter((link) => link.target.node_id === n.node_id || link.source.node_id === n.node_id) + const links = this.links.filter((link) => link.target.node_id === eventNode.node.node_id || link.source.node_id === eventNode.node.node_id) links.forEach((link) => { linksWidget.redrawLink(this.svg, link); diff --git a/src/app/cartography/widgets/nodes.ts b/src/app/cartography/widgets/nodes.ts index e06f05b6..228a94ea 100644 --- a/src/app/cartography/widgets/nodes.ts +++ b/src/app/cartography/widgets/nodes.ts @@ -1,4 +1,4 @@ -import { Injectable } from "@angular/core"; +import { Injectable, EventEmitter } from "@angular/core"; import { event, select, Selection } from "d3-selection"; import { D3DragEvent, drag } from "d3-drag"; @@ -12,6 +12,14 @@ import { CssFixer } from "../helpers/css-fixer"; import { FontFixer } from "../helpers/font-fixer"; +export class NodeEvent { + constructor( + public event: any, + public node: Node + ) {} +} + + @Injectable() export class NodesWidget implements Widget { static NODE_LABEL_MARGIN = 3; @@ -19,13 +27,13 @@ export class NodesWidget implements Widget { private debug = false; private draggingEnabled = false; - private onContextMenuCallback: (event: any, node: Node) => void; - private onNodeClickedCallback: (event: any, node: Node) => void; - private onNodeDraggedCallback: (event: any, node: Node) => void; - private onNodeDraggingCallbacks: ((event: any, node: Node) => void)[] = []; - private symbols: Symbol[] = []; + public onContextMenu = new EventEmitter(); + public onNodeClicked = new EventEmitter(); + public onNodeDragged = new EventEmitter(); + public onNodeDragging = new EventEmitter(); + constructor( private cssFixer: CssFixer, private fontFixer: FontFixer @@ -33,22 +41,6 @@ export class NodesWidget implements Widget { this.symbols = []; } - public setOnContextMenuCallback(onContextMenuCallback: (event: any, node: Node) => void) { - this.onContextMenuCallback = onContextMenuCallback; - } - - public setOnNodeClickedCallback(onNodeClickedCallback: (event: any, node: Node) => void) { - this.onNodeClickedCallback = onNodeClickedCallback; - } - - public setOnNodeDraggedCallback(onNodeDraggedCallback: (event: any, node: Node) => void) { - this.onNodeDraggedCallback = onNodeDraggedCallback; - } - - public addOnNodeDraggingCallback(onNodeDraggingCallback: (event: any, n: Node) => void) { - this.onNodeDraggingCallbacks.push(onNodeDraggingCallback); - } - public setSymbols(symbols: Symbol[]) { this.symbols = symbols; } @@ -57,12 +49,6 @@ export class NodesWidget implements Widget { this.draggingEnabled = enabled; } - private executeOnNodeDraggingCallback(callback_event: any, node: Node) { - this.onNodeDraggingCallbacks.forEach((callback: (e: any, n: Node) => void) => { - callback(callback_event, node); - }); - } - public revise(selection: SVGSelection) { selection .attr('transform', (n: Node) => { @@ -151,14 +137,10 @@ export class NodesWidget implements Widget { .classed('selected', (n: Node) => n.is_selected) .on("contextmenu", function (n: Node, i: number) { event.preventDefault(); - if (self.onContextMenuCallback !== null) { - self.onContextMenuCallback(event, n); - } + self.onContextMenu.emit(new NodeEvent(event, n)); }) .on('click', (n: Node) => { - if (self.onNodeClickedCallback) { - self.onNodeClickedCallback(event, n); - } + this.onNodeClicked.emit(new NodeEvent(event, n)); }); // update image of node @@ -192,17 +174,15 @@ export class NodesWidget implements Widget { n.y = e.y; self.revise(select(this)); - self.executeOnNodeDraggingCallback(event, n); + self.onNodeDragging.emit(new NodeEvent(event, n)); }; const dragging = () => { return drag() .on('drag', callback) .on('end', (n: Node) => { - if (self.onNodeDraggedCallback) { - const e: D3DragEvent = event; - self.onNodeDraggedCallback(e, n); - } + const e: D3DragEvent = event; + self.onNodeDragged.emit(new NodeEvent(e, n)); }); }; diff --git a/src/app/components/project-map/node-context-menu/node-context-menu.component.ts b/src/app/components/project-map/node-context-menu/node-context-menu.component.ts index 22927c9e..16d67795 100644 --- a/src/app/components/project-map/node-context-menu/node-context-menu.component.ts +++ b/src/app/components/project-map/node-context-menu/node-context-menu.component.ts @@ -18,8 +18,8 @@ export class NodeContextMenuComponent implements OnInit { @ViewChild(MatMenuTrigger) contextMenu: MatMenuTrigger; - private topPosition; - private leftPosition; + protected topPosition; + protected leftPosition; public node: Node; constructor( diff --git a/src/app/components/project-map/project-map.component.ts b/src/app/components/project-map/project-map.component.ts index edc91470..7fc90932 100644 --- a/src/app/components/project-map/project-map.component.ts +++ b/src/app/components/project-map/project-map.component.ts @@ -28,6 +28,7 @@ import { SelectionManager } from "../../cartography/managers/selection-manager"; import { InRectangleHelper } from "../../cartography/helpers/in-rectangle-helper"; import { DrawingsDataSource } from "../../cartography/datasources/drawings-datasource"; import { ProgressService } from "../../common/progress/progress.service"; +import { NodeEvent } from '../../cartography/widgets/nodes'; @Component({ @@ -194,27 +195,34 @@ export class ProjectMapComponent implements OnInit, OnDestroy { this.mapChild.graphLayout.getNodesWidget().setDraggingEnabled(!this.readonly); - this.mapChild.graphLayout.getNodesWidget().setOnContextMenuCallback((event: any, node: Node) => { - this.nodeContextMenu.open(node, event.clientY, event.clientX); + + const onContextMenu = this.mapChild.graphLayout.getNodesWidget().onContextMenu.subscribe((eventNode: NodeEvent) => { + this.nodeContextMenu.open(eventNode.node, eventNode.event.clientY, eventNode.event.clientX); }); - this.mapChild.graphLayout.getNodesWidget().setOnNodeClickedCallback((event: any, node: Node) => { + this.subscriptions.push(onContextMenu); + + const onNodeClicked = this.mapChild.graphLayout.getNodesWidget().onNodeClicked.subscribe((eventNode: NodeEvent) => { this.selectionManager.clearSelection(); - this.selectionManager.setSelectedNodes([node]); + this.selectionManager.setSelectedNodes([eventNode.node]); if (this.drawLineMode) { - this.nodeSelectInterfaceMenu.open(node, event.clientY, event.clientX); + this.nodeSelectInterfaceMenu.open(eventNode.node, eventNode.event.clientY, eventNode.event.clientX); } }); - this.mapChild.graphLayout.getNodesWidget().setOnNodeDraggedCallback((event: any, node: Node) => { - this.nodesDataSource.update(node); + this.subscriptions.push(onNodeClicked); + + const onNodeDragged = this.mapChild.graphLayout.getNodesWidget().onNodeDragged.subscribe((eventNode: NodeEvent) => { + this.nodesDataSource.update(eventNode.node); this.nodeService - .updatePosition(this.server, node, node.x, node.y) + .updatePosition(this.server, eventNode.node, eventNode.node.x, eventNode.node.y) .subscribe((n: Node) => { this.nodesDataSource.update(n); }); }); + this.subscriptions.push(onNodeDragged); + this.subscriptions.push( this.selectionManager.subscribe( this.mapChild.graphLayout.getSelectionTool().rectangleSelected)